From fd1aae7c331ade394c1e5173f8c53f7a0e93457b Mon Sep 17 00:00:00 2001 From: xinyangli Date: Tue, 3 Sep 2024 11:29:22 +0800 Subject: [PATCH] npc,wip: group components into stages --- flake.lock | 870 ++++++++++++++++- flake.nix | 71 +- npc/.envrc | 2 +- npc/core/src/main/scala/components/ALU.scala | 173 +++- npc/core/src/main/scala/components/CSR.scala | 17 +- npc/core/src/main/scala/components/Mem.scala | 57 ++ .../scala/components/ProgramCounter.scala | 71 ++ .../main/scala/components/RegisterFile.scala | 107 ++- npc/core/src/main/scala/components/util.scala | 28 + npc/core/src/main/scala/stages/Base.scala | 74 ++ npc/core/src/main/scala/stages/EX.scala | 72 ++ npc/core/src/main/scala/stages/ID.scala | 62 ++ npc/core/src/main/scala/stages/IF.scala | 46 + npc/core/src/main/scala/stages/LS.scala | 51 + npc/core/src/main/scala/stages/Messages.scala | 73 ++ npc/core/src/main/scala/stages/WB.scala | 28 + npc/core/src/main/scala/top/Config.scala | 7 +- npc/core/src/main/scala/top/FlowMain.scala | 903 +++++++++--------- npc/core/src/main/scala/top/Main.scala | 1 - npc/core/src/test/scala/CSR.scala | 91 +- npc/core/src/test/scala/Main.scala | 52 +- npc/core/src/test/scala/ProgramCounter.scala | 24 + npc/core/src/test/scala/RegisterFile.scala | 150 +-- npc/core/src/test/scala/StageConnect.scala | 70 ++ npc/core/src/test/scala/params.scala | 2 +- npc/flake.nix | 23 + npc/include/components.hpp | 4 +- 27 files changed, 2456 insertions(+), 673 deletions(-) create mode 100644 npc/core/src/main/scala/components/util.scala create mode 100644 npc/core/src/main/scala/stages/Base.scala create mode 100644 npc/core/src/main/scala/stages/EX.scala create mode 100644 npc/core/src/main/scala/stages/ID.scala create mode 100644 npc/core/src/main/scala/stages/IF.scala create mode 100644 npc/core/src/main/scala/stages/LS.scala create mode 100644 npc/core/src/main/scala/stages/Messages.scala create mode 100644 npc/core/src/main/scala/stages/WB.scala create mode 100644 npc/core/src/test/scala/ProgramCounter.scala create mode 100644 npc/core/src/test/scala/StageConnect.scala 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..aab526e 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,15 +149,18 @@ 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 { @@ -141,7 +168,15 @@ diffu.packages.${system}.default am-kernels.packages.${system}.rv32Cross.am-kernels-npc self.packages.${system}.nemu-lib + spike-diff.packages.${system}.default ]; + + DIFFU_IMAGES_PATH = "${am-kernels.packages.${system}.rv32Cross.am-kernels-npc}/share"; + }; + + devShells.default = pkgs.mkShell { + inherit (self.checks.${system}.pre-commit-check) shellHook; + buildInputs = self.checks.${system}.pre-commit-check.enabledPackages; }; } ); 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/core/src/main/scala/components/ALU.scala b/npc/core/src/main/scala/components/ALU.scala index 0c1f0ae..f172a7b 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,21 +18,27 @@ 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) + 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, tpe)) + val b = Input(Vec(SrcBSelect.all.length, tpe)) }) val out = IO(new Bundle { val eq = Output(Bool()) @@ -53,13 +62,12 @@ class ALU[T <: UInt](tpe: T) extends Module { val sra = a.asSInt >> b(log2Ceil(tpe.getWidth), 0) out.eq := a === b - import control.OpSelect._ + import ALUControlInterface.OpSelect._ out.result := MuxLookup(control.op, 0.U)( Seq( aOpAdd -> add, aOpSub -> sub, - aOpNot -> not, aOpAnd -> and, aOpOr -> or, aOpXor -> xor, @@ -77,3 +85,140 @@ object ALU { Module(new ALU(tpe)) } } + +class newALU(implicit p: Params) extends Module { + import ALUControlInterface._ + val control = IO(ALUControlInterface()) + val in = IO(new Bundle { + 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(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 + val not = ~a + val or = a | b + val xor = a ^ b + val slt = a.asSInt < b.asSInt + val sltu = a < b + val sll = a << b(5, 0) + val srl = a >> b(5, 0) + val sra = a.asSInt >> b(5, 0) + out.eq := a === b + + import OpSelect._ + + out.result := MuxLookup(control.op, 0.U)( + Seq( + aOpAdd -> add, + aOpSub -> sub, + aOpAnd -> and, + aOpOr -> or, + aOpXor -> xor, + aOpSlt -> slt, + aOpSltu -> sltu, + aOpSll -> sll, + aOpSrl -> srl, + aOpSra -> sra.asUInt + ) + ) +} + +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..9b8519e 100644 --- a/npc/core/src/main/scala/components/Mem.scala +++ b/npc/core/src/main/scala/components/Mem.scala @@ -5,11 +5,16 @@ 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()) @@ -40,3 +45,55 @@ class RamDpi extends BlackBox with HasBlackBoxResource { val io = IO((new RamInterface(UInt(32.W), 32))) addResource("/RamDpi.v") } + +class DpiRamControlInterface(implicit p: Params) extends Bundle { + val valid = Input(Bool()) + 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 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, writeMaskMapping) + out.writeMask := decoder(in.inst, writeMaskMapping) +} diff --git a/npc/core/src/main/scala/components/ProgramCounter.scala b/npc/core/src/main/scala/components/ProgramCounter.scala index 287ca7f..fe57f35 100644 --- a/npc/core/src/main/scala/components/ProgramCounter.scala +++ b/npc/core/src/main/scala/components/ProgramCounter.scala @@ -1,8 +1,14 @@ 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 SrcSelect extends ChiselEnum { @@ -46,3 +52,68 @@ object ProgramCounter { pc } } + +object newPcControlInterface { + object SrcSelect extends ChiselEnum { + val pStatic, pJmp, pBR = Value + } + + class newPcControlInterface extends Bundle { + val srcSelect = Input(SrcSelect()) + + def ctrlBindPorts = { + srcSelect :: HNil + } + } + def apply() = new newPcControlInterface; +} + +class newProgramCounter(implicit p: Params) extends Module { + val control = IO(newPcControlInterface()) + import newPcControlInterface.SrcSelect._ + val in = IO(new Bundle { + val brAddr = Input(UInt(p.XLEN)) + val jAddr = Input(UInt(p.XLEN)) + }) + val out = IO(Output(UInt(p.XLEN))) + + private val pcReg = RegInit(p.resetVector.U) + out := pcReg + + private val npc = MuxLookup(control.srcSelect, 4.U)( + Seq( + pStatic -> (pcReg + 4.U), + pJmp -> in.brAddr, + pBR -> in.jAddr + ) + ) + + pcReg := npc +} + +class PcController(implicit p: Params) extends Module { + val in = IO(new Bundle { + val inst = Input(UInt(p.instWidth)) + }) + + val out = IO(Flipped(newPcControlInterface())) + + import RV32Inst._ + import newPcControlInterface.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 := newPcControlInterface.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..7a88a37 100644 --- a/npc/core/src/main/scala/components/RegisterFile.scala +++ b/npc/core/src/main/scala/components/RegisterFile.scala @@ -4,31 +4,38 @@ 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, ::} +import flow.Params +import flow.components.util._ +import flow.components.RV32Inst._ -class RegControl extends Bundle { +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 control = IO(RegControl()) val dataAddrWidth = log2Ceil(regCount).W val in = IO(new Bundle { val writeAddr = Input(UInt(dataAddrWidth)) - val writeData = Input(Vec(control.WriteSelect.all.length, tpe)) + val writeData = Input(Vec(RegControl.WriteSelect.all.length, tpe)) val rs = Input(Vec(numReadPorts, UInt(dataAddrWidth))) }) val out = IO(new Bundle { @@ -54,3 +61,85 @@ class RegisterFile[T <: Data](tpe: T, regCount: Int, numReadPorts: Int) traceName(regFile) dontTouch(regFile) } + +class newRegisterFile(implicit p: Params) extends Module { + val in = IO(new Bundle { + 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 src1 = Output(UInt(p.XLEN)) + val src2 = Output(UInt(p.XLEN)) + }) + + val control = IO(RegControl()) + + 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 + + out.src1 := regFile(in.rs1) + out.src2 := regFile(in.rs2) +} + +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( + 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(true.B)) + ), + BitPat(false.B) + ) + + 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..f2b4bac --- /dev/null +++ b/npc/core/src/main/scala/stages/EX.scala @@ -0,0 +1,72 @@ +package flow.stages + +import chisel3._ +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import flow.Params +import flow.stages.utils._ +import flow.components.newALU +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 newALU) + alu.control := _in.aluCtrl; + + { + import flow.components.ALUControlInterface.SrcASelect._ + import flow.components.util.chiselEnumAsInt + alu.in.a(aSrcARs1) := _in.inst.rs1 + alu.in.a(aSrcAPc) := _in.pc + alu.in.a(aSrcAZero) := 0.U + + import flow.components.ALUControlInterface.SrcBSelect._ + alu.in.b(aSrcBRs2) := _in.inst.rs2 + 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.exeEq := alu.out.result + _out.exeOut := alu.out.eq + + _toIF.jAddr := alu.out.result + _toIF.brAddr := _in.inst.immB + + import flow.components.newPcControlInterface.SrcSelect._ + when(_in.pcCtrl.srcSelect === pBR) { + val branchUseSlt = _in.inst(14) + val branchInvertResult = _in.inst(12) + val _branchResult = Mux(branchUseSlt, alu.out.result(0), alu.out.eq) + val branchResult = Mux(branchInvertResult, !_branchResult, _branchResult) + _toIF.pcCtrl.srcSelect := Mux(branchInvertResult, 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..3bac38e --- /dev/null +++ b/npc/core/src/main/scala/stages/ID.scala @@ -0,0 +1,62 @@ +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 + +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 newRegisterFile) + + // 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..f0455f1 --- /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.newProgramCounter +import flow.components.newPcControlInterface +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 newProgramCounter) + + // PC update + pc.in.brAddr := _fromEx.brAddr + 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..ad8eeff --- /dev/null +++ b/npc/core/src/main/scala/stages/LS.scala @@ -0,0 +1,51 @@ +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.src1 + ram.io.writeMask := _in.ramCtrl.writeMask + 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.pc + + _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..9eb7828 --- /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(newPcControlInterface()) + 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) + val exeEq = Bool() + + // 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 brAddr = UInt(p.XLEN) + val jAddr = UInt(p.XLEN) + + // Control + val pcCtrl = Flipped(newPcControlInterface()) +} + +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..e9eed8d --- /dev/null +++ b/npc/core/src/main/scala/stages/WB.scala @@ -0,0 +1,28 @@ +package flow.stages + +import chisel3._ +import chisel3.util.Decoupled +import chisel3.util.DecoupledIO +import flow.Params +import flow.stages.utils._ +import flow.stages.messages._ + +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 +} diff --git a/npc/core/src/main/scala/top/Config.scala b/npc/core/src/main/scala/top/Config.scala index 4c21a25..84a5128 100644 --- a/npc/core/src/main/scala/top/Config.scala +++ b/npc/core/src/main/scala/top/Config.scala @@ -18,6 +18,11 @@ 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) ) diff --git a/npc/core/src/main/scala/top/FlowMain.scala b/npc/core/src/main/scala/top/FlowMain.scala index 01b1972..75497aa 100644 --- a/npc/core/src/main/scala/top/FlowMain.scala +++ b/npc/core/src/main/scala/top/FlowMain.scala @@ -16,451 +16,472 @@ import shapeless.Poly1 import flow.components.RamControlInterface 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._ - 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))) - - 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 } + +// 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))) +// +// val reg = IO(Flipped(RegControl())) +// val pc = IO(Flipped(PcControlInterface())) +// val alu = IO(Flipped(ALUControlInterface())) +// val ram = IO(Flipped(RamControlInterface(32))) +// +// 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(controWidth.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) +// }) +// } + +// class Flow extends Module { +// def lit(x: Data) = { x.litValue.toInt } +// +// 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(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(rMemOut) := maskedData +// // printf(cf"!doSignExt\n") +// }.elsewhen(signExt16) { +// reg.in.writeData(rMemOut) := Cat( +// Fill(16, maskedData(15)), +// maskedData(15, 0) +// ) +// // printf(cf"elsewhen\n") +// }.otherwise { +// reg.in +// .writeData(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(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(aSrcARs1) := reg.out.src(0) +// alu.in.a(aSrcAPc) := pc.out +// alu.in.a(aSrcAZero) := 0.U +// +// alu.in.b(aSrcBRs2) := reg.out.src(1) +// // alu.in.b(lit(aSrcBImmI)) := inst(31, 20).pad(aSrcBImmI.getWidth) +// alu.in.b(aSrcBImmI) := inst.immI +// alu.in.b(aSrcBImmJ) := inst.immJ +// alu.in.b(aSrcBImmS) := inst.immS +// alu.in.b(aSrcBImmU) := inst.immU +// +// Trace.traceName(pc.out) +// dontTouch(control.out) +// } diff --git a/npc/core/src/main/scala/top/Main.scala b/npc/core/src/main/scala/top/Main.scala index ba4ce99..52c117a 100644 --- a/npc/core/src/main/scala/top/Main.scala +++ b/npc/core/src/main/scala/top/Main.scala @@ -7,7 +7,6 @@ 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 diff --git a/npc/core/src/test/scala/CSR.scala b/npc/core/src/test/scala/CSR.scala index 35d41e3..bd49a91 100644 --- a/npc/core/src/test/scala/CSR.scala +++ b/npc/core/src/test/scala/CSR.scala @@ -10,50 +10,51 @@ 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) - } - } - } + // import flow.components.CSRControlInterface + // "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(CSRControlInterface.csrWrite.csrWriteData) + // c.clock.step(1) + // + // c.control.readEnable.poke(CSRControlInterface.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(CSRControlInterface.csrRead.csrReadEnabled) + // c.control.writeEnable.poke(CSRControlInterface.csrWrite.csrWriteData) + // c.clock.step(1) + // + // c.control.readEnable.poke(CSRControlInterface.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/Main.scala b/npc/core/src/test/scala/Main.scala index cbca1f4..44b89a2 100644 --- a/npc/core/src/test/scala/Main.scala +++ b/npc/core/src/test/scala/Main.scala @@ -4,44 +4,28 @@ import chisel3._ import chiseltest._ import org.scalatest.freespec.AnyFreeSpec import chiseltest.simulator.WriteVcdAnnotation +import flow.stages._ +import flow.Params import flow.Flow +import flow.tests.defaultParams +import flow.stages.messages._ 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) - } - } + "IF" - { + implicit val p: Params = defaultParams() + class TestIF extends Module { + val IF = Module(new IF) + val io = IO(new Bundle { + val out = Output(new IF2ID) + }) + io.out := IF.msgio.out + IF.msgio.out.ready := DontCare + IF.io.fromRam := DontCare + IF.io.fromEx := DontCare + } + "should compile" in { + test(new TestIF) { c => } } } - "should compile" in { - test(new Flow) { c => - c.clock.step(1) - } - } - } diff --git a/npc/core/src/test/scala/ProgramCounter.scala b/npc/core/src/test/scala/ProgramCounter.scala new file mode 100644 index 0000000..9b4f84e --- /dev/null +++ b/npc/core/src/test/scala/ProgramCounter.scala @@ -0,0 +1,24 @@ +package flow.tests + +import chisel3._ +import chiseltest._ +import org.scalatest.freespec.AnyFreeSpec +import flow.components._ + +class ProgramCounterSpec extends AnyFreeSpec with ChiselScalatestTester { + implicit val p: flow.Params = defaultParams() + "should compile" in { + test(new newProgramCounter) { c => + c.clock.step(1) + } + } + + "Static next pc" in { + test(new newProgramCounter) { c => + import flow.components.newPcControlInterface.SrcSelect._ + c.control.srcSelect.poke(pStatic) + c.clock.step(1) + c.out.expect(p.resetVector + 4) + } + } +} diff --git a/npc/core/src/test/scala/RegisterFile.scala b/npc/core/src/test/scala/RegisterFile.scala index ebc59ee..5c32d29 100644 --- a/npc/core/src/test/scala/RegisterFile.scala +++ b/npc/core/src/test/scala/RegisterFile.scala @@ -1,81 +1,81 @@ -package flow +// package flow -import chisel3._ -import chiseltest._ -import org.scalatest.freespec.AnyFreeSpec -import chiseltest.simulator.WriteVcdAnnotation +// 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) +// 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.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.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.control.writeEnable.poke(false) +// c.io.in.writeData(writePort).poke(0x1234) +// c.clock.step(1) - c.io.out.src(0).expect(0xcdef) - } - } - } -} +// c.io.out.src(0).expect(0xcdef) +// } +// } +// } +// } diff --git a/npc/core/src/test/scala/StageConnect.scala b/npc/core/src/test/scala/StageConnect.scala new file mode 100644 index 0000000..14f1dcb --- /dev/null +++ b/npc/core/src/test/scala/StageConnect.scala @@ -0,0 +1,70 @@ +package flow.tests + +import chisel3._ +import chiseltest._ +import org.scalatest.freespec.AnyFreeSpec +import chiseltest.simulator.WriteVcdAnnotation + +import flow.tests.defaultParams +import flow.stages.utils._ +import flow.stages.DecoupledMsgIO +import chisel3.util.Decoupled + +class StageConnect extends AnyFreeSpec with ChiselScalatestTester { + "should compile" in { + implicit val p: flow.Params = defaultParams().copy(arch = "single") + + class stage1 extends Module { + val io = DecoupledMsgIO(out = (new Bundle { + val data = UInt(12.W) + }).S) + io.out.valid := true.B + io.out.bits.data := 1.U + } + + class stage2 extends Module { + val io = DecoupledMsgIO(Some(new Bundle { + val data = UInt(12.W) + })) + io.in.ready := true.B + } + + class stage3 extends Module { + val wireOut = DecoupledMsgIO( + out = Some(new Bundle { + val data = UInt(12.W) + }), + isIO = false + ) + val wireIn = DecoupledMsgIO( + Some(new Bundle { + val data = UInt(12.W) + }), + isIO = false + ) + wireOut connect [Nothing] wireIn + + wireOut.out.valid := true.B + wireOut.out.bits.data := 1.U + wireIn.in.ready := true.B + } + + class stage extends Module { + val s1 = Module(new stage1) + val s2 = Module(new stage2) + s1.io connect [Nothing] s2.io + } + + import circt.stage.ChiselStage + println(ChiselStage.emitSystemVerilog(new stage1)) + + test(new stage) { c => + println(c) + } + + test(new stage3) { c => + println(c) + } + + } +} diff --git a/npc/core/src/test/scala/params.scala b/npc/core/src/test/scala/params.scala index 2bb752d..97e87a6 100644 --- a/npc/core/src/test/scala/params.scala +++ b/npc/core/src/test/scala/params.scala @@ -4,5 +4,5 @@ import chisel3._ import flow.Params object defaultParams { - def apply(): Params = new Params(XLEN = 32.W) + def apply(): Params = new Params(XLEN = 32.W, arch = "single") } diff --git a/npc/flake.nix b/npc/flake.nix index d725b57..73d673c 100644 --- a/npc/flake.nix +++ b/npc/flake.nix @@ -37,5 +37,28 @@ inherit flow; }; }; + + devShells.default = pkgs.mkShell.override { stdenv = pkgs.ccacheStdenv; } { + nativeBuildInputs = with pkgs; [ + cmake + ninja + flex + bison + nvboard + verilator + flow + espresso + bloop + coursier + sbt + ]; + CHISEL_FIRTOOL_PATH = "${nixpkgs-circt162.legacyPackages.${system}.circt}/bin"; + + buildInputs = with pkgs; [ + cli11 + spdlog + mini-gdbstub + ]; + }; }); } diff --git a/npc/include/components.hpp b/npc/include/components.hpp index 887ded0..76a2cea 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); }