diff --git a/.gitea/workflows/build-npc.yml b/.gitea/workflows/build-npc.yml index 7336129..81238db 100644 --- a/.gitea/workflows/build-npc.yml +++ b/.gitea/workflows/build-npc.yml @@ -5,7 +5,7 @@ jobs: npc-build: strategy: matrix: - package: [ "flow", "flow-simlib"] + package: [ "flow", "flow-simlib" ] runs-on: nix defaults: run: diff --git a/.gitignore b/.gitignore index e9c6af4..018413a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ difftest/ **/result /.pre-commit-config.yaml **/.vscode/ +*.sock +logs/ +**/.envrc +**/.gdbinit diff --git a/flake.lock b/flake.lock index 1aa5691..9b857c0 100644 --- a/flake.lock +++ b/flake.lock @@ -7,6 +7,28 @@ "pre-commit-hooks": "pre-commit-hooks", "ysyx-workbench": "ysyx-workbench" }, + "locked": { + "lastModified": 1723715524, + "narHash": "sha256-dLTI8ah5Ub7mvXlFly6pGSUxpnwWyRBafoQqMhP6KQM=", + "ref": "dev", + "rev": "8630fe7667967009757721bece55235dca5b7614", + "revCount": 83, + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + }, + "original": { + "ref": "dev", + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + } + }, + "am-kernels_2": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks_2", + "ysyx-workbench": "ysyx-workbench_2" + }, "locked": { "lastModified": 1723617032, "narHash": "sha256-oL5Vx933Jhn+T9jn67wFbh8vy7w8OJNCn4DOOlX/r0U=", @@ -24,10 +46,10 @@ }, "diffu": { "inputs": { - "flake-utils": "flake-utils_5", - "nixpkgs": "nixpkgs_2", + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_3", "nur-xin": "nur-xin_2", - "pre-commit-hooks": "pre-commit-hooks_3" + "pre-commit-hooks": "pre-commit-hooks_4" }, "locked": { "lastModified": 1723627842, @@ -43,6 +65,27 @@ "url": "https://git.xinyang.life/xin/diffu.git" } }, + "diffu_2": { + "inputs": { + "flake-utils": "flake-utils_11", + "nixpkgs": "nixpkgs_4", + "nur-xin": "nur-xin_4", + "pre-commit-hooks": "pre-commit-hooks_6" + }, + "locked": { + "lastModified": 1723782444, + "narHash": "sha256-d5mtlOgA11mSl2S0ID0VYrk0JdnLT1r521od3NiAcxs=", + "ref": "refs/heads/master", + "rev": "507d20390c294466a22ad8722341e7510f28222c", + "revCount": 19, + "type": "git", + "url": "https://git.xinyang.life/xin/diffu.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/diffu.git" + } + }, "flake-compat": { "flake": false, "locked": { @@ -107,6 +150,70 @@ "type": "github" } }, + "flake-compat_5": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_6": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_7": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_8": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -125,6 +232,132 @@ "type": "github" } }, + "flake-utils_10": { + "inputs": { + "systems": "systems_10" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_11": { + "inputs": { + "systems": "systems_11" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_12": { + "inputs": { + "systems": "systems_12" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_13": { + "inputs": { + "systems": "systems_13" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_14": { + "inputs": { + "systems": "systems_14" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_15": { + "inputs": { + "systems": "systems_15" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_16": { + "inputs": { + "systems": "systems_16" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "flake-utils_2": { "inputs": { "systems": "systems_2" @@ -184,11 +417,11 @@ "systems": "systems_5" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", "type": "github" }, "original": { @@ -220,11 +453,11 @@ "systems": "systems_7" }, "locked": { - "lastModified": 1709126324, - "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -251,6 +484,24 @@ "type": "github" } }, + "flake-utils_9": { + "inputs": { + "systems": "systems_9" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -278,6 +529,7 @@ "nixpkgs": [ "am-kernels", "ysyx-workbench", + "am-kernels", "pre-commit-hooks", "nixpkgs" ] @@ -299,7 +551,10 @@ "gitignore_3": { "inputs": { "nixpkgs": [ - "diffu", + "am-kernels", + "ysyx-workbench", + "am-kernels", + "ysyx-workbench", "pre-commit-hooks", "nixpkgs" ] @@ -321,6 +576,97 @@ "gitignore_4": { "inputs": { "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "diffu", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_5": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_6": { + "inputs": { + "nixpkgs": [ + "diffu", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_7": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_8": { + "inputs": { + "nixpkgs": [ + "spike-diff", "pre-commit-hooks", "nixpkgs" ] @@ -387,6 +733,22 @@ "type": "github" } }, + "nixpkgs-circt162_3": { + "locked": { + "lastModified": 1705645507, + "narHash": "sha256-tX3vipIAmNDBA8WNWG4oY4KyTfnm2YieTHO2BhG8ISA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + } + }, "nixpkgs-stable": { "locked": { "lastModified": 1710695816, @@ -451,23 +813,71 @@ "type": "github" } }, - "nixpkgs_2": { + "nixpkgs-stable_5": { "locked": { - "lastModified": 1711703276, - "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_3": { + "nixpkgs-stable_6": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_7": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_8": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { "locked": { "lastModified": 1709237383, "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", @@ -483,9 +893,75 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1709237383, + "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nur-xin": { "inputs": { "nixpkgs": [ + "am-kernels", + "ysyx-workbench", "am-kernels", "ysyx-workbench", "nixpkgs" @@ -508,6 +984,8 @@ "nur-xin_2": { "inputs": { "nixpkgs": [ + "am-kernels", + "ysyx-workbench", "diffu", "nixpkgs" ] @@ -529,6 +1007,8 @@ "nur-xin_3": { "inputs": { "nixpkgs": [ + "am-kernels", + "ysyx-workbench", "nixpkgs" ] }, @@ -546,6 +1026,68 @@ "url": "https://git.xinyang.life/xin/nur.git" } }, + "nur-xin_4": { + "inputs": { + "nixpkgs": [ + "diffu", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + } + }, + "nur-xin_5": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + } + }, + "nur-xin_6": { + "inputs": { + "nixpkgs": [ + "spike-diff", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat", @@ -579,6 +1121,7 @@ "nixpkgs": [ "am-kernels", "ysyx-workbench", + "am-kernels", "nixpkgs" ], "nixpkgs-stable": "nixpkgs-stable_2" @@ -603,7 +1146,10 @@ "flake-utils": "flake-utils_6", "gitignore": "gitignore_3", "nixpkgs": [ - "diffu", + "am-kernels", + "ysyx-workbench", + "am-kernels", + "ysyx-workbench", "nixpkgs" ], "nixpkgs-stable": "nixpkgs-stable_3" @@ -628,6 +1174,9 @@ "flake-utils": "flake-utils_8", "gitignore": "gitignore_4", "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "diffu", "nixpkgs" ], "nixpkgs-stable": "nixpkgs-stable_4" @@ -646,15 +1195,137 @@ "type": "github" } }, + "pre-commit-hooks_5": { + "inputs": { + "flake-compat": "flake-compat_5", + "flake-utils": "flake-utils_10", + "gitignore": "gitignore_5", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_5" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_6": { + "inputs": { + "flake-compat": "flake-compat_6", + "flake-utils": "flake-utils_12", + "gitignore": "gitignore_6", + "nixpkgs": [ + "diffu", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_6" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_7": { + "inputs": { + "flake-compat": "flake-compat_7", + "flake-utils": "flake-utils_14", + "gitignore": "gitignore_7", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_7" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_8": { + "inputs": { + "flake-compat": "flake-compat_8", + "flake-utils": "flake-utils_16", + "gitignore": "gitignore_8", + "nixpkgs": [ + "spike-diff", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_8" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "am-kernels": "am-kernels", - "diffu": "diffu", - "flake-utils": "flake-utils_7", - "nixpkgs": "nixpkgs_3", - "nixpkgs-circt162": "nixpkgs-circt162_2", - "nur-xin": "nur-xin_3", - "pre-commit-hooks": "pre-commit-hooks_4" + "diffu": "diffu_2", + "flake-utils": "flake-utils_13", + "nixpkgs": "nixpkgs_5", + "nixpkgs-circt162": "nixpkgs-circt162_3", + "nur-xin": "nur-xin_5", + "pre-commit-hooks": "pre-commit-hooks_7", + "spike-diff": "spike-diff" + } + }, + "spike-diff": { + "inputs": { + "flake-utils": "flake-utils_15", + "nixpkgs": "nixpkgs_6", + "nur-xin": "nur-xin_6", + "pre-commit-hooks": "pre-commit-hooks_8" + }, + "locked": { + "lastModified": 1723687708, + "narHash": "sha256-tXW+Toqfr1QFKvlKvmNJq6ZegZ+F4PdIJh1dTBIvCj0=", + "ref": "refs/heads/main", + "rev": "c0de3e619e0fe2fb83d926d8c3d0127071d21510", + "revCount": 4, + "type": "git", + "url": "https://git.xinyang.life/xin/spike-diff.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/spike-diff.git" } }, "systems": { @@ -672,6 +1343,111 @@ "type": "github" } }, + "systems_10": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_11": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_12": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_13": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_14": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_15": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_16": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "systems_2": { "locked": { "lastModified": 1681028828, @@ -777,16 +1553,60 @@ "type": "github" } }, + "systems_9": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "ysyx-workbench": { "inputs": { - "flake-utils": "flake-utils_3", + "am-kernels": "am-kernels_2", + "diffu": "diffu", + "flake-utils": "flake-utils_9", "nixpkgs": [ "am-kernels", "nixpkgs" ], + "nixpkgs-circt162": "nixpkgs-circt162_2", + "nur-xin": "nur-xin_3", + "pre-commit-hooks": "pre-commit-hooks_5" + }, + "locked": { + "lastModified": 1723714692, + "narHash": "sha256-EU6HE8DfSorD2Wx7yjBicSSLxGKxKbDD/3XI+RUB7Gs=", + "ref": "refs/heads/master", + "rev": "0e408882b21b17fa19158b2044498ddad8e691e7", + "revCount": 126, + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + } + }, + "ysyx-workbench_2": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "nixpkgs" + ], "nixpkgs-circt162": "nixpkgs-circt162", "nur-xin": "nur-xin", - "pre-commit-hooks": "pre-commit-hooks_2" + "pre-commit-hooks": "pre-commit-hooks_3" }, "locked": { "lastModified": 1723551098, diff --git a/flake.nix b/flake.nix index 86c9a4f..b625815 100644 --- a/flake.nix +++ b/flake.nix @@ -13,10 +13,23 @@ }; diffu.url = "git+https://git.xinyang.life/xin/diffu.git"; am-kernels.url = "git+https://git.xinyang.life/xin/am-kernels.git?ref=dev"; + spike-diff.url = "git+https://git.xinyang.life/xin/spike-diff.git"; }; - outputs = { self, flake-utils, nixpkgs, nixpkgs-circt162, pre-commit-hooks, nur-xin, diffu, am-kernels }@inputs: - flake-utils.lib.eachDefaultSystem (system: + outputs = + { + self, + flake-utils, + nixpkgs, + nixpkgs-circt162, + pre-commit-hooks, + nur-xin, + diffu, + am-kernels, + spike-diff, + }@inputs: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = import nixpkgs { inherit system; @@ -39,6 +52,8 @@ }; }; }; + + am-kernels-nemu = am-kernels.packages.${system}.rv32Cross.am-kernels-nemu; in { checks = { @@ -50,7 +65,10 @@ cmake-format.enable = true; clang-format = { enable = true; - types_or = pkgs.lib.mkForce [ "c" "c++" ]; + types_or = pkgs.lib.mkForce [ + "c" + "c++" + ]; }; scalafmt = { enable = true; @@ -63,13 +81,19 @@ }; }; - packages = rec { + packages = { abstract-machine = pkgs.callPackage ./abstract-machine { isa = "native"; }; - nemu = pkgs.callPackage ./nemu { }; - nemu-lib = pkgs.callPackage ./nemu { }; + nemu = pkgs.callPackage ./nemu { am-kernels = am-kernels-nemu; }; + nemu-lib = pkgs.callPackage ./nemu { defconfig = "libdefconfig"; }; - rv32Cross = rec { - abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; }; + rv32Cross = { + abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { + isa = "riscv"; + platform = [ + "nemu" + "npc" + ]; + }; }; }; @@ -92,7 +116,7 @@ self.packages.${system}.nemu ]; NEMU_HOME = "/home/xin/repo/ysyx-workbench/nemu"; - # NEMU_IMAGES_PATH = self.packages.${system}.rv32Cross.am-kernels-nemu + "/share/am-kernels"; + NEMU_IMAGES_PATH = am-kernels.packages.${system}.rv32Cross.am-kernels-nemu + "/share/am-kernels"; }; devShells.npc = pkgs.mkShell.override { stdenv = pkgs.ccacheStdenv; } { @@ -125,23 +149,36 @@ verilator ]; - buildInputs = with pkgs; [ - spdlog - nvboard - openssl - libllvm - libxml2 - readline - mini-gdbstub - ] ++ self.checks.${system}.pre-commit-check.enabledPackages; + buildInputs = + with pkgs; + [ + spdlog + nvboard + openssl + libllvm + libxml2 + readline + mini-gdbstub + ] + ++ self.checks.${system}.pre-commit-check.enabledPackages; }; - devShells.difftest = pkgs.mkShell { + devShells.default = pkgs.mkShell { + inherit (self.checks.${system}.pre-commit-check) shellHook; + buildInputs = self.checks.${system}.pre-commit-check.enabledPackages; + packages = [ diffu.packages.${system}.default am-kernels.packages.${system}.rv32Cross.am-kernels-npc self.packages.${system}.nemu-lib + spike-diff.packages.${system}.default + pkgs.gef + pkgs.gtkwave ]; + + DIFFU_IMAGES_PATH = "${am-kernels.packages.${system}.rv32Cross.am-kernels-npc}"; + NEMU_SO = "${self.packages.${system}.nemu-lib}/lib/riscv32-nemu-interpreter-so"; + NPC_SO = "/home/xin/repo/ysyx-workbench/npc/build/csrc/Flow/libFlow.so"; }; } ); diff --git a/npc/.envrc b/npc/.envrc index beaa935..3550a30 100644 --- a/npc/.envrc +++ b/npc/.envrc @@ -1 +1 @@ -use flake ".?submodules=1#npc" +use flake diff --git a/npc/.gitignore b/npc/.gitignore index 5a4f7bc..d3a1927 100644 --- a/npc/.gitignore +++ b/npc/.gitignore @@ -17,3 +17,5 @@ hs_err_pid* compile_commands.json *.vcd +*.gtkw +*.sock diff --git a/npc/CMakePresets.json b/npc/CMakePresets.json new file mode 100644 index 0000000..8e361b5 --- /dev/null +++ b/npc/CMakePresets.json @@ -0,0 +1,28 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 19, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "ENABLE_YSYX_GIT_TRACKER": "ON", + "BUILD_CHISEL_EMIT_TARGET": "ON", + "TOPMODULE": "Flow", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ] +} diff --git a/npc/cmake/ChiselBuild.cmake b/npc/cmake/ChiselBuild.cmake index f446790..ba27957 100644 --- a/npc/cmake/ChiselBuild.cmake +++ b/npc/cmake/ChiselBuild.cmake @@ -32,7 +32,9 @@ else() set(CHISEL_TEST_TARGET sbt_${TOPMODULE}_test) add_custom_command( OUTPUT ${CHISEL_OUTPUT_TOPMODULE} ${CHISEL_OUTPUT_VERILATOR_CONF} - COMMAND sbt "run ${CHISEL_EMIT_ARGS}" + # Try to use native sbt to increase performance when possible + COMMAND ${CMAKE_COMMAND} -E env SBT_NATIVE_CLIENT=true sbt + "run ${CHISEL_EMIT_ARGS}" WORKING_DIRECTORY ${SCALA_CORE} DEPENDS ${CHISEL_DEPENDENCY} VERBATIM diff --git a/npc/core/build.sbt b/npc/core/build.sbt index e5de39d..ff6b22b 100644 --- a/npc/core/build.sbt +++ b/npc/core/build.sbt @@ -1,7 +1,7 @@ ThisBuild / scalaVersion := "2.13.12" -ThisBuild / version := "0.1.0" +ThisBuild / version := "0.1.1" -val chiselVersion = "6.2.0" +val chiselVersion = "6.5.0" val circeVersion = "0.14.1" lazy val root = (project in file(".")) diff --git a/npc/core/project/build.properties b/npc/core/project/build.properties index 04267b1..ee4c672 100644 --- a/npc/core/project/build.properties +++ b/npc/core/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.9 +sbt.version=1.10.1 diff --git a/npc/core/src/main/resources/RamDpi.v b/npc/core/src/main/resources/RamDpi.v index cbab381..89bf2b6 100644 --- a/npc/core/src/main/resources/RamDpi.v +++ b/npc/core/src/main/resources/RamDpi.v @@ -1,4 +1,4 @@ -import "DPI-C" function int pmem_read(input int addr); +import "DPI-C" function int pmem_read(input int addr, input byte rmask); import "DPI-C" function void pmem_write(input int waddr, input int wdata, input byte wmask); module RamDpi ( @@ -9,6 +9,7 @@ module RamDpi ( input [31:0] writeAddr, input [31:0] writeData, input [3:0] writeMask, + input [3:0] readMask, input reg [31:0] readAddr, output reg [31:0] readData, input reg [31:0] pc, @@ -16,7 +17,7 @@ module RamDpi ( ); always @(posedge clock) begin if (valid) begin // 有读写请求时 - readData = pmem_read(readAddr); + readData = pmem_read(readAddr, { 4'h0, readMask }); if (writeEnable) begin // 有写请求时 pmem_write(writeAddr, writeData, { 4'h0, writeMask }); end @@ -25,5 +26,5 @@ module RamDpi ( readData = 32'h80000000; end end - assign inst = pmem_read(pc); + assign inst = pmem_read(pc, 8'hF); endmodule diff --git a/npc/core/src/main/scala/components/ALU.scala b/npc/core/src/main/scala/components/ALU.scala index 0c1f0ae..6607fea 100644 --- a/npc/core/src/main/scala/components/ALU.scala +++ b/npc/core/src/main/scala/components/ALU.scala @@ -3,11 +3,14 @@ package flow.components import chisel3._ import chisel3.util._ import shapeless.{HNil, ::} +import flow.Params +import flow.components.util._ +import chisel3.util.experimental.decode.{decoder, TruthTable} -class ALUControlInterface extends Bundle { +object ALUControlInterface { object OpSelect extends ChiselEnum { - val aOpAdd, aOpSub, aOpNot, aOpAnd, aOpOr, aOpXor, aOpSlt, aOpSltu, aOpSll, - aOpSrl, aOpSra = Value + val aOpAdd, aOpSub, aOpAnd, aOpOr, aOpXor, aOpSlt, aOpSltu, aOpSll, aOpSrl, + aOpSra = Value } object SrcASelect extends ChiselEnum { val aSrcARs1, aSrcAPc, aSrcAZero = Value @@ -15,31 +18,34 @@ class ALUControlInterface extends Bundle { object SrcBSelect extends ChiselEnum { val aSrcBRs2, aSrcBImmI, aSrcBImmJ, aSrcBImmS, aSrcBImmU = Value } - val op = Input(OpSelect()) - val srcASelect = Input(SrcASelect()) - val srcBSelect = Input(SrcBSelect()) - val signExt = Input(Bool()) + class ALUControlInterface extends Bundle { + val op = Input(OpSelect()) + val srcASelect = Input(SrcASelect()) + val srcBSelect = Input(SrcBSelect()) + val signExt = Input(Bool()) - def ctrlBindPorts = { - op :: srcASelect :: srcBSelect :: signExt :: HNil + def ctrlBindPorts = { + op :: srcASelect :: srcBSelect :: signExt :: HNil + } } + + def apply() = new ALUControlInterface; } -class ALU[T <: UInt](tpe: T) extends Module { - val control = IO(new ALUControlInterface) +class ALU(implicit p: Params) extends Module { + import ALUControlInterface._ + val control = IO(ALUControlInterface()) val in = IO(new Bundle { - val a = Input(Vec(control.SrcASelect.all.length, tpe)) - val b = Input(Vec(control.SrcBSelect.all.length, tpe)) + val a = Input(Vec(SrcASelect.all.length, UInt(p.XLEN))) + val b = Input(Vec(SrcBSelect.all.length, UInt(p.XLEN))) }) val out = IO(new Bundle { - val eq = Output(Bool()) - val result = Output(tpe) + val result = Output(UInt(p.XLEN)) }) val a = in.a(control.srcASelect.asUInt) val b = in.b(control.srcBSelect.asUInt) - // val adder_b = (Fill(tpe.getWidth, io.op(0)) ^ io.b) + io.op(0) // take (-b) if sub val add = a + b val sub = a - b val and = a & b @@ -48,18 +54,16 @@ class ALU[T <: UInt](tpe: T) extends Module { val xor = a ^ b val slt = a.asSInt < b.asSInt val sltu = a < b - val sll = a << b(log2Ceil(tpe.getWidth), 0) - val srl = a >> b(log2Ceil(tpe.getWidth), 0) - val sra = a.asSInt >> b(log2Ceil(tpe.getWidth), 0) - out.eq := a === b + val sll = a << b(5, 0) + val srl = a >> b(5, 0) + val sra = a.asSInt >> b(5, 0) - import control.OpSelect._ + import OpSelect._ out.result := MuxLookup(control.op, 0.U)( Seq( aOpAdd -> add, aOpSub -> sub, - aOpNot -> not, aOpAnd -> and, aOpOr -> or, aOpXor -> xor, @@ -72,8 +76,92 @@ class ALU[T <: UInt](tpe: T) extends Module { ) } -object ALU { - def apply[T <: UInt](tpe: T): ALU[T] = { - Module(new ALU(tpe)) - } +class AluController(implicit p: Params) extends Module { + val out = IO(Flipped(ALUControlInterface())) + val in = IO(new Bundle { + val inst = Input(UInt(p.XLEN)) + }) + import flow.components.RV32Inst._ + import ALUControlInterface._ + // OpSelect + // format: off + val aOpAdd = Array( + lui, auipc, + jal, jalr, + lb, lbu, lh, lhu, lw, + sb, sh, sw, + addi, add + ).map(_ -> OpSelect.aOpAdd.BP) + // format: on + + val aOpAnd = Array(and, andi).map(_ -> OpSelect.aOpAnd.BP) + + val aOpSub = Array(sub).map(_ -> OpSelect.aOpSub.BP) + + val aOpOr = Array(ori, or).map(_ -> OpSelect.aOpOr.BP) + + val aOpXor = Array(xori, xor).map(_ -> OpSelect.aOpXor.BP) + + val aOpSlt = Array(beq, bne, blt, bge, slti, slt).map(_ -> OpSelect.aOpSlt.BP) + + val aOpSltu = Array(sltiu, sltu, bltu, bgeu).map(_ -> OpSelect.aOpSltu.BP) + + val aOpSll = Array(slli, sll).map(_ -> OpSelect.aOpSll.BP) + + val aOpSrl = Array(srli, srl).map(_ -> OpSelect.aOpSrl.BP) + + val aOpSra = Array( + sra, + srai + ).map(_ -> OpSelect.aOpSra.BP) + + val OpCodeMapping = TruthTable( + aOpAdd ++ aOpAnd ++ aOpSub ++ aOpOr ++ aOpXor ++ aOpSlt ++ aOpSltu ++ aOpSll ++ aOpSrl ++ aOpSra, + BitPat.dontCare(OpSelect.getWidth) + ) + + val aSrcAZero = Array( + lui + ).map(_ -> SrcASelect.aSrcAZero.BP) + + val aSrcAPc = Array( + auipc, + jal + ).map(_ -> SrcASelect.aSrcAPc.BP) + + val srcAMapping = TruthTable( + aSrcAZero ++ aSrcAPc, + SrcASelect.aSrcARs1.BP + ) + val aSrcBImmS = Array(sb, sh, sw).map(_ -> SrcBSelect.aSrcBImmS.BP) + + val aSrcBImmU = Array(lui, auipc).map(_ -> SrcBSelect.aSrcBImmU.BP) + + val aSrcBImmJ = Array(jal).map(_ -> SrcBSelect.aSrcBImmJ.BP) + + // format: off + val aSrcBImmI = Array( + jalr, + lb, lbu, lh, lhu, lw, + addi, slti, sltiu, xori, ori, andi, slli, srli, srai + ).map(_ -> SrcBSelect.aSrcBImmI.BP) + // format: on + + val srcBMapping = TruthTable( + aSrcBImmI ++ aSrcBImmJ ++ aSrcBImmU ++ aSrcBImmS, + SrcBSelect.aSrcBRs2.BP + ) + + val doSignExt = Array(blt, bge, slt, slti).map(_ -> BitPat(true.B)) + + val noSignExt = Array(lui, auipc, jal, jalr, bltu, bgeu, sltiu, sltu).map( + _ -> BitPat(false.B) + ) + + val signExtMapping = TruthTable(doSignExt ++ noSignExt, BitPat.dontCare(1)) + + out.op := OpSelect.safe(decoder(in.inst, OpCodeMapping))._1 + out.srcASelect := SrcASelect.safe(decoder(in.inst, srcAMapping))._1 + out.srcBSelect := SrcBSelect.safe(decoder(in.inst, srcBMapping))._1 + out.signExt := decoder(in.inst, signExtMapping) } diff --git a/npc/core/src/main/scala/components/CSR.scala b/npc/core/src/main/scala/components/CSR.scala index 5ea795f..9738fe9 100644 --- a/npc/core/src/main/scala/components/CSR.scala +++ b/npc/core/src/main/scala/components/CSR.scala @@ -11,25 +11,28 @@ import flow.Params import chisel3.util.BitPat import chisel3.util.Fill -class CSRControlInterface extends Bundle { +object CSRControlInterface extends Bundle { object csrRead extends ChiselEnum { val csrReadDisabled, csrReadEnabled = Value } object csrWrite extends ChiselEnum { - val csrWriteDisabled, csrWriteEnabled = Value + val csrWriteDisabled, csrWriteData, csrSetBit, csrClearBit = Value } - val readEnable = Input(csrRead()) - val writeEnable = Input(csrWrite()) + class CSRControlInterface extends Bundle { + val readEnable = Input(csrRead()) + val writeEnable = Input(csrWrite()) - def ctrlBindPorts = { - readEnable :: writeEnable :: HNil + def ctrlBindPorts = { + readEnable :: writeEnable :: HNil + } } + def apply() = new CSRControlInterface } class CSRCore(implicit val p: Params) extends Module { - val control = IO(new CSRControlInterface) + val control = IO(CSRControlInterface()) val in = IO(new Bundle { val csrAddr = Input(UInt(p.csrAddrWidth)) diff --git a/npc/core/src/main/scala/components/Mem.scala b/npc/core/src/main/scala/components/Mem.scala index 52889cb..d3faeda 100644 --- a/npc/core/src/main/scala/components/Mem.scala +++ b/npc/core/src/main/scala/components/Mem.scala @@ -5,38 +5,81 @@ import chisel3.experimental.noPrefix import chisel3.util.HasBlackBoxPath import chisel3.util.HasBlackBoxResource import chisel3.util.log2Ceil +import chisel3.util.BitPat import flow.components +import flow.Params import shapeless.:: import shapeless.HNil import scala.collection.SeqMap +import chisel3.util.experimental.decode.{decoder, TruthTable} +import flow.components.util._ +import flow.components.RV32Inst._ -class RamControlInterface(addrWidth: Int) extends Bundle { - val valid = Input(Bool()) - val writeMask = Input(UInt((addrWidth / 8).W)) - val writeEnable = Input(Bool()) - def ctrlBindPorts = { - valid :: writeMask :: writeEnable :: HNil - } - -} - -/* FIXME: Extends here might not be the best solution. - * We need a way to merge two bundles together - */ -class RamInterface[T <: Data](tpe: T, addrWidth: Int) - extends RamControlInterface(addrWidth) { - val clock = Input(Clock()) - val reset = Input(Reset()) - val writeAddr = Input(UInt(addrWidth.W)) - val writeData = Input(tpe) - val readAddr = Input(UInt(addrWidth.W)) - val readData = Output(tpe) - val pc = Input(UInt(addrWidth.W)) - val inst = Output(tpe) -} - -class RamDpi extends BlackBox with HasBlackBoxResource { - val io = IO((new RamInterface(UInt(32.W), 32))) +class RamDpi(implicit p: Params) extends BlackBox with HasBlackBoxResource { + val io = IO(new DpiRamInterface) addResource("/RamDpi.v") } + +class DpiRamControlInterface(implicit p: Params) extends Bundle { + val valid = Input(Bool()) + val readMask = Input(UInt((p.XLEN.get / 8).W)) + val writeMask = Input(UInt((p.XLEN.get / 8).W)) + val writeEnable = Input(Bool()) +} + +class DpiRamInterface(implicit p: Params) extends DpiRamControlInterface { + val clock = Input(Clock()) + val reset = Input(Reset()) + + // Data + val writeAddr = Input(UInt(p.XLEN)) + val writeData = Input(UInt(p.XLEN)) + val readAddr = Input(UInt(p.XLEN)) + val readData = Output(UInt(p.XLEN)) + val pc = Input(UInt(p.XLEN)) + val inst = Output(UInt(p.XLEN)) +} + +class RamController(implicit p: Params) extends Module { + val in = new Bundle { + val inst = IO(Flipped(UInt(p.XLEN))) + } + val out = IO(Flipped(new DpiRamControlInterface)) + private val validMapping = TruthTable( + Array(sb, sh, sw, lb, lbu, lh, lhu, lw).map(_ -> BitPat("b1")), + BitPat("b0") + ) + + private val writeMaskMapping = TruthTable( + Array( + sb -> BitPat("b0001"), + sh -> BitPat("b0011"), + sw -> BitPat("b1111") + ), + BitPat.dontCare(out.writeMask.getWidth) + ) + + private val readMaskMapping = TruthTable( + Array( + lb -> BitPat("b0001"), + lh -> BitPat("b0011"), + lw -> BitPat("b1111") + ), + BitPat.dontCare(out.readMask.getWidth) + ) + + private val writeEnableMapping = TruthTable( + Array( + sb -> BitPat("b1"), + sh -> BitPat("b1"), + sw -> BitPat("b1") + ), + BitPat("b0") + ) + + out.valid := decoder(in.inst, validMapping) + out.writeEnable := decoder(in.inst, writeEnableMapping) + out.writeMask := decoder(in.inst, writeMaskMapping) + out.readMask := decoder(in.inst, readMaskMapping) +} diff --git a/npc/core/src/main/scala/components/ProgramCounter.scala b/npc/core/src/main/scala/components/ProgramCounter.scala index 287ca7f..3388849 100644 --- a/npc/core/src/main/scala/components/ProgramCounter.scala +++ b/npc/core/src/main/scala/components/ProgramCounter.scala @@ -1,48 +1,76 @@ package flow.components import chisel3._ +import chisel3.util.experimental.decode.{decoder, TruthTable} import chisel3.util.{Valid, log2Ceil} import chisel3.util.MuxLookup +import chisel3.util.BitPat import shapeless.{HNil, ::} +import shapeless.HList +import flow.Params +import RV32InstSubfields._ +import flow.components.util._ -class PcControlInterface extends Bundle { +object PcControlInterface { object SrcSelect extends ChiselEnum { - val pStaticNpc, pExeOut = Value + val pStatic, pJmp, pBR = Value } - val useImmB = Input(Bool()) - val srcSelect = Input(SrcSelect()) + class newPcControlInterface extends Bundle { + val srcSelect = Input(SrcSelect()) - def ctrlBindPorts = { - useImmB :: srcSelect :: HNil + def ctrlBindPorts = { + srcSelect :: HNil + } } + def apply() = new newPcControlInterface; } -class ProgramCounter[T <: UInt](tpe: T) extends Module { - - val control = IO(new PcControlInterface) +class ProgramCounter(implicit p: Params) extends Module { + val control = IO(PcControlInterface()) + import PcControlInterface.SrcSelect._ val in = IO(new Bundle { - val immB = Input(tpe) - val exeOut = Input(tpe) + val brOffset = Input(UInt(p.XLEN)) + val jAddr = Input(UInt(p.XLEN)) }) - val out = IO(Output(tpe)) + val out = IO(Output(UInt(p.XLEN))) - private val pc_reg = RegInit(0x80000000L.U) + private val pcReg = RegInit(p.resetVector.U) + out := pcReg -// pc := in.pcSrcs(control.srcSelect.asUInt) - import control.SrcSelect._ - when(control.useImmB === true.B) { - pc_reg := pc_reg + in.immB - }.elsewhen(control.srcSelect === pStaticNpc) { - pc_reg := pc_reg + 4.U - }.elsewhen(control.srcSelect === pExeOut) { - pc_reg := in.exeOut - } - out := pc_reg + private val npc = MuxLookup(control.srcSelect, 4.U)( + Seq( + pStatic -> (pcReg + 4.U), + pJmp -> in.jAddr, + pBR -> (pcReg + in.brOffset) + ) + ) + + pcReg := npc } -object ProgramCounter { - def apply[T <: UInt](tpe: T): ProgramCounter[T] = { - val pc = Module(new ProgramCounter(tpe)) - pc - } +class PcController(implicit p: Params) extends Module { + val in = IO(new Bundle { + val inst = Input(UInt(p.instWidth)) + }) + + val out = IO(Flipped(PcControlInterface())) + + import RV32Inst._ + import PcControlInterface.SrcSelect._ + private val _jmpMapping = Array(jal, jalr).map(_ -> pJmp.BP) + private val _brMapping = + Array(beq, bne, blt, bge, bltu, bgeu).map(_ -> pBR.BP) + + val mapping = TruthTable( + _jmpMapping ++ _brMapping, + pStatic.BP + ) + + out.srcSelect := PcControlInterface.SrcSelect + .safe( + ( + decoder(in.inst, mapping) + ) + ) + ._1 } diff --git a/npc/core/src/main/scala/components/RegisterFile.scala b/npc/core/src/main/scala/components/RegisterFile.scala index fe646fd..7574bf8 100644 --- a/npc/core/src/main/scala/components/RegisterFile.scala +++ b/npc/core/src/main/scala/components/RegisterFile.scala @@ -4,53 +4,109 @@ import chisel3._ import chisel3.util.log2Ceil import chisel3.util.UIntToOH import chisel3.util.MuxLookup +import chisel3.util.BitPat +import chisel3.util.experimental.decode.{decoder, TruthTable} import chisel3.experimental.Trace._ import shapeless.{HList, HNil, ::} - -class RegControl extends Bundle { +import flow.Params +import flow.components.util._ +import flow.components.RV32Inst._ +object RegControl { object WriteSelect extends ChiselEnum { val rAluOut, rMemOut, rNpc = Value } + class RegControl extends Bundle { + val writeEnable = Input(Bool()) + val writeSelect = Input(WriteSelect()) - val writeEnable = Input(Bool()) - val writeSelect = Input(WriteSelect()) - - def ctrlBindPorts = { - writeEnable :: writeSelect :: HNil + def ctrlBindPorts = { + writeEnable :: writeSelect :: HNil + } } - traceName(writeEnable) + + def apply() = new RegControl } -class RegisterFile[T <: Data](tpe: T, regCount: Int, numReadPorts: Int) - extends Module { - require(numReadPorts >= 0) - val control = IO(new RegControl) - val dataAddrWidth = log2Ceil(regCount).W +class RegisterFile(implicit p: Params) extends Module { val in = IO(new Bundle { - val writeAddr = Input(UInt(dataAddrWidth)) - val writeData = Input(Vec(control.WriteSelect.all.length, tpe)) - val rs = Input(Vec(numReadPorts, UInt(dataAddrWidth))) + val rd = Input(UInt(p.regsAddrWidth)) + val writeData = Input(Vec(RegControl.WriteSelect.all.length, UInt(p.XLEN))) + val rs1 = Input(UInt(p.regsAddrWidth)) + val rs2 = Input(UInt(p.regsAddrWidth)) }) + val out = IO(new Bundle { - val src = Output(Vec(numReadPorts, tpe)) + val src1 = Output(UInt(p.XLEN)) + val src2 = Output(UInt(p.XLEN)) }) - val regResetValue = 0.U(tpe.getWidth.W) - val regFile = RegInit(VecInit(Seq.fill(regCount)(regResetValue))) - val writeAddrOH = UIntToOH(in.writeAddr) + val control = IO(RegControl()) - for ((reg, i) <- regFile.zipWithIndex.tail) { - reg := Mux( - writeAddrOH(i.U(log2Ceil(regCount).W)) && control.writeEnable, - in.writeData(control.writeSelect.asUInt), - reg - ) - } + val regFile = RegInit( + VecInit(Seq.fill(p.regsCount)(p.regsResetValue.U(p.XLEN))) + ) + + // 0.U -> writeData(0), ... + val writeDataMux = + MuxBindCtrlSrc(control.writeSelect, in.writeData, regFile(in.rd)) + + regFile(in.rd) := Mux( + control.writeEnable, + writeDataMux, + regFile(in.rd) + ) regFile(0) := 0.U - for (port <- 0 until numReadPorts) { - out.src(port) := regFile(in.rs(port).asUInt) - } + out.src1 := regFile(in.rs1) + out.src2 := regFile(in.rs2) traceName(regFile) dontTouch(regFile) } + +class RegisterFileController(implicit p: Params) extends Module { + val in = IO(new Bundle { + val inst = Input(UInt(p.XLEN)) + }) + + val out = IO(Flipped(RegControl())) + + // format: off + import RegControl._ + private val aluOutMapping = + Array( + lui, auipc, + addi, slti, sltiu, xori, ori, andi, slli, srli, srai, + add, sub, sll, slt, sltu, xor, srl, sra, or, and, + ).map(_ -> WriteSelect.rAluOut.BP) + + private val memOutMapping = + Array( + lb, lbu, lh, lhu, lw + ).map(_ -> WriteSelect.rMemOut.BP) + + private val npcMapping = + Array( + jal, jalr + ).map(_ -> WriteSelect.rNpc.BP) + // format: on + + private val writeSelectMapping = TruthTable( + aluOutMapping ++ memOutMapping ++ npcMapping, + BitPat.dontCare(out.writeSelect.getWidth) + ) + + // enable write if instruction belongs to any mapping above + private val writeEnableMapping = TruthTable( + (aluOutMapping ++ memOutMapping ++ npcMapping).map(x => + (x._1 -> BitPat("b1")) + ), + BitPat("b0") + ) + + out.writeSelect := RegControl.WriteSelect + .safe( + decoder(in.inst, writeSelectMapping) + ) + ._1 + out.writeEnable := decoder(in.inst, writeEnableMapping) +} diff --git a/npc/core/src/main/scala/components/util.scala b/npc/core/src/main/scala/components/util.scala new file mode 100644 index 0000000..9065c1c --- /dev/null +++ b/npc/core/src/main/scala/components/util.scala @@ -0,0 +1,28 @@ +package flow.components + +import chisel3._ +import chisel3.util.BitPat +import chisel3.util.MuxLookup + +object util { + implicit class enumToUInt[T <: EnumType](e: T) { + def U = { + e.asUInt + } + def BP = { + BitPat(e.litValue.toInt.U(e.getWidth.W)) + } + } + + import scala.language.implicitConversions + implicit def chiselEnumAsInt[T <: EnumType](e: T): Int = { + e.litValue.toInt + } + + object MuxBindCtrlSrc { + def apply[E <: EnumType, T <: Data](ctrl: E, src: Vec[T], default: T) = { + val map = (0 until src.length).map(_.U).zip(src) + MuxLookup(ctrl.U, default)(map) + } + } +} diff --git a/npc/core/src/main/scala/stages/Base.scala b/npc/core/src/main/scala/stages/Base.scala new file mode 100644 index 0000000..4c43954 --- /dev/null +++ b/npc/core/src/main/scala/stages/Base.scala @@ -0,0 +1,74 @@ +package flow.stages + +import chisel3._ +import flow.Params +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import chisel3.util.ReadyValidIO + +class DecoupledMsgIO[Tin <: Data, Tout <: Data]( + _in: => Option[DecoupledIO[Tin]], + _out: => Option[DecoupledIO[Tout]] +)(implicit + p: Params +) extends Bundle { + implicit class optionWithGetThrow[T](o: Option[T]) { + def getOrThrow[E <: Exception](e: E): T = o match { + case Some(x) => x + case None => throw e + } + } + lazy val in = _in.getOrThrow(new Exception(s"No input port at $this")) + lazy val out = _out.getOrThrow(new Exception(s"No output port at $this")) + + def connect[Tout_ <: Data]( + other: DecoupledMsgIO[Tout, Tout_] + ) = { + if (p.arch == "single") { + // out.ready := DontCare + // out.valid := DontCare + // other.in.valid := DontCare + // other.in.ready := DontCare + other.in.bits := out.bits + } else if (p.arch == "multi") { + out :<>= other.in + } else { + throw new Exception("Unknown architecture") + } + other + } +} + +object DecoupledMsgIO { + import scala.language.implicitConversions + + /** Wrap input and output messages in ReadValidIO + */ + def apply[Tin <: Data, Tout <: Data]( + in: Option[Tin] = None, + out: Option[Tout] = None, + isIO: Boolean = true + )(implicit + p: Params + ) = { + val _in = in match { + case Some(d) => + if (isIO) Some(Flipped(Decoupled(d))) + else Some(Wire(Flipped(Decoupled(d)))) + case None => None + } + + val _out = out match { + case Some(d) => + if (isIO) Some(Decoupled(d)) else Some(Decoupled(d)) + case None => None + } + new DecoupledMsgIO(_in, _out) + } +} + +object utils { + implicit class dataWrapBySome[T <: Data](d: T) { + def S = Some(d) + } +} diff --git a/npc/core/src/main/scala/stages/EX.scala b/npc/core/src/main/scala/stages/EX.scala new file mode 100644 index 0000000..9f5bad7 --- /dev/null +++ b/npc/core/src/main/scala/stages/EX.scala @@ -0,0 +1,75 @@ +package flow.stages + +import chisel3._ +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import flow.Params +import flow.stages.utils._ +import flow.components.ALU +import flow.components.ALUControlInterface +import flow.stages.messages._ +import flow.components.RV32InstSubfields._ + +class EX(implicit val p: Params) extends Module { + + // val msgio = IO(DecoupledMsgIO((new ID2EX).S, (new EX2LS).S)) + val msgio = IO(new Bundle { + val in = Flipped(DecoupledIO(new ID2EX)) + val out = DecoupledIO(new EX2LS) + }) + msgio.in.ready := DontCare + msgio.out.valid := DontCare + + val io = IO(new Bundle { + val toIF = Output(new EX2IF) + }) + + private val _toIF = io.toIF + private val _in = msgio.in.bits + private val _out = msgio.out.bits + + val alu = Module(new ALU) + alu.control := _in.aluCtrl; + + { + import flow.components.ALUControlInterface.SrcASelect._ + import flow.components.util.chiselEnumAsInt + alu.in.a(aSrcARs1) := _in.src1 + alu.in.a(aSrcAPc) := _in.pc + alu.in.a(aSrcAZero) := 0.U + + import flow.components.ALUControlInterface.SrcBSelect._ + alu.in.b(aSrcBRs2) := _in.src2 + alu.in.b(aSrcBImmI) := _in.inst.immI + alu.in.b(aSrcBImmJ) := _in.inst.immJ + alu.in.b(aSrcBImmU) := _in.inst.immU + alu.in.b(aSrcBImmS) := _in.inst.immS + } + + _out.exeOut := alu.out.result + + _toIF.jAddr := alu.out.result + _toIF.brOffset := _in.inst.immB + _toIF.pc := _in.pc + + import flow.components.PcControlInterface.SrcSelect._ + val regSrcEq = Wire(Bool()); + regSrcEq := (_in.src1 === _in.src2); + when(_in.pcCtrl.srcSelect === pBR) { + val branchUseSlt = _in.inst(14) + val branchInvertResult = _in.inst(12) + val _branchResult = + Mux(branchUseSlt, alu.out.result(0), regSrcEq) + val branchResult = Mux(branchInvertResult, !_branchResult, _branchResult) + _toIF.pcCtrl.srcSelect := Mux(branchResult, pBR, pStatic) + }.otherwise { + _toIF.pcCtrl.srcSelect := _in.pcCtrl.srcSelect + } + + _out.ramCtrl := _in.ramCtrl + _out.pc := _in.pc + _out.rd := _in.inst.rd + _out.src1 := _in.src1 + _out.src2 := _in.src2 + _out.regCtrl := _in.regCtrl +} diff --git a/npc/core/src/main/scala/stages/ID.scala b/npc/core/src/main/scala/stages/ID.scala new file mode 100644 index 0000000..eae4de2 --- /dev/null +++ b/npc/core/src/main/scala/stages/ID.scala @@ -0,0 +1,64 @@ +package flow.stages + +import chisel3._ +import flow.Params +import flow.stages.utils._ +import flow.stages.messages._ +import flow.components._ +import flow.components.RV32InstSubfields._ +import chisel3.util.DecoupledIO +import chisel3.experimental.Trace._ +import chisel3.util.experimental.InlineInstance + +class ID(implicit val p: Params) extends Module { + val io = IO(new Bundle { + val fromWB = Input(new WB2ID) + }) + + // val msgio = IO(DecoupledMsgIO((new IF2ID).S, (new ID2EX).S)) + val msgio = IO(new Bundle { + val in = Flipped(DecoupledIO(new IF2ID)) + val out = DecoupledIO(new ID2EX) + }) + msgio.in.ready := DontCare + msgio.out.valid := DontCare + + val _in = msgio.in.bits + val _out = msgio.out.bits + val _fromWB = io.fromWB + + val regs = Module(new RegisterFile with InlineInstance) + + // Controllers + val pcController = Module(new PcController) + val regFileController = Module(new RegisterFileController) + val aluController = Module(new AluController) + val ramController = Module(new RamController) + + pcController.in.inst := _in.inst + regFileController.in.inst := _in.inst + aluController.in.inst := _in.inst + ramController.in.inst := _in.inst + + regs.in.rs1 := _in.inst.rs1 + regs.in.rs2 := _in.inst.rs2 + _out.src1 := regs.out.src1 + _out.src2 := regs.out.src2 + + _out.pc := _in.pc + _out.pcCtrl := pcController.out + + _out.regCtrl := regFileController.out + _out.aluCtrl := aluController.out + _out.ramCtrl := ramController.out + _out.inst := _in.inst + + // register file write back + import flow.components.RegControl.WriteSelect._ + import flow.components.util.chiselEnumAsInt + regs.control := _fromWB.regCtrl + regs.in.rd := _fromWB.rd + regs.in.writeData(rAluOut) := _fromWB.exeOut + regs.in.writeData(rMemOut) := _fromWB.memOut + regs.in.writeData(rNpc) := _fromWB.npc +} diff --git a/npc/core/src/main/scala/stages/IF.scala b/npc/core/src/main/scala/stages/IF.scala new file mode 100644 index 0000000..c1084b3 --- /dev/null +++ b/npc/core/src/main/scala/stages/IF.scala @@ -0,0 +1,46 @@ +package flow.stages + +import chisel3._ +import flow.Params +import flow.components.ProgramCounter +import flow.components.PcControlInterface +import flow.stages.utils._ +import flow.stages.messages._ +import chisel3.util.DecoupledIO + +class IF(implicit val p: Params) extends Module { + import flow.components.RV32InstSubfields._ + + // Use DPI-C for instant instruction fetch for now + val io = IO(new Bundle { + val fromRam = Input(new Ram2IF) + val toRam = Output(new IF2Ram) + + val fromEx = Input(new EX2IF) + }) + + val msgio = IO(new Bundle { + val out = DecoupledIO(new IF2ID) + }) + msgio.out.valid := DontCare + // val msgio = IO(DecoupledMsgIO(out = (new IF2ID).S)) + + val _out = msgio.out.bits + val _fromRam = io.fromRam + val _toRam = io.toRam + val _fromEx = io.fromEx + + // Program Counter + private val pc = Module(new ProgramCounter) + + // PC update + pc.in.brOffset := _fromEx.brOffset + pc.in.jAddr := _fromEx.jAddr + + pc.control := _fromEx.pcCtrl + + // Instruction fetch + _toRam.pc := pc.out + _out.inst := _fromRam.inst + _out.pc := pc.out +} diff --git a/npc/core/src/main/scala/stages/LS.scala b/npc/core/src/main/scala/stages/LS.scala new file mode 100644 index 0000000..e71744a --- /dev/null +++ b/npc/core/src/main/scala/stages/LS.scala @@ -0,0 +1,53 @@ +package flow.stages + +import chisel3._ +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import flow.Params +import flow.stages.utils._ +import flow.stages.messages._ +import flow.components.RamDpi + +class LS(implicit val p: Params) extends Module { + val io = IO(new Bundle { + val toIF = Output(new Ram2IF) + val fromIF = Input(new IF2Ram) + }) + // val msgio = IO(DecoupledMsgIO((new EX2LS).S, (new LS2WB).S)) + val msgio = IO(new Bundle { + val in = Flipped(DecoupledIO(new EX2LS)) + val out = DecoupledIO(new LS2WB) + }) + msgio.in.ready := DontCare + msgio.out.valid := DontCare + private val _in = msgio.in.bits + private val _out = msgio.out.bits + private val _toIF = io.toIF + private val _fromIF = io.fromIF + + val ram = Module(new RamDpi) + + ram.io.clock := clock + ram.io.reset := reset + ram.io.writeAddr := _in.exeOut + ram.io.writeData := _in.src2 + ram.io.writeMask := _in.ramCtrl.writeMask + ram.io.readMask := _in.ramCtrl.readMask + + ram.io.writeEnable := _in.ramCtrl.writeEnable + ram.io.valid := _in.ramCtrl.valid // TODO: change to a better name + ram.io.readAddr := _in.exeOut + + // TODO: Change to icache, and move to IF stage. + // Change to arbitor here + ram.io.pc := _fromIF.pc + _toIF.inst := ram.io.inst + + _out.memOut := ram.io.readData + _out.exeOut := _in.exeOut + + // passthrough + _out.regCtrl := _in.regCtrl + _out.rd := _in.rd + _out.pc := _in.pc +} diff --git a/npc/core/src/main/scala/stages/Messages.scala b/npc/core/src/main/scala/stages/Messages.scala new file mode 100644 index 0000000..b6002c3 --- /dev/null +++ b/npc/core/src/main/scala/stages/Messages.scala @@ -0,0 +1,73 @@ +package flow.stages.messages + +import chisel3._ +import flow.Params +import flow.components._ + +class IF2ID(implicit p: Params) extends Bundle { + val inst = UInt(p.instWidth) + val pc = UInt(p.XLEN) +} + +class ID2EX(implicit p: Params) extends Bundle { + // Data + val pc = UInt(p.XLEN) + val inst = UInt(p.XLEN) + val src1 = UInt(p.XLEN) + val src2 = UInt(p.XLEN) + + // Control + val aluCtrl = Flipped(ALUControlInterface()) + val ramCtrl = Flipped(new DpiRamControlInterface) + val pcCtrl = Flipped(PcControlInterface()) + val regCtrl = Flipped(RegControl()) +} + +class EX2LS(implicit p: Params) extends Bundle { + val pc = UInt(p.XLEN) + val rd = UInt(p.regsAddrWidth) + val src1 = UInt(p.XLEN) + val src2 = UInt(p.XLEN) + + val exeOut = UInt(p.XLEN) + + // Control + val ramCtrl = Flipped(new DpiRamControlInterface) + val regCtrl = Flipped(RegControl()) +} + +class LS2WB(implicit p: Params) extends Bundle { + val pc = UInt(p.XLEN) + val rd = UInt(p.regsAddrWidth) + val memOut = UInt(p.XLEN) + val exeOut = UInt(p.XLEN) + + val regCtrl = Flipped(RegControl()) +} + +class EX2IF(implicit p: Params) extends Bundle { + val pc = UInt(p.XLEN) + val brOffset = UInt(p.XLEN) + val jAddr = UInt(p.XLEN) + + // Control + val pcCtrl = Flipped(PcControlInterface()) +} + +class IF2Ram(implicit p: Params) extends Bundle { + val pc = UInt(p.XLEN) +} + +class Ram2IF(implicit p: Params) extends Bundle { + val inst = UInt(p.XLEN) +} + +/** Commit result back to registers + */ +class WB2ID(implicit p: Params) extends Bundle { + val regCtrl = Flipped(RegControl()) + val exeOut = UInt(p.XLEN) + val memOut = UInt(p.XLEN) + val rd = UInt(p.regsAddrWidth) + val npc = UInt(p.XLEN) +} diff --git a/npc/core/src/main/scala/stages/WB.scala b/npc/core/src/main/scala/stages/WB.scala new file mode 100644 index 0000000..e194f0e --- /dev/null +++ b/npc/core/src/main/scala/stages/WB.scala @@ -0,0 +1,32 @@ +package flow.stages + +import chisel3._ +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import flow.Params +import flow.stages.utils._ +import flow.stages.messages._ +import chisel3.experimental.Trace._ + +class WB(implicit val p: Params) extends Module { + // val msgio = IO(DecoupledMsgIO(in = (new LS2WB).S)) + val io = IO(new Bundle { + val toID = Output(new WB2ID) + }) + val msgio = IO(new Bundle { + val in = Flipped(DecoupledIO(new LS2WB)) + }) + msgio.in.ready := DontCare + + private val _in = msgio.in.bits + private val _toID = io.toID + + _toID.exeOut := _in.exeOut; + _toID.memOut := _in.memOut; + _toID.regCtrl := _in.regCtrl; + _toID.rd := _in.rd + _toID.npc := _in.pc + 4.U + + traceName(_in.pc) + traceName(_in.rd) +} diff --git a/npc/core/src/main/scala/top/Config.scala b/npc/core/src/main/scala/top/Config.scala index 4c21a25..e7c4453 100644 --- a/npc/core/src/main/scala/top/Config.scala +++ b/npc/core/src/main/scala/top/Config.scala @@ -18,6 +18,20 @@ import io.circe.generic.JsonCodec import chisel3._ case class Params( XLEN: Width, + instWidth: Width = 32.W, + regsCount: Int = 32, + regsAddrWidth: Width = 5.W, + regsResetValue: BigInt = 0L, arch: String, - csrAddrWidth: Width = 12.W + csrAddrWidth: Width = 12.W, + resetVector: BigInt = BigInt(0x80000000L), + csrNameToAddr: Map[String, Int] = Map( + "mstatus" -> 0x300, + "mtvec" -> 0x305, + "mie" -> 0x304, + "mepc" -> 0x341, + "mcause" -> 0x342, + "mtval" -> 0x343, + "mip" -> 0x344 + ) ) diff --git a/npc/core/src/main/scala/top/FlowMain.scala b/npc/core/src/main/scala/top/FlowMain.scala index 01b1972..8ab67d3 100644 --- a/npc/core/src/main/scala/top/FlowMain.scala +++ b/npc/core/src/main/scala/top/FlowMain.scala @@ -13,454 +13,35 @@ import chisel3.util.{BinaryMemoryFile, HexMemoryFile} import chisel3.experimental.Trace import scala.collection.IndexedSeqView import shapeless.Poly1 -import flow.components.RamControlInterface +import flow.components.DpiRamControlInterface import flow.components.RV32Inst import flow.components.RV32InstSubfields._ +import flow.components.util._ import flow.components.{RegControl, PcControlInterface, ALUControlInterface} -class Control(width: Int) extends RawModule { - // Helpers - class WrapList[T](vl: T) { type Type = T; val v = vl } - object wrap extends Poly1 { - implicit def default[A] = at[A](Right(_).withLeft[Int]) - } - def lit(x: Element) = { x.litValue.toInt } - def toBits(t: dst.Type): BitPat = { - val list = t.toList - list - .map(e => - e match { - case Right(x) => BitPat(lit(x).U(x.getWidth.W)) - case Left(x) => BitPat.dontCare(x) - } - ) - .reduceLeft(_ ## _) - } - val r = Right - def l[T <: Any](x: T) = x match { - case x: ChiselEnum => Left(log2Ceil(x.all.length)) - case x: Data => Left(x.getWidth) - case _ => throw new IllegalArgumentException - } - val inst = IO(Input(UInt(width.W))) +import flow.stages._ +import chisel3.experimental.annotate +import chisel3.experimental.ChiselAnnotation - val reg = IO(Flipped(new RegControl)) - val pc = IO(Flipped(new PcControlInterface)) - val alu = IO(Flipped(new ALUControlInterface)) - val ram = IO(Flipped(new RamControlInterface(32))) +import chisel3.Data +import chisel3.experimental.{annotate, requireIsAnnotatable, ChiselAnnotation} - val dst = new WrapList( - (reg.ctrlBindPorts ++ - pc.ctrlBindPorts ++ - alu.ctrlBindPorts ++ - ram.ctrlBindPorts).map(wrap) - ) - - val dstList = dst.v.toList - val controlWidth = dstList.map(_.toOption.get.getWidth).reduce(_ + _) - val reversePrefixSum = dstList.scanLeft(0)(_ + _.toOption.get.getWidth) - val sliceIndex = reversePrefixSum.map(controlWidth - _) - val slices = sliceIndex.map(_ - 1).zip(sliceIndex.tail) - - import reg.WriteSelect._ - import reg._ - import pc.SrcSelect._ - import pc._ - import alu.OpSelect._ - import alu.SrcASelect._ - import alu.SrcBSelect._ - import pc._ - import RV32Inst._ - // format: off - val ControlMapping: Array[(BitPat, dst.Type)] = Array( - // Regs | writeEnable :: writeSelect :: HNil - // PC | useImmB :: srcSelect :: HNil - // Exe | op :: srcASelect :: srcBSelect :: signExt :: HNil - // Mem | valid :: writeMask :: writeEnable :: HNil - - (lui , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc):: - r(aOpAdd) :: r(aSrcAZero) :: r(aSrcBImmU) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (auipc , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc):: - r(aOpAdd) :: r(aSrcAPc) :: r(aSrcBImmU) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - // ---- Control Transfer Instructions ---- - (jal , ( - r(true.B) :: r(rNpc) :: - r(false.B) :: r(pExeOut) :: - r(aOpAdd) :: r(aSrcAPc) :: r(aSrcBImmJ) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (jalr , ( - r(true.B) :: r(rNpc) :: - r(false.B) :: r(pExeOut) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (beq , ( - r(false.B) :: l(WriteSelect) :: - r(true.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (bne , ( - r(false.B) :: l(WriteSelect) :: - r(true.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (blt , ( - r(false.B) :: l(WriteSelect) :: - r(true.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(true.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (bge , ( - r(false.B) :: l(WriteSelect) :: - r(true.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(true.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (bltu , ( - r(false.B) :: l(WriteSelect):: - r(true.B) :: r(pStaticNpc) :: - r(aOpSltu) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)) :: r(false.B) :: HNil - )), - - (bgeu , ( - r(false.B) :: l(WriteSelect):: - r(true.B) :: r(pStaticNpc) :: - r(aOpSltu) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)) :: r(false.B) :: HNil - )), - - // ---- Memory Access Instructions ---- - - (lb , ( - r(true.B) :: r(rMemOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(true.B) :: r(1.U(4.W)) :: r(false.B) :: HNil - )), - - (lbu , ( - r(true.B) :: r(rMemOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(true.B) :: r(0.U(4.W)) :: r(false.B) :: HNil - )), - - (lh , ( - r(true.B) :: r(rMemOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(true.B) :: r(3.U(4.W)) :: r(false.B) :: HNil - )), - - (lhu , ( - r(true.B) :: r(rMemOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(true.B) :: r(2.U(4.W)) :: r(false.B) :: HNil - )), - - (lw , ( - r(true.B) :: r(rMemOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(true.B) :: r(14.U(4.W)) :: r(false.B) :: HNil - )), - - (sb , ( - r(false.B) :: l(WriteSelect):: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmS) :: l(Bool()) :: - r(true.B) :: r(1.U(4.W)) :: r(true.B) :: HNil - )), - - (sh , ( - r(false.B) :: l(WriteSelect):: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmS) :: l(Bool()) :: - r(true.B) :: r(3.U(4.W)) :: r(true.B) :: HNil - )), - - (sw , ( - r(false.B) :: l(WriteSelect):: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmS) :: l(Bool()) :: - r(true.B) :: r(15.U(4.W)) :: r(true.B) :: HNil - )), - - // ---- Integer Computational Instructions --- - - (addi , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (slti , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBImmI) :: r(true.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (sltiu , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSltu) :: r(aSrcARs1) :: r(aSrcBImmI) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (xori , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpXor) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (ori , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpOr) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (andi , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAnd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (slli , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSll) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (srli , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSrl) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (srai , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSra) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (add , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (sub , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSub) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (sll , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSll) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (slt , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(true.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (sltu , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSltu) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(false.B) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (xor , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpXor) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (srl , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSrl) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (sra , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpSra) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (or , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpOr) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - - (and , ( - r(true.B) :: r(rAluOut) :: - r(false.B) :: r(pStaticNpc) :: - r(aOpAnd) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) :: - r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil - )), - ) - // format: on - - val default = BitPat(0.U(controlWidth.W)) - -// println(s"ControlMapping = ${ControlMapping.map(it => (it._1 -> toBits(it._2))).foreach(x => println(x._2))}\n") - val out = decoder( - inst, - TruthTable(ControlMapping.map(it => (it._1 -> toBits(it._2))), default) - ) - val srcList = slices.map(s => out(s._1, s._2)) - - assert(out != default) - println(s"out = $out, default = $default\n") - println(s"dstList = ${dstList}\n") - println(s"srcList = ${srcList}\n") - srcList - .zip(dstList) - .foreach({ case (src, dst) => - dst.toOption.get := src.asTypeOf(dst.toOption.get) - }) -} - -import flow.components.{RegisterFile, ProgramCounter, ALU, RamDpi} -import chisel3.util.experimental.loadMemoryFromFileInline class Flow extends Module { - def lit(x: Data) = { x.litValue.toInt } + implicit val p: Params = new Params(XLEN = 32.W, arch = "single") + val IF = Module(new IF) + val ID = Module(new ID) + val EX = Module(new EX) + val LS = Module(new LS) + val WB = Module(new WB) + // IF.msgio connect ID.msgio connect EX.msgio connect LS.msgio connect [Nothing] WB.msgio + ID.msgio.in :<>= IF.msgio.out + EX.msgio.in :<>= ID.msgio.out + LS.msgio.in :<>= EX.msgio.out + WB.msgio.in :<>= LS.msgio.out - val dataType = UInt(32.W) - val ram = Module(new RamDpi) - val control = Module(new Control(32)) - val reg = Module(new RegisterFile(dataType, 32, 2)) - val pc = Module(new ProgramCounter(dataType)) - val alu = Module(new ALU(dataType)) - - // TODO: Switch to Decoupled and Arbiter later - ram.io.pc := pc.out - val inst = ram.io.inst - - dontTouch(reg.control.writeEnable) - - import control.pc.SrcSelect._ - - val npc = Wire(dataType) - npc := pc.out + 4.U - pc.in.exeOut := alu.out.result - pc.in.immB := inst.immB - - control.inst := inst - reg.control <> control.reg - // FIXME: Probably optimizable with bulk connection - pc.control <> control.pc - pc.control.useImmB := control.pc.useImmB - alu.control <> control.alu - val branchUseSlt = Wire(Bool()) - val branchInvertResult = Wire(Bool()) - branchUseSlt := inst(14) - branchInvertResult := inst(12) - val _branchResult = Mux(branchUseSlt, alu.out.result(0), alu.out.eq) - val branchResult = Mux(branchInvertResult, !_branchResult, _branchResult) - pc.control.useImmB := control.pc.useImmB && branchResult - // printf(cf"_branchResult = ${_branchResult}, branchResult = ${branchResult}\n") - // printf(cf"pcin.useImmB = ${pc.control.useImmB}, control.out.useImmB = ${control.pc.useImmB} \n") - - import control.reg.WriteSelect._ - reg.in.writeData(lit(rAluOut)) := alu.out.result - val maskedData = ram.io.readData & Cat( - Fill(8, ram.io.writeMask(3)), - Fill(8, ram.io.writeMask(2)), - Fill(8, ram.io.writeMask(1)), - "b11111111".U - ) - - val doSignExt = control.ram.writeMask(0) - val signExt16 = control.ram.writeMask(1) - when(!doSignExt) { - reg.in.writeData(lit(rMemOut)) := maskedData - // printf(cf"!doSignExt\n") - }.elsewhen(signExt16) { - reg.in.writeData(lit(rMemOut)) := Cat( - Fill(16, maskedData(15)), - maskedData(15, 0) - ) - // printf(cf"elsewhen\n") - }.otherwise { - reg.in - .writeData(lit(rMemOut)) := Cat(Fill(24, maskedData(7)), maskedData(7, 0)) - // printf(cf"otherwise\n") - } - // printf(cf"maskedData = ${maskedData}, writeData = ${reg.in.writeData(lit(rMemOut))}\n") - reg.in.writeData(lit(rNpc)) := npc - - reg.in.writeAddr := inst.rd - reg.in.rs(0) := inst.rs1 - reg.in.rs(1) := inst.rs2 - - // TODO: Bulk connection here - ram.io.clock := clock - ram.io.reset := reset - ram.io.writeAddr := alu.out.result - ram.io.writeData := reg.out.src(1) - ram.io.writeMask := control.ram.writeMask - ram.io.writeEnable := control.ram.writeEnable - ram.io.valid := control.ram.valid - ram.io.readAddr := alu.out.result - - import control.alu.SrcASelect._ - import control.alu.SrcBSelect._ - alu.in.a(lit(aSrcARs1)) := reg.out.src(0) - alu.in.a(lit(aSrcAPc)) := pc.out - alu.in.a(lit(aSrcAZero)) := 0.U - - alu.in.b(lit(aSrcBRs2)) := reg.out.src(1) - // alu.in.b(lit(aSrcBImmI)) := inst(31, 20).pad(aSrcBImmI.getWidth) - alu.in.b(lit(aSrcBImmI)) := inst.immI - alu.in.b(lit(aSrcBImmJ)) := inst.immJ - alu.in.b(lit(aSrcBImmS)) := inst.immS - alu.in.b(lit(aSrcBImmU)) := inst.immU - - Trace.traceName(pc.out) - dontTouch(control.out) + IF.io.fromRam := LS.io.toIF + IF.io.fromEx := EX.io.toIF + LS.io.fromIF := IF.io.toRam + ID.io.fromWB := WB.io.toID } diff --git a/npc/core/src/main/scala/top/Main.scala b/npc/core/src/main/scala/top/Main.scala index ba4ce99..d7a40bc 100644 --- a/npc/core/src/main/scala/top/Main.scala +++ b/npc/core/src/main/scala/top/Main.scala @@ -7,11 +7,10 @@ import chisel3.experimental.Trace._ import chisel3.stage.{ChiselGeneratorAnnotation, DesignAnnotation} import chisel3.util.experimental.InlineInstance import circt.stage.ChiselStage -import firrtl.AnnotationSeq -import firrtl.annotations.TargetToken.{Instance, OfModule, Ref} import java.io.PrintWriter import scala.io.Source import java.io.File +import firrtl.annotations.TargetToken.{OfModule, Instance, Ref} // TODO: Generate verilator config file diff --git a/npc/core/src/test/scala/CSR.scala b/npc/core/src/test/scala/CSR.scala deleted file mode 100644 index 35d41e3..0000000 --- a/npc/core/src/test/scala/CSR.scala +++ /dev/null @@ -1,59 +0,0 @@ -package flow.tests - -import chisel3._ -import chiseltest._ -import org.scalatest.freespec.AnyFreeSpec -import chiseltest.simulator.WriteVcdAnnotation - -import flow.components.CSRCore -import flow.tests.defaultParams - -class CSRSpec extends AnyFreeSpec with ChiselScalatestTester { - implicit val p: flow.Params = defaultParams() - "should compile" in { - test(new CSRCore) { c => - c.clock.step(1) - } - } - "Write" - { - "delayed" in { - test(new CSRCore) { c => - val tv = BigInt("deadbeef", 16) - c.in.csrAddr.poke(c.nameToAddr("mstatus")) - c.in.writeData.poke(tv) - c.control.writeEnable.poke(c.control.csrWrite.csrWriteEnabled) - c.clock.step(1) - - c.control.readEnable.poke(c.control.csrRead.csrReadEnabled) - c.out.readData.expect(0) - c.out.readValid.expect(1) - - c.clock.step(1) - c.out.readValid.expect(1) - c.out.readData.expect(tv) - } - } - } - - "Read" - { - "controlled by readEnable" in { - test(new CSRCore) { c => - val tv = BigInt("deadbeef", 16) - c.in.csrAddr.poke(c.nameToAddr("mstatus")) - c.in.writeData.poke(tv) - c.control.readEnable.poke(c.control.csrRead.csrReadEnabled) - c.control.writeEnable.poke(c.control.csrWrite.csrWriteEnabled) - c.clock.step(1) - - c.control.readEnable.poke(c.control.csrRead.csrReadDisabled) - c.out.readData.expect(0) - c.out.readValid.expect(0) - - c.clock.step(1) - c.out.readData.expect(0) - c.out.readValid.expect(0) - } - } - } - -} diff --git a/npc/core/src/test/scala/Keyboard.scala b/npc/core/src/test/scala/Keyboard.scala deleted file mode 100644 index 92ecadb..0000000 --- a/npc/core/src/test/scala/Keyboard.scala +++ /dev/null @@ -1,62 +0,0 @@ -package npc.keyboard - -import chisel3._ -import chiseltest._ -import org.scalatest.freespec.AnyFreeSpec -import chiseltest.simulator.WriteVcdAnnotation - -import npc.util._ - -class KeyboardControllerSpec extends AnyFreeSpec with ChiselScalatestTester { - def transfer(keycode: Int, clock: Clock, ps2: PS2Port) : Unit = { - require(keycode >= 0 && keycode < 0xFF) - var cycle = 0 - var keycode_remain = keycode << 1 // Shift 1 to do nothing at cycle 0 - var keycode_collect = 0 - - ps2.data.poke(1) - ps2.clk.poke(true) - clock.step(1) - for (cycle <- 0 until 9) { - val last_digit = keycode_remain & 1 - ps2.clk.poke(true) - ps2.data.poke(last_digit) - clock.step(32) - keycode_collect = keycode_collect | (last_digit << cycle) - keycode_remain = keycode_remain >> 1 - ps2.clk.poke(false) - clock.step(32) - } - for (_ <- 9 until 11) { - ps2.clk.poke(true) - clock.step(32) - ps2.clk.poke(false) - clock.step(32) - } - assert(keycode_collect >> 1 == keycode) - clock.step(32) - } - "Simple test" in { - test(new KeyboardController).withAnnotations(Seq(WriteVcdAnnotation)) { c => - val data = Array(0xE4, 0xD4, 0xC4, 0xA9) - data.foreach(d => { - transfer(d, c.clock, c.io.ps2) - c.io.out.valid.expect(1.U) - c.io.out.bits.expect(d) - c.io.out.ready.poke(1) - c.clock.step(1) - c.io.out.ready.poke(0) - }) - data.foreach(d => { - transfer(d, c.clock, c.io.ps2) - }) - data.foreach(d => { - c.io.out.valid.expect(1.U) - c.io.out.bits.expect(d) - c.io.out.ready.poke(1) - c.clock.step(1) - c.io.out.ready.poke(0) - }) - } - } -} diff --git a/npc/core/src/test/scala/Main.scala b/npc/core/src/test/scala/Main.scala deleted file mode 100644 index cbca1f4..0000000 --- a/npc/core/src/test/scala/Main.scala +++ /dev/null @@ -1,47 +0,0 @@ -package flow - -import chisel3._ -import chiseltest._ -import org.scalatest.freespec.AnyFreeSpec -import chiseltest.simulator.WriteVcdAnnotation - -import flow.Flow - -class RV32CPUSpec extends AnyFreeSpec with ChiselScalatestTester { - "MemoryFile" - { - "correctly load" in { - import chisel3.util.{SRAM, SRAMInterface, HexMemoryFile} - class UserMem extends Module { - val io = IO(new SRAMInterface(1024, UInt(32.W), 1, 1, 0)) - val memoryFile = HexMemoryFile("../resource/addi.txt") - io :<>= SRAM( - size = 1024, - tpe = UInt(32.W), - numReadPorts = 1, - numWritePorts = 1, - numReadwritePorts = 0, - memoryFile = memoryFile - ) - - val read = io.readPorts(0).data - printf(cf"memoryFile=$memoryFile, readPort=$read%x\n") - } - test(new UserMem).withAnnotations(Seq(WriteVcdAnnotation)) { c => - c.io.readPorts(0).enable.poke(true.B) - c.io.writePorts(0).enable.poke(false.B) - c.io.writePorts(0).address.poke(0.U) - c.io.writePorts(0).data.poke(0.U) - for (i <- 0 until 32) { - c.io.readPorts(0).address.poke(i.U) - c.clock.step(1) - } - } - } - } - "should compile" in { - test(new Flow) { c => - c.clock.step(1) - } - } - -} diff --git a/npc/core/src/test/scala/RegisterFile.scala b/npc/core/src/test/scala/RegisterFile.scala deleted file mode 100644 index ebc59ee..0000000 --- a/npc/core/src/test/scala/RegisterFile.scala +++ /dev/null @@ -1,81 +0,0 @@ -package flow - -import chisel3._ -import chiseltest._ -import org.scalatest.freespec.AnyFreeSpec -import chiseltest.simulator.WriteVcdAnnotation - -import flow.components._ -class RegisterFileSpec extends AnyFreeSpec with ChiselScalatestTester { - "RegisterFileCore" - { - "register 0 is always 0" in { - test(new RegisterFileCore(32, UInt(32.W), 2)) { c => - c.readPorts(0).addr.poke(0) - c.readPorts(1).addr.poke(0) - c.writePort.enable.poke(true) - c.writePort.addr.poke(0) - c.writePort.data.poke(0x1234) - - c.readPorts(0).data.expect(0) - c.readPorts(1).data.expect(0) - c.clock.step(2) - c.readPorts(0).data.expect(0) - c.readPorts(1).data.expect(0) - } - } - "register other than 0 can be written" in { - test(new RegisterFileCore(32, UInt(32.W), 2)) { c => - import scala.util.Random - val r = new Random() - for (i <- 1 until 32) { - val v = r.nextLong() & 0xFFFFFFFFL - c.readPorts(0).addr.poke(i) - c.writePort.enable.poke(true) - c.writePort.addr.poke(i) - c.writePort.data.poke(v) - - c.clock.step(1) - c.readPorts(0).data.expect(v) - } - } - } - } - "RegisterInterface" - { - class Top extends Module { - val io = IO(new RegFileInterface(32, UInt(32.W), 2, 2)) - val rf = RegisterFile(32, UInt(32.W), 2, 2) - io :<>= rf - } - "write" in { - test(new Top).withAnnotations(Seq(WriteVcdAnnotation)) { c => - import c.io.control.WriteSelect._ - val writePort = rAluOut.litValue.toInt - c.io.control.writeEnable.poke(true) - c.io.control.writeSelect.poke(rAluOut) - c.io.in.writeAddr.poke(5) - c.io.in.writeData(writePort).poke(0xcdef) - c.io.in.rs(0).poke(5) - c.clock.step(1) - c.io.out.src(0).expect(0xcdef) - } - } - "no data is written when not enabled" in { - test(new Top).withAnnotations(Seq(WriteVcdAnnotation)) { c => - import c.io.control.WriteSelect._ - val writePort = rAluOut.litValue.toInt - c.io.control.writeEnable.poke(true) - c.io.control.writeSelect.poke(rAluOut) - c.io.in.writeAddr.poke(5) - c.io.in.writeData(writePort).poke(0xcdef) - c.io.in.rs(0).poke(5) - c.clock.step(1) - - c.io.control.writeEnable.poke(false) - c.io.in.writeData(writePort).poke(0x1234) - c.clock.step(1) - - c.io.out.src(0).expect(0xcdef) - } - } - } -} diff --git a/npc/core/src/test/scala/params.scala b/npc/core/src/test/scala/params.scala deleted file mode 100644 index 2bb752d..0000000 --- a/npc/core/src/test/scala/params.scala +++ /dev/null @@ -1,8 +0,0 @@ -package flow.tests - -import chisel3._ -import flow.Params - -object defaultParams { - def apply(): Params = new Params(XLEN = 32.W) -} diff --git a/npc/csrc/Flow/config.cpp b/npc/csrc/Flow/config.cpp index e8e224b..7265b45 100644 --- a/npc/csrc/Flow/config.cpp +++ b/npc/csrc/Flow/config.cpp @@ -19,4 +19,4 @@ void Config::cli_parse(int argc, char **argv) { } } -Config config; +Config config{.wavefile = "flowwave.vcd"}; diff --git a/npc/csrc/Flow/gdbstub_wrapper.cpp b/npc/csrc/Flow/gdbstub_wrapper.cpp index 970ce55..8dd800c 100644 --- a/npc/csrc/Flow/gdbstub_wrapper.cpp +++ b/npc/csrc/Flow/gdbstub_wrapper.cpp @@ -7,6 +7,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -39,21 +40,19 @@ void *pmem_get() { return pmem; } -int pmem_read(int raddr) { +int pmem_read(int raddr, int rmask) { void *pmem = pmem_get(); auto mem = static_cast(pmem); // TODO: Do memory difftest at memory read and write to diagnose at a finer // granularity - mem->trace(raddr, true, regs->get_pc()); if (g_skip_memcheck) - return mem->read(PMEM_START); - return mem->read(raddr); + return mem->read(PMEM_START, rmask); + return mem->read(raddr, rmask); } void pmem_write(int waddr, int wdata, char wmask) { void *pmem = pmem_get(); auto mem = static_cast(pmem); - mem->trace((std::size_t)waddr, false, regs->get_pc(), wdata); return mem->write((std::size_t)waddr, wdata, wmask); } @@ -146,13 +145,37 @@ void npc_init(void *args) { DbgState *dbg = (DbgState *)args; void *mem = pmem_get(); dbg->bp = new std::vector; + dbg->cmd_return_buf = new std::string; top = new VlModule; - regs = new Registers("TOP.Flow.reg_0.regFile_", "TOP.Flow.pc.out"); + regs = new Registers("TOP.Flow.ID.regs_regFile_", + "TOP.Flow.WB.msgio_in_bits_pc"); top->setup(config.wavefile, regs); top->reset_eval(10); } +char *npc_monitor(void *args, char **argv, int argc) { + DbgState *dbg = (DbgState *)args; + std::string *cmd_return_buf = dbg->cmd_return_buf; + + if (strncmp(argv[0], "trace", 5) == 0) { + if (strncmp(argv[1], "on", 2) == 0) { + *cmd_return_buf = "Tracing turned on\n"; + if (!top->start_trace()) + *cmd_return_buf = "Failed to turn on tracing\n"; + return cmd_return_buf->data(); + } else if (strncmp(argv[1], "off", 3) == 0) { + *cmd_return_buf = "Tracing turned off\n"; + if (!top->end_trace()) + *cmd_return_buf = "Failed to turn on tracing\n"; + return cmd_return_buf->data(); + } + } + + *cmd_return_buf = "Command not found\n"; + return cmd_return_buf->data(); +} + bool npc_do_difftest = true; static gdbstub_t gdbstub_priv; diff --git a/npc/flake.lock b/npc/flake.lock index b473f33..763aec4 100644 --- a/npc/flake.lock +++ b/npc/flake.lock @@ -1,9 +1,172 @@ { "nodes": { + "am-kernels": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", + "ysyx-workbench": "ysyx-workbench" + }, + "locked": { + "lastModified": 1723715524, + "narHash": "sha256-dLTI8ah5Ub7mvXlFly6pGSUxpnwWyRBafoQqMhP6KQM=", + "ref": "dev", + "rev": "8630fe7667967009757721bece55235dca5b7614", + "revCount": 83, + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + }, + "original": { + "ref": "dev", + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + } + }, + "am-kernels_2": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks_2", + "ysyx-workbench": "ysyx-workbench_2" + }, + "locked": { + "lastModified": 1723617032, + "narHash": "sha256-oL5Vx933Jhn+T9jn67wFbh8vy7w8OJNCn4DOOlX/r0U=", + "ref": "dev", + "rev": "3ee527c3de481e38767fffbd9e16bf48359fc638", + "revCount": 78, + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + }, + "original": { + "ref": "dev", + "type": "git", + "url": "https://git.xinyang.life/xin/am-kernels.git" + } + }, + "diffu": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_3", + "nur-xin": "nur-xin_2", + "pre-commit-hooks": "pre-commit-hooks_4" + }, + "locked": { + "lastModified": 1723627842, + "narHash": "sha256-+Ovf1e5ESap4sGMsH945SkZLhyYUxGE7shKVl3Ue1CQ=", + "ref": "refs/heads/master", + "rev": "7b3881a9712bcb7bfea90614a44888ae5df6e849", + "revCount": 17, + "type": "git", + "url": "https://git.xinyang.life/xin/diffu.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/diffu.git" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_10": { + "inputs": { + "systems": "systems_10" + }, "locked": { "lastModified": 1710146030, "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", @@ -18,7 +181,25 @@ "type": "github" } }, - "flake-utils_2": { + "flake-utils_11": { + "inputs": { + "systems": "systems_11" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_12": { "locked": { "lastModified": 1667395993, "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", @@ -33,13 +214,275 @@ "type": "github" } }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "inputs": { + "systems": "systems_6" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "inputs": { + "systems": "systems_7" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_8": { + "inputs": { + "systems": "systems_8" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_9": { + "inputs": { + "systems": "systems_9" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_3": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "ysyx-workbench", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_4": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "diffu", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_5": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1723362943, - "narHash": "sha256-dFZRVSgmJkyM0bkPpaYRtG/kRMRTorUIDj8BxoOt1T4=", + "lastModified": 1709237383, + "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a58bc8ad779655e790115244571758e8de055e3d", + "rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8", "type": "github" }, "original": { @@ -65,7 +508,252 @@ "type": "github" } }, + "nixpkgs-circt162_2": { + "locked": { + "lastModified": 1705645507, + "narHash": "sha256-tX3vipIAmNDBA8WNWG4oY4KyTfnm2YieTHO2BhG8ISA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + } + }, + "nixpkgs-circt162_3": { + "locked": { + "lastModified": 1705645507, + "narHash": "sha256-tX3vipIAmNDBA8WNWG4oY4KyTfnm2YieTHO2BhG8ISA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7995cae3ad60e3d6931283d650d7f43d31aaa5c7", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_4": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_5": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_6": { + "locked": { + "lastModified": 1725001927, + "narHash": "sha256-eV+63gK0Mp7ygCR0Oy4yIYSNcum2VQwnZamHxYTNi+M=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6e99f2a27d600612004fbd2c3282d614bfee6421", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1709237383, + "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1725103162, + "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nur-xin": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "ysyx-workbench", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + } + }, + "nur-xin_2": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "diffu", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + } + }, + "nur-xin_3": { + "inputs": { + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", + "ref": "refs/heads/master", + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/nur.git" + } + }, + "nur-xin_4": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -85,18 +773,153 @@ "url": "https://git.xinyang.life/xin/nur.git" } }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": [ + "am-kernels", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_2": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_4", + "gitignore": "gitignore_2", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_3": { + "inputs": { + "flake-compat": "flake-compat_3", + "flake-utils": "flake-utils_6", + "gitignore": "gitignore_3", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "ysyx-workbench", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_3" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_4": { + "inputs": { + "flake-compat": "flake-compat_4", + "flake-utils": "flake-utils_8", + "gitignore": "gitignore_4", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "diffu", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_4" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_5": { + "inputs": { + "flake-compat": "flake-compat_5", + "flake-utils": "flake-utils_10", + "gitignore": "gitignore_5", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_5" + }, + "locked": { + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "nixpkgs-circt162": "nixpkgs-circt162", - "nur-xin": "nur-xin", + "am-kernels": "am-kernels", + "flake-utils": "flake-utils_11", + "nixpkgs": "nixpkgs_4", + "nixpkgs-circt162": "nixpkgs-circt162_3", + "nixpkgs-stable": "nixpkgs-stable_6", + "nur-xin": "nur-xin_4", "sbt-derivation": "sbt-derivation" } }, "sbt-derivation": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils_12", "nixpkgs": [ "nixpkgs" ] @@ -129,6 +952,210 @@ "repo": "default", "type": "github" } + }, + "systems_10": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_11": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_8": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_9": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "ysyx-workbench": { + "inputs": { + "am-kernels": "am-kernels_2", + "diffu": "diffu", + "flake-utils": "flake-utils_9", + "nixpkgs": [ + "am-kernels", + "nixpkgs" + ], + "nixpkgs-circt162": "nixpkgs-circt162_2", + "nur-xin": "nur-xin_3", + "pre-commit-hooks": "pre-commit-hooks_5" + }, + "locked": { + "lastModified": 1723714692, + "narHash": "sha256-EU6HE8DfSorD2Wx7yjBicSSLxGKxKbDD/3XI+RUB7Gs=", + "ref": "refs/heads/master", + "rev": "0e408882b21b17fa19158b2044498ddad8e691e7", + "revCount": 126, + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + } + }, + "ysyx-workbench_2": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": [ + "am-kernels", + "ysyx-workbench", + "am-kernels", + "nixpkgs" + ], + "nixpkgs-circt162": "nixpkgs-circt162", + "nur-xin": "nur-xin", + "pre-commit-hooks": "pre-commit-hooks_3" + }, + "locked": { + "lastModified": 1723551098, + "narHash": "sha256-/AnVxufgQoAuvNBSKm0BG+tTS++/HuaNoW+loroSQig=", + "ref": "refs/heads/master", + "rev": "8ee1551dc2857091fca6456c1367aab7090899fe", + "revCount": 119, + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + }, + "original": { + "type": "git", + "url": "https://git.xinyang.life/xin/ysyx-workbench" + } } }, "root": "root", diff --git a/npc/flake.nix b/npc/flake.nix index d725b57..2c6a69a 100644 --- a/npc/flake.nix +++ b/npc/flake.nix @@ -1,6 +1,7 @@ { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-24.05"; nixpkgs-circt162.url = "github:NixOS/nixpkgs/7995cae3ad60e3d6931283d650d7f43d31aaa5c7"; nur-xin = { url = "git+https://git.xinyang.life/xin/nur.git"; @@ -11,11 +12,18 @@ url = "github:zaninime/sbt-derivation"; inputs.nixpkgs.follows = "nixpkgs"; }; + am-kernels.url = "git+https://git.xinyang.life/xin/am-kernels.git?ref=dev"; }; - outputs = { self, nixpkgs, flake-utils, nur-xin, nixpkgs-circt162, sbt-derivation }: + outputs = { self, nixpkgs, nixpkgs-stable, flake-utils, nur-xin, nixpkgs-circt162, sbt-derivation, am-kernels }: flake-utils.lib.eachDefaultSystem (system: let + stablePkgs = import nixpkgs-stable { + inherit system; + config.allowUnfree = true; + overlays = [ + ]; + }; pkgs = import nixpkgs { inherit system; config.allowUnfree = true; @@ -37,5 +45,28 @@ inherit flow; }; }; + + devShells.default = pkgs.mkShell.override { stdenv = pkgs.ccacheStdenv; } { + nativeBuildInputs = with pkgs; [ + cmake + ninja + flex + bison + nvboard + flow + espresso + coursier + sbt-with-scala-native + gef + ] ++ [stablePkgs.verilator]; + CHISEL_FIRTOOL_PATH = "${nixpkgs-circt162.legacyPackages.${system}.circt}/bin"; + NPC_IMAGES_PATH = "${am-kernels.packages.${system}.rv32Cross.am-kernels-npc}/share"; + + buildInputs = with pkgs; [ + cli11 + spdlog + mini-gdbstub + ]; + }; }); } diff --git a/npc/include/components.hpp b/npc/include/components.hpp index 887ded0..e91ac31 100644 --- a/npc/include/components.hpp +++ b/npc/include/components.hpp @@ -31,7 +31,9 @@ public: Memory(std::filesystem::path filepath, bool is_binary, paddr_t pmem_start, paddr_t pmem_end) : pmem_start(pmem_start), pmem_end(pmem_end) { - read_memory(filepath, is_binary); + if (!filepath.empty()) { + read_memory(filepath, is_binary); + } } const word_t &operator[](std::size_t addr) { return this->read(addr); } @@ -86,14 +88,18 @@ public: ram->transfer(waddr, (uint8_t *)&wdata, len, true); } else if (devices->handle(waddr, (uint8_t *)&wdata, len, true)) { } + logger->trace("[W] 0x{:x}: 0x{:x}", waddr, wdata); } - word_t read(paddr_t raddr) const { + word_t read(paddr_t raddr, int rmask) const { word_t res = 0; + size_t len = (rmask & 1) + ((rmask & 2) >> 1) + ((rmask & 4) >> 2) + + ((rmask & 8) >> 3); if (ram->in_pmem(raddr)) { - ram->transfer(raddr, (uint8_t *)&res, 4, false); + ram->transfer(raddr, (uint8_t *)&res, len, false); } else if (devices->handle(raddr, (uint8_t *)&res, 4, false)) { } + logger->trace("[R] 0x{:x}: 0x{:x}", raddr, res); return res; } @@ -118,7 +124,7 @@ public: void *get_pmem() { return ram->mem.data(); } void trace(paddr_t addr, bool is_read, word_t pc = 0, word_t value = 0) { - logger->trace("[{}] 0x{:x}", is_read ? 'R' : 'W', this->read(addr)); + logger->trace("[{}] 0x{:x}", is_read ? 'R' : 'W', this->read(addr, value)); } private: diff --git a/npc/include/types.h b/npc/include/types.h index f34f168..9e347e9 100644 --- a/npc/include/types.h +++ b/npc/include/types.h @@ -1,6 +1,7 @@ #ifndef _NPC_TYPES_H__ #define _NPC_TYPES_H__ #ifdef __cplusplus +#include extern "C" { #endif #include @@ -32,6 +33,7 @@ struct Breakpoint { struct DbgState { std::vector *bp; + std::string *cmd_return_buf; }; #endif diff --git a/npc/include/vl_wrapper.hpp b/npc/include/vl_wrapper.hpp index aa8e798..414bd23 100644 --- a/npc/include/vl_wrapper.hpp +++ b/npc/include/vl_wrapper.hpp @@ -34,6 +34,7 @@ template class VlModuleInterfaceCommon : public T { uint64_t sim_time = 0; uint64_t posedge_cnt = 0; std::unique_ptr> tracer; + std::filesystem::path wavefile; public: const R *registers; @@ -43,8 +44,7 @@ public: } void setup(std::filesystem::path wavefile, const R *r) { - if (!wavefile.empty()) - tracer = std::make_unique>(this, wavefile); + wavefile = "wave.vcd"; registers = r; } @@ -89,10 +89,30 @@ public: this->reset = 0; g_skip_memcheck = false; } + bool is_posedge() { // Will be posedge when eval is called return T::clock == 0; } + + bool start_trace() { return init_tracer(wavefile); } + + bool end_trace() { + tracer.reset(); + return true; + } + +private: + bool init_tracer(std::filesystem::path wavefile) { + fmt::print("wavefile: {}", wavefile.string()); + std::filesystem::path wav = "wave.vcd"; + if (!wav.empty()) { + // Creating of tracer must happen after this class fully initialized + tracer = std::make_unique>(this, wav); + return true; + } + return false; + } }; #endif diff --git a/npc/include/vpi_wrapper.hpp b/npc/include/vpi_wrapper.hpp index 22b1876..a5310ae 100644 --- a/npc/include/vpi_wrapper.hpp +++ b/npc/include/vpi_wrapper.hpp @@ -27,18 +27,23 @@ public: } private: + static vpiHandle get_handle(const std::string name) { + vpiHandle hdl = vpi_handle_by_name((PLI_BYTE8 *)name.c_str(), nullptr); + if (hdl == nullptr) { + SPDLOG_ERROR("VPI Handle {} not found", name); + exit(EXIT_FAILURE); + } else { + SPDLOG_INFO("Found VPI handle {} at {}", name, (void *)hdl); + } + return hdl; + } + void init_handlers(const std::string regs_prefix, const std::string pcname) { + pc_handle = get_handle(pcname); for (int i = 0; i < nr; i++) { std::string regname = regs_prefix + std::to_string(i); - vpiHandle vh = vpi_handle_by_name((PLI_BYTE8 *)regname.c_str(), nullptr); - if (vh == nullptr) { - std::cerr << "vpiHandle " << regname.c_str() << " not found" - << std::endl; - exit(EXIT_FAILURE); - } - reg_handles[i] = vh; + reg_handles[i] = get_handle(regname); } - pc_handle = vpi_handle_by_name((PLI_BYTE8 *)pcname.c_str(), nullptr); } }; diff --git a/scripts/difftests.py b/scripts/difftests.py new file mode 100644 index 0000000..c9b2c02 --- /dev/null +++ b/scripts/difftests.py @@ -0,0 +1,86 @@ +#/usr/bin/env python + +""" +This script is used to provide a wrapper to difftest, so that they can be easily +deployed on ci environment. +""" + +import os +import os.path as osp +import sys +from multiprocessing import Pool, Process +from functools import partial + +def find_all_test_images(path): + tests = [] + for root, dirs, files in os.walk(path): + for file in files: + # Get file extensions and select files with .bin + ext = osp.splitext(file)[1] + if ext == ".bin": + tests.append(osp.join(root, file)) + return tests + +def run_test(test_image, ref, ref_prefix, dut, dut_prefix): + diffu = "diffu" + args = [ + "--images-path", "/", + "-m", test_image, + "--ref", ref, + "--ref-prefix", ref_prefix, + "--dut", dut, + "--dut-prefix", dut_prefix, + "> logs/" + osp.basename(test_image) + ".log", + "2>&1" + ] + + status = os.system(diffu + " " + " ".join(args)) + exitcode = os.waitstatus_to_exitcode(status) + + image_shortname = osp.basename(test_image) + print(f"{ 'FAILED' if exitcode else 'PASSED' } {image_shortname}") + if exitcode: + print(f"cmd: {diffu + ' ' + ' '.join(args)}") + print(f"exitcode: {exitcode}") + sys.exit(exitcode) + +def print_statistics(results): + pass + +def main(): + DIFFU_IMAGES_PATH = os.environ["DIFFU_IMAGES_PATH"] + print(DIFFU_IMAGES_PATH) + assert(osp.isdir(DIFFU_IMAGES_PATH)) + os.makedirs("logs", exist_ok = True) + # Run tests in a multiprocess pool + tests = find_all_test_images(DIFFU_IMAGES_PATH) + ref, ref_prefix, dut, dut_prefix = sys.argv[1:] + ref_shortname = osp.basename(ref) + dut_shortname = osp.basename(dut) + print(f"[{ref_shortname}, {dut_shortname}]") + procs = [] + for test in tests: + image_shortname = osp.basename(test) + p = Process(target=run_test, args=(test, ref, ref_prefix, dut, dut_prefix), name=image_shortname, daemon=True) + procs.append(p) + p.start() + + timeout = 0 + for p in procs: + p.join(5) + if p.exitcode is None: + print(f"{ 'TIMEOUT' } {p.name}") + p.terminate() + p.join() + timeout += 1 + + not_success = sum((1 for p in procs if p.exitcode != 0)) + failed = not_success - timeout + + print("==========") + print(f"TOTAL {len(procs)}\tFAILED: {failed}\tTIMEOUT: {timeout}") + + return not_success + +if __name__ == "__main__": + sys.exit(main())