diff --git a/.github/workflows/mill-ci.yml b/.github/workflows/mill-ci.yml index 0d03a2eb5ae..a75ab0300fc 100644 --- a/.github/workflows/mill-ci.yml +++ b/.github/workflows/mill-ci.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - config: [DefaultConfig, DefaultBufferlessConfig, DefaultRV32Config, TinyConfig, DefaultFP16Config] + config: [DefaultConfig, DefaultBufferlessConfig, DefaultRV32Config, TinyConfig, DefaultFP16Config, DefaultBConfig, DefaultRV32BConfig] steps: - uses: actions/checkout@v2 with: diff --git a/.gitmodules b/.gitmodules index 77819d7f768..b64ce5416e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,13 @@ -[submodule "hardfloat"] - path = hardfloat +[submodule "dependencies/hardfloat"] + path = dependencies/hardfloat url = https://github.com/ucb-bar/berkeley-hardfloat.git -[submodule "torture"] - path = torture - url = https://github.com/ucb-bar/riscv-torture.git -[submodule "cde"] - path = cde +[submodule "dependencies/cde"] + path = dependencies/cde url = https://github.com/chipsalliance/cde.git +[submodule "dependencies/chisel"] + path = dependencies/chisel + url = https://github.com/chipsalliance/chisel.git +[submodule "dependencies/diplomacy"] + path = dependencies/diplomacy + url = https://github.com/chipsalliance/diplomacy.git + branch = master diff --git a/build.sc b/build.sc index 429da095900..b63c6ae7900 100644 --- a/build.sc +++ b/build.sc @@ -2,20 +2,37 @@ import mill._ import mill.scalalib._ import mill.scalalib.publish._ import coursier.maven.MavenRepository -import $file.hardfloat.common -import $file.cde.common +import $file.dependencies.hardfloat.common +import $file.dependencies.cde.common +import $file.dependencies.diplomacy.common +import $file.dependencies.chisel.build import $file.common object v { - val scala = "2.13.10" + val scala = "2.13.12" // the first version in this Map is the mainly supported version which will be used to run tests val chiselCrossVersions = Map( - "3.6.0" -> (ivy"edu.berkeley.cs::chisel3:3.6.0", ivy"edu.berkeley.cs:::chisel3-plugin:3.6.0"), - "5.0.0" -> (ivy"org.chipsalliance::chisel:5.0.0", ivy"org.chipsalliance:::chisel-plugin:5.0.0"), + "5.1.0" -> (ivy"org.chipsalliance::chisel:5.1.0", ivy"org.chipsalliance:::chisel-plugin:5.1.0"), + // build from project from source + "source" -> (ivy"org.chipsalliance::chisel:99", ivy"org.chipsalliance:::chisel-plugin:99"), ) val mainargs = ivy"com.lihaoyi::mainargs:0.5.0" val json4sJackson = ivy"org.json4s::json4s-jackson:4.0.5" val scalaReflect = ivy"org.scala-lang:scala-reflect:${scala}" + val sourcecode = ivy"com.lihaoyi::sourcecode:0.3.1" + val sonatypesSnapshots = Seq( + MavenRepository("https://s01.oss.sonatype.org/content/repositories/snapshots") + ) +} + +// Build form source only for dev +object chisel extends Chisel + +trait Chisel + extends millbuild.dependencies.chisel.build.Chisel { + def crossValue = v.scala + override def millSourcePath = os.pwd / "dependencies" / "chisel" + def scalaVersion = T(v.scala) } object macros extends Macros @@ -33,33 +50,60 @@ trait Macros object hardfloat extends mill.define.Cross[Hardfloat](v.chiselCrossVersions.keys.toSeq) trait Hardfloat - extends millbuild.hardfloat.common.HardfloatModule + extends millbuild.dependencies.hardfloat.common.HardfloatModule with RocketChipPublishModule with Cross.Module[String] { def scalaVersion: T[String] = T(v.scala) - override def millSourcePath = os.pwd / "hardfloat" / "hardfloat" + override def millSourcePath = os.pwd / "dependencies" / "hardfloat" / "hardfloat" + + def chiselModule = Option.when(crossValue == "source")(chisel) - def chiselModule = None + def chiselPluginJar = T(Option.when(crossValue == "source")(chisel.pluginModule.jar())) - def chiselPluginJar = None + def chiselIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._1) - def chiselIvy = Some(v.chiselCrossVersions(crossValue)._1) + def chiselPluginIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._2) - def chiselPluginIvy = Some(v.chiselCrossVersions(crossValue)._2) + def repositoriesTask = T.task(super.repositoriesTask() ++ v.sonatypesSnapshots) } object cde extends CDE trait CDE - extends millbuild.cde.common.CDEModule + extends millbuild.dependencies.cde.common.CDEModule with RocketChipPublishModule with ScalaModule { def scalaVersion: T[String] = T(v.scala) - override def millSourcePath = os.pwd / "cde" / "cde" + override def millSourcePath = os.pwd / "dependencies" / "cde" / "cde" +} + +object diplomacy extends mill.define.Cross[Diplomacy](v.chiselCrossVersions.keys.toSeq) + +trait Diplomacy + extends millbuild.dependencies.diplomacy.common.DiplomacyModule + with RocketChipPublishModule + with Cross.Module[String] { + + override def scalaVersion: T[String] = T(v.scala) + + override def millSourcePath = os.pwd / "dependencies" / "diplomacy" / "diplomacy" + + // dont use chisel from source + def chiselModule = Option.when(crossValue == "source")(chisel) + def chiselPluginJar = T(Option.when(crossValue == "source")(chisel.pluginModule.jar())) + + // use chisel from ivy + def chiselIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._1) + def chiselPluginIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._2) + + // use CDE from source until published to sonatype + def cdeModule = cde + + def sourcecodeIvy = v.sourcecode } object rocketchip extends Cross[RocketChip](v.chiselCrossVersions.keys.toSeq) @@ -73,13 +117,13 @@ trait RocketChip override def millSourcePath = super.millSourcePath / os.up - def chiselModule = None + def chiselModule = Option.when(crossValue == "source")(chisel) - def chiselPluginJar = None + def chiselPluginJar = T(Option.when(crossValue == "source")(chisel.pluginModule.jar())) - def chiselIvy = Some(v.chiselCrossVersions(crossValue)._1) + def chiselIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._1) - def chiselPluginIvy = Some(v.chiselCrossVersions(crossValue)._2) + def chiselPluginIvy = Option.when(crossValue != "source")(v.chiselCrossVersions(crossValue)._2) def macrosModule = macros @@ -87,9 +131,15 @@ trait RocketChip def cdeModule = cde + def diplomacyModule = diplomacy(crossValue) + + def diplomacyIvy = None + def mainargsIvy = v.mainargs def json4sJacksonIvy = v.json4sJackson + + def repositoriesTask = T.task(super.repositoriesTask() ++ v.sonatypesSnapshots) } trait RocketChipPublishModule @@ -108,7 +158,6 @@ trait RocketChipPublishModule override def publishVersion: T[String] = T("1.6-SNAPSHOT") } - // Tests trait Emulator extends Cross.Module2[String, String] { val top: String = crossValue @@ -267,6 +316,7 @@ object emulator extends Cross[Emulator]( ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultBufferlessConfig"), // RocketSuiteC ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig"), + // Unittest ("freechips.rocketchip.unittest.TestHarness", "freechips.rocketchip.unittest.AMBAUnitTestConfig"), ("freechips.rocketchip.unittest.TestHarness", "freechips.rocketchip.unittest.TLSimpleUnitTestConfig"), @@ -294,6 +344,9 @@ object emulator extends Cross[Emulator]( // ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultFP16Config"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultBConfig"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32BConfig"), + ) object `runnable-riscv-test` extends mill.Cross[RiscvTest]( @@ -355,8 +408,8 @@ object `runnable-riscv-test` extends mill.Cross[RiscvTest]( ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32uc-v", "none"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32uf-p", "none"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32uf-v", "none"), - ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32ui-p", "none"), - ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32ui-v", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32ui-p", "ma_data"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32ui-v", "ma_data"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32um-p", "none"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32Config", "rv32um-v", "none"), @@ -368,11 +421,17 @@ object `runnable-riscv-test` extends mill.Cross[RiscvTest]( // lsrc is not implemented if usingDataScratchpad ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig", "rv32ua-p", "lrsc"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig", "rv32uc-p", "none"), - ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig", "rv32ui-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig", "rv32ui-p", "ma_data"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.TinyConfig", "rv32um-p", "none"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultFP16Config", "rv64uzfh-p", "none"), ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultFP16Config", "rv64uzfh-v", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultBConfig", "rv64uzba-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultBConfig", "rv64uzbb-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultBConfig", "rv64uzbs-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32BConfig", "rv32uzba-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32BConfig", "rv32uzbb-p", "none"), + ("freechips.rocketchip.system.TestHarness", "freechips.rocketchip.system.DefaultRV32BConfig", "rv32uzbs-p", "none"), ) object `runnable-arch-test` extends mill.Cross[ArchTest]( diff --git a/common.sc b/common.sc index 574f0ad4310..d11edcc116a 100644 --- a/common.sc +++ b/common.sc @@ -42,19 +42,18 @@ trait RocketChipModule // should be hardfloat/common.sc#HardfloatModule def hardfloatModule: ScalaModule - // should be cde/common.sc#CDEModule - def cdeModule: ScalaModule + def diplomacyModule: ScalaModule def mainargsIvy: Dep def json4sJacksonIvy: Dep - override def moduleDeps = super.moduleDeps ++ Seq(macrosModule, hardfloatModule, cdeModule) + override def moduleDeps = super.moduleDeps ++ Seq(macrosModule, hardfloatModule, diplomacyModule) override def ivyDeps = T( super.ivyDeps() ++ Agg( mainargsIvy, - json4sJacksonIvy + json4sJacksonIvy, ) ) } diff --git a/cde b/dependencies/cde similarity index 100% rename from cde rename to dependencies/cde diff --git a/dependencies/chisel b/dependencies/chisel new file mode 160000 index 00000000000..e3bcc90db37 --- /dev/null +++ b/dependencies/chisel @@ -0,0 +1 @@ +Subproject commit e3bcc90db37f1aec9f8048813f4f0666098d9bee diff --git a/dependencies/diplomacy b/dependencies/diplomacy new file mode 160000 index 00000000000..edf375300d9 --- /dev/null +++ b/dependencies/diplomacy @@ -0,0 +1 @@ +Subproject commit edf375300d99a4c260a214d7c1553de0040771d7 diff --git a/hardfloat b/dependencies/hardfloat similarity index 100% rename from hardfloat rename to dependencies/hardfloat diff --git a/docs/src/diplomacy/adder_tutorial.md b/docs/src/diplomacy/adder_tutorial.md index 9ab77ff29d5..2548ac43dc8 100644 --- a/docs/src/diplomacy/adder_tutorial.md +++ b/docs/src/diplomacy/adder_tutorial.md @@ -38,7 +38,7 @@ behavior of typical Chisel width inference. ```scala mdoc:invisible import chipsalliance.rocketchip.config.{Config, Parameters} import chisel3._ -import chisel3.internal.sourceinfo.SourceInfo +import chisel3.experimental.SourceInfo import chisel3.stage.ChiselStage import chisel3.util.random.FibonacciLFSR import freechips.rocketchip.diplomacy.{SimpleNodeImp, RenderedEdge, ValName, SourceNode, diff --git a/flake.lock b/flake.lock index b0128cb6f91..e0cf2cdc548 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,15 @@ { "nodes": { "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1676283394, - "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -17,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1676300157, - "narHash": "sha256-1HjRzfp6LOLfcj/HJHdVKWAkX9QRAouoh6AjzJiIerU=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "545c7a31e5dedea4a6d372712a18e00ce097d462", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { @@ -36,6 +39,21 @@ "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index d9a19fcf541..28d32e91fb4 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,8 @@ mill dtc verilator cmake ninja - python3 python3Packages.bootstrapped-pip + python3 + python3Packages.pip pkgsCross.riscv64-embedded.buildPackages.gcc pkgsCross.riscv64-embedded.buildPackages.gdb openocd diff --git a/overlay.nix b/overlay.nix index c7698a02821..3cd0989b795 100644 --- a/overlay.nix +++ b/overlay.nix @@ -8,12 +8,12 @@ final: prev: { }); riscvTests = final.pkgsCross.riscv64-embedded.stdenv.mkDerivation rec { pname = "riscv-tests"; - version = "55bbcc8c06637a31cc01970881ba8072838a9121"; + version = "f2f748ebb9cf8ea049103f85c4cbf7e8a2927b16"; src = final.fetchgit { url = "https://github.com/riscv-software-src/riscv-tests.git"; rev = "${version}"; fetchSubmodules = true; - sha256 = "sha256-TcIU+WFQxPqAG7lvfKPgHm4CnBpTkosqe+fYOxS+J7I="; + sha256 = "sha256-E3RfrP+PFIYy9c/pY04jYPxeGpnfgWwjV8iwL5+s+9w="; }; enableParallelBuilding = true; diff --git a/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary b/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary deleted file mode 100644 index abfcceb0559..00000000000 --- a/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary +++ /dev/null @@ -1 +0,0 @@ -firrtl.passes.memlib.MemLibOptions diff --git a/src/main/resources/vsrc/RoccBlackBox.v b/src/main/resources/vsrc/RoccBlackBox.v index 5c0a0766c95..4588cd38def 100644 --- a/src/main/resources/vsrc/RoccBlackBox.v +++ b/src/main/resources/vsrc/RoccBlackBox.v @@ -15,153 +15,156 @@ module RoccBlackBox fLen = 64, FPConstants_FLAGS_SZ = 5) ( input clock, - input reset, - output rocc_cmd_ready, - input rocc_cmd_valid, - input [6:0] rocc_cmd_bits_inst_funct, - input [4:0] rocc_cmd_bits_inst_rs2, - input [4:0] rocc_cmd_bits_inst_rs1, - input rocc_cmd_bits_inst_xd, - input rocc_cmd_bits_inst_xs1, - input rocc_cmd_bits_inst_xs2, - input [4:0] rocc_cmd_bits_inst_rd, - input [6:0] rocc_cmd_bits_inst_opcode, - input [xLen-1:0] rocc_cmd_bits_rs1, - input [xLen-1:0] rocc_cmd_bits_rs2, - input rocc_cmd_bits_status_debug, - input rocc_cmd_bits_status_cease, - input rocc_cmd_bits_status_wfi, - input [31:0] rocc_cmd_bits_status_isa, - input [PRV_SZ-1:0] rocc_cmd_bits_status_dprv, - input rocc_cmd_bits_status_dv, - input [PRV_SZ-1:0] rocc_cmd_bits_status_prv, - input rocc_cmd_bits_status_v, - input rocc_cmd_bits_status_sd, - input [22:0] rocc_cmd_bits_status_zero2, - input rocc_cmd_bits_status_mpv, - input rocc_cmd_bits_status_gva, - input rocc_cmd_bits_status_mbe, - input rocc_cmd_bits_status_sbe, - input [1:0] rocc_cmd_bits_status_sxl, - input [1:0] rocc_cmd_bits_status_uxl, - input rocc_cmd_bits_status_sd_rv32, - input [7:0] rocc_cmd_bits_status_zero1, - input rocc_cmd_bits_status_tsr, - input rocc_cmd_bits_status_tw, - input rocc_cmd_bits_status_tvm, - input rocc_cmd_bits_status_mxr, - input rocc_cmd_bits_status_sum, - input rocc_cmd_bits_status_mprv, - input [1:0] rocc_cmd_bits_status_xs, - input [1:0] rocc_cmd_bits_status_fs, - input [1:0] rocc_cmd_bits_status_vs, - input [1:0] rocc_cmd_bits_status_mpp, - input [0:0] rocc_cmd_bits_status_spp, - input rocc_cmd_bits_status_mpie, - input rocc_cmd_bits_status_ube, - input rocc_cmd_bits_status_spie, - input rocc_cmd_bits_status_upie, - input rocc_cmd_bits_status_mie, - input rocc_cmd_bits_status_hie, - input rocc_cmd_bits_status_sie, - input rocc_cmd_bits_status_uie, - input rocc_resp_ready, - output rocc_resp_valid, - output [4:0] rocc_resp_bits_rd, - output [xLen-1:0] rocc_resp_bits_data, - input rocc_mem_req_ready, - output rocc_mem_req_valid, - output [coreMaxAddrBits-1:0] rocc_mem_req_bits_addr, - output [dcacheReqTagBits-1:0] rocc_mem_req_bits_tag, - output [M_SZ-1:0] rocc_mem_req_bits_cmd, + input reset, + output rocc_cmd_ready, + input rocc_cmd_valid, + input [6:0] rocc_cmd_bits_inst_funct, + input [4:0] rocc_cmd_bits_inst_rs2, + input [4:0] rocc_cmd_bits_inst_rs1, + input rocc_cmd_bits_inst_xd, + input rocc_cmd_bits_inst_xs1, + input rocc_cmd_bits_inst_xs2, + input [4:0] rocc_cmd_bits_inst_rd, + input [6:0] rocc_cmd_bits_inst_opcode, + input [xLen-1:0] rocc_cmd_bits_rs1, + input [xLen-1:0] rocc_cmd_bits_rs2, + input rocc_cmd_bits_status_debug, + input rocc_cmd_bits_status_cease, + input rocc_cmd_bits_status_wfi, + input [31:0] rocc_cmd_bits_status_isa, + input [PRV_SZ-1:0] rocc_cmd_bits_status_dprv, + input rocc_cmd_bits_status_dv, + input [PRV_SZ-1:0] rocc_cmd_bits_status_prv, + input rocc_cmd_bits_status_v, + input rocc_cmd_bits_status_sd, + input [22:0] rocc_cmd_bits_status_zero2, + input rocc_cmd_bits_status_mpv, + input rocc_cmd_bits_status_gva, + input rocc_cmd_bits_status_mbe, + input rocc_cmd_bits_status_sbe, + input [1:0] rocc_cmd_bits_status_sxl, + input [1:0] rocc_cmd_bits_status_uxl, + input rocc_cmd_bits_status_sd_rv32, + input [7:0] rocc_cmd_bits_status_zero1, + input rocc_cmd_bits_status_tsr, + input rocc_cmd_bits_status_tw, + input rocc_cmd_bits_status_tvm, + input rocc_cmd_bits_status_mxr, + input rocc_cmd_bits_status_sum, + input rocc_cmd_bits_status_mprv, + input [1:0] rocc_cmd_bits_status_xs, + input [1:0] rocc_cmd_bits_status_fs, + input [1:0] rocc_cmd_bits_status_vs, + input [1:0] rocc_cmd_bits_status_mpp, + input [0:0] rocc_cmd_bits_status_spp, + input rocc_cmd_bits_status_mpie, + input rocc_cmd_bits_status_ube, + input rocc_cmd_bits_status_spie, + input rocc_cmd_bits_status_upie, + input rocc_cmd_bits_status_mie, + input rocc_cmd_bits_status_hie, + input rocc_cmd_bits_status_sie, + input rocc_cmd_bits_status_uie, + input rocc_resp_ready, + output rocc_resp_valid, + output [4:0] rocc_resp_bits_rd, + output [xLen-1:0] rocc_resp_bits_data, + input rocc_mem_req_ready, + output rocc_mem_req_valid, + output [coreMaxAddrBits-1:0] rocc_mem_req_bits_addr, + output [dcacheReqTagBits-1:0] rocc_mem_req_bits_tag, + output [M_SZ-1:0] rocc_mem_req_bits_cmd, output [mem_req_bits_size_width-1:0] rocc_mem_req_bits_size, - output rocc_mem_req_bits_signed, - output rocc_mem_req_bits_phys, - output rocc_mem_req_bits_no_alloc, - output rocc_mem_req_bits_no_xcpt, - output [1:0] rocc_mem_req_bits_dprv, - output rocc_mem_req_bits_dv, - output [coreDataBits-1:0] rocc_mem_req_bits_data, - output [coreDataBytes-1:0] rocc_mem_req_bits_mask, - output rocc_mem_s1_kill, - output [coreDataBits-1:0] rocc_mem_s1_data_data, - output [coreDataBytes-1:0] rocc_mem_s1_data_mask, - input rocc_mem_s2_nack, - input rocc_mem_s2_nack_cause_raw, - output rocc_mem_s2_kill, - input rocc_mem_s2_uncached, - input [paddrBits-1:0] rocc_mem_s2_paddr, - input [vaddrBitsExtended-1:0] rocc_mem_s2_gpa, - input rocc_mem_s2_gpa_is_pte, - input rocc_mem_resp_valid, - input [coreMaxAddrBits-1:0] rocc_mem_resp_bits_addr, - input [dcacheReqTagBits-1:0] rocc_mem_resp_bits_tag, - input [M_SZ-1:0] rocc_mem_resp_bits_cmd, - input [mem_req_bits_size_width-1:0] rocc_mem_resp_bits_size, - input rocc_mem_resp_bits_signed, - input [coreDataBits-1:0] rocc_mem_resp_bits_data, - input [coreDataBytes-1:0] rocc_mem_resp_bits_mask, - input rocc_mem_resp_bits_replay, - input rocc_mem_resp_bits_has_data, - input [coreDataBits-1:0] rocc_mem_resp_bits_data_word_bypass, - input [coreDataBits-1:0] rocc_mem_resp_bits_data_raw, - input [coreDataBits-1:0] rocc_mem_resp_bits_store_data, - input [1:0] rocc_mem_resp_bits_dprv, - input rocc_mem_resp_bits_dv, - input rocc_mem_replay_next, - input rocc_mem_s2_xcpt_ma_ld, - input rocc_mem_s2_xcpt_ma_st, - input rocc_mem_s2_xcpt_pf_ld, - input rocc_mem_s2_xcpt_pf_st, - input rocc_mem_s2_xcpt_gf_ld, - input rocc_mem_s2_xcpt_gf_st, - input rocc_mem_s2_xcpt_ae_ld, - input rocc_mem_s2_xcpt_ae_st, - input rocc_mem_ordered, - input rocc_mem_perf_acquire, - input rocc_mem_perf_release, - input rocc_mem_perf_grant, - input rocc_mem_perf_tlbMiss, - input rocc_mem_perf_blocked, - input rocc_mem_perf_canAcceptStoreThenLoad, - input rocc_mem_perf_canAcceptStoreThenRMW, - input rocc_mem_perf_canAcceptLoadThenLoad, - input rocc_mem_perf_storeBufferEmptyAfterLoad, - input rocc_mem_perf_storeBufferEmptyAfterStore, - output rocc_mem_keep_clock_enabled, - input rocc_mem_clock_enabled, - output rocc_busy, - output rocc_interrupt, - input rocc_exception, - input rocc_fpu_req_ready, - output rocc_fpu_req_valid, - output rocc_fpu_req_bits_ldst, - output rocc_fpu_req_bits_wen, - output rocc_fpu_req_bits_ren1, - output rocc_fpu_req_bits_ren2, - output rocc_fpu_req_bits_ren3, - output rocc_fpu_req_bits_swap12, - output rocc_fpu_req_bits_swap23, - output [1:0] rocc_fpu_req_bits_typeTagIn, - output [1:0] rocc_fpu_req_bits_typeTagOut, - output rocc_fpu_req_bits_fromint, - output rocc_fpu_req_bits_toint, - output rocc_fpu_req_bits_fastpipe, - output rocc_fpu_req_bits_fma, - output rocc_fpu_req_bits_div, - output rocc_fpu_req_bits_sqrt, - output rocc_fpu_req_bits_wflags, - output [FPConstants_RM_SZ-1:0] rocc_fpu_req_bits_rm, - output [1:0] rocc_fpu_req_bits_fmaCmd, - output [1:0] rocc_fpu_req_bits_typ, - output [1:0] rocc_fpu_req_bits_fmt, - output [fLen:0] rocc_fpu_req_bits_in1, - output [fLen:0] rocc_fpu_req_bits_in2, - output [fLen:0] rocc_fpu_req_bits_in3, - output rocc_fpu_resp_ready, - input rocc_fpu_resp_valid, - input [fLen:0] rocc_fpu_resp_bits_data, - input [FPConstants_FLAGS_SZ-1:0] rocc_fpu_resp_bits_exc ); + output rocc_mem_req_bits_signed, + output rocc_mem_req_bits_phys, + output rocc_mem_req_bits_no_alloc, + output rocc_mem_req_bits_no_xcpt, + output rocc_mem_req_bits_no_resp, + output [1:0] rocc_mem_req_bits_dprv, + output rocc_mem_req_bits_dv, + output [coreDataBits-1:0] rocc_mem_req_bits_data, + output [coreDataBytes-1:0] rocc_mem_req_bits_mask, + output rocc_mem_s1_kill, + output [coreDataBits-1:0] rocc_mem_s1_data_data, + output [coreDataBytes-1:0] rocc_mem_s1_data_mask, + input rocc_mem_s2_nack, + input rocc_mem_s2_nack_cause_raw, + output rocc_mem_s2_kill, + input rocc_mem_s2_uncached, + input [paddrBits-1:0] rocc_mem_s2_paddr, + input [vaddrBitsExtended-1:0] rocc_mem_s2_gpa, + input rocc_mem_s2_gpa_is_pte, + input rocc_mem_resp_valid, + input [coreMaxAddrBits-1:0] rocc_mem_resp_bits_addr, + input [dcacheReqTagBits-1:0] rocc_mem_resp_bits_tag, + input [M_SZ-1:0] rocc_mem_resp_bits_cmd, + input [mem_req_bits_size_width-1:0] rocc_mem_resp_bits_size, + input rocc_mem_resp_bits_signed, + input [coreDataBits-1:0] rocc_mem_resp_bits_data, + input [coreDataBytes-1:0] rocc_mem_resp_bits_mask, + input rocc_mem_resp_bits_replay, + input rocc_mem_resp_bits_has_data, + input [coreDataBits-1:0] rocc_mem_resp_bits_data_word_bypass, + input [coreDataBits-1:0] rocc_mem_resp_bits_data_raw, + input [coreDataBits-1:0] rocc_mem_resp_bits_store_data, + input [1:0] rocc_mem_resp_bits_dprv, + input rocc_mem_resp_bits_dv, + input rocc_mem_replay_next, + input rocc_mem_s2_xcpt_ma_ld, + input rocc_mem_s2_xcpt_ma_st, + input rocc_mem_s2_xcpt_pf_ld, + input rocc_mem_s2_xcpt_pf_st, + input rocc_mem_s2_xcpt_gf_ld, + input rocc_mem_s2_xcpt_gf_st, + input rocc_mem_s2_xcpt_ae_ld, + input rocc_mem_s2_xcpt_ae_st, + input rocc_mem_ordered, + input rocc_mem_store_pending, + input rocc_mem_perf_acquire, + input rocc_mem_perf_release, + input rocc_mem_perf_grant, + input rocc_mem_perf_tlbMiss, + input rocc_mem_perf_blocked, + input rocc_mem_perf_canAcceptStoreThenLoad, + input rocc_mem_perf_canAcceptStoreThenRMW, + input rocc_mem_perf_canAcceptLoadThenLoad, + input rocc_mem_perf_storeBufferEmptyAfterLoad, + input rocc_mem_perf_storeBufferEmptyAfterStore, + output rocc_mem_keep_clock_enabled, + input rocc_mem_clock_enabled, + output rocc_busy, + output rocc_interrupt, + input rocc_exception, + input rocc_fpu_req_ready, + output rocc_fpu_req_valid, + output rocc_fpu_req_bits_ldst, + output rocc_fpu_req_bits_wen, + output rocc_fpu_req_bits_ren1, + output rocc_fpu_req_bits_ren2, + output rocc_fpu_req_bits_ren3, + output rocc_fpu_req_bits_swap12, + output rocc_fpu_req_bits_swap23, + output [1:0] rocc_fpu_req_bits_typeTagIn, + output [1:0] rocc_fpu_req_bits_typeTagOut, + output rocc_fpu_req_bits_fromint, + output rocc_fpu_req_bits_toint, + output rocc_fpu_req_bits_fastpipe, + output rocc_fpu_req_bits_fma, + output rocc_fpu_req_bits_div, + output rocc_fpu_req_bits_sqrt, + output rocc_fpu_req_bits_wflags, + output [FPConstants_RM_SZ-1:0] rocc_fpu_req_bits_rm, + output [1:0] rocc_fpu_req_bits_fmaCmd, + output [1:0] rocc_fpu_req_bits_typ, + output [1:0] rocc_fpu_req_bits_fmt, + output [fLen:0] rocc_fpu_req_bits_in1, + output [fLen:0] rocc_fpu_req_bits_in2, + output [fLen:0] rocc_fpu_req_bits_in3, + output rocc_fpu_req_bits_vec, + output rocc_fpu_resp_ready, + input rocc_fpu_resp_valid, + input [fLen:0] rocc_fpu_resp_bits_data, + input [FPConstants_FLAGS_SZ-1:0] rocc_fpu_resp_bits_exc ); assign rocc_cmd_ready = 1'b1; diff --git a/src/main/scala/amba/ahb/AHBLite.scala b/src/main/scala/amba/ahb/AHBLite.scala index 633b46fc594..7e80611690c 100644 --- a/src/main/scala/amba/ahb/AHBLite.scala +++ b/src/main/scala/amba/ahb/AHBLite.scala @@ -4,7 +4,7 @@ package freechips.rocketchip.amba.ahb import chisel3._ import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} class AHBLite()(implicit p: Parameters) extends LazyModule { val node = AHBMasterAdapterNode( diff --git a/src/main/scala/amba/ahb/Nodes.scala b/src/main/scala/amba/ahb/Nodes.scala index 461157407f1..33c33ccd213 100644 --- a/src/main/scala/amba/ahb/Nodes.scala +++ b/src/main/scala/amba/ahb/Nodes.scala @@ -4,8 +4,11 @@ package freechips.rocketchip.amba.ahb import chisel3._ import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp, RenderedEdge, OutwardNode, InwardNode, SourceNode, SinkNode, IdentityNode, AdapterNode, MixedNexusNode, NexusNode} case object AHBSlaveMonitorBuilder extends Field[AHBSlaveMonitorArgs => AHBSlaveMonitorBase] diff --git a/src/main/scala/amba/ahb/Parameters.scala b/src/main/scala/amba/ahb/Parameters.scala index 62c951604df..0039b928b7c 100644 --- a/src/main/scala/amba/ahb/Parameters.scala +++ b/src/main/scala/amba/ahb/Parameters.scala @@ -2,11 +2,17 @@ package freechips.rocketchip.amba.ahb -import chisel3.util._ import chisel3.experimental.SourceInfo +import chisel3.util._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.nodes.BaseNode + +import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.util.{BundleField, BundleFieldBase, BundleKeyBase} + import scala.math.{max, min} case class AHBSlaveParameters( diff --git a/src/main/scala/amba/ahb/RegisterRouter.scala b/src/main/scala/amba/ahb/RegisterRouter.scala index a8721aedf3e..e2619b66c8c 100644 --- a/src/main/scala/amba/ahb/RegisterRouter.scala +++ b/src/main/scala/amba/ahb/RegisterRouter.scala @@ -3,12 +3,18 @@ package freechips.rocketchip.amba.ahb import chisel3._ -import chisel3.util._ +import chisel3.util.{log2Up, log2Ceil, Decoupled} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SinkNode} + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} +import freechips.rocketchip.regmapper.{RegMapperParams, RegField, RegMapperInput, RegisterRouter, RegMapper} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util._ +import freechips.rocketchip.util.MaskGen + import scala.math.min case class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName) @@ -68,50 +74,6 @@ case class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: } } -// These convenience methods below combine to make it possible to create a AHB -// register mapped device from a totally abstract register mapped device. - -@deprecated("Use HasAHBControlRegMap+HasInterruptSources traits in place of AHBRegisterRouter+AHBRegBundle+AHBRegModule", "rocket-chip 1.3") -abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule -{ - val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) -} - -@deprecated("AHBRegBundleArg is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -case class AHBRegBundleArg()(implicit val p: Parameters) - -@deprecated("AHBRegBundleBase is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle -{ - implicit val p = arg.p -} - -@deprecated("Use HasAHBControlRegMap+HasInterruptSources traits in place of AHBRegisterRouter+AHBRegBundle+AHBRegModule", "rocket-chip 1.3") -class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleBase(arg) - -@deprecated("Use HasAHBControlRegMap+HasInterruptSources traits in place of AHBRegisterRouter+AHBRegBundle+AHBRegModule", "rocket-chip 1.3") -class AHBRegModule[P, B <: AHBRegBundleBase](val params: P, bundleBuilder: => B, router: AHBRegisterRouterBase) - extends LazyModuleImp(router) with HasRegMap -{ - val io = IO(bundleBuilder) - val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 - def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) -} - -@deprecated("Use HasAHBControlRegMap+HasInterruptSources traits in place of AHBRegisterRouter+AHBRegBundle+AHBRegModule", "rocket-chip 1.3") -class AHBRegisterRouter[B <: AHBRegBundleBase, M <: LazyModuleImp] - (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Int = 0, val beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) - (bundleBuilder: AHBRegBundleArg => B) - (moduleBuilder: (=> B, AHBRegisterRouterBase) => M)(implicit p: Parameters) - extends AHBRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) -{ - require (isPow2(size)) - // require (size >= 4096) ... not absolutely required, but highly recommended - - lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg()), this) -} - /** Mix this trait into a RegisterRouter to be able to attach its register map to an AXI4 bus */ trait HasAHBControlRegMap { this: RegisterRouter => // Externally, this node should be used to connect the register control port to a bus diff --git a/src/main/scala/amba/ahb/SRAM.scala b/src/main/scala/amba/ahb/SRAM.scala index 51c8cddad3e..a4a8bdeae3b 100644 --- a/src/main/scala/amba/ahb/SRAM.scala +++ b/src/main/scala/amba/ahb/SRAM.scala @@ -5,9 +5,12 @@ package freechips.rocketchip.amba.ahb import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} import freechips.rocketchip.tilelink.LFSRNoiseMaker +import freechips.rocketchip.util.{MaskGen, DataToAugmentedData, SeqMemToAugmentedSeqMem, PlusArg} class AHBRAM( address: AddressSet, diff --git a/src/main/scala/amba/ahb/Test.scala b/src/main/scala/amba/ahb/Test.scala index bf28459454b..43a57977dcc 100644 --- a/src/main/scala/amba/ahb/Test.scala +++ b/src/main/scala/amba/ahb/Test.scala @@ -3,12 +3,16 @@ package freechips.rocketchip.amba.ahb import chisel3._ + import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp, SimpleLazyModule} + import freechips.rocketchip.devices.tilelink.TLTestRAM -import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.diplomacy.{AddressSet, BufferParams} import freechips.rocketchip.regmapper.{RRTest0, RRTest1} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.unittest._ +import freechips.rocketchip.tilelink.{TLFuzzer, TLRAMModel, TLToAHB, TLDelayer, TLBuffer, TLErrorEvaluator, TLFragmenter} +import freechips.rocketchip.unittest.{UnitTestModule, UnitTest} class AHBRRTest0(address: BigInt)(implicit p: Parameters) extends RRTest0(address) diff --git a/src/main/scala/amba/ahb/ToTL.scala b/src/main/scala/amba/ahb/ToTL.scala index f08feb167bf..e34d7c262ba 100644 --- a/src/main/scala/amba/ahb/ToTL.scala +++ b/src/main/scala/amba/ahb/ToTL.scala @@ -4,11 +4,17 @@ package freechips.rocketchip.amba.ahb import chisel3._ import chisel3.util._ -import freechips.rocketchip.amba._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{MixedAdapterNode} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.amba.{AMBAProtField, AMBAProt} +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.tilelink.{TLImp, TLMasterPortParameters, TLMessages, TLMasterParameters, TLMasterToSlaveTransferSizes} +import freechips.rocketchip.util.{BundleMap, MaskGen, DataToAugmentedData} case class AHBToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AHBImpSlave, TLImp)( dFn = { case mp => diff --git a/src/main/scala/amba/ahb/Xbar.scala b/src/main/scala/amba/ahb/Xbar.scala index 2db7d5cd187..d685ac1bed9 100644 --- a/src/main/scala/amba/ahb/Xbar.scala +++ b/src/main/scala/amba/ahb/Xbar.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.amba.ahb import chisel3._ -import chisel3.util._ +import chisel3.util.Mux1H + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.AddressDecoder +import freechips.rocketchip.util.BundleField + class AHBFanout()(implicit p: Parameters) extends LazyModule { val node = new AHBFanoutNode( diff --git a/src/main/scala/amba/ahb/package.scala b/src/main/scala/amba/ahb/package.scala index 8477adb2fbe..ffcf196951a 100644 --- a/src/main/scala/amba/ahb/package.scala +++ b/src/main/scala/amba/ahb/package.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.amba -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, SimpleNodeHandle} package object ahb { diff --git a/src/main/scala/amba/apb/Nodes.scala b/src/main/scala/amba/apb/Nodes.scala index 183a058e8e8..e2dd9307c74 100644 --- a/src/main/scala/amba/apb/Nodes.scala +++ b/src/main/scala/amba/apb/Nodes.scala @@ -4,8 +4,11 @@ package freechips.rocketchip.amba.apb import chisel3._ import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp,RenderedEdge, InwardNode, OutwardNode, SourceNode, SinkNode, NexusNode, IdentityNode} case object APBMonitorBuilder extends Field[APBMonitorArgs => APBMonitorBase] diff --git a/src/main/scala/amba/apb/Parameters.scala b/src/main/scala/amba/apb/Parameters.scala index 5c07d827f65..f39c8b03fef 100644 --- a/src/main/scala/amba/apb/Parameters.scala +++ b/src/main/scala/amba/apb/Parameters.scala @@ -2,11 +2,17 @@ package freechips.rocketchip.amba.apb -import chisel3.util._ +import chisel3.util.{isPow2, log2Up} import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.nodes.BaseNode + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType} +import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} +import freechips.rocketchip.util.{BundleField, BundleKeyBase, BundleFieldBase} + import scala.math.max case class APBSlaveParameters( diff --git a/src/main/scala/amba/apb/RegisterRouter.scala b/src/main/scala/amba/apb/RegisterRouter.scala index 9000399570c..07b62a5c67b 100644 --- a/src/main/scala/amba/apb/RegisterRouter.scala +++ b/src/main/scala/amba/apb/RegisterRouter.scala @@ -3,10 +3,15 @@ package freechips.rocketchip.amba.apb import chisel3._ -import chisel3.util._ +import chisel3.util.{Decoupled, log2Up, log2Ceil} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.SinkNode + +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.regmapper.{RegField, RegMapperParams, RegMapperInput, RegMapper, RegisterRouter} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} case class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName) @@ -49,50 +54,6 @@ case class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: } } -// These convenience methods below combine to make it possible to create a APB -// register mapped device from a totally abstract register mapped device. - -@deprecated("Use HasAPBControlRegMap+HasInterruptSources traits in place of APBRegisterRouter+APBRegBundle+APBRegModule", "rocket-chip 1.3") -abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule -{ - val node = APBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) -} - -@deprecated("APBRegBundleArg is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -case class APBRegBundleArg()(implicit val p: Parameters) - -@deprecated("AXI4RegBundleBase is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle -{ - implicit val p = arg.p -} - -@deprecated("Use HasAPBControlRegMap+HasInterruptSources traits in place of APBRegisterRouter+APBRegBundle+APBRegModule", "rocket-chip 1.3") -class APBRegBundle[P](val params: P, arg: APBRegBundleArg) extends APBRegBundleBase(arg) - -@deprecated("Use HasAPBControlRegMap+HasInterruptSources traits in place of APBRegisterRouter+APBRegBundle+APBRegModule", "rocket-chip 1.3") -class APBRegModule[P, B <: APBRegBundleBase](val params: P, bundleBuilder: => B, router: APBRegisterRouterBase) - extends LazyModuleImp(router) with HasRegMap -{ - val io = IO(bundleBuilder) - val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 - def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) -} - -@deprecated("Use HasAPBControlRegMap+HasInterruptSources traits in place of APBRegisterRouter+APBRegBundle+APBRegModule", "rocket-chip 1.3") -class APBRegisterRouter[B <: APBRegBundleBase, M <: LazyModuleImp] - (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Int = 0, val beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) - (bundleBuilder: APBRegBundleArg => B) - (moduleBuilder: (=> B, APBRegisterRouterBase) => M)(implicit p: Parameters) - extends APBRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) -{ - require (isPow2(size)) - // require (size >= 4096) ... not absolutely required, but highly recommended - - lazy val module = moduleBuilder(bundleBuilder(APBRegBundleArg()), this) -} - /** Mix this trait into a RegisterRouter to be able to attach its register map to an AXI4 bus */ trait HasAPBControlRegMap { this: RegisterRouter => // Externally, this node should be used to connect the register control port to a bus diff --git a/src/main/scala/amba/apb/SRAM.scala b/src/main/scala/amba/apb/SRAM.scala index 1e8325e2d5f..8c5a9c27487 100644 --- a/src/main/scala/amba/apb/SRAM.scala +++ b/src/main/scala/amba/apb/SRAM.scala @@ -3,11 +3,16 @@ package freechips.rocketchip.amba.apb import chisel3._ -import chisel3.util._ +import chisel3.util.{Cat, log2Ceil, RegEnable} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType} +import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} import freechips.rocketchip.tilelink.LFSRNoiseMaker +import freechips.rocketchip.util.SeqMemToAugmentedSeqMem class APBRAM( address: AddressSet, diff --git a/src/main/scala/amba/apb/Test.scala b/src/main/scala/amba/apb/Test.scala index 4b8d48c4b9a..0c907079b89 100644 --- a/src/main/scala/amba/apb/Test.scala +++ b/src/main/scala/amba/apb/Test.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.amba.apb import chisel3._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{BufferParams, AddressSet} import freechips.rocketchip.regmapper.{RRTest0, RRTest1} -import freechips.rocketchip.tilelink._ +import freechips.rocketchip.tilelink.{TLFuzzer, TLRAMModel, TLToAPB, TLDelayer, TLBuffer, TLFragmenter} import freechips.rocketchip.unittest._ class APBRRTest0(address: BigInt)(implicit p: Parameters) diff --git a/src/main/scala/amba/apb/ToTL.scala b/src/main/scala/amba/apb/ToTL.scala index 48511d13436..39d01ab5515 100644 --- a/src/main/scala/amba/apb/ToTL.scala +++ b/src/main/scala/amba/apb/ToTL.scala @@ -4,11 +4,16 @@ package freechips.rocketchip.amba.apb import chisel3._ import chisel3.util._ -import freechips.rocketchip.amba._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{MixedAdapterNode} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.tilelink.{TLImp, TLMessages, TLMasterPortParameters, TLMasterParameters} case class APBToTLNode()(implicit valName: ValName) extends MixedAdapterNode(APBImp, TLImp)( dFn = { mp => @@ -53,7 +58,7 @@ class APBToTL()(implicit p: Parameters) extends LazyModule val beat = TransferSizes(beatBytes, beatBytes) //TODO: The double negative here is to work around Chisel's broken implementation of widening ~x. - val aligned_addr = ~in.paddr + val aligned_addr = ~(~in.paddr | (beatBytes-1).U) require(beatBytes == in.params.dataBits/8, s"TL beatBytes(${beatBytes}) doesn't match expected APB data width(${in.params.dataBits})") val data_size = (log2Ceil(beatBytes)).U diff --git a/src/main/scala/amba/apb/Xbar.scala b/src/main/scala/amba/apb/Xbar.scala index 849edaa5f19..3f50fbb4ea1 100644 --- a/src/main/scala/amba/apb/Xbar.scala +++ b/src/main/scala/amba/apb/Xbar.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.amba.apb import chisel3._ -import chisel3.util._ +import chisel3.util.Mux1H + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.AddressDecoder +import freechips.rocketchip.util.BundleField class APBFanout()(implicit p: Parameters) extends LazyModule { val node = new APBNexusNode( diff --git a/src/main/scala/amba/apb/package.scala b/src/main/scala/amba/apb/package.scala index f5acbf903d9..872fd22be23 100644 --- a/src/main/scala/amba/apb/package.scala +++ b/src/main/scala/amba/apb/package.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.amba -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, SimpleNodeHandle} package object apb { diff --git a/src/main/scala/amba/axi4/AsyncCrossing.scala b/src/main/scala/amba/axi4/AsyncCrossing.scala index 3e086738ee4..b9303e5c108 100644 --- a/src/main/scala/amba/axi4/AsyncCrossing.scala +++ b/src/main/scala/amba/axi4/AsyncCrossing.scala @@ -3,11 +3,17 @@ package freechips.rocketchip.amba.axi4 import chisel3._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ + +import org.chipsalliance.diplomacy.nodes.{NodeHandle} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.prci.{AsynchronousCrossing} +import freechips.rocketchip.tilelink.{TLRAMModel, TLFuzzer, TLToAXI4} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util._ +import freechips.rocketchip.util.{ToAsyncBundle, FromAsyncBundle, AsyncQueueParams, Pow2ClockDivider} /** * Source(Master) side for AXI4 crossing clock domain diff --git a/src/main/scala/amba/axi4/Buffer.scala b/src/main/scala/amba/axi4/Buffer.scala index 71c3fdff30d..2b768e87ca5 100644 --- a/src/main/scala/amba/axi4/Buffer.scala +++ b/src/main/scala/amba/axi4/Buffer.scala @@ -4,8 +4,13 @@ package freechips.rocketchip.amba.axi4 import chisel3._ import chisel3.util.{Queue, IrrevocableIO} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.BufferParams + import scala.math.min /** diff --git a/src/main/scala/amba/axi4/Credited.scala b/src/main/scala/amba/axi4/Credited.scala index e2a0d59776d..3dbea790f8b 100644 --- a/src/main/scala/amba/axi4/Credited.scala +++ b/src/main/scala/amba/axi4/Credited.scala @@ -3,10 +3,15 @@ package freechips.rocketchip.amba.axi4 import chisel3._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.prci.{CreditedCrossing} import freechips.rocketchip.subsystem.CrossingWrapper +import freechips.rocketchip.tilelink._ import freechips.rocketchip.util._ class AXI4CreditedBuffer(delay: AXI4CreditedDelay)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/amba/axi4/CrossingHelper.scala b/src/main/scala/amba/axi4/CrossingHelper.scala index ebeb9dbb1e0..aaa1a372304 100644 --- a/src/main/scala/amba/axi4/CrossingHelper.scala +++ b/src/main/scala/amba/axi4/CrossingHelper.scala @@ -3,8 +3,9 @@ package freechips.rocketchip.amba.axi4 import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing} +import org.chipsalliance.diplomacy.lazymodule.{LazyScope} + +import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing, CrossingType, ClockCrossingType, NoCrossing, AsynchronousCrossing, RationalCrossing, SynchronousCrossing, CreditedCrossing} trait AXI4OutwardCrossingHelper { type HelperCrossingType <: CrossingType diff --git a/src/main/scala/amba/axi4/Deinterleaver.scala b/src/main/scala/amba/axi4/Deinterleaver.scala index 27f99823a5e..461507a5e0c 100644 --- a/src/main/scala/amba/axi4/Deinterleaver.scala +++ b/src/main/scala/amba/axi4/Deinterleaver.scala @@ -5,8 +5,12 @@ package freechips.rocketchip.amba.axi4 import chisel3._ import chisel3.util.{Cat, isPow2, log2Ceil, ReadyValidIO, log2Up, OHToUInt, Queue, QueueIO, UIntToOH} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{BufferParams, TransferSizes} import freechips.rocketchip.util.leftOR /** This adapter deinterleaves read responses on the R channel. diff --git a/src/main/scala/amba/axi4/Delayer.scala b/src/main/scala/amba/axi4/Delayer.scala index 37a8297abbb..58ceb88b7f9 100644 --- a/src/main/scala/amba/axi4/Delayer.scala +++ b/src/main/scala/amba/axi4/Delayer.scala @@ -3,9 +3,12 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ +import chisel3.util.IrrevocableIO + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + import freechips.rocketchip.tilelink.LFSRNoiseMaker /** diff --git a/src/main/scala/amba/axi4/Filter.scala b/src/main/scala/amba/axi4/Filter.scala index 77833e2594d..9093aa05448 100644 --- a/src/main/scala/amba/axi4/Filter.scala +++ b/src/main/scala/amba/axi4/Filter.scala @@ -2,8 +2,11 @@ package freechips.rocketchip.amba.axi4 -import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} class AXI4Filter( Sfilter: AXI4SlaveParameters => Option[AXI4SlaveParameters] = AXI4Filter.Sidentity, diff --git a/src/main/scala/amba/axi4/Fragmenter.scala b/src/main/scala/amba/axi4/Fragmenter.scala index 60ec2dc5597..85505374088 100644 --- a/src/main/scala/amba/axi4/Fragmenter.scala +++ b/src/main/scala/amba/axi4/Fragmenter.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ +import chisel3.util.{Mux1H, Queue, IrrevocableIO, log2Ceil, UIntToOH} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, TransferSizes} +import freechips.rocketchip.util.{ControlKey, SimpleBundleField, rightOR, leftOR, OH1ToOH, UIntToOH1} case object AXI4FragLast extends ControlKey[Bool]("real_last") case class AXI4FragLastField() extends SimpleBundleField(AXI4FragLast)(Output(Bool()), false.B) diff --git a/src/main/scala/amba/axi4/IdIndexer.scala b/src/main/scala/amba/axi4/IdIndexer.scala index 49cb9d92974..4687d5dc0f8 100644 --- a/src/main/scala/amba/axi4/IdIndexer.scala +++ b/src/main/scala/amba/axi4/IdIndexer.scala @@ -3,11 +3,15 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ import chisel3.util.{log2Ceil, Cat} +import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.IdRange +import freechips.rocketchip.util.{ControlKey, SimpleBundleField} + case object AXI4ExtraId extends ControlKey[UInt]("extra_id") case class AXI4ExtraIdField(width: Int) extends SimpleBundleField(AXI4ExtraId)(Output(UInt(width.W)), 0.U) diff --git a/src/main/scala/amba/axi4/Nodes.scala b/src/main/scala/amba/axi4/Nodes.scala index 8fcf58066d9..da53aa92ea6 100644 --- a/src/main/scala/amba/axi4/Nodes.scala +++ b/src/main/scala/amba/axi4/Nodes.scala @@ -4,8 +4,12 @@ package freechips.rocketchip.amba.axi4 import chisel3._ import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp, RenderedEdge, OutwardNode, InwardNode, SourceNode, SinkNode, NexusNode, AdapterNode, IdentityNode, MixedAdapterNode} + import freechips.rocketchip.util.AsyncQueueParams case object AXI4MonitorBuilder extends Field[AXI4MonitorArgs => AXI4MonitorBase] diff --git a/src/main/scala/amba/axi4/Parameters.scala b/src/main/scala/amba/axi4/Parameters.scala index b059fb1927e..088c226d825 100644 --- a/src/main/scala/amba/axi4/Parameters.scala +++ b/src/main/scala/amba/axi4/Parameters.scala @@ -3,11 +3,17 @@ package freechips.rocketchip.amba.axi4 import chisel3.experimental.SourceInfo +import chisel3.util.{isPow2, log2Up} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.nodes.BaseNode + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes, IdRange, BufferParams, IdMap, IdMapEntry, DirectedBuffers} +import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} +import freechips.rocketchip.util.{BundleField, BundleFieldBase, BundleKeyBase, AsyncQueueParams, CreditedDelay} + import scala.math.max -import chisel3.util.{isPow2, log2Up} /** * Parameters for AXI4 slave diff --git a/src/main/scala/amba/axi4/RegisterRouter.scala b/src/main/scala/amba/axi4/RegisterRouter.scala index 827c64e4952..be48fa2eaf9 100644 --- a/src/main/scala/amba/axi4/RegisterRouter.scala +++ b/src/main/scala/amba/axi4/RegisterRouter.scala @@ -3,10 +3,16 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ +import chisel3.util.{Decoupled, Queue, log2Ceil, log2Up} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SinkNode} + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} +import freechips.rocketchip.prci.{NoCrossing} +import freechips.rocketchip.regmapper.{RegField, RegMapper, RegMapperInput, RegMapperParams, RegisterRouter} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} import freechips.rocketchip.util._ @@ -83,50 +89,6 @@ case class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes } } -// These convenience methods below combine to make it possible to create a AXI4 -// register mapped device from a totally abstract register mapped device. - -@deprecated("Use HasAXI4ControlRegMap+HasInterruptSources traits in place of AXI4RegisterRouter+AXI4RegBundle+AXI4RegModule", "rocket-chip 1.3") -abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule -{ - val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) -} - -@deprecated("AXI4RegBundleArg is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -case class AXI4RegBundleArg()(implicit val p: Parameters) - -@deprecated("AXI4RegBundleBase is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle -{ - implicit val p = arg.p -} - -@deprecated("Use HasAXI4ControlRegMap+HasInterruptSources traits in place of AXI4RegisterRouter+AXI4RegBundle+AXI4RegModule", "rocket-chip 1.3") -class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBundleBase(arg) - -@deprecated("Use HasAXI4ControlRegMap+HasInterruptSources traits in place of AXI4RegisterRouter+AXI4RegBundle+AXI4RegModule", "rocket-chip 1.3") -class AXI4RegModule[P, B <: AXI4RegBundleBase](val params: P, bundleBuilder: => B, router: AXI4RegisterRouterBase) - extends LazyModuleImp(router) with HasRegMap -{ - val io = IO(bundleBuilder) - val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 - def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) -} - -@deprecated("Use HasAXI4ControlRegMap+HasInterruptSources traits in place of AXI4RegisterRouter+AXI4RegBundle+AXI4RegModule", "rocket-chip 1.3") -class AXI4RegisterRouter[B <: AXI4RegBundleBase, M <: LazyModuleImp] - (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Int = 0, val beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) - (bundleBuilder: AXI4RegBundleArg => B) - (moduleBuilder: (=> B, AXI4RegisterRouterBase) => M)(implicit p: Parameters) - extends AXI4RegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) -{ - require (isPow2(size)) - // require (size >= 4096) ... not absolutely required, but highly recommended - - lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg()), this) -} - /** Mix this trait into a RegisterRouter to be able to attach its register map to an AXI4 bus */ trait HasAXI4ControlRegMap { this: RegisterRouter => protected val controlNode = AXI4RegisterNode( diff --git a/src/main/scala/amba/axi4/SRAM.scala b/src/main/scala/amba/axi4/SRAM.scala index 791634deacf..f4838b73ab0 100644 --- a/src/main/scala/amba/axi4/SRAM.scala +++ b/src/main/scala/amba/axi4/SRAM.scala @@ -3,11 +3,16 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ +import chisel3.util.{Cat, log2Ceil} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import freechips.rocketchip.amba._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.amba.AMBACorrupt +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} +import freechips.rocketchip.util.{BundleMap, SeqMemToAugmentedSeqMem} /** * AXI4 slave device to provide a RAM storage diff --git a/src/main/scala/amba/axi4/Test.scala b/src/main/scala/amba/axi4/Test.scala index f6a6ccd9cab..ccda7093807 100644 --- a/src/main/scala/amba/axi4/Test.scala +++ b/src/main/scala/amba/axi4/Test.scala @@ -3,9 +3,13 @@ package freechips.rocketchip.amba.axi4 import chisel3._ + import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp, SimpleLazyModule} + import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.diplomacy.{AddressSet, BufferParams} import freechips.rocketchip.regmapper.{RRTest0, RRTest1} import freechips.rocketchip.tilelink._ import freechips.rocketchip.unittest._ diff --git a/src/main/scala/amba/axi4/ToTL.scala b/src/main/scala/amba/axi4/ToTL.scala index 54ef0f0029c..833be2e4e28 100644 --- a/src/main/scala/amba/axi4/ToTL.scala +++ b/src/main/scala/amba/axi4/ToTL.scala @@ -3,12 +3,18 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ -import freechips.rocketchip.amba._ +import chisel3.util.{Cat, log2Up, log2Ceil, UIntToOH, Queue} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{MixedAdapterNode, InwardNodeImp} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.amba.{AMBACorrupt, AMBAProt, AMBAProtField} +import freechips.rocketchip.diplomacy.{IdRange, IdMapEntry, TransferSizes} +import freechips.rocketchip.tilelink.{TLImp, TLMasterParameters, TLMasterPortParameters, TLArbiter} +import freechips.rocketchip.util.{OH1ToUInt, UIntToOH1} case class AXI4ToTLIdMapEntry(tlId: IdRange, axi4Id: IdRange, name: String) extends IdMapEntry diff --git a/src/main/scala/amba/axi4/UserYanker.scala b/src/main/scala/amba/axi4/UserYanker.scala index a332f5399d3..93e69cd4b92 100644 --- a/src/main/scala/amba/axi4/UserYanker.scala +++ b/src/main/scala/amba/axi4/UserYanker.scala @@ -3,10 +3,13 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ +import chisel3.util.{Queue, QueueIO, UIntToOH} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.util.BundleMap /** This adapter prunes all user bit fields of the echo type from request messages, * storing them in queues and echoing them back when matching response messages are received. diff --git a/src/main/scala/amba/axi4/Xbar.scala b/src/main/scala/amba/axi4/Xbar.scala index be65db13834..291e92acdbe 100644 --- a/src/main/scala/amba/axi4/Xbar.scala +++ b/src/main/scala/amba/axi4/Xbar.scala @@ -3,12 +3,16 @@ package freechips.rocketchip.amba.axi4 import chisel3._ -import chisel3.util._ -import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import freechips.rocketchip.unittest._ -import freechips.rocketchip.tilelink._ +import chisel3.util.{Cat, Queue, UIntToOH, log2Ceil, OHToUInt, Mux1H, IrrevocableIO} + +import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, BufferParams} +import freechips.rocketchip.tilelink.{TLArbiter, TLXbar, TLFilter, TLFuzzer, TLToAXI4, TLRAMModel} +import freechips.rocketchip.unittest.{UnitTest, UnitTestModule} +import freechips.rocketchip.util.BundleField /** * AXI4 Crossbar. It connects multiple AXI4 masters to slaves. @@ -85,7 +89,12 @@ class AXI4Xbar( // Transform input bundles val in = Wire(Vec(io_in.size, new AXI4Bundle(wide_bundle))) for (i <- 0 until in.size) { - in(i).squeezeAll :<>= io_in(i).squeezeAll + in(i).aw.bits.user := DontCare + in(i).aw.bits.echo := DontCare + in(i).ar.bits.user := DontCare + in(i).ar.bits.echo := DontCare + in(i).w.bits.user := DontCare + in(i).squeezeAll.waiveAll :<>= io_in(i).squeezeAll.waiveAll // Handle size = 1 gracefully (Chisel3 empty range is broken) def trim(id: UInt, size: Int) = if (size <= 1) 0.U else id(log2Ceil(size)-1, 0) @@ -168,7 +177,9 @@ class AXI4Xbar( // Transform output bundles val out = Wire(Vec(io_out.size, new AXI4Bundle(wide_bundle))) for (i <- 0 until out.size) { - io_out(i).squeezeAll :<>= out(i).squeezeAll + out(i).b.bits.user := DontCare + out(i).r.bits.user := DontCare + io_out(i).squeezeAll.waiveAll :<>= out(i).squeezeAll.waiveAll if (io_in.size > 1) { // Block AW if we cannot record the W source diff --git a/src/main/scala/amba/axi4/package.scala b/src/main/scala/amba/axi4/package.scala index d1673572f5b..57a5e8759e1 100644 --- a/src/main/scala/amba/axi4/package.scala +++ b/src/main/scala/amba/axi4/package.scala @@ -2,8 +2,10 @@ package freechips.rocketchip.amba -import freechips.rocketchip.diplomacy.{HasClockDomainCrossing, _} -import freechips.rocketchip.prci.{HasResetDomainCrossing} +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SimpleNodeHandle, OutwardNodeHandle, InwardNodeHandle} + +import freechips.rocketchip.prci.{HasClockDomainCrossing, HasResetDomainCrossing} /** * Provide bundles, adapters and devices etc for AMBA AXI4 protocol. @@ -15,15 +17,15 @@ package object axi4 type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] implicit class AXI4ClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal { - def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardClockCrossingHelper(valName.name, x, n) - def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardClockCrossingHelper(valName.name, x, n) + def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardClockCrossingHelper(valName.value, x, n) + def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardClockCrossingHelper(valName.value, x, n) def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n) def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n) } implicit class AXI4ResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal { - def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardResetCrossingHelper(valName.name, x, n) - def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardResetCrossingHelper(valName.name, x, n) + def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardResetCrossingHelper(valName.value, x, n) + def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardResetCrossingHelper(valName.value, x, n) def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n) def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n) } diff --git a/src/main/scala/amba/axis/Buffer.scala b/src/main/scala/amba/axis/Buffer.scala index a9ea9198d17..4ba04c950b8 100644 --- a/src/main/scala/amba/axis/Buffer.scala +++ b/src/main/scala/amba/axis/Buffer.scala @@ -2,8 +2,10 @@ package freechips.rocketchip.amba.axis -import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.diplomacy.BufferParams class AXISBuffer(val params: BufferParams)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/amba/axis/Nodes.scala b/src/main/scala/amba/axis/Nodes.scala index a82a2e2601b..133f79985a9 100644 --- a/src/main/scala/amba/axis/Nodes.scala +++ b/src/main/scala/amba/axis/Nodes.scala @@ -3,8 +3,10 @@ package freechips.rocketchip.amba.axis import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.ValName +import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp, SourceNode, SinkNode, NexusNode, AdapterNode, OutwardNode, IdentityNode, RenderedEdge, InwardNode} object AXISImp extends SimpleNodeImp[AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle] { diff --git a/src/main/scala/amba/axis/Parameters.scala b/src/main/scala/amba/axis/Parameters.scala index ea97a941e5c..bcc928bf36e 100644 --- a/src/main/scala/amba/axis/Parameters.scala +++ b/src/main/scala/amba/axis/Parameters.scala @@ -1,11 +1,16 @@ // See LICENSE.SiFive for license details. package freechips.rocketchip.amba.axis -import chisel3.util._ import chisel3.experimental.SourceInfo +import chisel3.util.{isPow2, log2Ceil} + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.nodes.BaseNode + +import freechips.rocketchip.diplomacy.{TransferSizes, IdRange} +import freechips.rocketchip.resources.{Resource} +import freechips.rocketchip.util.{BundleFieldBase, BundleField} + class AXISSlaveParameters private ( val name: String, diff --git a/src/main/scala/amba/axis/Xbar.scala b/src/main/scala/amba/axis/Xbar.scala index 7338bb4287c..cf154028f9c 100644 --- a/src/main/scala/amba/axis/Xbar.scala +++ b/src/main/scala/amba/axis/Xbar.scala @@ -3,10 +3,12 @@ package freechips.rocketchip.amba.axis import chisel3._ -import chisel3.util._ -import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import chisel3.util.{Cat, log2Ceil, Mux1H} + +import org.chipsalliance.cde.config.{Config, Parameters} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} + +import freechips.rocketchip.tilelink.{TLXbar, TLArbiter} class AXISXbar(beatBytes: Int, policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/amba/axis/package.scala b/src/main/scala/amba/axis/package.scala index 07183b86975..00500055acd 100644 --- a/src/main/scala/amba/axis/package.scala +++ b/src/main/scala/amba/axis/package.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.amba -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, NodeHandle} package object axis { diff --git a/src/main/scala/amba/package.scala b/src/main/scala/amba/package.scala index 2af015abd9b..75a971c7f75 100644 --- a/src/main/scala/amba/package.scala +++ b/src/main/scala/amba/package.scala @@ -3,7 +3,8 @@ package freechips.rocketchip import chisel3._ -import freechips.rocketchip.util._ + +import freechips.rocketchip.util.{ControlKey, DataKey, BundleField} package object amba { class AMBAProtBundle extends Bundle { @@ -31,4 +32,4 @@ package object amba { // Used to convert a TileLink corrupt signal into an AMBA user bit case object AMBACorrupt extends DataKey[Bool]("corrupt") case class AMBACorruptField() extends BundleField[Bool](AMBACorrupt, Output(Bool()), x => x := false.B) -} \ No newline at end of file +} diff --git a/src/main/scala/aop/Select.scala b/src/main/scala/aop/Select.scala deleted file mode 100644 index 132b859ed12..00000000000 --- a/src/main/scala/aop/Select.scala +++ /dev/null @@ -1,121 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.aop - -import chisel3.Data -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{ - AnyMixedNode, - BaseNode, - InwardNode, - LazyModule, - MixedNode, - OutwardNode, -} - -/** Combinators for finding specific sets of [[LazyModule]]s/[[Node]]s. - * - * These can be used for e.g. finding specific TLBundles in a design and - * placing monitors or annotating metadata. - */ -object Select { - - /** Contains information about an inward edge of a node - */ - case class InwardEdge[Bundle <: Data, EdgeInParams]( - params: Parameters, - bundle: Bundle, - edge: EdgeInParams, - node: OutwardNode[_, _, Bundle], - ) - - /** Contains information about an outward edge of a node - */ - case class OutwardEdge[Bundle <: Data, EdgeOutParams]( - params: Parameters, - bundle: Bundle, - edge: EdgeOutParams, - node: InwardNode[_, _, Bundle], - ) - - /** Collects the [[InwardEdge]]s of a node. Defined as a separate method so - * that the bundle/edge types can be set properly - */ - private def getInwardEdges[BI <: Data, EI](node: MixedNode[_, _, EI, BI, _, _, _, _ <: Data]): Iterable[InwardEdge[BI, EI]] = { - node.iPorts.zip(node.in).map { - case ((_, node, params, _), (bundle, edge)) => - InwardEdge(params, bundle, edge, node) - } - } - - /** Applies the collect function to each [[InwardEdge]] of a node - */ - def collectInwardEdges[T](node: BaseNode)(collect: PartialFunction[InwardEdge[_ <: Data, _], T]): Iterable[T] = { - node match { - case node: AnyMixedNode => getInwardEdges(node).collect(collect) - case _ => Seq.empty - } - } - - /** Collects the [[OutwardEdge]]s of a node. Defined as a separate method so - * that the bundle/edge types can be set properly - */ - private def getOutwardEdges[BO <: Data, EO](node: MixedNode[_, _, _, _ <: Data, _, _, EO, BO]): Iterable[OutwardEdge[BO, EO]] = { - node.oPorts.zip(node.out).map { - case ((_, node, params, _), (bundle, edge)) => - OutwardEdge(params, bundle, edge, node) - } - } - - /** Applies the collect function to each [[OutardEdge]] of a node - */ - def collectOutwardEdges[T](node: BaseNode)(collect: PartialFunction[OutwardEdge[_ <: Data, _], T]): Iterable[T] = { - node match { - case node: AnyMixedNode => getOutwardEdges(node).collect(collect) - case _ => Seq.empty - } - } - - /** Applies the collect function to a [[LazyModule]] and recursively to all - * of its children. - */ - def collectDeep[T](lmod: LazyModule)(collect: PartialFunction[LazyModule, T]): Iterable[T] = { - collect.lift(lmod) ++ - lmod.getChildren.flatMap { child => - collectDeep(child)(collect) - } - } - - /** Applies the collect function to a [[LazyModule]] and its children if the - * filter function returns true. Stops recursing when the filter function - * returns false. e.g. - * for this hierarchy - * A - * / \ - * B C - * / \ \ - * D E F - * - * the following select function - * {{{ - * filterCollectDeep(A) { - * case B => false - * case _ => true - * } { m => - * printl(m) - * } - * }}} - * - * will only print modules A, C, and F - */ - def filterCollectDeep[T](lmod: LazyModule)(filter: LazyModule => Boolean)(collect: PartialFunction[LazyModule, T]): Iterable[T] = { - if (filter(lmod)) { - collect.lift(lmod) ++ - lmod.getChildren.flatMap { child => - filterCollectDeep(child)(filter)(collect) - } - } else { - Iterable.empty - } - } -} diff --git a/src/main/scala/aop/package.scala b/src/main/scala/aop/package.scala new file mode 100644 index 00000000000..a773e153552 --- /dev/null +++ b/src/main/scala/aop/package.scala @@ -0,0 +1,6 @@ +package freechips.rocketchip + +object aop { + @deprecated("aop has moved to the standalone diplomacy library.", "rocketchip 2.0.0") + val Select = _root_.org.chipsalliance.diplomacy.aop.Select +} diff --git a/src/main/scala/devices/debug/APB.scala b/src/main/scala/devices/debug/APB.scala index 8191bb65835..8397eae8fc2 100644 --- a/src/main/scala/devices/debug/APB.scala +++ b/src/main/scala/devices/debug/APB.scala @@ -1,10 +1,13 @@ // See LICENSE.SiFive for license details. package freechips.rocketchip.devices.debug + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.amba.apb.{APBRegisterNode} +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.apb.APBRegisterNode +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.regmapper.RegField case object APBDebugRegistersKey extends Field[Map[Int, Seq[RegField]]](Map()) diff --git a/src/main/scala/devices/debug/Custom.scala b/src/main/scala/devices/debug/Custom.scala index 22086988a28..b359c01be10 100644 --- a/src/main/scala/devices/debug/Custom.scala +++ b/src/main/scala/devices/debug/Custom.scala @@ -3,11 +3,13 @@ package freechips.rocketchip.devices.debug import chisel3._ +import chisel3.experimental._ import chisel3.util._ -import chisel3.experimental.SourceInfo -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, NexusNode, RenderedEdge, - SimpleNodeImp, SinkNode, SourceNode, ValName} -import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ case class DebugCustomParams( addrs: List[Int], @@ -68,7 +70,7 @@ class DebugCustomXbar( ) lazy val module = new Impl - class Impl extends LazyModuleImp(this) { + class Impl extends LazyRawModuleImp(this) { // require only one sink require(node.out.size == 1, "Must have exactly one sink node, not ${node.out.size}") // send address to all sources diff --git a/src/main/scala/devices/debug/DMI.scala b/src/main/scala/devices/debug/DMI.scala index 014b838bfc6..eeffdc2917c 100644 --- a/src/main/scala/devices/debug/DMI.scala +++ b/src/main/scala/devices/debug/DMI.scala @@ -4,10 +4,13 @@ package freechips.rocketchip.devices.debug import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.util._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.tilelink.{TLClientNode, TLMasterParameters, TLMasterPortParameters, TLMasterToSlaveTransferSizes} +import freechips.rocketchip.util.ParameterizedBundle /** Constant values used by both Debug Bus Response & Request */ diff --git a/src/main/scala/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala index fec2caa14a3..efaf345fb5f 100755 --- a/src/main/scala/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -5,24 +5,29 @@ package freechips.rocketchip.devices.debug import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.apb.{APBFanout, APBToTL} +import freechips.rocketchip.devices.debug.systembusaccess.{SBToTL, SystemBusAccessModule} +import freechips.rocketchip.devices.tilelink.{DevNullParams, TLBusBypass, TLError} +import freechips.rocketchip.diplomacy.{AddressSet, BufferParams} +import freechips.rocketchip.resources.{Description, Device, Resource, ResourceBindings, ResourceString, SimpleDevice} +import freechips.rocketchip.interrupts.{IntNexusNode, IntSinkParameters, IntSinkPortParameters, IntSourceParameters, IntSourcePortParameters, IntSyncCrossingSource, IntSyncIdentityNode} +import freechips.rocketchip.regmapper.{RegField, RegFieldAccessType, RegFieldDesc, RegFieldGroup, RegFieldWrType, RegReadFn, RegWriteFn} import freechips.rocketchip.rocket.{CSRs, Instructions} import freechips.rocketchip.tile.MaxHartIdBits -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError} -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.util._ -import freechips.rocketchip.devices.debug.systembusaccess._ -import freechips.rocketchip.devices.tilelink.TLBusBypass -import freechips.rocketchip.amba.apb.{APBToTL, APBFanout} +import freechips.rocketchip.tilelink.{TLAsyncCrossingSink, TLAsyncCrossingSource, TLBuffer, TLRegisterNode, TLXbar} +import freechips.rocketchip.util.{Annotated, AsyncBundle, AsyncQueueParams, AsyncResetSynchronizerShiftReg, FromAsyncBundle, ParameterizedBundle, ResetSynchronizerShiftReg, ToAsyncBundle} + +import freechips.rocketchip.util.SeqBoolBitwiseOps +import freechips.rocketchip.util.SeqToAugmentedSeq import freechips.rocketchip.util.BooleanToAugmentedBoolean object DsbBusConsts { def sbAddrWidth = 12 - def sbIdWidth = 10 - + def sbIdWidth = 10 } object DsbRegAddrs{ @@ -667,7 +672,7 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La val cfg = p(DebugModuleKey).get - val dmiXbar = LazyModule (new TLXbar()) + val dmiXbar = LazyModule (new TLXbar(nameSuffix = Some("dmixbar"))) val dmi2tlOpt = (!p(ExportDebug).apb).option({ val dmi2tl = LazyModule(new DMIToTL()) @@ -693,7 +698,8 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La }) val dmOuter = LazyModule( new TLDebugModuleOuter(device)) - val intnode = IntSyncCrossingSource(alreadyRegistered = true) :*= dmOuter.intnode + val intnode = IntSyncIdentityNode() + intnode :*= IntSyncCrossingSource(alreadyRegistered = true) :*= dmOuter.intnode val dmiBypass = LazyModule(new TLBusBypass(beatBytes=4, bufferError=false, maxAtomic=0, maxTransfer=4)) val dmiInnerNode = TLAsyncCrossingSource() := dmiBypass.node := dmiXbar.node @@ -727,6 +733,7 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La childClock := io.dmi_clock childReset := io.dmi_reset + override def provideImplicitClockToLazyChildren = true withClockAndReset(childClock, childReset) { dmi2tlOpt.foreach { _.module.io.dmi <> io.dmi.get } @@ -916,7 +923,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I // Outer.hamask doesn't consider the hart selected by dmcontrol.hartsello, // so append it here when (selectedHartReg < nComponents.U) { - hamaskFull(selectedHartReg) := true.B + hamaskFull(if (nComponents == 1) 0.U(0.W) else selectedHartReg) := true.B } io.innerCtrl.ready := true.B @@ -1040,7 +1047,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I } } } - DMCS2RdData.haltgroup := hgParticipateHart(selectedHartReg) + DMCS2RdData.haltgroup := hgParticipateHart(if (nComponents == 1) 0.U(0.W) else selectedHartReg) if (nExtTriggers > 0) { val hgSelect = Reg(Bool()) @@ -1724,7 +1731,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I // This is not an initialization! val ctrlStateReg = Reg(chiselTypeOf(CtrlState(Waiting))) - val hartHalted = haltedBitRegs(selectedHartReg) + val hartHalted = haltedBitRegs(if (nComponents == 1) 0.U(0.W) else selectedHartReg) val ctrlStateNxt = WireInit(ctrlStateReg) //------------------------ @@ -1898,6 +1905,7 @@ class TLDebugModuleInnerAsync(device: Device, getNComponents: () => Int, beatByt childClock := io.debug_clock childReset := io.debug_reset + override def provideImplicitClockToLazyChildren = true val dmactive_synced = withClockAndReset(childClock, childReset) { val dmactive_synced = AsyncResetSynchronizerShiftReg(in=io.dmactive, sync=3, name=Some("dmactiveSync")) @@ -1986,6 +1994,7 @@ class TLDebugModule(beatBytes: Int)(implicit p: Parameters) extends LazyModule { childClock := io.tl_clock childReset := io.tl_reset + override def provideImplicitClockToLazyChildren = true dmOuter.module.io.dmi.foreach { dmOuterDMI => dmOuterDMI <> io.dmi.get.dmi diff --git a/src/main/scala/devices/debug/Periphery.scala b/src/main/scala/devices/debug/Periphery.scala index 8d015a08169..8aa3214af9b 100644 --- a/src/main/scala/devices/debug/Periphery.scala +++ b/src/main/scala/devices/debug/Periphery.scala @@ -3,18 +3,21 @@ package freechips.rocketchip.devices.debug import chisel3._ -import chisel3.experimental.{IntParam, noPrefix} +import chisel3.experimental.{noPrefix, IntParam} import chisel3.util._ -import chisel3.util.HasBlackBoxResource -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.amba.apb._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.jtag._ -import freechips.rocketchip.util._ -import freechips.rocketchip.prci.{ClockSinkParameters, ClockSinkNode} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.interrupts.{NullIntSyncSource, IntSyncXbar} + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.apb.{APBBundle, APBBundleParameters, APBMasterNode, APBMasterParameters, APBMasterPortParameters} +import freechips.rocketchip.interrupts.{IntSyncXbar, NullIntSyncSource} +import freechips.rocketchip.jtag.JTAGIO +import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters} +import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, FBUS, ResetSynchronous, SubsystemResetSchemeKey, TLBusWrapperLocation} +import freechips.rocketchip.tilelink.{TLFragmenter, TLWidthWidget} +import freechips.rocketchip.util.{AsyncResetSynchronizerShiftReg, CanHavePSDTestModeIO, ClockGate, PSDTestMode, PlusArg, ResetSynchronizerShiftReg} + +import freechips.rocketchip.util.BooleanToAugmentedBoolean /** Protocols used for communicating with external debugging tools */ sealed trait DebugExportProtocol @@ -84,7 +87,7 @@ trait HasPeripheryDebug { this: BaseSubsystem => lazy val debugOpt = p(DebugModuleKey).map { params => val tlDM = LazyModule(new TLDebugModule(tlbus.beatBytes)) - tlDM.node := tlbus.coupleTo("debug"){ TLFragmenter(tlbus) := _ } + tlDM.node := tlbus.coupleTo("debug"){ TLFragmenter(tlbus.beatBytes, tlbus.blockBytes, nameSuffix = Some("Debug")) := _ } tlDM.dmInner.dmInner.customNode := debugCustomXbarOpt.get.node (apbDebugNodeOpt zip tlDM.apbNodeOpt) foreach { case (master, slave) => @@ -99,7 +102,7 @@ trait HasPeripheryDebug { this: BaseSubsystem => tlDM } - lazy val debugNode = debugOpt.map(_.intnode).getOrElse(IntSyncXbar() := NullIntSyncSource()) + val debugNode = debugOpt.map(_.intnode) val psd = InModuleBody { val psd = IO(new PSDIO) @@ -323,6 +326,9 @@ object Debug { debug.clockeddmi.foreach { d => d.dmi.req.valid := false.B + d.dmi.req.bits.addr := 0.U + d.dmi.req.bits.data := 0.U + d.dmi.req.bits.op := 0.U d.dmi.resp.ready := true.B d.dmiClock := false.B.asClock d.dmiReset := true.B.asAsyncReset @@ -344,6 +350,7 @@ object Debug { t.out.ack := t.out.req } debug.disableDebug.foreach { x => x := false.B } + debug.dmactiveAck := false.B debug.ndreset }.getOrElse(false.B) } diff --git a/src/main/scala/devices/debug/SBA.scala b/src/main/scala/devices/debug/SBA.scala index f35b27ac05a..568291a221f 100644 --- a/src/main/scala/devices/debug/SBA.scala +++ b/src/main/scala/devices/debug/SBA.scala @@ -4,13 +4,16 @@ package freechips.rocketchip.devices.debug.systembusaccess import chisel3._ import chisel3.util._ -import freechips.rocketchip.amba._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} +import freechips.rocketchip.devices.debug.{DebugModuleKey, RWNotify, SBCSFields, WNotifyVal} +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup, RegFieldWrType} +import freechips.rocketchip.tilelink.{TLClientNode, TLMasterParameters, TLMasterPortParameters} import freechips.rocketchip.util.property -import freechips.rocketchip.devices.debug._ object SystemBusAccessState extends scala.Enumeration { type SystemBusAccessState = Value @@ -304,7 +307,7 @@ class SBToTL(implicit p: Parameters) extends LazyModule { val counter = RegInit(0.U((log2Ceil(cfg.maxSupportedSBAccess/8)+1).W)) val vecData = Wire(Vec(cfg.maxSupportedSBAccess/8, UInt(8.W))) vecData.zipWithIndex.map { case (vd, i) => vd := io.dataIn(8*i+7,8*i) } - muxedData := vecData(counter) + muxedData := vecData(counter(log2Ceil(vecData.size)-1,0)) // Need an additional check to determine if address is safe for Get/Put val rdLegal_addr = edge.manager.supportsGetSafe(io.addrIn, io.sizeIn, Some(TransferSizes(1,cfg.maxSupportedSBAccess/8))) diff --git a/src/main/scala/devices/tilelink/BootROM.scala b/src/main/scala/devices/tilelink/BootROM.scala index 9ffdac9e65e..7cbfcca6df8 100644 --- a/src/main/scala/devices/tilelink/BootROM.scala +++ b/src/main/scala/devices/tilelink/BootROM.scala @@ -3,12 +3,16 @@ package freechips.rocketchip.devices.tilelink import chisel3._ -import chisel3.util.log2Ceil -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.subsystem.{BaseSubsystem, HierarchicalLocation, HasTiles, TLBusWrapperLocation} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.prci.{ClockSinkDomain} +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{Resource, SimpleDevice} +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.tilelink.{TLFragmenter, TLManagerNode, TLSlaveParameters, TLSlavePortParameters} import java.nio.ByteBuffer import java.nio.file.{Files, Paths} @@ -66,11 +70,10 @@ object BootROM { * at a configurable location, but also drives the tiles' reset vectors to point * at its 'hang' address parameter value. */ - def attach(params: BootROMParams, subsystem: BaseSubsystem with HasTiles, where: TLBusWrapperLocation) + def attach(params: BootROMParams, subsystem: BaseSubsystem with HasHierarchicalElements with HasTileInputConstants, where: TLBusWrapperLocation) (implicit p: Parameters): TLROM = { val tlbus = subsystem.locateTLBusWrapper(where) - val bootROMDomainWrapper = LazyModule(new ClockSinkDomain(take = None)) - bootROMDomainWrapper.clockNode := tlbus.fixedClockNode + val bootROMDomainWrapper = tlbus.generateSynchronousDomain("BootROM").suggestName("bootrom_domain") val bootROMResetVectorSourceNode = BundleBridgeSource[UInt]() lazy val contents = { @@ -83,7 +86,7 @@ object BootROM { LazyModule(new TLROM(params.address, params.size, contents, true, tlbus.beatBytes)) } - bootrom.node := tlbus.coupleTo("bootrom"){ TLFragmenter(tlbus) := _ } + bootrom.node := tlbus.coupleTo("bootrom"){ TLFragmenter(tlbus, Some("BootROM")) := _ } // Drive the `subsystem` reset vector to the `hang` address of this Boot ROM. subsystem.tileResetVectorNexusNode := bootROMResetVectorSourceNode InModuleBody { diff --git a/src/main/scala/devices/tilelink/BusBlocker.scala b/src/main/scala/devices/tilelink/BusBlocker.scala index e86505826c2..60707b8f33b 100644 --- a/src/main/scala/devices/tilelink/BusBlocker.scala +++ b/src/main/scala/devices/tilelink/BusBlocker.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.devices.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, SimpleDevice} + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.regmapper.{RegField, RegFieldDesc} -import freechips.rocketchip.tilelink.{TLFragmenter, TLRegisterNode, TLBusWrapper, TLNameNode, TLNode} +import freechips.rocketchip.tilelink.{TLBusWrapper, TLFragmenter, TLNameNode, TLNode, TLRegisterNode} /** Parameterize a BasicBusBlocker. * diff --git a/src/main/scala/devices/tilelink/CLINT.scala b/src/main/scala/devices/tilelink/CLINT.scala index 8156706ee8d..81c7051ae46 100644 --- a/src/main/scala/devices/tilelink/CLINT.scala +++ b/src/main/scala/devices/tilelink/CLINT.scala @@ -3,14 +3,18 @@ package freechips.rocketchip.devices.tilelink import chisel3._ -import chisel3.util.ShiftRegister -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{Resource, SimpleDevice} +import freechips.rocketchip.interrupts.{IntNexusNode, IntSinkParameters, IntSinkPortParameters, IntSourceParameters, IntSourcePortParameters} +import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup} +import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, TLBusWrapperLocation} +import freechips.rocketchip.tilelink.{TLFragmenter, TLRegisterNode} +import freechips.rocketchip.util.Annotated object CLINTConsts { @@ -102,18 +106,17 @@ class CLINT(params: CLINTParams, beatBytes: Int)(implicit p: Parameters) extends /** Trait that will connect a CLINT to a subsystem */ trait CanHavePeripheryCLINT { this: BaseSubsystem => - val clintOpt = p(CLINTKey).map { params => + val (clintOpt, clintDomainOpt, clintTickOpt) = p(CLINTKey).map { params => val tlbus = locateTLBusWrapper(p(CLINTAttachKey).slaveWhere) - val clint = LazyModule(new CLINT(params, cbus.beatBytes)) - clint.node := tlbus.coupleTo("clint") { TLFragmenter(tlbus) := _ } - - // Override the implicit clock and reset -- could instead include a clockNode in the clint, and make it a RawModuleImp? - InModuleBody { - clint.module.clock := tlbus.module.clock - clint.module.reset := tlbus.module.reset - } - - clint - - } + val clintDomainWrapper = tlbus.generateSynchronousDomain("CLINT").suggestName("clint_domain") + val clint = clintDomainWrapper { LazyModule(new CLINT(params, tlbus.beatBytes)) } + clintDomainWrapper { clint.node := tlbus.coupleTo("clint") { TLFragmenter(tlbus, Some("CLINT")) := _ } } + val clintTick = clintDomainWrapper { InModuleBody { + val tick = IO(Input(Bool())) + clint.module.io.rtcTick := tick + tick + }} + + (clint, clintDomainWrapper, clintTick) + }.unzip3 } diff --git a/src/main/scala/devices/tilelink/CanHaveBuiltInDevices.scala b/src/main/scala/devices/tilelink/CanHaveBuiltInDevices.scala index 96ba3def845..6fad3f637d0 100644 --- a/src/main/scala/devices/tilelink/CanHaveBuiltInDevices.scala +++ b/src/main/scala/devices/tilelink/CanHaveBuiltInDevices.scala @@ -2,9 +2,11 @@ package freechips.rocketchip.devices.tilelink -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, BufferParams} +import freechips.rocketchip.tilelink.{HasTLBusParams, TLBuffer, TLCacheCork, TLCacheCorkParams, TLFragmenter, TLOutwardNode, TLTempNode} case class BuiltInZeroDeviceParams( addr: AddressSet, @@ -63,4 +65,3 @@ object BuiltInDevices { trait CanHaveBuiltInDevices { def builtInDevices: BuiltInDevices } - diff --git a/src/main/scala/devices/tilelink/ClockBlocker.scala b/src/main/scala/devices/tilelink/ClockBlocker.scala index 9076b6b08b0..6ee0f482288 100644 --- a/src/main/scala/devices/tilelink/ClockBlocker.scala +++ b/src/main/scala/devices/tilelink/ClockBlocker.scala @@ -3,12 +3,15 @@ package freechips.rocketchip.devices.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.prci.ClockAdapterNode +import freechips.rocketchip.regmapper.{RegField, RegFieldDesc} +import freechips.rocketchip.tilelink.TLRegisterNode +import freechips.rocketchip.util.ClockGate /** This device extends a basic bus blocker by allowing it to gate the clocks of the device * whose tilelink port is being blocked. For now it is only possible to block diff --git a/src/main/scala/devices/tilelink/Deadlock.scala b/src/main/scala/devices/tilelink/Deadlock.scala index 3756d94c61e..0d5e970b216 100644 --- a/src/main/scala/devices/tilelink/Deadlock.scala +++ b/src/main/scala/devices/tilelink/Deadlock.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.resources.{SimpleDevice} /** Adds a /dev/null slave that does not raise ready for any incoming traffic. * !!! WARNING: This device WILL cause your bus to deadlock for as long as you diff --git a/src/main/scala/devices/tilelink/DevNull.scala b/src/main/scala/devices/tilelink/DevNull.scala index 8b2eab69901..9d3462e715c 100644 --- a/src/main/scala/devices/tilelink/DevNull.scala +++ b/src/main/scala/devices/tilelink/DevNull.scala @@ -2,9 +2,15 @@ package freechips.rocketchip.devices.tilelink -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.prci.{HasClockDomainCrossing} +import freechips.rocketchip.tilelink.{TLManagerNode, TLSlaveParameters, TLSlavePortParameters} + +import freechips.rocketchip.tilelink.TLClockDomainCrossing case class DevNullParams( address: Seq[AddressSet], diff --git a/src/main/scala/devices/tilelink/Error.scala b/src/main/scala/devices/tilelink/Error.scala index dd6541d20f8..cb048c3aab3 100644 --- a/src/main/scala/devices/tilelink/Error.scala +++ b/src/main/scala/devices/tilelink/Error.scala @@ -4,9 +4,12 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.resources.SimpleDevice +import freechips.rocketchip.tilelink.{TLArbiter, TLMessages, TLPermissions} /** Adds a /dev/null slave that generates TL error response messages */ class TLError(params: DevNullParams, buffer: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) @@ -57,7 +60,7 @@ class TLError(params: DevNullParams, buffer: Boolean = true, beatBytes: Int = 4) // ReleaseAck is not allowed to report failure dc.bits.opcode := ReleaseAck - dc.bits.param := VecInit(toB, toN, toN)(c.bits.param) + dc.bits.param := VecInit(toB, toN, toN)(c.bits.param(1,0)) dc.bits.size := c.bits.size dc.bits.source := c.bits.source dc.bits.sink := 0.U diff --git a/src/main/scala/devices/tilelink/MaskROM.scala b/src/main/scala/devices/tilelink/MaskROM.scala index f4169a85a84..8a01ec5fd7b 100644 --- a/src/main/scala/devices/tilelink/MaskROM.scala +++ b/src/main/scala/devices/tilelink/MaskROM.scala @@ -4,11 +4,17 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{RegionType, AddressSet, TransferSizes} +import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.subsystem.{Attachable, HierarchicalLocation, TLBusWrapperLocation} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import freechips.rocketchip.tilelink.{TLFragmenter, TLManagerNode, TLSlaveParameters, TLSlavePortParameters, TLWidthWidget} +import freechips.rocketchip.util.{ROMConfig, ROMGenerator} + +import freechips.rocketchip.util.DataToAugmentedData case class MaskROMParams(address: BigInt, name: String, depth: Int = 2048, width: Int = 32) diff --git a/src/main/scala/devices/tilelink/MasterMux.scala b/src/main/scala/devices/tilelink/MasterMux.scala index 3ebedcde084..c1ddf82477b 100644 --- a/src/main/scala/devices/tilelink/MasterMux.scala +++ b/src/main/scala/devices/tilelink/MasterMux.scala @@ -3,9 +3,17 @@ package freechips.rocketchip.devices.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} +import freechips.rocketchip.tilelink.{ + LFSR64, TLBundleA, TLBundleC, TLBundleE, TLClientNode, TLCustomNode, TLFilter, TLFragmenter, + TLFuzzer, TLMasterParameters, TLMasterPortParameters, TLPermissions, TLRAM, TLRAMModel, + TLSlaveParameters, TLSlavePortParameters +} class MasterMuxNode(uFn: Seq[TLMasterPortParameters] => TLMasterPortParameters)(implicit valName: ValName) extends TLCustomNode { diff --git a/src/main/scala/devices/tilelink/PhysicalFilter.scala b/src/main/scala/devices/tilelink/PhysicalFilter.scala index 1c52bffca83..c56bfeb4bc3 100644 --- a/src/main/scala/devices/tilelink/PhysicalFilter.scala +++ b/src/main/scala/devices/tilelink/PhysicalFilter.scala @@ -4,11 +4,16 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup, RegFieldWrType, RegReadFn, RegWriteFn} +import freechips.rocketchip.tilelink.{TLAdapterNode, TLMessages, TLPermissions, TLRegisterNode} + +import freechips.rocketchip.util.DataToAugmentedData case class DevicePMPParams(addressBits: Int, pageBits: Int) @@ -235,7 +240,7 @@ class PhysicalFilter(params: PhysicalFilterParams)(implicit p: Parameters) exten // Frame an appropriate deny message val denyValid = RegInit(false.B) - val deny = Reg(in.d.bits) + val deny = Reg(chiselTypeOf(in.d.bits)) val d_opcode = TLMessages.adResponse(in.a.bits.opcode) val d_grant = edgeIn.manager.anySupportAcquireB.B && deny.opcode === TLMessages.Grant when (in.a.valid && !allow && deny_ready && a_first) { @@ -257,7 +262,7 @@ class PhysicalFilter(params: PhysicalFilterParams)(implicit p: Parameters) exten } } - val out_d = Wire(in.d.bits) + val out_d = Wire(chiselTypeOf(in.d.bits)) out_d := out.d.bits // Deny can have unconditional priority, because the only out.d message possible is diff --git a/src/main/scala/devices/tilelink/Plic.scala b/src/main/scala/devices/tilelink/Plic.scala index 3e6de570423..75cf30edf4b 100644 --- a/src/main/scala/devices/tilelink/Plic.scala +++ b/src/main/scala/devices/tilelink/Plic.scala @@ -3,20 +3,25 @@ package freechips.rocketchip.devices.tilelink import chisel3._ +import chisel3.experimental._ import chisel3.util._ -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property -import freechips.rocketchip.prci.{ClockSinkDomain} -import chisel3.experimental.SourceInfo + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{Description, Resource, ResourceBinding, ResourceBindings, ResourceInt, SimpleDevice} +import freechips.rocketchip.interrupts.{IntNexusNode, IntSinkParameters, IntSinkPortParameters, IntSourceParameters, IntSourcePortParameters} +import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldRdAction, RegFieldWrType, RegReadFn, RegWriteFn} +import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, TLBusWrapperLocation} +import freechips.rocketchip.tilelink.{TLFragmenter, TLRegisterNode} +import freechips.rocketchip.util.{Annotated, MuxT, property} import scala.math.min +import freechips.rocketchip.util.UIntToAugmentedUInt +import freechips.rocketchip.util.SeqToAugmentedSeq + class GatewayPLICIO extends Bundle { val valid = Output(Bool()) val ready = Input(Bool()) @@ -355,15 +360,14 @@ class PLICFanIn(nDevices: Int, prioBits: Int) extends Module { /** Trait that will connect a PLIC to a subsystem */ trait CanHavePeripheryPLIC { this: BaseSubsystem => - val plicOpt = p(PLICKey).map { params => + val (plicOpt, plicDomainOpt) = p(PLICKey).map { params => val tlbus = locateTLBusWrapper(p(PLICAttachKey).slaveWhere) - val plicDomainWrapper = LazyModule(new ClockSinkDomain(take = None)) - plicDomainWrapper.clockNode := tlbus.fixedClockNode + val plicDomainWrapper = tlbus.generateSynchronousDomain("PLIC").suggestName("plic_domain") val plic = plicDomainWrapper { LazyModule(new TLPLIC(params, tlbus.beatBytes)) } - plic.node := tlbus.coupleTo("plic") { TLFragmenter(tlbus) := _ } - plic.intnode :=* ibus.toPLIC + plicDomainWrapper { plic.node := tlbus.coupleTo("plic") { TLFragmenter(tlbus, Some("PLIC")) := _ } } + plicDomainWrapper { plic.intnode :=* ibus.toPLIC } - plic - } + (plic, plicDomainWrapper) + }.unzip } diff --git a/src/main/scala/devices/tilelink/TestRAM.scala b/src/main/scala/devices/tilelink/TestRAM.scala index 9fcb9a02d12..368c176a9ee 100644 --- a/src/main/scala/devices/tilelink/TestRAM.scala +++ b/src/main/scala/devices/tilelink/TestRAM.scala @@ -4,9 +4,13 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{MemoryDevice} +import freechips.rocketchip.tilelink.{TLDelayer, TLFuzzer, TLManagerNode, TLMessages, TLRAMModel, TLSlaveParameters, TLSlavePortParameters} // Do not use this for synthesis! Only for simulation. class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, trackCorruption: Boolean = true)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/devices/tilelink/Zero.scala b/src/main/scala/devices/tilelink/Zero.scala index 2d542b99b86..0e248479f70 100644 --- a/src/main/scala/devices/tilelink/Zero.scala +++ b/src/main/scala/devices/tilelink/Zero.scala @@ -4,8 +4,12 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType} +import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.tilelink.TLMessages /** This /dev/null device accepts single beat gets/puts, as well as atomics. diff --git a/src/main/scala/diplomacy/AddressRange.scala b/src/main/scala/diplomacy/AddressRange.scala index c6d55766932..0235d393a50 100644 --- a/src/main/scala/diplomacy/AddressRange.scala +++ b/src/main/scala/diplomacy/AddressRange.scala @@ -60,21 +60,3 @@ object AddressRange def subtract(from: Seq[AddressRange], take: Seq[AddressRange]): Seq[AddressRange] = take.foldLeft(from) { case (left, r) => left.flatMap { _.subtract(r) } } } - -case class AddressMapEntry(range: AddressRange, permissions: ResourcePermissions, names: Seq[String]) { - val ResourcePermissions(r, w, x, c, a) = permissions - - def toString(aw: Int) = s"\t%${aw}x - %${aw}x %c%c%c%c%c %s".format( - range.base, - range.base+range.size, - if (a) 'A' else ' ', - if (r) 'R' else ' ', - if (w) 'W' else ' ', - if (x) 'X' else ' ', - if (c) 'C' else ' ', - names.mkString(", ")) - - def toJSON = s"""{"base":[${range.base}],"size":[${range.size}],""" + - s""""r":[$r],"w":[$w],"x":[$x],"c":[$c],"a":[$a],""" + - s""""names":[${names.map('"'+_+'"').mkString(",")}]}""" -} diff --git a/src/main/scala/diplomacy/BundleBridge.scala b/src/main/scala/diplomacy/BundleBridge.scala deleted file mode 100644 index e02d6f4f966..00000000000 --- a/src/main/scala/diplomacy/BundleBridge.scala +++ /dev/null @@ -1,205 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.diplomacy - -import chisel3._ -import chisel3.experimental.{DataMirror, SourceInfo} -import chisel3.experimental.DataMirror.internal.chiselTypeClone -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util.DataToAugmentedData - -case class BundleBridgeParams[T <: Data](genOpt: Option[() => T]) - -case object BundleBridgeParams { - def apply[T <: Data](gen: () => T): BundleBridgeParams[T] = BundleBridgeParams(Some(gen)) -} - -case class BundleBridgeEdgeParams[T <: Data](source: BundleBridgeParams[T], sink: BundleBridgeParams[T]) - -class BundleBridgeImp[T <: Data]() extends SimpleNodeImp[BundleBridgeParams[T], BundleBridgeParams[T], BundleBridgeEdgeParams[T], T] -{ - def edge(pd: BundleBridgeParams[T], pu: BundleBridgeParams[T], p: Parameters, sourceInfo: SourceInfo) = BundleBridgeEdgeParams(pd, pu) - def bundle(e: BundleBridgeEdgeParams[T]): T = { - val sourceOpt = e.source.genOpt.map(_()) - val sinkOpt = e.sink.genOpt.map(_()) - (sourceOpt, sinkOpt) match { - case (None, None) => - throw new Exception("BundleBridge needs source or sink to provide bundle generator function") - case (Some(a), None) => chiselTypeClone(a) - case (None, Some(b)) => chiselTypeClone(b) - case (Some(a), Some(b)) => { - require(DataMirror.checkTypeEquivalence(a, b), - s"BundleBridge requires doubly-specified source and sink generators to have equivalent Chisel Data types, but got \n$a\n vs\n$b") - chiselTypeClone(a) - } - } - } - def render(e: BundleBridgeEdgeParams[T]) = RenderedEdge(colour = "#cccc00" /* yellow */) -} - -case class BundleBridgeSink[T <: Data](genOpt: Option[() => T] = None) - (implicit valName: ValName) - extends SinkNode(new BundleBridgeImp[T])(Seq(BundleBridgeParams(genOpt))) -{ - def bundle: T = in(0)._1 - - private def inferOutput = bundle.getElements.forall { elt => - DataMirror.directionOf(elt) == ActualDirection.Unspecified - } - - def makeIO()(implicit valName: ValName): T = { - val io: T = IO(if (inferOutput) Output(chiselTypeOf(bundle)) else chiselTypeClone(bundle)) - io.suggestName(valName.name) - io <> bundle - io - } - def makeIO(name: String): T = makeIO()(ValName(name)) -} - -object BundleBridgeSink { - def apply[T <: Data]()(implicit valName: ValName): BundleBridgeSink[T] = { - BundleBridgeSink(None) - } -} - -case class BundleBridgeSource[T <: Data](genOpt: Option[() => T] = None)(implicit valName: ValName) extends SourceNode(new BundleBridgeImp[T])(Seq(BundleBridgeParams(genOpt))) -{ - def bundle: T = out(0)._1 - - private def inferInput = bundle.getElements.forall { elt => - DataMirror.directionOf(elt) == ActualDirection.Unspecified - } - - def makeIO()(implicit valName: ValName): T = { - val io: T = IO(if (inferInput) Input(chiselTypeOf(bundle)) else Flipped(chiselTypeClone(bundle))) - io.suggestName(valName.name) - bundle <> io - io - } - def makeIO(name: String): T = makeIO()(ValName(name)) - - private var doneSink = false - def makeSink()(implicit p: Parameters) = { - require (!doneSink, "Can only call makeSink() once") - doneSink = true - val sink = BundleBridgeSink[T]() - sink := this - sink - } -} - -object BundleBridgeSource { - def apply[T <: Data]()(implicit valName: ValName): BundleBridgeSource[T] = { - BundleBridgeSource(None) - } - def apply[T <: Data](gen: () => T)(implicit valName: ValName): BundleBridgeSource[T] = { - BundleBridgeSource(Some(gen)) - } -} - -case class BundleBridgeIdentityNode[T <: Data]()(implicit valName: ValName) extends IdentityNode(new BundleBridgeImp[T])() -case class BundleBridgeEphemeralNode[T <: Data]()(implicit valName: ValName) extends EphemeralNode(new BundleBridgeImp[T])() - -object BundleBridgeNameNode { - def apply[T <: Data](name: String) = BundleBridgeIdentityNode[T]()(ValName(name)) -} - -case class BundleBridgeNexusNode[T <: Data](default: Option[() => T] = None, - inputRequiresOutput: Boolean = false) // when false, connecting a source does not mandate connecting a sink - (implicit valName: ValName) - extends NexusNode(new BundleBridgeImp[T])( - dFn = seq => seq.headOption.getOrElse(BundleBridgeParams(default)), - uFn = seq => seq.headOption.getOrElse(BundleBridgeParams(None)), - inputRequiresOutput = inputRequiresOutput, - outputRequiresInput = !default.isDefined) - -class BundleBridgeNexus[T <: Data]( - inputFn: Seq[T] => T, - outputFn: (T, Int) => Seq[T], - default: Option[() => T] = None, - inputRequiresOutput: Boolean = false, - override val shouldBeInlined: Boolean = true -) (implicit p: Parameters) extends LazyModule -{ - val node = BundleBridgeNexusNode[T](default, inputRequiresOutput) - - lazy val module = new Impl - class Impl extends LazyModuleImp(this) { - val defaultWireOpt = default.map(_()) - val inputs: Seq[T] = node.in.map(_._1) - inputs.foreach { i => require(DataMirror.checkTypeEquivalence(i, inputs.head), - s"${node.context} requires all inputs have equivalent Chisel Data types, but got\n$i\nvs\n${inputs.head}") - } - inputs.flatMap(_.getElements).foreach { elt => DataMirror.directionOf(elt) match { - case ActualDirection.Output => () - case ActualDirection.Unspecified => () - case _ => require(false, s"${node.context} can only be used with Output-directed Bundles") - } } - - val outputs: Seq[T] = if (node.out.size > 0) { - val broadcast: T = if (inputs.size >= 1) inputFn(inputs) else defaultWireOpt.get - outputFn(broadcast, node.out.size) - } else { Nil } - - node.out.map(_._1).foreach { o => require(DataMirror.checkTypeEquivalence(o, outputs.head), - s"${node.context} requires all outputs have equivalent Chisel Data types, but got\n$o\nvs\n${outputs.head}") - } - - require(outputs.size == node.out.size, - s"${node.context} outputFn must generate one output wire per edgeOut, but got ${outputs.size} vs ${node.out.size}") - - node.out.zip(outputs).foreach { case ((out, _), bcast) => out := bcast } - } -} - -object BundleBridgeNexus { - def safeRegNext[T <: Data](x: T): T = { - val reg = Reg(chiselTypeOf(x)) - reg := x - reg - } - - def requireOne[T <: Data](registered: Boolean)(seq: Seq[T]): T = { - require(seq.size == 1, "BundleBroadcast default requires one input") - if (registered) safeRegNext(seq.head) else seq.head - } - - def orReduction[T <: Data](registered: Boolean)(seq: Seq[T]): T = { - val x = seq.reduce((a,b) => (a.asUInt | b.asUInt).asTypeOf(seq.head)) - if (registered) safeRegNext(x) else x - } - - def fillN[T <: Data](registered: Boolean)(x: T, n: Int): Seq[T] = Seq.fill(n) { - if (registered) safeRegNext(x) else x - } - - def apply[T <: Data]( - inputFn: Seq[T] => T = orReduction[T](false) _, - outputFn: (T, Int) => Seq[T] = fillN[T](false) _, - default: Option[() => T] = None, - inputRequiresOutput: Boolean = false, - shouldBeInlined: Boolean = true - )(implicit p: Parameters): BundleBridgeNexusNode[T] = { - val nexus = LazyModule(new BundleBridgeNexus[T](inputFn, outputFn, default, inputRequiresOutput, shouldBeInlined)) - nexus.node - } -} - -object BundleBroadcast { - def apply[T <: Data]( - name: Option[String] = None, - registered: Boolean = false, - default: Option[() => T] = None, - inputRequiresOutput: Boolean = false, // when false, connecting a source does not mandate connecting a sink - shouldBeInlined: Boolean = true - )(implicit p: Parameters): BundleBridgeNexusNode[T] = { - val broadcast = LazyModule(new BundleBridgeNexus[T]( - inputFn = BundleBridgeNexus.requireOne[T](registered) _, - outputFn = BundleBridgeNexus.fillN[T](registered) _, - default = default, - inputRequiresOutput = inputRequiresOutput, - shouldBeInlined = shouldBeInlined)) - name.foreach(broadcast.suggestName(_)) - broadcast.node - } -} diff --git a/src/main/scala/diplomacy/Clone.scala b/src/main/scala/diplomacy/Clone.scala deleted file mode 100644 index 4e0b9209d65..00000000000 --- a/src/main/scala/diplomacy/Clone.scala +++ /dev/null @@ -1,37 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.diplomacy - -import chisel3._ -import chisel3.experimental.{CloneModuleAsRecord, SourceInfo} - -final class CloneLazyModule private (val base: LazyModule) -{ - // Pay special attention to the .iParams and .oParams of the node, which - // indicate the parameters a stand-in master must supply. - def clone[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](node: NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO])(implicit valName: ValName) = - new MixedTestNode(node, this) - - protected[diplomacy] lazy val io = CloneModuleAsRecord(base.module) -} - -object CloneLazyModule -{ - /** The old API **/ - def apply(base: LazyModule) = new CloneLazyModule(base) - - - /** Constructs a [[LazyModule]], but replaces its [[LazyModuleImp]] with a cloned [[LazyModuleImp]] - * from another source. The user of [[CloneLazyModule]] must be careful to guarantee that - * bc and cloneProto have equivalent [[LazyModuleImp]]'s. - * - * @param bc [[LazyModule]] instance to wrap, this instance will not evaluate its own [[LazyModuleImp]] - * @param cloneProto [[LazyModule]] instance which will provide the [[LazyModuleImp]] implementation for bc - */ - def apply[A <: LazyModule, B <: LazyModule](bc: A, cloneProto: B)(implicit valName: ValName, sourceInfo: SourceInfo): A = { - require(LazyModule.scope.isDefined, s"CloneLazyModule ${bc.name} ${sourceLine(sourceInfo)} can only exist as the child of a parent LazyModule") - LazyModule(bc) - bc.cloneProto = Some(cloneProto) - bc - } -} diff --git a/src/main/scala/diplomacy/LazyModule.scala b/src/main/scala/diplomacy/LazyModule.scala deleted file mode 100644 index 5f4da46cb9a..00000000000 --- a/src/main/scala/diplomacy/LazyModule.scala +++ /dev/null @@ -1,612 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.diplomacy - -import chisel3._ -import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -import chisel3.{Module, RawModule, Reset, withClockAndReset} -import chisel3.experimental.{ChiselAnnotation, CloneModuleAsRecord} -import firrtl.passes.InlineAnnotation -import org.chipsalliance.cde.config.Parameters - -import scala.collection.immutable.{SeqMap, SortedMap} -import scala.util.matching._ - -/** While the [[freechips.rocketchip.diplomacy]] package allows fairly abstract parameter negotiation while constructing a DAG, - * [[LazyModule]] builds on top of the DAG annotated with the negotiated parameters and leverage's Scala's lazy evaluation property to split Chisel module generation into two phases: - * - * - Phase 1 (diplomatic) states parameters, hierarchy, and connections: - * - [[LazyModule]] and [[BaseNode]] instantiation. - * - [[BaseNode]] binding. - * - Phase 2 (lazy) generates [[chisel3]] Modules: - * - Parameters are negotiated across [[BaseNode]]s. - * - Concrete [[Bundle]]s are created along [[BaseNode]]s and connected - * - [[AutoBundle]] are automatically connected along [[Edges]], punching IO as necessary though module hierarchy - * - [[LazyModuleImpLike]] generates [[chisel3.Module]]s. - */ -abstract class LazyModule()(implicit val p: Parameters) { - /** Contains sub-[[LazyModule]]s; can be accessed by [[getChildren]]. */ - protected[diplomacy] var children: List[LazyModule] = List[LazyModule]() - /** Contains the [[BaseNode]]s instantiated within this instance. */ - protected[diplomacy] var nodes: List[BaseNode] = List[BaseNode]() - /** Stores [[SourceInfo]] of this instance. - * - * The companion object factory method will set this to the correct value. - */ - protected[diplomacy] var info: SourceInfo = UnlocatableSourceInfo - /** Parent of this LazyModule. If this instance is at the top of the hierarchy, this will be [[None]]. */ - protected[diplomacy] val parent: Option[LazyModule] = LazyModule.scope - /** If set, the LazyModule this LazyModule will be a clone of - * Note that children of a cloned module will also have this set - */ - protected[diplomacy] var cloneProto: Option[LazyModule] = None - - /** Code snippets from [[InModuleBody]] injection. */ - protected[diplomacy] var inModuleBody: List[() => Unit] = List[() => Unit]() - - /** Sequence of ancestor LazyModules, starting with [[parent]]. */ - def parents: Seq[LazyModule] = parent match { - case None => Nil - case Some(x) => x +: x.parents - } - - // Push this instance onto the [[LazyModule.scope]] stack. - LazyModule.scope = Some(this) - parent.foreach(p => p.children = this :: p.children) - - /** Accumulates Some(names), taking the final one. `None`s are ignored. */ - private var suggestedNameVar: Option[String] = None - - /** Suggests instance name for [[LazyModuleImpLike]] module. */ - def suggestName(x: String): this.type = suggestName(Some(x)) - - def suggestName(x: Option[String]): this.type = { - x.foreach { n => suggestedNameVar = Some(n) } - this - } - - /** Finds the name of the first non-anonymous Scala class while walking up the class hierarchy. */ - private def findClassName(c: Class[_]): String = { - val n = c.getName.split('.').last - if (n.contains('$')) findClassName(c.getSuperclass) else n - } - - /** Scala class name of this instance. */ - lazy val className: String = findClassName(getClass) - /** Suggested instance name. Defaults to [[className]].*/ - lazy val suggestedName: String = suggestedNameVar.getOrElse(className) - /** Suggested module name. Defaults to [[className]].*/ - lazy val desiredName: String = className // + hashcode? - - /** Return instance name. */ - def name: String = suggestedName // className + suggestedName ++ hashcode ? - /** Return source line that defines this instance. */ - def line: String = sourceLine(info) - - // Accessing these names can only be done after circuit elaboration! - /** Module name in verilog, used in GraphML. - * For cloned lazyModules, this is the name of the prototype - */ - lazy val moduleName: String = cloneProto.map(_.module.name).getOrElse(module.name) - /** Hierarchical path of this instance, used in GraphML. - * For cloned modules, construct this manually (since this.module should not be evaluated) - */ - lazy val pathName: String = cloneProto.map(p => s"${parent.get.pathName}.${p.instanceName}") - .getOrElse(module.pathName) - - /** Instance name in verilog. Should only be accessed after circuit elaboration. */ - lazy val instanceName: String = pathName.split('.').last - - /** [[chisel3]] hardware implementation of this [[LazyModule]]. - * - * Subclasses should define this function as `lazy val`s for lazy evaluation. - * Generally, the evaluation of this marks the beginning of phase 2. - */ - def module: LazyModuleImpLike - - /** Recursively traverse all child LazyModules and Nodes of this LazyModule - * to construct the set of empty [[Dangle]]'s that are this module's top-level IO - * This is effectively doing the same thing as [[LazyModuleImp.instantiate]], but - * without constructing any [[Module]]'s - */ - protected[diplomacy] def cloneDangles(): List[Dangle] = { - children.foreach(c => require(c.cloneProto.isDefined, s"${c.info}, ${c.parent.get.info}")) - val childDangles = children.reverse.flatMap { c => c.cloneDangles() } - val nodeDangles = nodes.reverse.flatMap(n => n.cloneDangles()) - val allDangles = nodeDangles ++ childDangles - val pairing = SortedMap(allDangles.groupBy(_.source).toSeq: _*) - val done = Set() ++ pairing.values.filter(_.size == 2).map { - case Seq(a, b) => - require(a.flipped != b.flipped) - a.source - case _ => - None - } - val forward = allDangles.filter(d => !done(d.source)) - val dangles = forward.map { d => - d.copy(name = suggestedName + "_" + d.name) - } - dangles - } - - /** Whether to omit generating the GraphML for this [[LazyModule]]. - * - * Recursively checks whether all [[BaseNode]]s and children [[LazyModule]]s should omit GraphML - * generation. - */ - def omitGraphML: Boolean = nodes.forall(_.omitGraphML) && children.forall(_.omitGraphML) - - /** Whether this [[LazyModule]]'s module should be marked for in-lining by FIRRTL. - * - * The default heuristic is to inline any parents whose children have been inlined - * and whose nodes all produce identity circuits. - */ - def shouldBeInlined: Boolean = nodes.forall(_.circuitIdentity) && children.forall(_.shouldBeInlined) - - /** GraphML representation for this instance. - * - * This is a representation of the Nodes, Edges, LazyModule hierarchy, - * and any other information that is added in by implementations. - * It can be converted to an image with various third-party tools. - */ - lazy val graphML: String = parent.map(_.graphML).getOrElse { - val buf = new StringBuilder - buf ++= "\n" - buf ++= "\n" - buf ++= " \n" - buf ++= " \n" - buf ++= " \n" - buf ++= " \n" - nodesGraphML(buf, " ") - edgesGraphML(buf, " ") - buf ++= " \n" - buf ++= "\n" - buf.toString - } - - /** A globally unique [[LazyModule]] index for this instance. */ - private val index = { - LazyModule.index = LazyModule.index + 1 - LazyModule.index - } - - /** Generate GraphML fragment for nodes. - * - * @param buf String buffer to write to. - * @param pad Padding as prefix for indentation purposes. - */ - private def nodesGraphML(buf: StringBuilder, pad: String): Unit = { - buf ++= s"""$pad\n""" - buf ++= s"""$pad $instanceName\n""" - buf ++= s"""$pad $moduleName ($pathName)\n""" - buf ++= s"""$pad \n""" - nodes.filter(!_.omitGraphML).foreach { n => - buf ++= s"""$pad \n""" - buf ++= s"""$pad \n""" - buf ++= s"""$pad ${n.formatNode}, \n${n.nodedebugstring}\n""" - buf ++= s"""$pad \n""" - } - children.filter(!_.omitGraphML).foreach(_.nodesGraphML(buf, pad + " ")) - buf ++= s"""$pad \n""" - buf ++= s"""$pad\n""" - } - - /** Generate GraphML fragment for edges. - * - * @param buf String buffer to write to. - * @param pad Padding as prefix for indentation purposes. - */ - private def edgesGraphML(buf: StringBuilder, pad: String): Unit = { - nodes.filter(!_.omitGraphML) foreach { n => - n.outputs.filter(!_._1.omitGraphML).foreach { case (o, edge) => - val RenderedEdge(colour, label, flipped) = edge - buf ++= pad - buf ++= """" - } else { - buf ++= s""" source=\"$index::${n.index}\"""" - buf ++= s""" target=\"${o.lazyModule.index}::${o.index}\">""" - } - buf ++= s"""""" - if (flipped) { - buf ++= s"""""" - } else { - buf ++= s"""""" - } - buf ++= s"""""" - buf ++= s"""$label""" - buf ++= s"""\n""" - } - } - children.filter(!_.omitGraphML).foreach { c => c.edgesGraphML(buf, pad) } - } - - /** Call function on all of this [[LazyModule]]'s [[children]]. - * - * @param iterfunc Function to call on each descendant. - */ - def childrenIterator(iterfunc: LazyModule => Unit): Unit = { - iterfunc(this) - children.foreach(_.childrenIterator(iterfunc)) - } - - /** Call function on all of this [[LazyModule]]'s [[nodes]]. - * - * @param iterfunc Function to call on each descendant. - */ - def nodeIterator(iterfunc: BaseNode => Unit): Unit = { - nodes.foreach(iterfunc) - childrenIterator(_.nodes.foreach(iterfunc)) - } - - /** Accessor for [[children]]. */ - def getChildren: List[LazyModule] = children - - /** Accessor for [[nodes]]. */ - def getNodes: List[BaseNode] = nodes -} - -object LazyModule { - /** Current [[LazyModule]] scope. The scope is a stack of [[LazyModule]]/[[LazyScope]]s. - * - * Each call to [[LazyScope.apply]] or [[LazyModule.apply]] will push that item onto the current scope. - */ - protected[diplomacy] var scope: Option[LazyModule] = None - /** Global index of [[LazyModule]]. Note that there is no zeroth module. */ - private var index = 0 - - /** Wraps a [[LazyModule]], handling bookkeeping of scopes. - * - * This method manages the scope and index of the [[LazyModule]]s. All [[LazyModule]]s must be - * wrapped exactly once. - * - * @param bc [[LazyModule]] instance to be wrapped. - * @param valName [[ValName]] used to name this instance, - * it can be automatically generated by [[ValName]] macro, or specified manually. - * @param sourceInfo [[SourceInfo]] information about where this [[LazyModule]] is being generated - */ - def apply[T <: LazyModule](bc: T)(implicit valName: ValName, sourceInfo: SourceInfo): T = { - // Make sure the user puts [[LazyModule]] around modules in the correct order. - require(scope.isDefined, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}. Ensure that descendant LazyModules are instantiated with the LazyModule() wrapper and that you did not call LazyModule() twice.") - require(scope.get eq bc, s"LazyModule() applied to ${bc.name} before ${scope.get.name} ${sourceLine(sourceInfo)}") - // Pop from the [[LazyModule.scope]] stack. - scope = bc.parent - bc.info = sourceInfo - if (bc.suggestedNameVar.isEmpty) bc.suggestName(valName.name) - bc - } -} - -/** Trait describing the actual [[Module]] implementation wrapped by a [[LazyModule]]. - * - * This is the actual Chisel module that is lazily-evaluated in the second phase of Diplomacy. - */ -sealed trait LazyModuleImpLike extends RawModule { - /** [[LazyModule]] that contains this instance. */ - val wrapper: LazyModule - /** IOs that will be automatically "punched" for this instance. */ - val auto: AutoBundle - /** The metadata that describes the [[HalfEdge]]s which generated [[auto]]. */ - protected[diplomacy] val dangles: Seq[Dangle] - - // [[wrapper.module]] had better not be accessed while LazyModules are still being built! - require(LazyModule.scope.isEmpty, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.scope.get.name}") - - /** Set module name. Defaults to the containing LazyModule's desiredName.*/ - override def desiredName: String = wrapper.desiredName - - suggestName(wrapper.suggestedName) - - /** [[Parameters]] for chisel [[Module]]s. */ - implicit val p: Parameters = wrapper.p - - /** instantiate this [[LazyModule]], - * return [[AutoBundle]] and a unconnected [[Dangle]]s from this module and submodules. */ - protected[diplomacy] def instantiate(): (AutoBundle, List[Dangle]) = { - // 1. It will recursively append [[wrapper.children]] into [[chisel3.internal.Builder]], - // 2. return [[Dangle]]s from each module. - val childDangles = wrapper.children.reverse.flatMap { c => - implicit val sourceInfo: SourceInfo = c.info - c.cloneProto.map { cp => - // If the child is a clone, then recursively set cloneProto of its children as well - def assignCloneProtos(bases: Seq[LazyModule], clones: Seq[LazyModule]): Unit = { - require(bases.size == clones.size) - (bases zip clones).map { case (l,r) => - require(l.getClass == r.getClass, s"Cloned children class mismatch ${l.name} != ${r.name}") - l.cloneProto = Some(r) - assignCloneProtos(l.children, r.children) - } - } - assignCloneProtos(c.children, cp.children) - // Clone the child module as a record, and get its [[AutoBundle]] - val clone = CloneModuleAsRecord(cp.module).suggestName(c.suggestedName) - val clonedAuto = clone("auto").asInstanceOf[AutoBundle] - // Get the empty [[Dangle]]'s of the cloned child - val rawDangles = c.cloneDangles() - require(rawDangles.size == clonedAuto.elements.size) - // Assign the [[AutoBundle]] fields of the cloned record to the empty [[Dangle]]'s - val dangles = (rawDangles zip clonedAuto.elements).map { case (d, (_, io)) => - d.copy(dataOpt = Some(io)) - } - dangles - } .getOrElse { - // For non-clones, instantiate the child module - val mod = try { - Module(c.module) - } catch { - case e: ChiselException => { - println(s"Chisel exception caught when instantiating ${c.name} within ${this.name} at ${c.line}") - throw e - } - } - mod.dangles - } - } - - // Ask each node in this [[LazyModule]] to call [[BaseNode.instantiate]]. - // This will result in a sequence of [[Dangle]] from these [[BaseNode]]s. - val nodeDangles = wrapper.nodes.reverse.flatMap(_.instantiate()) - // Accumulate all the [[Dangle]]s from this node and any accumulated from its [[wrapper.children]] - val allDangles = nodeDangles ++ childDangles - // Group [[allDangles]] by their [[source]]. - val pairing = SortedMap(allDangles.groupBy(_.source).toSeq: _*) - // For each [[source]] set of [[Dangle]]s of size 2, ensure that these - // can be connected as a source-sink pair (have opposite flipped value). - // Make the connection and mark them as [[done]]. - val done = Set() ++ pairing.values.filter(_.size == 2).map { - case Seq(a, b) => - require(a.flipped != b.flipped) - // @todo <> in chisel3 makes directionless connection. - if (a.flipped) { - a.data <> b.data - } else { - b.data <> a.data - } - a.source - case _ => - None - } - // Find all [[Dangle]]s which are still not connected. These will end up as [[AutoBundle]] [[IO]] ports on the module. - val forward = allDangles.filter(d => !done(d.source)) - // Generate [[AutoBundle]] IO from [[forward]]. - val auto = IO(new AutoBundle(forward.map { d => (d.name, d.data, d.flipped) }: _*)) - // Pass the [[Dangle]]s which remained and were used to generate the [[AutoBundle]] I/O ports up to the [[parent]] [[LazyModule]] - val dangles = (forward zip auto.elements) map { case (d, (_, io)) => - if (d.flipped) { - d.data <> io - } else { - io <> d.data - } - d.copy(dataOpt = Some(io), name = wrapper.suggestedName + "_" + d.name) - } - // Push all [[LazyModule.inModuleBody]] to [[chisel3.internal.Builder]]. - wrapper.inModuleBody.reverse.foreach { - _ () - } - - if (wrapper.shouldBeInlined) { - chisel3.experimental.annotate(new ChiselAnnotation { - def toFirrtl = InlineAnnotation(toNamed) - }) - } - - // Return [[IO]] and [[Dangle]] of this [[LazyModuleImp]]. - (auto, dangles) - } -} - -/** Actual description of a [[Module]] which can be instantiated by a call to [[LazyModule.module]]. - * - * @param wrapper the [[LazyModule]] from which the `.module` call is being made. - */ -class LazyModuleImp(val wrapper: LazyModule) extends Module with LazyModuleImpLike { - /** Instantiate hardware of this `Module`. */ - val (auto, dangles) = instantiate() -} - -/** Actual description of a [[RawModule]] which can be instantiated by a call to [[LazyModule.module]]. - * - * @param wrapper the [[LazyModule]] from which the `.module` call is being made. - */ -class LazyRawModuleImp(val wrapper: LazyModule) extends RawModule with LazyModuleImpLike { - // These wires are the default clock+reset for all LazyModule children. - // It is recommended to drive these even if you manually drive the [[clock]] and [[reset]] of all of the - // [[LazyRawModuleImp]] children. - // Otherwise, anonymous children ([[Monitor]]s for example) will not have their [[clock]] and/or [[reset]] driven properly. - /** drive clock explicitly. */ - val childClock: Clock = Wire(Clock()) - /** drive reset explicitly. */ - val childReset: Reset = Wire(Reset()) - // the default is that these are disabled - childClock := false.B.asClock - childReset := chisel3.DontCare - val (auto, dangles) = withClockAndReset(childClock, childReset) { - instantiate() - } -} - -/** Used for a [[LazyModule]] which does not need to define any [[LazyModuleImp]] implementation. - * - * It can be used as wrapper that only instantiates and connects [[LazyModule]]s. - */ -class SimpleLazyModule(implicit p: Parameters) extends LazyModule { - lazy val module = new LazyModuleImp(this) -} - -/** Allows dynamic creation of [[Module]] hierarchy and "shoving" logic into a [[LazyModule]]. */ -trait LazyScope { - this: LazyModule => - override def toString: String = s"LazyScope named $name" - - /** Evaluate `body` in the current [[LazyModule.scope]] */ - def apply[T](body: => T): T = { - // Preserve the previous value of the [[LazyModule.scope]], because when calling [[apply]] function, - // [[LazyModule.scope]] will be altered. - val saved = LazyModule.scope - // [[LazyModule.scope]] stack push. - LazyModule.scope = Some(this) - // Evaluate [[body]] in the current `scope`, saving the result to [[out]]. - val out = body - // Check that the `scope` after evaluating `body` is the same as when we started. - require(LazyModule.scope.isDefined, s"LazyScope $name tried to exit, but scope was empty!") - require(LazyModule.scope.get eq this, s"LazyScope $name exited before LazyModule ${LazyModule.scope.get.name} was closed") - // [[LazyModule.scope]] stack pop. - LazyModule.scope = saved - out - } -} - -/** Used to automatically create a level of module hierarchy (a [[SimpleLazyModule]]) within which [[LazyModule]]s can be instantiated and connected. - * - * It will instantiate a [[SimpleLazyModule]] to manage evaluation of `body` and evaluate `body` code snippets in this scope. - */ -object LazyScope { - /** Create a [[LazyScope]] with an implicit instance name. - * - * @param body code executed within the generated [[SimpleLazyModule]]. - * @param valName instance name of generated [[SimpleLazyModule]]. - * @param p [[Parameters]] propagated to [[SimpleLazyModule]]. - */ - def apply[T](body: => T)(implicit valName: ValName, p: Parameters): T = { - apply(valName.name, "SimpleLazyModule", None)(body)(p) - } - - /** Create a [[LazyScope]] with an explicitly defined instance name. - * - * @param name instance name of generated [[SimpleLazyModule]]. - * @param body code executed within the generated `SimpleLazyModule` - * @param p [[Parameters]] propagated to [[SimpleLazyModule]]. - */ - def apply[T](name: String)(body: => T)(implicit p: Parameters): T = { - apply(name, "SimpleLazyModule", None)(body)(p) - } - - /** Create a [[LazyScope]] with an explicit instance and class name, and control inlining. - * - * @param name instance name of generated [[SimpleLazyModule]]. - * @param desiredModuleName class name of generated [[SimpleLazyModule]]. - * @param overrideInlining tell FIRRTL that this [[SimpleLazyModule]]'s module should be inlined. - * @param body code executed within the generated `SimpleLazyModule` - * @param p [[Parameters]] propagated to [[SimpleLazyModule]]. - */ - def apply[T]( - name: String, - desiredModuleName: String, - overrideInlining: Option[Boolean] = None) - (body: => T) - (implicit p: Parameters): T = - { - val scope = LazyModule(new SimpleLazyModule with LazyScope { - override lazy val desiredName = desiredModuleName - override def shouldBeInlined = overrideInlining.getOrElse(super.shouldBeInlined) - }).suggestName(name) - scope { - body - } - } - - /** Create a [[LazyScope]] to temporarily group children for some reason, but tell Firrtl to inline it. - * - * For example, we might want to control a set of children's clocks but then not keep the parent wrapper. - * - * @param body code executed within the generated `SimpleLazyModule` - * @param p [[Parameters]] propagated to [[SimpleLazyModule]]. - */ - def inline[T](body: => T)(implicit p: Parameters): T = { - apply("noname", "ShouldBeInlined", Some(false))(body)(p) - } -} - -/** One side metadata of a [[Dangle]]. - * - * Describes one side of an edge going into or out of a [[BaseNode]]. - * - * @param serial the global [[BaseNode.serial]] number of the [[BaseNode]] that this [[HalfEdge]] connects to. - * @param index the `index` in the [[BaseNode]]'s input or output port list that this [[HalfEdge]] belongs to. - */ -case class HalfEdge(serial: Int, index: Int) extends Ordered[HalfEdge] { - - import scala.math.Ordered.orderingToOrdered - - def compare(that: HalfEdge): Int = HalfEdge.unapply(this) compare HalfEdge.unapply(that) -} - -/** [[Dangle]] captures the `IO` information of a [[LazyModule]] and which two [[BaseNode]]s the [[Edges]]/[[Bundle]] connects. - * - * [[Dangle]]s are generated by [[BaseNode.instantiate]] - * using [[MixedNode.danglesOut]] and [[MixedNode.danglesIn]] , - * [[LazyModuleImp.instantiate]] connects those that go to internal or explicit IO connections - * in a [[LazyModule]]. - * - * @param source the source [[HalfEdge]] of this [[Dangle]], which captures the source [[BaseNode]] and the port `index` within that [[BaseNode]]. - * @param sink sink [[HalfEdge]] of this [[Dangle]], which captures the sink [[BaseNode]] and the port `index` within that [[BaseNode]]. - * @param flipped flip or not in [[AutoBundle.makeElements]]. If true this corresponds to `danglesOut`, if false it corresponds to `danglesIn`. - * @param dataOpt actual [[Data]] for the hardware connection. Can be empty if this belongs to a cloned module - */ -case class Dangle(source: HalfEdge, sink: HalfEdge, flipped: Boolean, name: String, dataOpt: Option[Data]) { - def data = dataOpt.get -} - -/** [[AutoBundle]] will construct the [[Bundle]]s for a [[LazyModule]] in [[LazyModuleImpLike.instantiate]], - * - * @param elts is a sequence of data containing for each IO port a tuple of (name, data, flipped), where - * name: IO name - * data: actual data for connection. - * flipped: flip or not in [[makeElements]] - */ -final class AutoBundle(elts: (String, Data, Boolean)*) extends Record { - // We need to preserve the order of elts, despite grouping by name to disambiguate things. - val elements: SeqMap[String, Data] = SeqMap() ++ elts.zipWithIndex.map(makeElements).groupBy(_._1).values.flatMap { - // If name is unique, it will return a Seq[index -> (name -> data)]. - case Seq((key, element, i)) => Seq(i -> (key -> element)) - // If name is not unique, name will append with j, and return `Seq[index -> (s"${name}_${j}" -> data)]`. - case seq => seq.zipWithIndex.map { case ((key, element, i), j) => i -> (key + "_" + j -> element) } - }.toList.sortBy(_._1).map(_._2) - require(elements.size == elts.size) - - // Trim final "(_[0-9]+)*$" in the name, flip data with flipped. - private def makeElements(tuple: ((String, Data, Boolean), Int)) = { - val ((key, data, flip), i) = tuple - // Trim trailing _0_1_2 stuff so that when we append _# we don't create collisions. - val regex = new Regex("(_[0-9]+)*$") - val element = if (flip) Flipped(data.cloneType) else data.cloneType - (regex.replaceAllIn(key, ""), element, i) - } -} - -trait ModuleValue[T] { - def getWrappedValue: T -} - -/** Used to inject code snippets to be evaluated in [[LazyModuleImp.instantiate]] in the current [[LazyModule.scope]]. - * - * It can be used to create additional hardware outside of the [[LazyModule.children]], - * connections other than the internal [[BaseNode]] connections, - * or additional IOs aside from the [[AutoBundle]] - */ -object InModuleBody { - def apply[T](body: => T): ModuleValue[T] = { - require(LazyModule.scope.isDefined, s"InModuleBody invoked outside a LazyModule") - val scope = LazyModule.scope.get - // a wrapper to [[body]], being able to extract result after `execute`. - val out = new ModuleValue[T] { - var result: Option[T] = None - - def execute(): Unit = { - result = Some(body) - } - - def getWrappedValue: T = { - require(result.isDefined, s"InModuleBody contents were requested before module was evaluated!") - result.get - } - } - - // Prepend [[out.execute]] to [[scope.inModuleBody]], - // it is a val with type of `() => Unit`, which will be executed in [[LazyModuleImp.instantiate]]. - scope.inModuleBody = out.execute _ +: scope.inModuleBody - out - } -} diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala deleted file mode 100644 index 51d3b7e92ad..00000000000 --- a/src/main/scala/diplomacy/Nodes.scala +++ /dev/null @@ -1,1800 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.diplomacy - -import chisel3._ -import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.util.HeterogeneousBag - -import scala.collection.immutable -import scala.collection.mutable.ListBuffer - -/** A field available in [[Parameters]] used to determine whether [[InwardNodeImp.monitor]] will be called. */ -case object MonitorsEnabled extends Field[Boolean](true) - -/** When rendering the edge in a graphical format, flip the order in which the edges' source and sink are presented. - * - * For example, when rendering graphML, yEd by default tries to put the source node vertically above the sink node, but - * [[RenderFlipped]] inverts this relationship. When a particular [[LazyModule]] contains both source nodes and sink nodes, - * flipping the rendering of one node's edge will usual produce a more concise visual layout for the [[LazyModule]]. - */ -case object RenderFlipped extends Field[Boolean](false) - -/** [[RenderedEdge]] can set the color and label of the visualization of the DAG. */ -case class RenderedEdge( - colour: String, - label: String = "", - flipped: Boolean = false) - -/** [[InwardNodeImp]] defines the types that describe the inward side of the [[BaseNode]]. - * - * @tparam DI The type of the downward-flowing parameters received on the inner side of the node. - * @tparam UI The type of the upward-flowing parameters generated by the inner side of the node. - * @tparam EI The type of the diplomatically-resolved parameters for an Edge connected to the inner side of the node. - * @tparam BI The type of the [[chisel3.Data]] (usually a [[chisel3.Bundle]]) used when connecting to the inner side of the node, - * corresponding to the real hardware interface that is emitted along the graph edge, - * generally parameterized by the [[EI]] type. - */ -trait InwardNodeImp[DI, UI, EI, BI <: Data] -{ - /** Creates the inward edge parameters by combining the downward-flowing and upward-flowing parameters for edges - * that connect to the inward side of this [[BaseNode]]. - * - * It is left up to a user defining a particular protocol implementation to decide how the parameters flowing through - * the graph in both directions on this Edge are combined into a single representation. - * - * @param pd The downward-flowing parameters into the node along the edge. - * @param pu The upward-flowing parameters going out of the node along the edge. - * @param p A view of [[Parameters]] at the point at which the returned edge is being bound. - * @param sourceInfo [[SourceInfo]] of this edge. - * @return An inward edge of this node. - */ - def edgeI(pd: DI, pu: UI, p: Parameters, sourceInfo: SourceInfo): EI - - /** Create an inward bundle parameterized by the inward edge. - * - * @param ei Inward edge of this node. - * @return An outward Bundle of this node parameterized by the negotiated Edge parameters. - */ - def bundleI(ei: EI): BI - - /** Defines how input parameters can be "mixed" or negotiated together. - * - * The default behavior is to just return `pu`. - * - * @param pu The upward-flowing parameters going out of the node along the edge. - * @param node An inward node to "mix" the upward-flowing parameters into. - * @return Altered version of the upward-flowing parameters. - */ - def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu - - /** Function to generate and attach a monitor for this node input. - * - * @param bundle Inward bundle of this node to attach the monitor to. - * @param edge Edge of this node used to parameterize the bundle. - */ - def monitor(bundle: BI, edge: EI): Unit = {} - - /** Define how the edge should be rendered (e.g. in GraphML). - * - * @param e Edge to render. - * @return [[RenderedEdge]] description of how the edge should be generated. - */ - def render(e: EI): RenderedEdge -} - -/** [[OutwardNodeImp]] defines the types that describe the outwards side of the [[BaseNode]]. - * - * @tparam DO The type of the downward-flowing parameters generated by the outer side of the node - * @tparam UO Tye type of the upward-flowing parameters received by the outer side of the node - * @tparam EO The type of the diplomatically-resolved parameters for an Edge connected to the outer side of the node. - * @tparam BO The type of the [[chisel3.Data]] (usually a [[chisel3.Bundle]]) used when connecting to the outer side of the node, - * corresponding to the real hardware interface that is emitted along the graph edge, - * generally parameterized by the [[EO]] type. - */ -trait OutwardNodeImp[DO, UO, EO, BO <: Data] -{ - /** Creates the outward edge parameters by combining the downward-flowing and upward-flowing parameters for edges - * that connect to the outward side of this [[BaseNode]]. - * - * It is left up to a user defining a particular protocol implementation to decide how the parameters flowing through - * the graph in both directions on this Edge are combined into a single representation. - * - * @param pd The downward-flowing parameters going out of the node along the edge. - * @param pu The upward-flowing parameters into the node along the edge. - * @param p A view of [[Parameters]] at the point at which the returned edge is being bound. - * @param sourceInfo [[SourceInfo]] of this edge. - * @return An outward edge of this node. - */ - def edgeO(pd: DO, pu: UO, p: Parameters, sourceInfo: SourceInfo): EO - - /** Create an outward Bundle parameterized by the outward edge. - * - * @param eo Outward Edge of this node. - * @return An outward Bundle of this node parameterized by the negotiated Edge parameters. - */ - def bundleO(eo: EO): BO - - /** Defines how outward parameters can be "mixed" or negotiated together. - * - * The default behavior is to just return `pd`. - * - * @param pd The downward-flowing parameters into the node along the edge. - * @param node An outward node to "mix" the downward-flowing parameters into. - * @return Altered version of the downward-flowing parameters. - */ - def mixO(pd: DO, node: OutwardNode[DO, UO, BO]): DO = pd -} - -/** The [[NodeImp]] combines an [[InwardNodeImp]] and an [[OutwardNodeImp]]. - * - * This allows it to define whether it is a protocol-modifying (bridging) sort of node, - * or whether it is an adapter type node that just modifies the parameters within a protocol. - * - * This class has no members and is solely used for holding type information. - * Applications of diplomacy should extend [[NodeImp]] with a case object that sets concrete type arguments. - * - * @tparam D Type of the downward-flowing parameters of the node. - * @tparam U Type of upward-flowing parameters of the node. - * @tparam EO Type of the parameters describing an edge on the outer side of the node. - * @tparam EI Type of the parameters describing an edge on the inner side of the node. - * @tparam B Bundle type generated on edges connecting to this node. - */ -abstract class NodeImp[D, U, EO, EI, B <: Data] extends Object - with InwardNodeImp[D, U, EI, B] - with OutwardNodeImp[D, U, EO, B] - -/** A [[NodeImp]] where the inward and outward edge parameters are of the same type. - * - * If, in a given protocol implementation, the parameters visible to the node on the inward side of an edge are - * the same as the parameters visible to the node on the outward side of an edge, - * [[SimpleNodeImp]] can be used instead of [[NodeImp]]. - * - * @tparam D Type of the downward-flowing parameters of the node. - * @tparam U Type of the upward-flowing parameters of the node. - * @tparam E Edge Parameters describing the connections on either side of the node. - * @tparam B Bundle type generated on edges connecting to this node. - */ -abstract class SimpleNodeImp[D, U, E, B <: Data] - extends NodeImp[D, U, E, E, B] { - /** Creates the edge parameters by combining the downward-flowing and upward-flowing parameters for edges that connect to this node. - * - * It is left up to a user defining a particular protocol implementation to decide how the parameters flowing through the graph in - * both directions are combined into a single representation on an Edge. - * - * @param pd The downward-flowing parameters into the node along the edge. - * @param pu The upward-flowing parameters going out of the node along the edge. - * @param p [[Parameters]]s which can be used during negotiation. - * @param sourceInfo [[SourceInfo]] of this edge. - * @return Negotiated edge parameters. - */ - def edge(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo): E - - def edgeO(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo): E = edge(pd, pu, p, sourceInfo) - - def edgeI(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo): E = edge(pd, pu, p, sourceInfo) - - /** Generate the Bundle from the negotiated Edge parameters. - * - * @param e the negotiated Edge parameters - * @return the corresponding Bundle of this node - */ - def bundle(e: E): B - - def bundleO(e: E): B = bundle(e) - - def bundleI(e: E): B = bundle(e) -} - -/** [[BaseNode]] is the abstract base class of the type hierarchy of diplomacy node classes. - * - * @param valName [[ValName]] of this node, used by naming inference. - */ -abstract class BaseNode(implicit val valName: ValName) { - /** All subclasses of [[BaseNode]]s are expected to be instantiated only within [[LazyModule]]s. - * - * Sometimes one wants to view the entire diplomacy graph in a way - * where you do not care about the specific types of the edges. - * [[BaseNode]]s are type-erased and provide this view. - * - * @return The [[LazyModule]] which contains this Node. - */ - val scope: Option[LazyModule] = LazyModule.scope - - /** @return The index for this node in the containing [[LazyModule]]/[[LazyScope]]'s list of [[BaseNode]]s */ - val index: Int = scope.map(_.nodes.size).getOrElse(0) - - /** @return The [[LazyModule]] which contains this [[BaseNode]] */ - def lazyModule: LazyModule = scope.get - - // Prepend this node to the current [[LazyModule]]'s list of nodes - scope.foreach { lm => lm.nodes = this :: lm.nodes } - - /** @return The serial number for this node in the global list of [[BaseNode]]s. */ - val serial: Int = BaseNode.serial - - BaseNode.serial = BaseNode.serial + 1 - - /** Instantiate this node. - * - * This happens after all nodes connections have been made and we are ready to perform parameter negotiation. - * This also determines which connections need to leave this node's LazyScope and cross hierarchical boundaries. - * That information is captured in [[Dangle]]s which are returned from this function. - * - * @return A sequence of [[Dangle]]s from this node that leave this [[BaseNode]]'s [[LazyScope]]. - */ - protected[diplomacy] def instantiate(): Seq[Dangle] - /** Determine the [[Dangle]]'s for connections without instantiating the node, or any child nodes - * - * @return A sequence of [[Dangle]]s from this node that leave this [[BaseNode]]'s [[LazyScope]]. - */ - protected[diplomacy] def cloneDangles(): Seq[Dangle] - - /** @return name of this node. */ - def name: String = scope.map(_.name).getOrElse("TOP") + "." + valName.name - - /** Determines whether or not this node will be excluded from the graph visualization. - * - * By default, if this node has neither inputs nor outputs it will be excluded. - */ - def omitGraphML: Boolean = outputs.isEmpty && inputs.isEmpty - - /** Debug string of this node, used in [[LazyModule.graphML]]. */ - lazy val nodedebugstring: String = "" - - /** Mark whether this node represents a circuit "identity" that outputs its inputs unchanged. - * - * This information may be used to elide monitors or inline the parent module. - */ - def circuitIdentity: Boolean = false - - /** @return A sequence of [[LazyModule]] up to and including Top. */ - def parents: Seq[LazyModule] = scope.map(lm => lm +: lm.parents).getOrElse(Nil) - - /** @return The context string for debug. */ - def context: String = { - s"""$description $name node: - |parents: ${parents.map(_.name).mkString("/")} - |locator: ${scope.map(_.line).getOrElse("")} - |""".stripMargin - } - - /** Determines the name to be used in elements of auto-punched bundles. - * - * It takes the name of the node as determined from [[valName]], - * converts camel case into snake case, and strips "Node" or "NodeOpt" suffixes. - */ - def wirePrefix: String = { - val camelCase = "([a-z])([A-Z])".r - val decamel = camelCase.replaceAllIn(valName.name, _ match { case camelCase(l, h) => l + "_" + h }) - val name = decamel.toLowerCase.stripSuffix("_opt").stripSuffix("node").stripSuffix("_") - if (name.isEmpty) "" else name + "_" - } - - /** @return [[BaseNode]] description, which should be defined by subclasses and is generally expected to be a constant. */ - def description: String - - /** @return [[BaseNode]] instance description, which can be overridden with more detailed information about each node. */ - def formatNode: String = "" - - /** @return Metadata to visualize inward edges into this node. */ - def inputs: Seq[(BaseNode, RenderedEdge)] - - /** @return Metadata to visualize outward edges from this node. */ - def outputs: Seq[(BaseNode, RenderedEdge)] - - /** @return Whether this node can handle [[BIND_FLEX]] type connections on either side. - * - * For example, a node `b` will have [[flexibleArityDirection]] be `true` if both are legal: - * `a :*=* b :*= c`, which resolves to `a :*= b :*= c` - * or - * `a :=* b :*=* c`, which resolves to `a :=* b :=* c` - * - * If this is `false`, the node can only support `:*=*` if it connects to a node with `flexibleArityDirection = true` - */ - protected[diplomacy] def flexibleArityDirection: Boolean = false - - /** @return The sink cardinality. - * - * How many times is this node used as a sink. - */ - protected[diplomacy] val sinkCard: Int - - /** @return The source cardinality. - * - * How many times is this node used as a source. - */ - protected[diplomacy] val sourceCard: Int - - /** @return The "flex" cardinality. - * - * How many times is this node used in a way that could be either source or sink, depending on final - * directional determination. - */ - protected[diplomacy] val flexes: Seq[BaseNode] - - /** Resolves the flex to be either source or sink. - * - * @return A value >= 0 if it is sink cardinality, a negative value for source cardinality. The magnitude of the value does not matter. - */ - protected[diplomacy] val flexOffset: Int -} - -/** Companion object for [[BaseNode]], which is only used to hold the the global serial number of all [[BaseNode]]s. */ -object BaseNode { - protected[diplomacy] var serial = 0 -} - -/** Trait that enables a string representation of an edge. */ -trait FormatEdge { - def formatEdge: String -} - -/** Trait that enables iterating over a [[BaseNode]]'s edges to produce a formatted string representation. - * - * In practice this is generally GraphML metadata. - */ -trait FormatNode[I <: FormatEdge, O <: FormatEdge] extends BaseNode { - def edges: Edges[I,O] - - /** Format the edges of the [[BaseNode]] for emission (generally in GraphML). */ - override def formatNode = if (circuitIdentity) "" else { - edges.out.map(currEdge => - "On Output Edge:\n\n" + currEdge.formatEdge).mkString + - "\n---------------------------------------------\n\n" + - edges.in.map(currEdge => - "On Input Edge:\n\n" + currEdge.formatEdge).mkString - } -} - -/** A Handle with no explicitly defined binding functionality. - * - * A [[NoHandle]] is at the top of the Handle type hierarchy, but it does not define any binding operators, - * so by itself a [[NoHandle]] cannot be used on either side of a bind operator. - * - * For example, a source node connected directly to a sink node produces a [[NoHandle]], - * because there are no further bindings that could be applied to either side of the pair of nodes. - * - * The other Handle types extend this type and bestow actual binding semantics. - * They can always be used wherever a [[NoHandle]] is expected because a [[NoHandle]] - * doesn't provide any guaranteed behavior. - * - * Handle algebra: - * - * "x---x" [[NoHandle]] - * "x---<" [[InwardNodeHandle]] - * "<---x" [[OutwardNodeHandle]] - * "<---<" (Full) [[NodeHandle]] - * - * "<" can be bound to (arrow points in the direction of binding). - * "x" cannot be bound to. - * - * The left side is outer, the right side is inner. - * - * Two Handles can be bound if their adjacent ends are both "<". - */ -trait NoHandle -case object NoHandleObject extends NoHandle - -/** A Handle that can be used on either side of a bind operator. */ -trait NodeHandle[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] - extends InwardNodeHandle[DI, UI, EI, BI] with OutwardNodeHandle[DO, UO, EO, BO] { - /** Connects two full nodes handles => full node handle. - * - * <---< := <---< == <---< - * This and that node are both [[BIND_ONCE]]. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - override def := [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_ONCE); NodeHandle(h, this) } - - /** Connects two full nodes handles => full node handle. - * - * <---< :*= <---< == <---< - * [[BIND_STAR]] this node as sink, [[BIND_QUERY]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `InwardNode`, this node as `OutwardNode`. - */ - override def :*= [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_STAR); NodeHandle(h, this) } - - /** Connects two full nodes handles => full node handle. - * - * <---< :=* <---< == <---< - * [[BIND_QUERY]] this node as sink, [[BIND_STAR]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `InwardNode`, this node as `OutwardNode`. - */ - override def :=* [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_QUERY); NodeHandle(h, this) } - - /** Connects two full nodes handles => full node handle. - * - * <---< :*=* <---< == <---< - * [[BIND_FLEX]] this node as sink, [[BIND_FLEX]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - override def :*=*[DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_FLEX); NodeHandle(h, this) } - - /** Connects a full node with an output node => an output handle. - * - * <---< := <---x == <---x - * [[BIND_ONCE]] this node as sink, [[BIND_ONCE]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[OutwardNodeHandle]] with this node as `outwardNode`. - */ - override def := [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_ONCE); this } - - /** Connects a full node with an output node => an output handle. - * - * <---< :*= <---x == <---x - * [[BIND_STAR]] this node as sink, [[BIND_QUERY]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[OutwardNodeHandle]] with this node as `outwardNode`. - */ - override def :*= [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_STAR); this } - - /** Connects a full node with an output => an output. - * - * <---< :=* <---x == <---x - * [[BIND_QUERY]] this node as sink, [[BIND_STAR]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[OutwardNodeHandle]] with this node as `outwardNode`. - */ - override def :=* [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_QUERY); this } - - /** Connects a full node with an output => an output. - * - * <---< :*=* <---x == <---x - * [[BIND_FLEX]] this node as sink, [[BIND_FLEX]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[OutwardNodeHandle]] with this node as `outwardNode`. - */ - override def :*=*[EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_FLEX); this } -} - -object NodeHandle { - /** generate a [[NodeHandle]] by combining an [[InwardNodeHandle]] and an [[OutwardNodeHandle]]. - * - * @param i Inward node handle. - * @param o Outward node handle. - * @return [[NodeHandlePair]] with `inwardNode` of `i`, `outwardNode` of `o`. - */ - def apply[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](i: InwardNodeHandle[DI, UI, EI, BI], o: OutwardNodeHandle[DO, UO, EO, BO]) = new NodeHandlePair(i, o) -} - -/** A data structure that preserves information about the innermost and outermost Nodes in a [[NodeHandle]]. */ -class NodeHandlePair[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] - (inwardHandle: InwardNodeHandle[DI, UI, EI, BI], outwardHandle: OutwardNodeHandle[DO, UO, EO, BO]) - extends NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] { - /** @return [[InwardNode]] of [[inwardHandle]]. */ - val inward: InwardNode[DI, UI, BI] = inwardHandle.inward - - /** @return [[OutwardNode]] of [[outwardHandle]]. */ - val outward: OutwardNode[DO, UO, BO] = outwardHandle.outward - - /** @return The innermost [[InwardNodeImp]] of this [[NodeHandlePair]]. */ - def inner: InwardNodeImp[DI, UI, EI, BI] = inwardHandle.inner - - /** @return The outermost [[OutwardNodeImp]] of [[NodeHandlePair]]. */ - def outer: OutwardNodeImp[DO, UO, EO, BO] = outwardHandle.outer -} - -/** A handle for an [[InwardNode]], which may appear on the left side of a bind operator. */ -trait InwardNodeHandle[DI, UI, EI, BI <: Data] extends NoHandle -{ - /** @return [[InwardNode]] of `inwardHandle`. */ - def inward: InwardNode[DI, UI, BI] - - /** @return [[InwardNodeImp]] of `inwardHandle`. */ - def inner: InwardNodeImp[DI, UI, EI, BI] - - /** Bind this node to an [[OutwardNodeHandle]]. */ - protected def bind[EY](h: OutwardNodeHandle[DI, UI, EY, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = inward.bind(h.outward, binding) - - /** Connect an input node with a full node => inward node handle. - * - * x---< := <---< == x---< - * [[BIND_ONCE]] this node as sink, [[BIND_ONCE]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - def := [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_ONCE); h } - - /** Connect an input node with a full node => an input node. - * - * x---< :*= <---< == x---< - * [[BIND_STAR]] this node as sink, [[BIND_QUERY]] that node as source. - * - * @param h A Source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - def :*= [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_STAR); h } - - /** Connect an input node with a full node => an inward node handle. - * - * x---< :=* <---< == x---< - * [[BIND_QUERY]] this node as sink, [[BIND_STAR]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - def :=* [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_QUERY); h } - - /** Connect an input node with a full node => an input node. - * - * x---< :*=* <---< == x---< - * [[BIND_FLEX]] this node as sink, [[BIND_FLEX]] that node as source. - * - * @param h A source node also with sink handle. - * @return A [[NodeHandle]] with that node as `inwardNode`, this node as `outwardNode`. - */ - def :*=*[DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_FLEX); h } - - /** Connect an input node with output node => no node. - * - * x---< := <---x == x---x - * [[BIND_ONCE]] this node as sink, [[BIND_ONCE]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[NoHandle]] since neither side can bind to a node. - */ - def := [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_ONCE); NoHandleObject } - - /** Connect an input node with output node => no node. - * - * x---< :*= <---x == x---x - * [[BIND_STAR]] this node as sink, [[BIND_QUERY]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[NoHandle]] since neither side can bind to a node. - */ - def :*= [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_STAR); NoHandleObject } - - /** Connect an input node with output node => no node. - * - * x---< :=* <---x == x---x - * [[BIND_QUERY]] this node as sink, [[BIND_STAR]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[NoHandle]] since neither side can bind to another node. - */ - def :=* [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_QUERY); NoHandleObject } - - /** Connect an input node with output node => no node. - * - * x---< :*=* <---x == x---x - * [[BIND_FLEX]] this node as sink, [[BIND_FLEX]] that node as source. - * - * @param h A source node also without sink handle. - * @return A [[NoHandle]] since neither side can bind to another node. - */ - def :*=*[EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_FLEX); NoHandleObject } -} - -/** Enumeration of types of binding operations. */ -sealed trait NodeBinding - -/** Only connects a single edge. */ -case object BIND_ONCE extends NodeBinding { - override def toString: String = "once" -} - -/** Connects N (N >= 0) edges. - * - * The other side of the edge determines cardinality. - */ -case object BIND_QUERY extends NodeBinding { - override def toString: String = "query" -} - -/** Connect N (N >= 0) edges. - * - * Our side of the edge determines cardinality. - */ -case object BIND_STAR extends NodeBinding { - override def toString: String = "star" -} - -/** Connect N (N >= 0) connections. - * - * The number of edges N will be determined by either the right or left side, - * once the direction ([[BIND_STAR]] or [[BIND_QUERY]]) is determined by the other connections as well. - */ -case object BIND_FLEX extends NodeBinding { - override def toString: String = "flex" -} - -/** A Node that defines inward behavior, meaning that it can have edges coming into it and be used on the left side of binding expressions. */ -trait InwardNode[DI, UI, BI <: Data] extends BaseNode { - /** accumulates input connections. */ - private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters, SourceInfo)]() - - /** Initially `false`, set to `true` once [[iBindings]] has been evaluated. */ - private var iRealized = false - - /** @return debug information of [[iBindings]]. */ - def iBindingInfo: String = s"""${iBindings.size} inward nodes bound: [${iBindings.map(n => s"${n._3}-${n._2.name}").mkString(",")}]""" - - - /** The accumulated number of input connections. */ - protected[diplomacy] def iPushed: Int = accPI.size - - /** Accumulate an input connection. - * - * Can only be called before [[iBindings]] is accessed. - * - * @param index index of this [[InwardNode]] in that [[OutwardNode]]. - * @param node the [[OutwardNode]] to bind to this [[InwardNode]]. - * @param binding [[NodeBinding]] type. - */ - protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = { - val info = sourceLine(sourceInfo, " at ", "") - require (!iRealized, - s"""Diplomacy has detected a problem in your code: - |The following node was incorrectly connected as a sink to ${node.name} after its .module was evaluated at $info. - |$context - |$iBindingInfo - |""".stripMargin) - accPI += ((index, node, binding, p, sourceInfo)) - } - - /** Ends the binding accumulation stage and returns all the input bindings to this node. - * - * Evaluating this lazy val will mark the inwards bindings as frozen, - * preventing subsequent bindings from being created via [[iPush]]. - * - * The bindings are each a tuple of: - * - numeric index of this binding in the other end of [[OutwardNode]]. - * - [[OutwardNode]] on the other end of this binding. - * - [[NodeBinding]] describing the type of binding. - * - A view of [[Parameters]] where the binding occurred. - * - [[SourceInfo]] for source-level error reporting. - */ - protected[diplomacy] lazy val iBindings: immutable.Seq[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters, SourceInfo)] = { iRealized = true; accPI.result() } - - /** resolved [[BIND_STAR]] binding of inward nodes: how many connections the star represents. */ - protected[diplomacy] val iStar: Int - - /** A mapping to convert Node binding index to port range. - * - * @return a sequence of tuple of mapping, the item in each a tuple of: - * - index: the index of connected [[OutwardNode]] - * - element: port range of connected [[OutwardNode]] - */ - protected[diplomacy] val iPortMapping: Seq[(Int, Int)] - - /** "Forward" an input connection through this node so that the node can be removed from the graph. - * - * @return None if no forwarding is needing. - */ - protected[diplomacy] def iForward(x: Int): Option[(Int, InwardNode[DI, UI, BI])] = None - - /** Downward-flowing inward parameters. - * - * Generated from the nodes connected to the inward side of this node and sent downstream to this node. - */ - protected[diplomacy] val diParams: Seq[DI] - - /** Upward-flowing inward parameters. - * - * Generated by this node and sent upstream to the nodes connected to the inward side of this node. - */ - protected[diplomacy] val uiParams: Seq[UI] - - /** Create a binding from this node to an [[OutwardNode]]. - * - * @param h The [[OutwardNode]] to bind to. - * @param binding [[NodeBinding]] the type of binding. - */ - protected[diplomacy] def bind(h: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit -} - -/** A Handle for OutwardNodes, which may appear on the right side of a bind operator. */ -trait OutwardNodeHandle[DO, UO, EO, BO <: Data] extends NoHandle { - /** @return [[OutwardNode]] of `outwardHandle`. */ - def outward: OutwardNode[DO, UO, BO] - - /** @return [[OutwardNodeImp]] of `inwardHandle`. */ - def outer: OutwardNodeImp[DO, UO, EO, BO] -} - -/** A Node that defines outward behavior, meaning that it can have edges coming out of it. */ -trait OutwardNode[DO, UO, BO <: Data] extends BaseNode { - /** Accumulates output connections. */ - private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters, SourceInfo)]() - - /** Initially set to `true`, this is set to false once [[oBindings]] is referenced. */ - private var oRealized = false - - /** @return debug information of [[oBindings]]. */ - def oBindingInfo: String = s"""${oBindings.size} outward nodes bound: [${oBindings.map(n => s"${n._3}-${n._2.name}").mkString(",")}]""" - - /** The accumulated number of output connections of this node. */ - protected[diplomacy] def oPushed: Int = accPO.size - - /** Accumulate an output connection. - * - * Can only be called before [[oBindings]] is accessed. - * - * @param index Index of this [[OutwardNode]] in that [[InwardNode]]. - * @param node [[InwardNode]] to bind to. - * @param binding Binding type. - */ - protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = { - val info = sourceLine(sourceInfo, " at ", "") - require (!oRealized, - s"""Diplomacy has detected a problem in your code: - |The following node was incorrectly connected as a source to ${node.name} after its .module was evaluated at $info. - |$context - |$oBindingInfo - |""".stripMargin) - accPO += ((index, node, binding, p, sourceInfo)) - } - - /** Ends the binding accumulation stage and returns all the output bindings to this node. - * - * Evaluating this lazy val will mark the outward bindings as frozen, - * preventing subsequent bindings from being created via [[oPush]]. - * - * The bindings are each a tuple of: - * - numeric index of this binding in the other end of [[InwardNode]]. - * - [[InwardNode]] on the other end of this binding - * - [[NodeBinding]] describing the type of binding - * - A view of [[Parameters]] where the binding occurred. - * - [[SourceInfo]] for source-level error reporting - */ - protected[diplomacy] lazy val oBindings: Seq[(Int, InwardNode[DO, UO, BO], NodeBinding, Parameters, SourceInfo)] = { oRealized = true; accPO.result() } - - /** resolved [[BIND_STAR]] binding of outward nodes: how many connections the star represents. */ - protected[diplomacy] val oStar: Int - - /** A mapping to convert Node binding index to port range. - * - * @return a sequence of tuple of mapping, the item in each a tuple of: - * - index: the index of connected [[InwardNode]] - * - element: port range of connected [[InwardNode]] - */ - protected[diplomacy] val oPortMapping: Seq[(Int, Int)] - - /** "Forward" an output connection through this node so that the node can be removed from the graph. - * - * @return None if no forwarding is needed. - */ - protected[diplomacy] def oForward(x: Int): Option[(Int, OutwardNode[DO, UO, BO])] = None - - /** Upward-flowing outward parameters. - * - * Generated from the nodes connected to the outward side of this node and sent upstream to this node. - */ - protected[diplomacy] val uoParams: Seq[UO] - - /** Downward-flowing outward parameters. - * - * Generated by this node and sent downstream to the nodes connected to the outward side of this node. - */ - protected[diplomacy] val doParams: Seq[DO] -} - -abstract class CycleException(kind: String, loop: Seq[String]) extends Exception(s"Diplomatic $kind cycle detected involving $loop") -case class StarCycleException(loop: Seq[String] = Nil) extends CycleException("star", loop) -case class DownwardCycleException(loop: Seq[String] = Nil) extends CycleException("downward", loop) -case class UpwardCycleException(loop: Seq[String] = Nil) extends CycleException("upward", loop) - -/** [[Edges]] is a collection of parameters describing the functionality and connection for an interface, - * which is often derived from the interconnection protocol and can inform the parameterization - * of the hardware bundles that actually implement the protocol. - */ -case class Edges[EI, EO](in: Seq[EI], out: Seq[EO]) - -/** The sealed node class in the package, all node are derived from it. - * - * @param inner Sink interface implementation. - * @param outer Source interface implementation. - * @param valName val name of this node. - * @tparam DI Downward-flowing parameters received on the inner side of the node. - * It is usually a brunch of parameters describing the protocol parameters from a source. - * For an [[InwardNode]], it is determined by the connected [[OutwardNode]]. - * Since it can be connected to multiple sources, this parameter is always a Seq of source port parameters. - * @tparam UI Upward-flowing parameters generated by the inner side of the node. - * It is usually a brunch of parameters describing the protocol parameters of a sink. - * For an [[InwardNode]], it is determined itself. - * @tparam EI Edge Parameters describing a connection on the inner side of the node. - * It is usually a brunch of transfers specified for a sink according to protocol. - * @tparam BI Bundle type used when connecting to the inner side of the node. - * It is a hardware interface of this sink interface. - * It should extends from [[chisel3.Data]], which represents the real hardware. - * @tparam DO Downward-flowing parameters generated on the outer side of the node. - * It is usually a brunch of parameters describing the protocol parameters of a source. - * For an [[OutwardNode]], it is determined itself. - * @tparam UO Upward-flowing parameters received by the outer side of the node. - * It is usually a brunch of parameters describing the protocol parameters from a sink. - * For an [[OutwardNode]], it is determined by the connected [[InwardNode]]. - * Since it can be connected to multiple sinks, this parameter is always a Seq of sink port parameters. - * @tparam EO Edge Parameters describing a connection on the outer side of the node. - * It is usually a brunch of transfers specified for a source according to protocol. - * @tparam BO Bundle type used when connecting to the outer side of the node. - * It is a hardware interface of this source interface. - * It should extends from [[chisel3.Data]], which represents the real hardware. - * - * @note Call Graph of [[MixedNode]] - * - line `─`: source is process by a function and generate pass to others - * - Arrow `→`: target of arrow is generated by source - * - * {{{ - * (from the other node) - * ┌─────────────────────────────────────────────────────────[[InwardNode.uiParams]]─────────────┐ - * ↓ │ - * (binding node when elaboration) [[OutwardNode.uoParams]]────────────────────────[[MixedNode.mapParamsU]]→──────────┐ │ - * [[InwardNode.accPI]] │ │ │ - * │ │ (based on protocol) │ - * │ │ [[MixedNode.inner.edgeI]] │ - * │ │ ↓ │ - * ↓ │ │ │ - * (immobilize after elaboration) (inward port from [[OutwardNode]]) │ ↓ │ - * [[InwardNode.iBindings]]──┐ [[MixedNode.iDirectPorts]]────────────────────→[[MixedNode.iPorts]] [[InwardNode.uiParams]] │ - * │ │ ↑ │ │ │ - * │ │ │ [[OutwardNode.doParams]] │ │ - * │ │ │ (from the other node) │ │ - * │ │ │ │ │ │ - * │ │ │ │ │ │ - * │ │ │ └────────┬──────────────┤ │ - * │ │ │ │ │ │ - * │ │ │ │ (based on protocol) │ - * │ │ │ │ [[MixedNode.inner.edgeI]] │ - * │ │ │ │ │ │ - * │ │ (from the other node) │ ↓ │ - * │ └───[[OutwardNode.oPortMapping]] [[OutwardNode.oStar]] │ [[MixedNode.edgesIn]]───┐ │ - * │ ↑ ↑ │ │ ↓ │ - * │ │ │ │ │ [[MixedNode.in]] │ - * │ │ │ │ ↓ ↑ │ - * │ (solve star connection) │ │ │ [[MixedNode.bundleIn]]──┘ │ - * ├───[[MixedNode.resolveStar]]→─┼─────────────────────────────┤ └────────────────────────────────────┐ │ - * │ │ │ [[MixedNode.bundleOut]]─┐ │ │ - * │ │ │ ↑ ↓ │ │ - * │ │ │ │ [[MixedNode.out]] │ │ - * │ ↓ ↓ │ ↑ │ │ - * │ ┌─────[[InwardNode.iPortMapping]] [[InwardNode.iStar]] [[MixedNode.edgesOut]]──┘ │ │ - * │ │ (from the other node) ↑ │ │ - * │ │ │ │ │ │ - * │ │ │ [[MixedNode.outer.edgeO]] │ │ - * │ │ │ (based on protocol) │ │ - * │ │ │ │ │ │ - * │ │ │ ┌────────────────────────────────────────┤ │ │ - * │ │ │ │ │ │ │ - * │ │ │ │ │ │ │ - * │ │ │ │ │ │ │ - * (immobilize after elaboration)│ ↓ │ │ │ │ - * [[OutwardNode.oBindings]]─┘ [[MixedNode.oDirectPorts]]───→[[MixedNode.oPorts]] [[OutwardNode.doParams]] │ │ - * ↑ (inward port from [[OutwardNode]]) │ │ │ │ - * │ ┌─────────────────────────────────────────┤ │ │ │ - * │ │ │ │ │ │ - * │ │ │ │ │ │ - * [[OutwardNode.accPO]] │ ↓ │ │ │ - * (binding node when elaboration) │ [[InwardNode.diParams]]─────→[[MixedNode.mapParamsD]]────────────────────────────┘ │ │ - * │ ↑ │ │ - * │ └──────────────────────────────────────────────────────────────────────────────────────────┘ │ - * └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - * }}} - */ -sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - val inner: InwardNodeImp [DI, UI, EI, BI], - val outer: OutwardNodeImp[DO, UO, EO, BO])( - implicit valName: ValName) - extends BaseNode with NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] { - // Generate a [[NodeHandle]] with inward and outward node are both this node. - val inward = this - val outward = this - - /** Debug info of nodes binding. */ - def bindingInfo: String = - s"""$iBindingInfo - |$oBindingInfo - |""".stripMargin - - /** Debug info of ports connecting. */ - def connectedPortsInfo: String = - s"""${oPorts.size} outward ports connected: [${oPorts.map(_._2.name).mkString(",")}] - |${iPorts.size} inward ports connected: [${iPorts.map(_._2.name).mkString(",")}] - |""".stripMargin - - /** Debug info of parameters propagations. */ - def parametersInfo: String = - s"""${doParams.size} downstream outward parameters: [${doParams.mkString(",")}] - |${uoParams.size} upstream outward parameters: [${uoParams.mkString(",")}] - |${diParams.size} downstream inward parameters: [${diParams.mkString(",")}] - |${uiParams.size} upstream inward parameters: [${uiParams.mkString(",")}] - |""".stripMargin - - /** For a given node, converts [[OutwardNode.accPO]] and [[InwardNode.accPI]] to [[MixedNode.oPortMapping]] and [[MixedNode.iPortMapping]]. - * - * Given counts of known inward and outward binding and inward and outward star bindings, return the resolved inward stars and outward stars. - * - * This method will also validate the arguments and throw a runtime error if the values are unsuitable for this type of node. - * - * @param iKnown Number of known-size ([[BIND_ONCE]]) input bindings. - * @param oKnown Number of known-size ([[BIND_ONCE]]) output bindings. - * @param iStar Number of unknown size ([[BIND_STAR]]) input bindings. - * @param oStar Number of unknown size ([[BIND_STAR]]) output bindings. - * @return A Tuple of the resolved number of input and output connections. - */ - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int) - - /** Function to generate downward-flowing outward params from the downward-flowing input params and the current output ports. - * - * @param n The size of the output sequence to generate. - * @param p Sequence of downward-flowing input parameters of this node. - * @return A `n`-sized sequence of downward-flowing output edge parameters. - */ - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] - - /** Function to generate upward-flowing input parameters from the upward-flowing output parameters [[uiParams]]. - * - * @param n Size of the output sequence. - * @param p Upward-flowing output edge parameters. - * @return A n-sized sequence of upward-flowing input edge parameters. - */ - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] - - /** @return The sink cardinality of the node, the number of outputs bound with [[BIND_QUERY]] summed with inputs bound with [[BIND_STAR]]. */ - protected[diplomacy] lazy val sinkCard: Int = oBindings.count(_._3 == BIND_QUERY) + iBindings.count(_._3 == BIND_STAR) - - /** @return The source cardinality of this node, the number of inputs bound with [[BIND_QUERY]] summed with the number of output bindings bound with [[BIND_STAR]]. */ - protected[diplomacy] lazy val sourceCard: Int = iBindings.count(_._3 == BIND_QUERY) + oBindings.count(_._3 == BIND_STAR) - - /** @return list of nodes involved in flex bindings with this node. */ - protected[diplomacy] lazy val flexes: Seq[BaseNode] = oBindings.filter(_._3 == BIND_FLEX).map(_._2) ++ iBindings.filter(_._3 == BIND_FLEX).map(_._2) - - /** Resolves the flex to be either source or sink and returns the offset where the [[BIND_STAR]] operators begin greedily taking up the remaining connections. - * - * @return A value >= 0 if it is sink cardinality, a negative value for source cardinality. The magnitude of the return value is not relevant. - */ - protected[diplomacy] lazy val flexOffset: Int = { - /** Recursively performs a depth-first search of the [[flexes]], - * [[BaseNode]]s connected to this node with flex operators. - * The algorithm bottoms out when we either get to a node we have already visited - * or when we get to a connection that is not a flex and can set the direction for us. - * Otherwise, recurse by visiting the `flexes` of each node in the current set - * and decide whether they should be added to the set or not. - * - * @return the mapping of [[BaseNode]] indexed by their serial numbers. - */ - def DFS(v: BaseNode, visited: Map[Int, BaseNode]): Map[Int, BaseNode] = { - if (visited.contains(v.serial) || !v.flexibleArityDirection) { - visited - } else { - v.flexes.foldLeft(visited + (v.serial -> v))((sum, n) => DFS(n, sum)) - } - } - - /** Determine which [[BaseNode]] are involved in resolving the flex connections to/from this node. - * - * @example - * {{{ - * a :*=* b :*=* c - * d :*=* b - * e :*=* f - * }}} - * - * `flexSet` for `a`, `b`, `c`, or `d` will be `Set(a, b, c, d)` - * `flexSet` for `e` or `f` will be `Set(e,f)` - */ - val flexSet = DFS(this, Map()).values - - /** The total number of :*= operators where we're on the left. */ - val allSink = flexSet.map(_.sinkCard).sum - - /** The total number of :=* operators used when we're on the right. */ - val allSource = flexSet.map(_.sourceCard).sum - - require (allSink == 0 || allSource == 0, - s"The nodes ${flexSet.map(_.name)} which are inter-connected by :*=* have ${allSink} :*= operators and ${allSource} :=* operators connected to them, making it impossible to determine cardinality inference direction.") - allSink - allSource - } - - /** @return A value >= 0 if it is sink cardinality, a negative value for source cardinality. */ - protected[diplomacy] def edgeArityDirection(n: BaseNode): Int = { - if ( flexibleArityDirection) flexOffset else - if (n.flexibleArityDirection) n.flexOffset else - 0 - } - - /** For a node which is connected between two nodes, select the one that will influence the direction of the flex resolution. */ - protected[diplomacy] def edgeAritySelect(n: BaseNode, l: => Int, r: => Int): Int = { - val dir = edgeArityDirection(n) - if (dir < 0) l else if (dir > 0) r else 1 - } - - /** Ensure that the same node is not visited twice in resolving `:*=`, etc operators. */ - private var starCycleGuard = false - - /** Resolve all the star operators into concrete indicies. - * As connections are being made, some may be "star" connections which need to be resolved. - * In some way to determine how many actual edges they correspond to. - * We also need to build up the ranges of edges which correspond to each binding operator, so that - * We can apply the correct edge parameters and later build up correct bundle connections. - * - * [[oPortMapping]]: `Seq[(Int, Int)]` where each item is the range of edges corresponding to that oPort (binding operator). - * [[iPortMapping]]: `Seq[(Int, Int)]` where each item is the range of edges corresponding to that iPort (binding operator). - * [[oStar]]: `Int` the value to return for this node `N` for any `N :*= foo` or `N :*=* foo :*= bar` - * [[iStar]]: `Int` the value to return for this node `N` for any `foo :=* N` or `bar :=* foo :*=* N` - */ - protected[diplomacy] lazy val (oPortMapping: Seq[(Int, Int)], iPortMapping: Seq[(Int, Int)], oStar: Int, iStar: Int) = { - try { - if (starCycleGuard) throw StarCycleException() - starCycleGuard = true - // For a given node N... - // Number of foo :=* N - // + Number of bar :=* foo :*=* N - val oStars = oBindings.count { case (_,n,b,_,_) => b == BIND_STAR || (b == BIND_FLEX && edgeArityDirection(n) < 0) } - // Number of N :*= foo - // + Number of N :*=* foo :*= bar - val iStars = iBindings.count { case (_,n,b,_,_) => b == BIND_STAR || (b == BIND_FLEX && edgeArityDirection(n) > 0) } - // 1 for foo := N - // + bar.iStar for bar :*= foo :*=* N - // + foo.iStar for foo :*= N - // + 0 for foo :=* N - val oKnown = oBindings.map { case (_, n, b, _, _) => b match { - case BIND_ONCE => 1 - case BIND_FLEX => edgeAritySelect(n, 0, n.iStar) - case BIND_QUERY => n.iStar - case BIND_STAR => 0 }}.sum - // 1 for N := foo - // + bar.oStar for N :*=* foo :=* bar - // + foo.oStar for N :=* foo - // + 0 for N :*= foo - val iKnown = iBindings.map { case (_, n, b, _, _) => b match { - case BIND_ONCE => 1 - case BIND_FLEX => edgeAritySelect(n, n.oStar, 0) - case BIND_QUERY => n.oStar - case BIND_STAR => 0 }}.sum - // Resolve star depends on the node subclass to implement the algorithm for this. - val (iStar, oStar) = resolveStar(iKnown, oKnown, iStars, oStars) - // Cumulative list of resolved outward binding range starting points - val oSum = oBindings.map { case (_, n, b, _, _) => b match { - case BIND_ONCE => 1 - case BIND_FLEX => edgeAritySelect(n, oStar, n.iStar) - case BIND_QUERY => n.iStar - case BIND_STAR => oStar }}.scanLeft(0)(_+_) - // Cumulative list of resolved inward binding range starting points - val iSum = iBindings.map { case (_, n, b, _, _) => b match { - case BIND_ONCE => 1 - case BIND_FLEX => edgeAritySelect(n, n.oStar, iStar) - case BIND_QUERY => n.oStar - case BIND_STAR => iStar }}.scanLeft(0)(_+_) - // Create ranges for each binding based on the running sums and return - // those along with resolved values for the star operations. - (oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar) - } catch { - case c: StarCycleException => throw c.copy(loop = context +: c.loop) - } - } - - /** Sequence of inward ports. - * - * This should be called after all star bindings are resolved. - * - * Each element is: - * `j` Port index of this binding in the Node's [[oPortMapping]] on the other side of the binding. - * `n` Instance of inward node. - * `p` View of [[Parameters]] where this connection was made. - * `s` Source info where this connection was made in the source code. - */ - protected[diplomacy] lazy val oDirectPorts: Seq[(Int, InwardNode[DO, UO, BO], Parameters, SourceInfo)] = oBindings.flatMap { case (i, n, _, p, s) => - // for each binding operator in this node, look at what it connects to - val (start, end) = n.iPortMapping(i) - (start until end) map { j => (j, n, p, s) } - } - - /** Sequence of outward ports. - * - * This should be called after all star bindings are resolved. - * - * `j` Port index of this binding in the Node's [[oPortMapping]] on the other side of the binding. - * `n` Instance of outward node. - * `p` View of [[Parameters]] where this connection was made. - * `s` [[SourceInfo]] where this connection was made in the source code. - */ - protected[diplomacy] lazy val iDirectPorts: Seq[(Int, OutwardNode[DI, UI, BI], Parameters, SourceInfo)] = iBindings.flatMap { case (i, n, _, p, s) => - // query this port index range of this node in the other side of node. - val (start, end) = n.oPortMapping(i) - (start until end) map { j => (j, n, p, s) } - } - - // Ephemeral nodes ( which have non-None iForward/oForward) have in_degree = out_degree - // Thus, there must exist an Eulerian path and the below algorithms terminate - @scala.annotation.tailrec - private def oTrace(tuple: (Int, InwardNode[DO, UO, BO], Parameters, SourceInfo)): (Int, InwardNode[DO, UO, BO], Parameters, SourceInfo) = - tuple match { case (i, n, p, s) => n.iForward(i) match { - case None => (i, n, p, s) - case Some ((j, m)) => oTrace((j, m, p, s)) - } } - - @scala.annotation.tailrec - private def iTrace(tuple: (Int, OutwardNode[DI, UI, BI], Parameters, SourceInfo)): (Int, OutwardNode[DI, UI, BI], Parameters, SourceInfo) = - tuple match { case (i, n, p, s) => n.oForward(i) match { - case None => (i, n, p, s) - case Some ((j, m)) => iTrace((j, m, p, s)) - } } - - /** Final output ports after all stars and port forwarding (e.g. [[EphemeralNode]]s) have been resolved. - * - * Each Port is a tuple of: - * - Numeric index of this binding in the [[InwardNode]] on the other end. - * - [[InwardNode]] on the other end of this binding. - * - A view of [[Parameters]] where the binding occurred. - * - [[SourceInfo]] for source-level error reporting. - */ - lazy val oPorts: Seq[(Int, InwardNode[DO, UO, BO], Parameters, SourceInfo)] = oDirectPorts.map(oTrace) - - /** Final input ports after all stars and port forwarding (e.g. [[EphemeralNode]]s) have been resolved. - * - * Each Port is a tuple of: - * - numeric index of this binding in [[OutwardNode]] on the other end. - * - [[OutwardNode]] on the other end of this binding. - * - a view of [[Parameters]] where the binding occurred. - * - [[SourceInfo]] for source-level error reporting. - */ - lazy val iPorts: Seq[(Int, OutwardNode[DI, UI, BI], Parameters, SourceInfo)] = iDirectPorts.map(iTrace) - - private var oParamsCycleGuard = false - protected[diplomacy] lazy val diParams: Seq[DI] = iPorts.map { case (i, n, _, _) => n.doParams(i) } - protected[diplomacy] lazy val doParams: Seq[DO] = { - try { - if (oParamsCycleGuard) throw DownwardCycleException() - oParamsCycleGuard = true - val o = mapParamsD(oPorts.size, diParams) - require (o.size == oPorts.size, - s"""Diplomacy has detected a problem with your graph: - |At the following node, the number of outward ports should equal the number of produced outward parameters. - |$context - |$connectedPortsInfo - |Downstreamed inward parameters: [${diParams.mkString(",")}] - |Produced outward parameters: [${o.mkString(",")}] - |""".stripMargin) - o.map(outer.mixO(_, this)) - } catch { - case c: DownwardCycleException => throw c.copy(loop = context +: c.loop) - } - } - - private var iParamsCycleGuard = false - protected[diplomacy] lazy val uoParams: Seq[UO] = oPorts.map { case (o, n, _, _) => n.uiParams(o) } - protected[diplomacy] lazy val uiParams: Seq[UI] = { - try { - if (iParamsCycleGuard) throw UpwardCycleException() - iParamsCycleGuard = true - val i = mapParamsU(iPorts.size, uoParams) - require (i.size == iPorts.size, - s"""Diplomacy has detected a problem with your graph: - |At the following node, the number of inward ports should equal the number of produced inward parameters. - |$context - |$connectedPortsInfo - |Upstreamed outward parameters: [${uoParams.mkString(",")}] - |Produced inward parameters: [${i.mkString(",")}] - |""".stripMargin) - i.map(inner.mixI(_, this)) - } catch { - case c: UpwardCycleException => throw c.copy(loop = context +: c.loop) - } - } - - /** Outward edge parameters. */ - protected[diplomacy] lazy val edgesOut: Seq[EO] = (oPorts zip doParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.uiParams(i), p, s) } - - /** Inward edge parameters. */ - protected[diplomacy] lazy val edgesIn: Seq[EI] = (iPorts zip uiParams).map { case ((o, n, p, s), i) => inner.edgeI(n.doParams(o), i, p, s) } - - /** A tuple of the input edge parameters and output edge parameters for the edges bound to this node. - * - * If you need to access to the edges of a foreign Node, use this method (in/out create bundles). - */ - lazy val edges: Edges[EI, EO] = Edges(edgesIn, edgesOut) - - /** Create actual Wires corresponding to the Bundles parameterized by the outward edges of this node. */ - protected[diplomacy] lazy val bundleOut: Seq[BO] = edgesOut.map { e => - val x = Wire(outer.bundleO(e)).suggestName(s"${valName.name}Out") - // TODO: Don't care unconnected forwarded diplomatic signals for compatibility issue, - // In the future, we should add an option to decide whether allowing unconnected in the LazyModule - x := DontCare - x - } - - /** Create actual Wires corresponding to the Bundles parameterized by the inward edges of this node. */ - protected[diplomacy] lazy val bundleIn: Seq[BI] = edgesIn .map { e => - val x = Wire(inner.bundleI(e)).suggestName(s"${valName.name}In") - // TODO: Don't care unconnected forwarded diplomatic signals for compatibility issue, - // In the future, we should add an option to decide whether allowing unconnected in the LazyModule - x := DontCare - x - } - - private def emptyDanglesOut: Seq[Dangle] = oPorts.zipWithIndex.map { case ((j, n, _, _), i) => - Dangle( - source = HalfEdge(serial, i), - sink = HalfEdge(n.serial, j), - flipped= false, - name = wirePrefix + "out", - dataOpt= None) - } - private def emptyDanglesIn: Seq[Dangle] = iPorts.zipWithIndex.map { case ((j, n, _, _), i) => - Dangle( - source = HalfEdge(n.serial, j), - sink = HalfEdge(serial, i), - flipped= true, - name = wirePrefix + "in", - dataOpt=None) - } - - - /** Create the [[Dangle]]s which describe the connections from this node output to other nodes inputs. */ - protected[diplomacy] def danglesOut: Seq[Dangle] = emptyDanglesOut.zipWithIndex.map { - case (d,i) => d.copy(dataOpt = Some(bundleOut(i))) - } - - /** Create the [[Dangle]]s which describe the connections from this node input from other nodes outputs. */ - protected[diplomacy] def danglesIn: Seq[Dangle] = emptyDanglesIn.zipWithIndex.map { - case (d,i) => d.copy(dataOpt = Some(bundleIn(i))) - } - - private[diplomacy] var instantiated = false - - /** Gather Bundle and edge parameters of outward ports. - * - * Accessors to the result of negotiation to be used within - * [[LazyModuleImp]] Code. Should only be used within [[LazyModuleImp]] code - * or after its instantiation has completed. - */ - def out: Seq[(BO, EO)] = { - require(instantiated, s"$name.out should not be called until after instantiation of its parent LazyModule.module has begun") - bundleOut zip edgesOut - } - - /** Gather Bundle and edge parameters of inward ports. - * - * Accessors to the result of negotiation to be used within - * [[LazyModuleImp]] Code. Should only be used within [[LazyModuleImp]] code - * or after its instantiation has completed. - */ - def in: Seq[(BI, EI)] = { - require(instantiated, s"$name.in should not be called until after instantiation of its parent LazyModule.module has begun") - bundleIn zip edgesIn - } - - /** Actually instantiate this node during [[LazyModuleImp]] evaluation. - * Mark that it's safe to use the Bundle wires, - * instantiate monitors on all input ports if appropriate, - * and return all the dangles of this node. - */ - protected[diplomacy] def instantiate(): Seq[Dangle] = { - instantiated = true - if (!circuitIdentity) { - (iPorts zip in) foreach { - case ((_, _, p, _), (b, e)) => if (p(MonitorsEnabled)) inner.monitor(b, e) - } } - danglesOut ++ danglesIn - } - - protected[diplomacy] def cloneDangles(): Seq[Dangle] = emptyDanglesOut ++ emptyDanglesIn - - /** Connects the outward part of a node with the inward part of this node. */ - protected[diplomacy] def bind(h: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = { - val x = this // x := y - val y = h - val info = sourceLine(sourceInfo, " at ", "") - val i = x.iPushed - val o = y.oPushed - y.oPush(i, x, binding match { - case BIND_ONCE => BIND_ONCE - case BIND_FLEX => BIND_FLEX - case BIND_STAR => BIND_QUERY - case BIND_QUERY => BIND_STAR - }) - x.iPush(o, y, binding) - } - - /* Metadata for printing the node graph. */ - def inputs: Seq[(OutwardNode[DI, UI, BI], RenderedEdge)] = (iPorts zip edgesIn) map { case ((_, n, p, _), e) => - val re = inner.render(e) - (n, re.copy(flipped = re.flipped != p(RenderFlipped))) - } - /** Metadata for printing the node graph */ - def outputs: Seq[(InwardNode[DO, UO, BO], RenderedEdge)] = oPorts map { case (i, n, _, _) => (n, n.inputs(i)._2) } -} - -/** A [[MixedNode]] that may be extended with custom behavior. */ -abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - inner: InwardNodeImp [DI, UI, EI, BI], - outer: OutwardNodeImp[DO, UO, EO, BO])( - implicit valName: ValName) - extends MixedNode(inner, outer) { - override def description = "custom" - def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) - def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] - def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] -} - -/** A [[NodeImp]] that may be extended with custom behavior. - * - * Different from a [[MixedNode]] in that the inner and outer [[NodeImp]]s are the same. - */ -abstract class CustomNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( - implicit valName: ValName) - extends MixedCustomNode(imp, imp) - -/** A JunctionNode creates multiple parallel arbiters. - * - * @example - * {{{ - * val jbar = LazyModule(new JBar) - * slave1.node := jbar.node - * slave2.node := jbar.node - * extras.node :=* jbar.node - * jbar.node :*= masters1.node - * jbar.node :*= masters2.node - * }}} - * - * In the above example, only the first two connections have their multiplicity specified. - * All the other connections include a '*' on the JBar's side, so the JBar decides the multiplicity. - * Thus, in this example, we get 2x crossbars with 2 masters like this: - * {slave1, extras.1} <= jbar.1 <= {masters1.1, masters2.1} - * {slave2, extras.2} <= jbar.2 <= {masters1.2, masters2,2} - * - * @example - * {{{ - * val jbar = LazyModule(new JBar) - * jbar.node :=* masters.node - * slaves1.node :=* jbar.node - * slaves2.node :=* jbar.node - * }}} - * In the above example, the first connection takes multiplicity (*) from the right (masters). - * Supposing masters.node had 3 edges, this would result in these three arbiters: - * {slaves1.1, slaves2.1} <= jbar.1 <= { masters.1 } - * {slaves1.2, slaves2.2} <= jbar.2 <= { masters.2 } - * {slaves1.3, slaves2.3} <= jbar.3 <= { masters.3 } - */ -class MixedJunctionNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - inner: InwardNodeImp [DI, UI, EI, BI], - outer: OutwardNodeImp[DO, UO, EO, BO])( - dFn: Seq[DI] => Seq[DO], - uFn: Seq[UO] => Seq[UI])( - implicit valName: ValName) - extends MixedNode(inner, outer) { - protected[diplomacy] var multiplicity = 0 - - def uRatio: Int = iPorts.size / multiplicity - def dRatio: Int = oPorts.size / multiplicity - - override def description = "junction" - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - require (iKnown == 0 || oKnown == 0, - s"""Diplomacy has detected a problem with your graph: - |The following node appears left of a :=* or a := and right of a :*= or :=. Only one side may drive multiplicity. - |$context - |$bindingInfo - |""".stripMargin) - multiplicity = iKnown max oKnown - (multiplicity, multiplicity) - } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = - p.grouped(multiplicity).toList.transpose.map(dFn).transpose.flatten - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = - p.grouped(multiplicity).toList.transpose.map(uFn).transpose.flatten - - def inoutGrouped: Seq[(Seq[(BI, EI)], Seq[(BO, EO)])] = { - val iGroups = in .grouped(multiplicity).toList.transpose - val oGroups = out.grouped(multiplicity).toList.transpose - iGroups zip oGroups - } -} - -/** A node type which has a fixed ratio between the number of input edges and output edges. - * - * The [[NodeImp]] on either side is the same. - * - * One example usage would be for putting down a series of 2:1 arbiters. - * - * Suppose you had N banks of L2 and wanted to connect those to two different driver crossbars. - * In that case you can do this: - * {{{ - * l2banks.node :*= jbar.node - * jbar.node :*= xbar1.node - * jbar.node :*= xbar2.node - * }}} - * If the L2 has 4 banks, now there are 4 egress ports on both xbar1 and xbar2 and they are arbitrated by the jbar. - */ -class JunctionNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( - dFn: Seq[D] => Seq[D], - uFn: Seq[U] => Seq[U])( - implicit valName: ValName) - extends MixedJunctionNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn) - -/** [[MixedAdapterNode]] is used to transform between different diplomacy protocols ([[NodeImp]]), without changing the number of edges passing through it. - * - * For example, a [[MixedAdapterNode]] is needed for a TL to AXI bridge (interface). - * {{{ - * case class TLToAXI4Node(stripBits: Int = 0)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AXI4Imp) - * }}} - * - * @param dFn convert downward parameter from input to output. - * @param uFn convert upward parameter from output to input. - */ -class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - inner: InwardNodeImp [DI, UI, EI, BI], - outer: OutwardNodeImp[DO, UO, EO, BO])( - dFn: DI => DO, - uFn: UO => UI)( - implicit valName: ValName) - extends MixedNode(inner, outer) { - override def description = "adapter" - protected[diplomacy] override def flexibleArityDirection = true - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - require (oStars + iStars <= 1, - s"""Diplomacy has detected a problem with your graph: - |The following node appears left of a :*= $iStars times and right of a :=* $oStars times, at most once is allowed. - |$context - |$bindingInfo - |""".stripMargin) - if (oStars > 0) { - require (iKnown >= oKnown, - s"""Diplomacy has detected a problem with your graph: - |After being connected right of :=*, the following node appears left of a := $iKnown times and right of a := $oKnown times. - |${iKnown - oKnown} additional right of := bindings are required to resolve :=* successfully. - |$context - |$bindingInfo - |""".stripMargin) - (0, iKnown - oKnown) - } else if (iStars > 0) { - require (oKnown >= iKnown, - s"""Diplomacy has detected a problem with your graph: - |After being connected left of :*=, the following node appears left of a := $iKnown times and right of a := $oKnown times. - |${oKnown - iKnown} additional left := bindings are required to resolve :*= successfully. - |$context - |$bindingInfo - |""".stripMargin) - (oKnown - iKnown, 0) - } else { - require (oKnown == iKnown, - s"""Diplomacy has detected a problem with your graph: - |The following node appears left of a := $iKnown times and right of a := $oKnown times. - |Either the number of bindings on both sides of the node match, or connect this node by left-hand side of :*= or right-hand side of :=* - |$context - |$bindingInfo - |""".stripMargin) - (0, 0) - } - } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { - require(n == p.size, - s"""Diplomacy has detected a problem with your graph: - |The following node has ${p.size} inputs and $n outputs, they must match. - |$context - |$bindingInfo - |""".stripMargin) - p.map(dFn) - } - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { - require(n == p.size, - s"""Diplomacy has detected a problem with your graph: - |The following node has $n inputs and ${p.size} outputs, they must match - |$context - |$bindingInfo - |""".stripMargin) - p.map(uFn) - } -} - -/** A node which modifies the parameters flowing through it, but without changing the number of edges or the diplomatic protocol implementation. */ -class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( - dFn: D => D, - uFn: U => U)( - implicit valName: ValName) - extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn) - -/** A node which does not modify the parameters nor the protocol for edges that pass through it. - * - * During hardware generation, [[IdentityNode]]s automatically connect their inputs to outputs. - */ -class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])()(implicit valName: ValName) - extends AdapterNode(imp)({ s => s }, { s => s }) { - override def description = "identity" - override final def circuitIdentity = true - override protected[diplomacy] def instantiate(): Seq[Dangle] = { - val dangles = super.instantiate() - (out zip in) foreach { case ((o, _), (i, _)) => o :<>= i } - dangles - } - override protected[diplomacy] def cloneDangles(): Seq[Dangle] = super.cloneDangles() -} - -/** [[EphemeralNode]]s are used as temporary connectivity placeholders, but disappear from the final node graph. - * An ephemeral node provides a mechanism to directly connect two nodes to each other where neither node knows about the other, - * but both know about an ephemeral node they can use to facilitate the connection. - */ -class EphemeralNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])()(implicit valName: ValName) - extends AdapterNode(imp)({ s => s }, { s => s }) { - override def description = "ephemeral" - override final def circuitIdentity = true - override def omitGraphML = true - override def oForward(x: Int): Option[(Int, OutwardNode[D, U, B])] = Some(iDirectPorts(x) match { case (i, n, _, _) => (i, n) }) - override def iForward(x: Int): Option[(Int, InwardNode[D, U, B])] = Some(oDirectPorts(x) match { case (i, n, _, _) => (i, n) }) - override protected[diplomacy] def instantiate(): Seq[Dangle] = { - instantiated = true - Nil - } - override protected[diplomacy] def cloneDangles(): Seq[Dangle] = Nil -} - -/** [[MixedNexusNode]] is used when the number of nodes connecting from either side is unknown (e.g. a Crossbar which also is a protocol adapter). - * - * The [[NodeImp]] is different between [[inner]] and [[outer]], - * - * @param dFn Function for mapping the parameters flowing downward into new outward flowing down parameters. - * @param uFn Function for mapping the parameters flowing upward into new inward flowing up parameters. - * @param inputRequiresOutput True if it is required that if there are input connections, there are output connections (this node can't just be a sink). - * @param outputRequiresInput True if it is required that if there are output connections, there are input connections (this node can't just be a source). - */ -class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - inner: InwardNodeImp [DI, UI, EI, BI], - outer: OutwardNodeImp[DO, UO, EO, BO])( - dFn: Seq[DI] => DO, - uFn: Seq[UO] => UI, - // no inputs and no outputs is always allowed - inputRequiresOutput: Boolean = true, - outputRequiresInput: Boolean = true)( - implicit valName: ValName) - extends MixedNode(inner, outer) -{ - override def description = "nexus" - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - // a nexus treats :=* as a weak pointer - def resolveStarInfo: String = - s"""$context - |$bindingInfo - |number of known := bindings to inward nodes: $iKnown - |number of known := bindings to outward nodes: $oKnown - |number of binding queries from inward nodes: $iStars - |number of binding queries from outward nodes: $oStars - |""".stripMargin - require(!outputRequiresInput || oKnown == 0 || iStars + iKnown != 0, - s"""Diplomacy has detected a problem with your graph: - |The following node has $oKnown outward connections and no inward connections. At least one inward connection was required. - |$resolveStarInfo - |""".stripMargin) - require(!inputRequiresOutput || iKnown == 0 || oStars + oKnown != 0, - s"""Diplomacy has detected a problem with your graph: - |The following node node has $iKnown inward connections and no outward connections. At least one outward connection was required. - |$resolveStarInfo - |""".stripMargin) - if (iKnown == 0 && oKnown == 0) (0, 0) else (1, 1) - } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { if (n > 0) { val a = dFn(p); Seq.fill(n)(a) } else Nil } - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { if (n > 0) { val a = uFn(p); Seq.fill(n)(a) } else Nil } -} - -/** [[NexusNode]] is a [[MixedNexusNode]], in which the inward and outward side of the node have the same [[NodeImp]] implementation. */ -class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( - dFn: Seq[D] => D, - uFn: Seq[U] => U, - inputRequiresOutput: Boolean = true, - outputRequiresInput: Boolean = true)( - implicit valName: ValName) - extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, inputRequiresOutput, outputRequiresInput) - -/** A node which represents a node in the graph which only has outward edges and no inward edges. - * - * A [[SourceNode]] cannot appear left of a `:=`, `:*=`, `:=*, or `:*=*` - * There are no Mixed [[SourceNode]]s, There are no "Mixed" [[SourceNode]]s because each one only has an outward side. - */ -class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])(implicit valName: ValName) - extends MixedNode(imp, imp) -{ - override def description = "source" - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - def resolveStarInfo: String = - s"""$context - |$bindingInfo - |number of known := bindings to inward nodes: $iKnown - |number of known := bindings to outward nodes: $oKnown - |number of binding queries from inward nodes: $iStars - |number of binding queries from outward nodes: $oStars - |${po.size} outward parameters: [${po.map(_.toString).mkString(",")}] - |""".stripMargin - require(oStars <= 1, - s"""Diplomacy has detected a problem with your graph: - |The following node appears right of a :=* $oStars times; at most once is allowed. - |$resolveStarInfo - |""".stripMargin) - require(iStars == 0, - s"""Diplomacy has detected a problem with your graph: - |The following node cannot appear left of a :*= - |$resolveStarInfo - |""".stripMargin) - require(iKnown == 0, - s"""Diplomacy has detected a problem with your graph: - |The following node cannot appear left of a := - |$resolveStarInfo - |""".stripMargin) - if (oStars == 0) - require(po.size == oKnown, - s"""Diplomacy has detected a problem with your graph: - |The following node has $oKnown outward bindings connected to it, but ${po.size} sources were specified to the node constructor. - |Either the number of outward := bindings should be exactly equal to the number of sources, or connect this node on the right-hand side of a :=* - |$resolveStarInfo - |""".stripMargin) - else - require(po.size >= oKnown, - s"""Diplomacy has detected a problem with your graph: - |The following node has $oKnown outward bindings connected to it, but ${po.size} sources were specified to the node constructor. - |To resolve :=*, size of outward parameters can not be less than bindings. - |$resolveStarInfo - |""".stripMargin - ) - (0, po.size - oKnown) - } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = po - protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = Seq() - - def makeIOs()(implicit valName: ValName): HeterogeneousBag[B] = { - val bundles = this.out.map(_._1) - val ios = IO(Flipped(new HeterogeneousBag(bundles))) - ios.suggestName(valName.name) - bundles.zip(ios).foreach { case (bundle, io) => bundle <> io } - ios - } -} - -/** A node which represents a node in the graph which has only inward edges, no outward edges. - * - * A [[SinkNode]] cannot appear cannot appear right of a `:=`, `:*=`, `:=*`, or `:*=*` - * - * There are no "Mixed" [[SinkNode]]s because each one only has an inward side. - */ -class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])(implicit valName: ValName) - extends MixedNode(imp, imp) -{ - override def description = "sink" - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - def resolveStarInfo: String = - s"""$context - |$bindingInfo - |number of known := bindings to inward nodes: $iKnown - |number of known := bindings to outward nodes: $oKnown - |number of binding queries from inward nodes: $iStars - |number of binding queries from outward nodes: $oStars - |${pi.size} inward parameters: [${pi.map(_.toString).mkString(",")}] - |""".stripMargin - require (iStars <= 1, - s"""Diplomacy has detected a problem with your graph: - |The following node appears left of a :*= $iStars times; at most once is allowed. - |$resolveStarInfo - |""".stripMargin) - require (oStars == 0, - s"""Diplomacy has detected a problem with your graph: - |The following node cannot appear right of a :=* - |$resolveStarInfo - |""".stripMargin) - require (oKnown == 0, - s"""Diplomacy has detected a problem with your graph: - |The following node cannot appear right of a := - |$resolveStarInfo - |""".stripMargin) - if (iStars == 0) - require(pi.size == iKnown, - s"""Diplomacy has detected a problem with your graph: - |The following node has $iKnown inward bindings connected to it, but ${pi.size} sinks were specified to the node constructor. - |Either the number of inward := bindings should be exactly equal to the number of sink, or connect this node on the left-hand side of a :*= - |$resolveStarInfo - |""".stripMargin) - else - require(pi.size >= iKnown, - s"""Diplomacy has detected a problem with your graph: - |The following node has $iKnown inward bindings connected to it, but ${pi.size} sinks were specified to the node constructor. - |To resolve :*=, size of inward parameters can not be less than bindings. - |$resolveStarInfo - |""".stripMargin - ) - (pi.size - iKnown, 0) - } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = Seq() - protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = pi - - def makeIOs()(implicit valName: ValName): HeterogeneousBag[B] = { - val bundles = this.in.map(_._1) - val ios = IO(new HeterogeneousBag(bundles)) - ios.suggestName(valName.name) - bundles.zip(ios).foreach { case (bundle, io) => io <> bundle } - ios - } -} - -/** A node intended to replace a portion of the diplomatic graph in order to test functionality of a copy (cloned) [[LazyModule]] - * - * @param node the node to copy - * @param clone the copy of the LazyModule containing [[node]] - */ -class MixedTestNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] protected[diplomacy]( - node: NodeHandle [DI, UI, EI, BI, DO, UO, EO, BO], clone: CloneLazyModule)( - implicit valName: ValName) - extends MixedNode(node.inner, node.outer) -{ - // The devices connected to this test node must recreate these parameters: - def iParams: Seq[DI] = node.inward .diParams - def oParams: Seq[UO] = node.outward.uoParams - - override def description = "test" - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - def resolveStarInfo: String = - s"""$context - |$bindingInfo - |number of known := bindings to inward nodes: $iKnown - |number of known := bindings to outward nodes: $oKnown - |number of binding queries from inward nodes: $iStars - |number of binding queries from outward nodes: $oStars - |downstream inward parameters: ${node.inward.diParams} - |upstream inward parameters: ${node.inward.uiParams} - |upstream outward parameters: ${node.outward.uoParams} - |downstream outward parameters: ${node.outward.doParams} - |node.inward.uiParams.size - |""".stripMargin - - require(oStars <= 1, - s"""Diplomacy has detected a problem with your graph: - |The following node appears right of a :=* $oStars times; at most once is allowed. - |$resolveStarInfo - |""".stripMargin) - require(iStars <= 1, - s"""Diplomacy has detected a problem with your graph: - |The following node appears left of a :*= $iStars times; at most once is allowed. - |$resolveStarInfo - |""".stripMargin) - require(node.inward .uiParams.size == iKnown || iStars == 1, - s"""Diplomacy has detected a problem with your graph: - |The following node has only $iKnown inputs, which should be ${node.inward.uiParams.size}, or connect this node on the left-hand side of :*= - |$resolveStarInfo - |""".stripMargin) - require(node.outward.doParams.size == oKnown || oStars == 1, - s"""Diplomacy has detected a problem with your graph: - |The following node has only $oKnown outputs, which should be ${node.outward.doParams.size}, or connect this node on the right-hand side of :=* - |$resolveStarInfo - |""".stripMargin) - (node.inward.uiParams.size - iKnown, node.outward.doParams.size - oKnown) - } - - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = node.inward .uiParams - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = node.outward.doParams - - override protected[diplomacy] def instantiate(): Seq[Dangle] = { - val dangles = super.instantiate() - val orig_module = clone.base.module - val clone_auto = clone.io("auto").asInstanceOf[AutoBundle] - - danglesOut.zipWithIndex.foreach { case (d, i) => - val orig = orig_module.dangles.find(_.source == HalfEdge(node.outward.serial, i)) - require (orig.isDefined, s"Cloned node ${node.outward.name} must be connected externally out ${orig_module.name}") - val io_name = orig_module.auto.elements.find(_._2 eq orig.get.data).get._1 - d.data <> clone_auto.elements(io_name) - } - danglesIn.zipWithIndex.foreach { case (d, i) => - val orig = orig_module.dangles.find(_.sink == HalfEdge(node.inward.serial, i)) - require (orig.isDefined, s"Cloned node ${node.inward.name} must be connected externally in ${orig_module.name}") - val io_name = orig_module.auto.elements.find(_._2 eq orig.get.data).get._1 - clone_auto.elements(io_name) <> d.data - } - - dangles - } - override protected[diplomacy] def cloneDangles(): Seq[Dangle] = { - require(false, "Unsupported") - super.cloneDangles() - } -} diff --git a/src/main/scala/diplomacy/ValName.scala b/src/main/scala/diplomacy/ValName.scala deleted file mode 100644 index bf0e5812298..00000000000 --- a/src/main/scala/diplomacy/ValName.scala +++ /dev/null @@ -1,12 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.diplomacy - -import freechips.rocketchip.macros.ValNameImpl - -case class ValName(name: String) - -object ValName -{ - implicit def materialize(implicit x: ValNameImpl): ValName = ValName(x.name) -} diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 5433147fae1..f6f0ed668a8 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -2,190 +2,15 @@ package freechips.rocketchip -import chisel3.experimental.{SourceInfo, SourceLine} import chisel3.Data +import chisel3.experimental.{SourceInfo, SourceLine} import org.chipsalliance.cde.config.Parameters -import scala.language.implicitConversions +import scala.language.implicitConversions -/** Diplomacy is a set of abstractions for describing directed, acyclic graphs - * where parameters will be negotiated between nodes. These abstractions are - * expressed in the form of abstract classes, traits, and type parameters, which - * comprises nearly all of the types defined in this package. - * - * The [[NodeImp]] ("node implementation") is the main abstract type that associates - * the type parameters of all other abstract types. Defining a concrete - * implementation of [[NodeImp]] will therefore determine concrete types for all - * type parameters. For example, passing in a concrete instance of NodeImp to a - * SourceNode will fully determine concrete types for all of a SourceNode's type - * parameters. - * - * Specific applications of Diplomacy are expected to either extend these types - * or to specify concrete types for the type parameters. This allows for - * creating and associating application-specific node, edge, parameter, and bundle types. - * - * - * =Concepts, metaphors, and mnemonics to help with understanding Diplomacy code= - * - * ==Parameter Types== - * - * There are several types of parameters involved in diplomacy code. - * - * - Upward-flowing/Downward-flowing Parameters: These parameter types flow along edges and can be considered as the - * pre-negotiated, unresolved parameters. - * - Edge Parameters: These parameters are the result of the diplomatic negotiation and that is resolved for each edge. - * They are metadata, or an abstract concept of the connection represented by their edge, and contain any sort. - * These are an abstract concept which carry any sort of conceptual information that is useful to pass along the graph edge. - * For example, the full address map visible from a given edge and the supported access types for each memory region. - * - "p" Parameters: These are parameters of type [[Parameters]] which are implicit and generally available - * in various stages of the diplomacy codebase. - * Often they are captured from the context in which a particular diplomatic node or edge is created or bound. - * - Bundle Parameters: These parameters are used for actual hardware generation of the [[chisel3.Data]]s which connect - * diplomatic components. In contrast to edge parameters, this may carry information like the width of an address - * or opcode field. - * While they are derived from Edge parameters holding all metadata computed over an edge, - * Bundle parameters often contain only concrete information required to create the hardware type, - * such as [[freechips.rocketchip.tilelink.TLBundleParameters]] and [[freechips.rocketchip.amba.axi4.AXI4BundleParameters]] - * - * ==Inward/Outward vs. Upward/Downward== - * - * Diplomacy defines two dimensions: inward/outward and upward/downward. - * - * Inward/outward refer to the direction of edges from the perspective of a given node. - * For a given node: - * - Inward refers to edges that point into itself. - * - Outward refers to edges that point out from itself. - * - * Therefore, a given edge is always described as inward to one node and as outward from another. - * - * Upward/downward refer to the direction of the overall directed acyclic graph. - * Because each each edge is directed, we say that the directions flow from sources (nodes that only have outward edges) - * downwards to sinks (nodes that only have inward edges), or from sinks upwards to sources. - * These terms are used in parameter negotiation, where parameters flow both - * upwards and downwards on edges. Note that diplomacy avoids terms like "master/slave", - * "producer/consumer", though these can be defined by the concrete implementations of diplomatic systems. - * Such terms imply something about the transactional behavior of agents within a protocol, - * whereas source/sink and up/down refer only to the structure of the graph and the flow of parameters. - * - Upward refers to the flow of parameters along edges in the upwards direction. - * - Downward refers to a flow of parameters along edges in the downwards direction. - * - * A useful mnemonic for distinguishing between upward and downward is to imagine - * a diplomatic graph as a literal network of rivers where water flows in the direction of the edges, - * and parameters that move in the upstream direction, - * while downward refers to parameters that move in the downstream direction. - * - * ==Acronyms== - * - * Diplomacy has some commonly used acronyms described below: - * D[IO], U[IO], E[IO], B[IO] are the types of parameters which will be propagated. - * D: Downwards -- parameters passed in the same direction as the edge. - * U: Upwards -- parameters passed in the opposite direction as the edge. - * E: Edge -- resolved (negotiated) parameters describing conceptual information on graph edges. - * B: Bundle should extends from [[chisel3.Data]]. - * - * {{{ - * - * - * Upwards (a.k.a. towards Sources) ↓ - * ↓ - * inward edge of (parameter) type EI ↓ - * created from parameters of type UI and DI ↓ - * will result in a Bundle of type BI ↓ - * ↓ - * ^ ↓ * - * . ↓ * - * ┌───────────────────────────────.──↓──*───────────────────────────────┐ - * │ . ↓ * BaseNode │ - * │ . ↓ * (NodeImp) │ - * │ . ↓ * │ - * │ ┌────────────────────────────.──↓──*────────────────────────────┐ │ - * │ │ . ↓ * InwardNode (InwardNodeImp)│ │ - * │ │ (mixI)↓ * │ │ - * │ │ . ↓ * │ │ - * │ │ Upward-flowing inwards . ↓ * Downward-Flowing inwards │ │ - * │ │ parameters of type UI . ↓ * parameters of type DI │ │ - * │ └────────────────────────────.──↓──*────────────────────────────┘ │ - * │ . ↓ * │ - * │ . I v │ - * │ (mapParamsU) (mapParamsD) │ - * │ ^ O + │ - * │ : ↓ + │ - * │ ┌────────────────────────────:──↓──+────────────────────────────┐ │ - * │ │ : ↓ + OutwardNode(OutwardNodeImp)│ │ - * │ │ : ↓ (mixO) │ │ - * │ │ : ↓ + │ │ - * │ │ Upward-flowing outwards : ↓ + Downward-Flowing outward │ │ - * │ │ parameters of type UO : ↓ + parameters of type DO │ │ - * │ └────────────────────────────:──↓──+────────────────────────────┘ │ - * │ : ↓ + │ - * │ : ↓ + │ - * └───────────────────────────────.──↓──*───────────────────────────────┘ - * : ↓ * - * : ↓ v - * ↓ outward edge of (parameter) type EO - * ↓ created from parameters of type UO and DO - * ↓ will result in a Bundle of type BO - * ↓ - * ↓ Downwards (a.k.a. towards Sinks) - * - * }}} - * - * == Handles == - * - * Two Diplomatic nodes can be bound together using the `:=` operator or one of - * its sibling operators. Binding is asymmetric, and the binding operation will - * connect the outward of one node to the inward of the other. - * - * For example, the expression `a := b` will connect the outward of `b` to the - * inward of `a`. - * - * We would like the `:=` operator to have additional properties that make it - * intuitive to use: - * - * 1. It should be chainable, so that `a := b := c` will have the intuitive effect - * of binding c to b and b to a. This requires that the return type of `:=` be the - * same as its arguments, because the result of one `:=` operation must be - * valid as an argument to other `:=` operations. - * - * 2. It should be associative, so that `(a := b) := c` is equivalent to `a := (b := c).` - * This means that the order in which the bind operations execute does - * not matter, even if split across multiple files. - * - * 3. `a := b` should only be allowed if and only if `b` allows outward edges and `a` - * allows inward edges. This should be preserved even when chaining - * operations, and it should ideally be enforced at compile time. - * - * [[NodeHandle]] are a way of satisfying all of these properties. A Handle represents - * the aggregation of a chain of Nodes, and it preserves information about - * the connectability of the innermost and the outermost sides of the chain. - * - * If `b` supports inward edges, then `a := b` returns a [[NodeHandle]] that supports inward - * edges that go into `b`. If `a` supports outward edges, then `a := b` returns a - * [[NodeHandle]] that supports outward edges coming out of `a`. - * - * ==Node Terms== - * - * These are some conventionally used terms for diplomatic Nodes, - * which describe different common subtypes that certain protocol implementation might utilize: - * - Mixed: implies that the inward and outward NodeImp are not the same (some sort of protocol conversion is occurring between the two implementations). - * - Adapter: the number of inward and outward edges must be the same. - * - Nexus: the number of nodes connecting from either side are unknown until the graph is constructed and can differ from one another. - * - Identity: modifies neither the parameters nor the protocol-specific circuitry for the edges that pass through it. - * - Source: cannot have inward edges. - * - Sink: cannot have outward edges. - * - Junction: the number of inward and outward edges must have a fixed ratio to one another - * - Ephemeral: a temporary placeholder used for connectivity operations +/** Rocketchip Specific Diplomacy code. All other Diplomacy core functionality has been moved to standalone diplomacy */ -package object diplomacy -{ - type SimpleNodeHandle[D, U, E, B <: Data] = NodeHandle[D, U, E, B, D, U, E, B] - type AnyMixedNode = MixedNode[_, _, _, _ <: Data, _, _, _, _ <: Data] - - def sourceLine(sourceInfo: SourceInfo, prefix: String = " (", suffix: String = ")") = sourceInfo match { - case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix" - case _ => "" - } - +package object diplomacy { def bitIndexes(x: BigInt, tail: Seq[Int] = Nil): Seq[Int] = { require (x >= 0) if (x == 0) { @@ -196,47 +21,290 @@ package object diplomacy } } - implicit class BigIntHexContext(private val sc: StringContext) extends AnyVal { - def x(args: Any*): BigInt = { - val orig = sc.s(args: _*) - BigInt(orig.replace("_", ""), 16) - } - } - - type PropertyOption = Option[(String, Seq[ResourceValue])] - type PropertyMap = Iterable[(String, Seq[ResourceValue])] - - implicit class IntToProperty(x: Int) { - def asProperty: Seq[ResourceValue] = Seq(ResourceInt(BigInt(x))) - } - - implicit class BigIntToProperty(x: BigInt) { - def asProperty: Seq[ResourceValue] = Seq(ResourceInt(x)) + // TODO - Remove compatibility layer for deprecated diplomacy api once all local references are moved to standalone diplomacy lib. + // package.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def sourceLine(sourceInfo: SourceInfo, prefix: String = " (", suffix: String = ")") = sourceInfo match { + case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix" + case _ => "" } + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def EnableMonitors[T]( + body: Parameters => T + )( + implicit p: Parameters + ) = _root_.org.chipsalliance.diplomacy.EnableMonitors(body)(p) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def DisableMonitors[T]( + body: Parameters => T + )( + implicit p: Parameters + ) = _root_.org.chipsalliance.diplomacy.DisableMonitors(body)(p) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def FlipRendering[T]( + body: Parameters => T + )( + implicit p: Parameters + ) = _root_.org.chipsalliance.diplomacy.FlipRendering(body)(p) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + implicit def moduleValue[T](value: ModuleValue[T]): T = _root_.org.chipsalliance.diplomacy.moduleValue(value) - implicit class StringToProperty(x: String) { - def asProperty: Seq[ResourceValue] = Seq(ResourceString(x)) - } +// Clone.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val CloneLazyModule = _root_.org.chipsalliance.diplomacy.lazymodule.CloneLazyModule - implicit class DeviceToProperty(x: Device) { - def asProperty: Seq[ResourceValue] = Seq(ResourceReference(x.label)) - } +// ValName.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type ValName = _root_.org.chipsalliance.diplomacy.ValName + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def ValName(value: String) = _root_.org.chipsalliance.diplomacy.ValName(value) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + implicit def SourcecodeNameExt(x: sourcecode.Name) = _root_.org.chipsalliance.diplomacy.SourcecodeNameExt(x) - def EnableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { - case MonitorsEnabled => true - }) - def DisableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { - case MonitorsEnabled => false - }) - def FlipRendering[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { - case RenderFlipped => !p(RenderFlipped) - }) +// LazyModule.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type LazyModule = _root_.org.chipsalliance.diplomacy.lazymodule.LazyModule + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val LazyModule = _root_.org.chipsalliance.diplomacy.lazymodule.LazyModule + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type LazyModuleImpLike = _root_.org.chipsalliance.diplomacy.lazymodule.LazyModuleImpLike + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type LazyModuleImp = _root_.org.chipsalliance.diplomacy.lazymodule.LazyModuleImp + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type LazyRawModuleImp = _root_.org.chipsalliance.diplomacy.lazymodule.LazyRawModuleImp + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type SimpleLazyModule = _root_.org.chipsalliance.diplomacy.lazymodule.SimpleLazyModule + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type LazyScope = _root_.org.chipsalliance.diplomacy.lazymodule.LazyScope + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val LazyScope = _root_.org.chipsalliance.diplomacy.lazymodule.LazyScope + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type ModuleValue[T] = _root_.org.chipsalliance.diplomacy.lazymodule.ModuleValue[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val InModuleBody = _root_.org.chipsalliance.diplomacy.lazymodule.InModuleBody - implicit def moduleValue[T](value: ModuleValue[T]): T = value.getWrappedValue +// Nodes.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type Dangle = _root_.org.chipsalliance.diplomacy.nodes.Dangle + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val Dangle = _root_.org.chipsalliance.diplomacy.nodes.Dangle + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type HalfEdge = _root_.org.chipsalliance.diplomacy.nodes.HalfEdge + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val HalfEdge = _root_.org.chipsalliance.diplomacy.nodes.HalfEdge + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val MonitorsEnabled = _root_.org.chipsalliance.diplomacy.nodes.MonitorsEnabled + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val RenderFlipped = _root_.org.chipsalliance.diplomacy.nodes.RenderFlipped + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val RenderedEdge = _root_.org.chipsalliance.diplomacy.nodes.RenderedEdge + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type RenderedEdge = _root_.org.chipsalliance.diplomacy.nodes.RenderedEdge + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type InwardNodeImp[DI, UI, EI, BI <: Data] = _root_.org.chipsalliance.diplomacy.nodes.InwardNodeImp[DI, UI, EI, BI] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type OutwardNodeImp[DO, UO, EO, BO <: Data] = _root_.org.chipsalliance.diplomacy.nodes.OutwardNodeImp[DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NodeImp[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.NodeImp[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type SimpleNodeImp[D, U, E, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.SimpleNodeImp[D, U, E, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BaseNode = _root_.org.chipsalliance.diplomacy.nodes.BaseNode + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BaseNode = _root_.org.chipsalliance.diplomacy.nodes.BaseNode + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type FormatEdge = _root_.org.chipsalliance.diplomacy.nodes.FormatEdge + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type FormatNode[I <: FormatEdge, O <: FormatEdge] = _root_.org.chipsalliance.diplomacy.nodes.FormatNode[I, O] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NoHandle = _root_.org.chipsalliance.diplomacy.nodes.NoHandle + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val NoHandleObject = _root_.org.chipsalliance.diplomacy.nodes.NoHandleObject + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NodeHandle[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val NodeHandle = _root_.org.chipsalliance.diplomacy.nodes.NodeHandle + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NodeHandlePair[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.NodeHandlePair[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type InwardNodeHandle[DI, UI, EI, BI <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.InwardNodeHandle[DI, UI, EI, BI] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NodeBinding = _root_.org.chipsalliance.diplomacy.nodes.NodeBinding + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BIND_ONCE = _root_.org.chipsalliance.diplomacy.nodes.BIND_ONCE + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BIND_QUERY = _root_.org.chipsalliance.diplomacy.nodes.BIND_QUERY + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BIND_STAR = _root_.org.chipsalliance.diplomacy.nodes.BIND_STAR + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BIND_FLEX = _root_.org.chipsalliance.diplomacy.nodes.BIND_FLEX + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type InwardNode[DI, UI, BI <: Data] = _root_.org.chipsalliance.diplomacy.nodes.InwardNode[DI, UI, BI] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type OutwardNodeHandle[DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.OutwardNodeHandle[DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type OutwardNode[DO, UO, BO <: Data] = _root_.org.chipsalliance.diplomacy.nodes.OutwardNode[DO, UO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type CycleException = _root_.org.chipsalliance.diplomacy.nodes.CycleException + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type StarCycleException = _root_.org.chipsalliance.diplomacy.nodes.StarCycleException + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type DownwardCycleException = _root_.org.chipsalliance.diplomacy.nodes.DownwardCycleException + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type UpwardCycleException = _root_.org.chipsalliance.diplomacy.nodes.UpwardCycleException + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val Edges = _root_.org.chipsalliance.diplomacy.nodes.Edges + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type Edges[EI, EO] = _root_.org.chipsalliance.diplomacy.nodes.Edges[EI, EO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.MixedCustomNode[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type CustomNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.CustomNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type MixedJunctionNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.MixedJunctionNode[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type JunctionNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.JunctionNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.MixedAdapterNode[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type AdapterNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.AdapterNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type IdentityNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.IdentityNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type EphemeralNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.EphemeralNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] = + _root_.org.chipsalliance.diplomacy.nodes.MixedNexusNode[DI, UI, EI, BI, DO, UO, EO, BO] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type NexusNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.NexusNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type SourceNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.SourceNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type SinkNode[D, U, EO, EI, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.SinkNode[D, U, EO, EI, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type SimpleNodeHandle[D, U, E, B <: Data] = _root_.org.chipsalliance.diplomacy.nodes.SimpleNodeHandle[D, U, E, B] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type AnyMixedNode = _root_.org.chipsalliance.diplomacy.nodes.AnyMixedNode - implicit def noCrossing(value: NoCrossing.type): ClockCrossingType = SynchronousCrossing(BufferParams.none) +// BundleBridge.scala + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeParams[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeParams[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeParams = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeParams + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeEdgeParams[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeEdgeParams[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeImp[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeImp[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeSink[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeSink[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeSink = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeSink + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeSource[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeSource[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeSource = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeSource + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeIdentityNode[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeIdentityNode[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeIdentityNode = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeIdentityNode + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeEphemeralNode[T <: Data] = + _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeEphemeralNode[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeEphemeralNode = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeEphemeralNode + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def BundleBridgeNameNode[T <: Data](name: String) = + _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNameNode[T](name) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeNexusNode[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexusNode[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeNexus[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexus[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + val BundleBridgeNexus = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexus + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + def BundleBroadcast[T <: Data]( + name: Option[String] = None, + registered: Boolean = false, + default: Option[() => T] = None, + inputRequiresOutput: Boolean = false, // when false, connecting a source does not mandate connecting a sink + shouldBeInlined: Boolean = true + )( + implicit p: Parameters + ) = _root_.org.chipsalliance.diplomacy.bundlebridge + .BundleBroadcast[T](name, registered, default, inputRequiresOutput, shouldBeInlined)(p) + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeInwardNode[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeInwardNode[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeOutwardNode[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeOutwardNode[T] + @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") + type BundleBridgeNode[T <: Data] = _root_.org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNode[T] - type BundleBridgeInwardNode[T <: Data] = InwardNodeHandle[BundleBridgeParams[T], BundleBridgeParams[T], BundleBridgeEdgeParams[T], T] - type BundleBridgeOutwardNode[T <: Data] = OutwardNodeHandle[BundleBridgeParams[T], BundleBridgeParams[T], BundleBridgeEdgeParams[T], T] - type BundleBridgeNode[T <: Data] = NodeHandle[BundleBridgeParams[T], BundleBridgeParams[T], BundleBridgeEdgeParams[T], T, BundleBridgeParams[T], BundleBridgeParams[T], BundleBridgeEdgeParams[T], T] +// Resources.scala + @deprecated("Use freechips.rocketchip.resources.ResourcePermissions", "rocketchip 2.0.0") + type ResourcePermissions = freechips.rocketchip.resources.ResourcePermissions + @deprecated("Use freechips.rocketchip.resources.Resource", "rocketchip 2.0.0") + type Resource = freechips.rocketchip.resources.Resource + @deprecated("Use freechips.rocketchip.resources.Resource", "rocketchip 2.0.0") + val Resource = freechips.rocketchip.resources.Resource + @deprecated("Use freechips.rocketchip.resources.ResourceAnchors", "rocketchip 2.0.0") + val ResourceAnchors = freechips.rocketchip.resources.ResourceAnchors + @deprecated("Use freechips.rocketchip.resources.ResourceAlias", "rocketchip 2.0.0") + type ResourceAlias = freechips.rocketchip.resources.ResourceAlias + @deprecated("Use freechips.rocketchip.resources.ResourceAlias", "rocketchip 2.0.0") + val ResourceAlias = freechips.rocketchip.resources.ResourceAlias + @deprecated("Use freechips.rocketchip.resources.ResourceMapping", "rocketchip 2.0.0") + type ResourceMapping = freechips.rocketchip.resources.ResourceMapping + @deprecated("Use freechips.rocketchip.resources.ResourceMapping", "rocketchip 2.0.0") + val ResourceMapping = freechips.rocketchip.resources.ResourceMapping + @deprecated("Use freechips.rocketchip.resources.ResourceMap", "rocketchip 2.0.0") + type ResourceMap = freechips.rocketchip.resources.ResourceMap + @deprecated("Use freechips.rocketchip.resources.ResourceMap", "rocketchip 2.0.0") + val ResourceMap = freechips.rocketchip.resources.ResourceMap + @deprecated("Use freechips.rocketchip.resources.ResourceReference", "rocketchip 2.0.0") + type ResourceReference = freechips.rocketchip.resources.ResourceReference + @deprecated("Use freechips.rocketchip.resources.ResourceReference", "rocketchip 2.0.0") + val ResourceReference = freechips.rocketchip.resources.ResourceReference + @deprecated("Use freechips.rocketchip.resources.ResourceAddress", "rocketchip 2.0.e0") + type ResourceAddress = freechips.rocketchip.resources.ResourceAddress + @deprecated("Use freechips.rocketchip.resources.ResourceAddress", "rocketchip 2.0.0") + val ResourceAddress = freechips.rocketchip.resources.ResourceAddress + @deprecated("Use freechips.rocketchip.resources.ResourceValue", "rocketchip 2.0.0") + type ResourceValue = freechips.rocketchip.resources.ResourceValue + @deprecated("Use freechips.rocketchip.resources.ResourceBinding", "rocketchip 2.0.0") + val ResourceBinding = freechips.rocketchip.resources.ResourceBinding + @deprecated("Use freechips.rocketchip.resources.ResourceBindings", "rocketchip 2.0.0") + type ResourceBindings = freechips.rocketchip.resources.ResourceBindings + @deprecated("Use freechips.rocketchip.resources.BindingScope", "rocketchip 2.0.0") + type BindingScope = freechips.rocketchip.resources.BindingScope + @deprecated("Use freechips.rocketchip.resources.Binding", "rocketchip 2.0.0") + type Binding = freechips.rocketchip.resources.Binding + @deprecated("Use freechips.rocketchip.resources.Binding", "rocketchip 2.0.0") + val Binding = freechips.rocketchip.resources.Binding + @deprecated("Use freechips.rocketchip.resources.ResourceInt", "rocketchip 2.0.0") + type ResourceInt = freechips.rocketchip.resources.ResourceInt + @deprecated("Use freechips.rocketchip.resources.ResourceInt", "rocketchip 2.0.0") + val ResourceInt = freechips.rocketchip.resources.ResourceInt + @deprecated("Use freechips.rocketchip.resources.ResourceString", "rocketchip 2.0.0") + type ResourceString = freechips.rocketchip.resources.ResourceString + @deprecated("Use freechips.rocketchip.resources.ResourceString", "rocketchip 2.0.0") + val ResourceString = freechips.rocketchip.resources.ResourceString + @deprecated("Use freechips.rocketchip.resources.SimpleDevice", "rocketchip 2.0.0") + type SimpleDevice = freechips.rocketchip.resources.SimpleDevice + @deprecated("Use freechips.rocketchip.resources.MemoryDevice", "rocketchip 2.0.0") + type MemoryDevice = freechips.rocketchip.resources.MemoryDevice + @deprecated("Use freechips.rocketchip.resources.Device", "rocketchip 2.0.0") + type Device = freechips.rocketchip.resources.Device + @deprecated("Use freechips.rocketchip.resources.Description", "rocketchip 2.0.0") + type Description = freechips.rocketchip.resources.Description + @deprecated("Use freechips.rocketchip.resources.Description", "rocketchip 2.0.0") + val Description = freechips.rocketchip.resources.Description + @deprecated("Use freechips.rocketchip.resources.SimpleBus", "rocketchip 2.0.0") + type SimpleBus = freechips.rocketchip.resources.SimpleBus } diff --git a/src/main/scala/examples/ExampleDevice.scala b/src/main/scala/examples/ExampleDevice.scala index ffdb69f8d2c..7358c6bdcdd 100644 --- a/src/main/scala/examples/ExampleDevice.scala +++ b/src/main/scala/examples/ExampleDevice.scala @@ -3,10 +3,12 @@ package freechips.rocketchip.examples import chisel3._ -import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.amba.ahb.HasAHBControlRegMap import freechips.rocketchip.amba.axi4.HasAXI4ControlRegMap -import freechips.rocketchip.diplomacy.LazyModuleImp import freechips.rocketchip.interrupts.HasInterruptSources import freechips.rocketchip.tilelink.HasTLControlRegMap import freechips.rocketchip.regmapper.{IORegisterRouter, RegisterRouterParams, RegField, RegFieldDesc} diff --git a/src/main/scala/formal/FormalUtils.scala b/src/main/scala/formal/FormalUtils.scala index 2df69574d58..07922d789fc 100644 --- a/src/main/scala/formal/FormalUtils.scala +++ b/src/main/scala/formal/FormalUtils.scala @@ -2,9 +2,10 @@ package freechips.rocketchip.formal import chisel3._ -import chisel3.util._ import chisel3.experimental.{SourceInfo, SourceLine} -import org.chipsalliance.cde.config.Field +import chisel3.util._ + +import org.chipsalliance.cde.config._ sealed abstract class MonitorDirection(name: String) { override def toString: String = name diff --git a/src/main/scala/groundtest/Configs.scala b/src/main/scala/groundtest/Configs.scala index bb0ccd71ab5..e9b00689aa9 100644 --- a/src/main/scala/groundtest/Configs.scala +++ b/src/main/scala/groundtest/Configs.scala @@ -3,13 +3,13 @@ package freechips.rocketchip.groundtest -import org.chipsalliance.cde.config.Config +import org.chipsalliance.cde.config._ + import freechips.rocketchip.devices.tilelink.{CLINTKey, PLICKey} import freechips.rocketchip.devices.debug.{DebugModuleKey} import freechips.rocketchip.subsystem._ import freechips.rocketchip.system.BaseConfig import freechips.rocketchip.rocket.{DCacheParams} -import freechips.rocketchip.tile.{XLen} /** Actual testing target Configs */ @@ -30,27 +30,27 @@ class GroundTestBaseConfig extends Config( case DebugModuleKey => None case CLINTKey => None case PLICKey => None - case SubsystemExternalResetVectorKey => true + case HasTilesExternalResetVectorKey => true }) ) class WithTraceGen( n: Int = 2, - overrideIdOffset: Option[Int] = None, overrideMemOffset: Option[BigInt] = None)( params: Seq[DCacheParams] = List.fill(n){ DCacheParams(nSets = 16, nWays = 1) }, - nReqs: Int = 8192 + nReqs: Int = 8192, + wordBits: Int = 32 ) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => { val prev = up(TilesLocated(InSubsystem), site) - val idOffset = overrideIdOffset.getOrElse(prev.size) + val idOffset = up(NumTiles) val memOffset: BigInt = overrideMemOffset.orElse(site(ExtMem).map(_.master.base)).getOrElse(0x0L) params.zipWithIndex.map { case (dcp, i) => TraceGenTileAttachParams( tileParams = TraceGenParams( - hartId = i + idOffset, + tileId = i + idOffset, dcache = Some(dcp), - wordBits = site(XLen), + wordBits = wordBits, addrBits = 32, addrBag = { val nSets = dcp.nSets @@ -68,4 +68,5 @@ class WithTraceGen( ) } ++ prev } + case NumTiles => up(NumTiles) + n }) diff --git a/src/main/scala/groundtest/DummyPTW.scala b/src/main/scala/groundtest/DummyPTW.scala index ce95b826d83..4dadd95a739 100644 --- a/src/main/scala/groundtest/DummyPTW.scala +++ b/src/main/scala/groundtest/DummyPTW.scala @@ -4,9 +4,9 @@ package freechips.rocketchip.groundtest import chisel3._ -import chisel3.util.{RRArbiter, Valid, log2Up, RegEnable} +import chisel3.util._ -import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.cde.config._ import freechips.rocketchip.rocket._ import freechips.rocketchip.tile.CoreModule import freechips.rocketchip.util.ParameterizedBundle diff --git a/src/main/scala/groundtest/GroundTestSubsystem.scala b/src/main/scala/groundtest/GroundTestSubsystem.scala index ba3215f7f53..11263966ebf 100644 --- a/src/main/scala/groundtest/GroundTestSubsystem.scala +++ b/src/main/scala/groundtest/GroundTestSubsystem.scala @@ -3,20 +3,30 @@ package freechips.rocketchip.groundtest import chisel3._ -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} -import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple} -import freechips.rocketchip.subsystem.{BaseSubsystem, BaseSubsystemModuleImp, HasTiles, CanHaveMasterAXI4MemPort} + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet + +import freechips.rocketchip.interrupts._ +import freechips.rocketchip.tile.{NMI} +import freechips.rocketchip.devices.tilelink.{CLINTConsts} +import freechips.rocketchip.subsystem._ import freechips.rocketchip.tilelink.{TLRAM, TLFragmenter} import freechips.rocketchip.interrupts.{NullIntSyncSource} class GroundTestSubsystem(implicit p: Parameters) extends BaseSubsystem - with HasTiles + with InstantiatesHierarchicalElements + with HasHierarchicalElementsRootContext + with HasHierarchicalElements + with HasTileNotificationSinks + with HasTileInputConstants with CanHaveMasterAXI4MemPort { - val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), beatBytes=pbus.beatBytes)) - pbus.coupleTo("TestRAM") { testram.node := TLFragmenter(pbus) := _ } + val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), beatBytes=tlBusWrapperLocationMap.get(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location)))).beatBytes)) + tlBusWrapperLocationMap.lift(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location)))).coupleTo("TestRAM") { testram.node := TLFragmenter(tlBusWrapperLocationMap.lift(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location))))) := _ } // No cores to monitor def coreMonitorBundles = Nil @@ -24,16 +34,18 @@ class GroundTestSubsystem(implicit p: Parameters) // No PLIC in ground test; so just sink the interrupts to nowhere IntSinkNode(IntSinkPortSimple()) :=* ibus.toPLIC - val tileStatusNodes = tiles.collect { case t: GroundTestTile => t.statusNode.makeSink() } - - // no debug module - val debugNode = NullIntSyncSource() + val tileStatusNodes = totalTiles.values.collect { case t: GroundTestTile => t.statusNode.makeSink() } + val clintOpt = None + val clintDomainOpt = None + val debugOpt = None + val plicOpt = None + val plicDomainOpt = None override lazy val module = new GroundTestSubsystemModuleImp(this) } class GroundTestSubsystemModuleImp[+L <: GroundTestSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) { val success = IO(Output(Bool())) - val status = dontTouch(DebugCombiner(outer.tileStatusNodes.map(_.bundle))) - success := outer.tileCeaseSinkNode.in.head._1.asUInt.andR + val status = dontTouch(DebugCombiner(_outer.tileStatusNodes.map(_.bundle).toSeq)) + success := _outer.tileCeaseSinkNode.in.head._1.asUInt.andR } diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index 2db67efbee7..348df5beb50 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -3,8 +3,10 @@ package freechips.rocketchip.groundtest import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.LazyModule + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.system.SimAXIMem class TestHarness(implicit p: Parameters) extends Module { diff --git a/src/main/scala/groundtest/Tile.scala b/src/main/scala/groundtest/Tile.scala index 912016f8ea4..c9516ab4965 100644 --- a/src/main/scala/groundtest/Tile.scala +++ b/src/main/scala/groundtest/Tile.scala @@ -4,8 +4,13 @@ package freechips.rocketchip.groundtest import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.prci.{ClockCrossingType} import freechips.rocketchip.interrupts._ import freechips.rocketchip.rocket.{BuildHellaCache, DCache, DCacheModule, ICacheParams, NonBlockingDCache, NonBlockingDCacheModule, RocketCoreParams} import freechips.rocketchip.tile._ @@ -34,7 +39,7 @@ abstract class GroundTestTile( with SourcesExternalNotifications { val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil) - val intOutwardNode: IntOutwardNode = IntIdentityNode() + val intOutwardNode = None val slaveNode: TLInwardNode = TLIdentityNode() val statusNode = BundleBridgeSource(() => new GroundTestStatus) @@ -43,10 +48,7 @@ abstract class GroundTestTile( dcacheOpt.foreach { m => m.hartIdSinkNodeOpt.foreach { _ := hartIdNexusNode } InModuleBody { - m.module match { - case module: DCacheModule => module.tlb_port := DontCare - case other => other - } + m.module.io.tlb_port := DontCare } } diff --git a/src/main/scala/groundtest/TraceGen.scala b/src/main/scala/groundtest/TraceGen.scala index 5c5cba9b5f7..588f930978d 100644 --- a/src/main/scala/groundtest/TraceGen.scala +++ b/src/main/scala/groundtest/TraceGen.scala @@ -20,15 +20,16 @@ package freechips.rocketchip.groundtest import chisel3._ -import chisel3.util.{log2Up, MuxLookup, Cat, log2Ceil, Enum} -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.diplomacy.{ClockCrossingType} +import chisel3.util._ + +import org.chipsalliance.cde.config._ + import freechips.rocketchip.rocket._ import freechips.rocketchip.tile._ import freechips.rocketchip.tilelink._ -import freechips.rocketchip.subsystem.{TileCrossingParamsLike, CanAttachTile} +import freechips.rocketchip.subsystem.{HierarchicalElementCrossingParamsLike, CanAttachTile} import freechips.rocketchip.util._ -import freechips.rocketchip.prci.{ClockSinkParameters} +import freechips.rocketchip.prci.{ClockSinkParameters, ClockCrossingType} // ======= // Outline @@ -61,22 +62,22 @@ import freechips.rocketchip.prci.{ClockSinkParameters} // to repeatedly recompile with a different address bag.) case class TraceGenParams( - wordBits: Int, // p(XLen) - addrBits: Int, // p(PAddrBits) - addrBag: List[BigInt], // p(AddressBag) + wordBits: Int, + addrBits: Int, + addrBag: List[BigInt], maxRequests: Int, - memStart: BigInt, //p(ExtMem).base + memStart: BigInt, numGens: Int, dcache: Option[DCacheParams] = Some(DCacheParams()), - hartId: Int = 0 + tileId: Int = 0 ) extends InstantiableTileParams[TraceGenTile] with GroundTestTileParams { - def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): TraceGenTile = { + def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): TraceGenTile = { new TraceGenTile(this, crossing, lookup) } - val beuAddr = None val blockerCtrlAddr = None - val name = None + val baseName = "tracegentile" + val uniqueName = s"${baseName}_$tileId" val clockSinkParams = ClockSinkParameters() } @@ -105,7 +106,7 @@ trait HasTraceGenParams { case class TraceGenTileAttachParams( tileParams: TraceGenParams, - crossingParams: TileCrossingParamsLike + crossingParams: HierarchicalElementCrossingParamsLike ) extends CanAttachTile { type TileType = TraceGenTile val lookup: LookupByHartIdImpl = HartsWontDeduplicate(tileParams) @@ -186,7 +187,7 @@ class TagMan(val logNumTags : Int) extends Module { io.tagOut := nextTag // Is the next tag available? - io.available := ~MuxLookup(nextTag, true.B, inUseMap) + io.available := ~MuxLookup(nextTag, true.B)(inUseMap) // When user takes a tag when (io.take) { @@ -249,7 +250,7 @@ class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) ext val addrBagIndices = (0 to addressBagLen-1). map(i => i.U(logAddressBagLen.W)) - val randAddrFromBag = MuxLookup(randAddrBagIndex, 0.U, + val randAddrFromBag = MuxLookup(randAddrBagIndex, 0.U)( addrBagIndices.zip(bagOfAddrs)) // Random address from the address bag or the extra addresses. @@ -268,7 +269,7 @@ class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) ext // A random address from the extra addresses. val randAddrFromExtra = Cat(0.U, - MuxLookup(randExtraAddrIndex, 0.U, + MuxLookup(randExtraAddrIndex, 0.U)( extraAddrIndices.zip(extraAddrs)), 0.U(3.W)) Frequency(List( @@ -279,7 +280,7 @@ class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) ext val allAddrs = extraAddrs ++ bagOfAddrs val allAddrIndices = (0 until totalNumAddrs) .map(i => i.U(log2Ceil(totalNumAddrs).W)) - val initAddr = MuxLookup(initCount, 0.U, + val initAddr = MuxLookup(initCount, 0.U)( allAddrIndices.zip(allAddrs)) // Random opcodes @@ -533,6 +534,7 @@ class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) ext io.mem.req.bits.tag := reqTag io.mem.req.bits.no_alloc := false.B io.mem.req.bits.no_xcpt := false.B + io.mem.req.bits.no_resp := false.B io.mem.req.bits.mask := ~(0.U((numBitsInWord / 8).W)) io.mem.req.bits.phys := false.B io.mem.req.bits.dprv := PRV.M.U @@ -617,7 +619,7 @@ class TraceGenTile private( q: Parameters ) extends GroundTestTile(params, crossing, lookup, q) { - def this(params: TraceGenParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) = + def this(params: TraceGenParams, crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) = this(params, crossing.crossingType, lookup, p) val masterNode: TLOutwardNode = TLIdentityNode() := visibilityNode := dcacheOpt.map(_.node).getOrElse(TLTempNode()) @@ -644,5 +646,5 @@ class TraceGenTileModuleImp(outer: TraceGenTile) extends GroundTestTileModuleImp status.timeout.bits := 0.U status.error.valid := false.B - assert(!tracegen.io.timeout, s"TraceGen tile ${outer.tileParams.hartId}: request timed out") + assert(!tracegen.io.timeout, s"TraceGen tile ${outer.tileParams.tileId}: request timed out") } diff --git a/src/main/scala/interrupts/BlockDuringReset.scala b/src/main/scala/interrupts/BlockDuringReset.scala index 35692c57360..a94c295b062 100644 --- a/src/main/scala/interrupts/BlockDuringReset.scala +++ b/src/main/scala/interrupts/BlockDuringReset.scala @@ -2,8 +2,9 @@ package freechips.rocketchip.interrupts -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.util.BlockDuringReset /** BlockDuringReset ensures that no interrupt is raised while reset is raised. */ diff --git a/src/main/scala/interrupts/Crossing.scala b/src/main/scala/interrupts/Crossing.scala index 77a15480529..d783e6bbd97 100644 --- a/src/main/scala/interrupts/Crossing.scala +++ b/src/main/scala/interrupts/Crossing.scala @@ -4,9 +4,10 @@ package freechips.rocketchip.interrupts import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.util.{SynchronizerShiftReg, AsyncResetReg} -import freechips.rocketchip.diplomacy._ @deprecated("IntXing does not ensure interrupt source is glitch free. Use IntSyncSource and IntSyncSink", "rocket-chip 1.2") class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule @@ -35,14 +36,20 @@ class IntSyncCrossingSource(alreadyRegistered: Boolean = false)(implicit p: Para { val node = IntSyncSourceNode(alreadyRegistered) - lazy val module = new Impl + lazy val module = if (alreadyRegistered) (new ImplRegistered) else (new Impl) + class Impl extends LazyModuleImp(this) { + def outSize = node.out.headOption.map(_._1.sync.size).getOrElse(0) + override def desiredName = s"IntSyncCrossingSource_n${node.out.size}x${outSize}" (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => - if (alreadyRegistered) { - out.sync := in - } else { - out.sync := AsyncResetReg(Cat(in.reverse)).asBools - } + out.sync := AsyncResetReg(Cat(in.reverse)).asBools + } + } + class ImplRegistered extends LazyRawModuleImp(this) { + def outSize = node.out.headOption.map(_._1.sync.size).getOrElse(0) + override def desiredName = s"IntSyncCrossingSource_n${node.out.size}x${outSize}_Registered" + (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => + out.sync := in } } } @@ -65,6 +72,7 @@ class IntSyncAsyncCrossingSink(sync: Int = 3)(implicit p: Parameters) extends La lazy val module = new Impl class Impl extends LazyModuleImp(this) { + override def desiredName = s"IntSyncAsyncCrossingSink_n${node.out.size}x${node.out.head._1.size}" (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => out := SynchronizerShiftReg(in.sync, sync) } @@ -85,7 +93,9 @@ class IntSyncSyncCrossingSink()(implicit p: Parameters) extends LazyModule val node = IntSyncSinkNode(0) lazy val module = new Impl - class Impl extends LazyModuleImp(this) { + class Impl extends LazyRawModuleImp(this) { + def outSize = node.out.headOption.map(_._1.size).getOrElse(0) + override def desiredName = s"IntSyncSyncCrossingSink_n${node.out.size}x${outSize}" (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => out := in.sync } @@ -107,6 +117,8 @@ class IntSyncRationalCrossingSink()(implicit p: Parameters) extends LazyModule lazy val module = new Impl class Impl extends LazyModuleImp(this) { + def outSize = node.out.headOption.map(_._1.size).getOrElse(0) + override def desiredName = s"IntSyncRationalCrossingSink_n${node.out.size}x${outSize}" (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => out := RegNext(in.sync) } diff --git a/src/main/scala/interrupts/CrossingHelper.scala b/src/main/scala/interrupts/CrossingHelper.scala index 814e13fe39b..d9cdd18b1ee 100644 --- a/src/main/scala/interrupts/CrossingHelper.scala +++ b/src/main/scala/interrupts/CrossingHelper.scala @@ -2,9 +2,10 @@ package freechips.rocketchip.interrupts -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing} +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing, CrossingType, ClockCrossingType, NoCrossing, AsynchronousCrossing, RationalCrossing, SynchronousCrossing, CreditedCrossing} import freechips.rocketchip.util.CreditedDelay trait IntOutwardCrossingHelper { diff --git a/src/main/scala/interrupts/Nodes.scala b/src/main/scala/interrupts/Nodes.scala index 25a5cd48354..d2b18122f96 100644 --- a/src/main/scala/interrupts/Nodes.scala +++ b/src/main/scala/interrupts/Nodes.scala @@ -4,8 +4,10 @@ package freechips.rocketchip.interrupts import chisel3._ import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ object IntImp extends SimpleNodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] { diff --git a/src/main/scala/interrupts/NullIntSource.scala b/src/main/scala/interrupts/NullIntSource.scala index d906ac36fd9..dc388960313 100644 --- a/src/main/scala/interrupts/NullIntSource.scala +++ b/src/main/scala/interrupts/NullIntSource.scala @@ -3,8 +3,9 @@ package freechips.rocketchip.interrupts import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ /** Useful for stubbing out parts of an interrupt interface where certain devices might be missing */ class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters) extends LazyModule @@ -12,7 +13,7 @@ class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: val intnode = IntSourceNode(IntSourcePortSimple(num, ports, sources)) lazy val module = new Impl - class Impl extends LazyModuleImp(this) { + class Impl extends LazyRawModuleImp(this) { intnode.out.foreach { case (o, _) => o.foreach { _ := false.B } } } } @@ -26,6 +27,6 @@ object NullIntSource { object NullIntSyncSource { def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntSyncOutwardNode = { - IntSyncCrossingSource() := NullIntSource(num, ports, sources) + IntSyncCrossingSource(alreadyRegistered = true) := NullIntSource(num, ports, sources) } } diff --git a/src/main/scala/interrupts/Parameters.scala b/src/main/scala/interrupts/Parameters.scala index d1c300241cf..e9d90a56e7d 100644 --- a/src/main/scala/interrupts/Parameters.scala +++ b/src/main/scala/interrupts/Parameters.scala @@ -3,8 +3,11 @@ package freechips.rocketchip.interrupts import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.resources.Resource // A potentially empty half-open range; [start, end) case class IntRange(start: Int, end: Int) diff --git a/src/main/scala/interrupts/RegisterRouter.scala b/src/main/scala/interrupts/RegisterRouter.scala index 419ec135d27..6e08a2c2c55 100644 --- a/src/main/scala/interrupts/RegisterRouter.scala +++ b/src/main/scala/interrupts/RegisterRouter.scala @@ -3,7 +3,11 @@ package freechips.rocketchip.interrupts import chisel3._ -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.resources.Resource + import freechips.rocketchip.regmapper._ /** Mix this trait into a RegisterRouter to be able to attach its interrupt sources to an interrupt bus */ diff --git a/src/main/scala/interrupts/Xbar.scala b/src/main/scala/interrupts/Xbar.scala index 472fead6955..65c3e045ac4 100644 --- a/src/main/scala/interrupts/Xbar.scala +++ b/src/main/scala/interrupts/Xbar.scala @@ -2,8 +2,8 @@ package freechips.rocketchip.interrupts -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ class IntXbar()(implicit p: Parameters) extends LazyModule { @@ -19,7 +19,8 @@ class IntXbar()(implicit p: Parameters) extends LazyModule } lazy val module = new Impl - class Impl extends LazyModuleImp(this) { + class Impl extends LazyRawModuleImp(this) { + override def desiredName = s"IntXbar_i${intnode.in.size}_o${intnode.out.size}" val cat = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten intnode.out.foreach { case (o, _) => o := cat } } @@ -40,6 +41,7 @@ class IntSyncXbar()(implicit p: Parameters) extends LazyModule lazy val module = new Impl class Impl extends LazyModuleImp(this) { + override def desiredName = s"IntSyncXbar_i${intnode.in.size}_o${intnode.out.size}" val cat = intnode.in.map { case (i, e) => i.sync.take(e.source.num) }.flatten intnode.out.foreach { case (o, _) => o.sync := cat } } diff --git a/src/main/scala/interrupts/package.scala b/src/main/scala/interrupts/package.scala index a29898210ba..aaa73bf4b3a 100644 --- a/src/main/scala/interrupts/package.scala +++ b/src/main/scala/interrupts/package.scala @@ -2,9 +2,12 @@ package freechips.rocketchip -import chisel3.{Bool, Vec} -import freechips.rocketchip.diplomacy.{HasClockDomainCrossing, _} -import freechips.rocketchip.prci.{HasResetDomainCrossing} +import chisel3._ + +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.prci.{HasClockDomainCrossing, HasResetDomainCrossing} package object interrupts { diff --git a/src/main/scala/jtag/JtagShifter.scala b/src/main/scala/jtag/JtagShifter.scala index 69f6d1272fa..cbd001a36f7 100644 --- a/src/main/scala/jtag/JtagShifter.scala +++ b/src/main/scala/jtag/JtagShifter.scala @@ -3,7 +3,7 @@ package freechips.rocketchip.jtag import chisel3._ -import chisel3.experimental.DataMirror +import chisel3.reflect.DataMirror import chisel3.internal.firrtl.KnownWidth import chisel3.util.{Cat, Valid} @@ -87,6 +87,7 @@ object JtagBypassChain { * 4.3.2a TDI captured on TCK rising edge, 6.1.2.1b assumed changes on TCK falling edge */ class CaptureChain[+T <: Data](gen: T)(implicit val p: Parameters) extends Chain { + override def desiredName = s"CaptureChain_${gen.typeName}" class ModIO extends ChainIO { val capture = Capture(gen) } @@ -134,6 +135,7 @@ object CaptureChain { * 4.3.2a TDI captured on TCK rising edge, 6.1.2.1b assumed changes on TCK falling edge */ class CaptureUpdateChain[+T <: Data, +V <: Data](genCapture: T, genUpdate: V)(implicit val p: Parameters) extends Chain { + override def desiredName = s"CaptureUpdateChain_${genCapture.typeName}_To_${genUpdate.typeName}" class ModIO extends ChainIO { val capture = Capture(genCapture) val update = Valid(genUpdate) // valid high when in update state (single cycle), contents may change any time after diff --git a/src/main/scala/prci/BundleBridgeBlockDuringReset.scala b/src/main/scala/prci/BundleBridgeBlockDuringReset.scala index 88baf78bfba..7bb37f98ace 100644 --- a/src/main/scala/prci/BundleBridgeBlockDuringReset.scala +++ b/src/main/scala/prci/BundleBridgeBlockDuringReset.scala @@ -3,9 +3,13 @@ package freechips.rocketchip.prci import chisel3._ -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.diplomacy.BundleBridgeNexus.fillN + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexus.fillN + import freechips.rocketchip.util.{BlockDuringReset, Blockable} object BundleBridgeBlockDuringReset { diff --git a/src/main/scala/prci/ClockBundles.scala b/src/main/scala/prci/ClockBundles.scala index 900e437a5af..0cf06cca6e5 100644 --- a/src/main/scala/prci/ClockBundles.scala +++ b/src/main/scala/prci/ClockBundles.scala @@ -5,7 +5,7 @@ import chisel3._ import freechips.rocketchip.util.RecordMap -class ClockBundle(val params: ClockBundleParameters) extends Bundle +class ClockBundle(val params: ClockBundleParameters = ClockBundleParameters()) extends Bundle { val clock = Output(Clock()) val reset = Output(Reset()) diff --git a/src/main/scala/diplomacy/ClockDomain.scala b/src/main/scala/prci/ClockCrossingType.scala similarity index 90% rename from src/main/scala/diplomacy/ClockDomain.scala rename to src/main/scala/prci/ClockCrossingType.scala index 89c8a82b3c6..cbb5183a6db 100644 --- a/src/main/scala/diplomacy/ClockDomain.scala +++ b/src/main/scala/prci/ClockCrossingType.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.prci +import org.chipsalliance.diplomacy.lazymodule.{LazyScope, LazyModule} +import freechips.rocketchip.diplomacy.{BufferParams} import freechips.rocketchip.util.{RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay} -// TODO this should all be moved to package freechips.rocketchip.prci now that it exists - trait CrossingType trait HasDomainCrossing extends LazyScope { this: LazyModule => diff --git a/src/main/scala/prci/ClockDivider.scala b/src/main/scala/prci/ClockDivider.scala index ceb91078f73..8c913f04c8c 100644 --- a/src/main/scala/prci/ClockDivider.scala +++ b/src/main/scala/prci/ClockDivider.scala @@ -2,9 +2,11 @@ package freechips.rocketchip.prci import chisel3._ -import chisel3.util.isPow2 -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.util.{ClockDivider3, Pow2ClockDivider} /* An example clock adapter that divides all clocks passed through this node by an integer factor diff --git a/src/main/scala/prci/ClockDomain.scala b/src/main/scala/prci/ClockDomain.scala index 665372ca500..9c25284d1d1 100644 --- a/src/main/scala/prci/ClockDomain.scala +++ b/src/main/scala/prci/ClockDomain.scala @@ -1,16 +1,20 @@ package freechips.rocketchip.prci import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -abstract class Domain(implicit p: Parameters) extends LazyModule with HasDomainCrossing { +import org.chipsalliance.cde.config._ + +import org.chipsalliance.diplomacy.lazymodule._ + +abstract class Domain(implicit p: Parameters) extends LazyModule with HasDomainCrossing +{ def clockBundle: ClockBundle lazy val module = new Impl class Impl extends LazyRawModuleImp(this) { childClock := clockBundle.clock childReset := clockBundle.reset + override def provideImplicitClockToLazyChildren = true // these are just for backwards compatibility with external devices // that were manually wiring themselves to the domain's clock/reset input: @@ -28,6 +32,7 @@ class ClockSinkDomain(val clockSinkParams: ClockSinkParameters)(implicit p: Para def this(take: Option[ClockParameters] = None, name: Option[String] = None)(implicit p: Parameters) = this(ClockSinkParameters(take = take, name = name)) val clockNode = ClockSinkNode(Seq(clockSinkParams)) def clockBundle = clockNode.in.head._1 + override lazy val desiredName = (clockSinkParams.name.toSeq :+ "ClockSinkDomain").mkString } class ClockSourceDomain(val clockSourceParams: ClockSourceParameters)(implicit p: Parameters) extends ClockDomain @@ -35,6 +40,7 @@ class ClockSourceDomain(val clockSourceParams: ClockSourceParameters)(implicit p def this(give: Option[ClockParameters] = None, name: Option[String] = None)(implicit p: Parameters) = this(ClockSourceParameters(give = give, name = name)) val clockNode = ClockSourceNode(Seq(clockSourceParams)) def clockBundle = clockNode.out.head._1 + override lazy val desiredName = (clockSourceParams.name.toSeq :+ "ClockSourceDomain").mkString } abstract class ResetDomain(implicit p: Parameters) extends Domain with HasResetDomainCrossing diff --git a/src/main/scala/prci/ClockGroup.scala b/src/main/scala/prci/ClockGroup.scala index ce2b8f98c97..afd113d4e49 100644 --- a/src/main/scala/prci/ClockGroup.scala +++ b/src/main/scala/prci/ClockGroup.scala @@ -1,10 +1,14 @@ // See LICENSE.SiFive for license details. package freechips.rocketchip.prci -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ -case class ClockGroupNode(groupName: String)(implicit valName: ValName) +import freechips.rocketchip.resources.FixedClockResource + +case class ClockGroupingNode(groupName: String)(implicit valName: ValName) extends MixedNexusNode(ClockGroupImp, ClockImp)( dFn = { _ => ClockSourceParameters() }, uFn = { seq => ClockGroupSinkParameters(name = groupName, members = seq) }) @@ -14,7 +18,7 @@ case class ClockGroupNode(groupName: String)(implicit valName: ValName) class ClockGroup(groupName: String)(implicit p: Parameters) extends LazyModule { - val node = ClockGroupNode(groupName) + val node = ClockGroupingNode(groupName) lazy val module = new Impl class Impl extends LazyRawModuleImp(this) { @@ -44,7 +48,7 @@ case class ClockGroupAggregateNode(groupName: String)(implicit valName: ValName) class ClockGroupAggregator(groupName: String)(implicit p: Parameters) extends LazyModule { val node = ClockGroupAggregateNode(groupName) - + override lazy val desiredName = s"ClockGroupAggregator_$groupName" lazy val module = new Impl class Impl extends LazyRawModuleImp(this) { val (in, _) = node.in.unzip @@ -100,6 +104,7 @@ class FixedClockBroadcast(fixedClockOpt: Option[ClockParameters])(implicit p: Pa class Impl extends LazyRawModuleImp(this) { val (in, _) = node.in(0) val (out, _) = node.out.unzip + override def desiredName = s"FixedClockBroadcast_${out.size}" require (node.in.size == 1, "FixedClockBroadcast can only broadcast a single clock") out.foreach { _ := in } } @@ -107,7 +112,7 @@ class FixedClockBroadcast(fixedClockOpt: Option[ClockParameters])(implicit p: Pa object FixedClockBroadcast { - def apply(fixedClockOpt: Option[ClockParameters])(implicit p: Parameters, valName: ValName) = LazyModule(new FixedClockBroadcast(fixedClockOpt)).node + def apply(fixedClockOpt: Option[ClockParameters] = None)(implicit p: Parameters, valName: ValName) = LazyModule(new FixedClockBroadcast(fixedClockOpt)).node } case class PRCIClockGroupNode()(implicit valName: ValName) diff --git a/src/main/scala/prci/ClockGroupDriver.scala b/src/main/scala/prci/ClockGroupDriver.scala deleted file mode 100644 index 63ff42f1e42..00000000000 --- a/src/main/scala/prci/ClockGroupDriver.scala +++ /dev/null @@ -1,46 +0,0 @@ -// See LICENSE.SiFive for license details. -package freechips.rocketchip.prci - -import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{InModuleBody, ModuleValue, ValName} -import freechips.rocketchip.util.{RecordMap} - -/** Used to parameterize the creation of simple clock group drivers */ -case class ClockGroupDriverParameters( - num: Int = 1, - driveFn: ClockGroupDriver.DriveFn = ClockGroupDriver.driveFromImplicitClock -) { - def drive(node: ClockGroupEphemeralNode)(implicit p: Parameters, vn: ValName): ModuleValue[RecordMap[ClockBundle]] = { - driveFn(node, num, p, vn) - } -} - -object ClockGroupDriver { - type DriveFn = (ClockGroupEphemeralNode, Int, Parameters, ValName) => ModuleValue[RecordMap[ClockBundle]] - - /** Drive all members of all groups from the Chisel implicit clock */ - def driveFromImplicitClock: DriveFn = { (groups, num, p, vn) => - implicit val pp = p - val dummyClockGroupSourceNode: ClockGroupSourceNode = SimpleClockGroupSource(num) - groups :*= dummyClockGroupSourceNode - InModuleBody { RecordMap[ClockBundle]() } - } - - /** Drive all members of all groups from a flattened IO representation */ - def driveFromIOs: DriveFn = { (groups, num, p, vn) => - implicit val pp = p - val ioClockGroupSourceNode = ClockGroupSourceNode(List.fill(num) { ClockGroupSourceParameters() }) - groups :*= ioClockGroupSourceNode - InModuleBody { - val bundles = ioClockGroupSourceNode.out.map(_._1) - val elements = bundles.map(_.member.elements).flatten - val io = IO(Flipped(RecordMap(elements.map { case (name, data) => - name -> data.cloneType - }:_*))) - - elements.foreach { case (name, data) => io(name).foreach { data := _ } } - io.suggestName(vn.name) - } - } -} diff --git a/src/main/scala/prci/ClockNodes.scala b/src/main/scala/prci/ClockNodes.scala index 16a9e01c894..e5c6748fb62 100644 --- a/src/main/scala/prci/ClockNodes.scala +++ b/src/main/scala/prci/ClockNodes.scala @@ -2,8 +2,14 @@ package freechips.rocketchip.prci import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ + +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.resources.FixedClockResource object ClockImp extends SimpleNodeImp[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] { diff --git a/src/main/scala/prci/IOHelper.scala b/src/main/scala/prci/IOHelper.scala index e33e618103b..6b7f75f6c40 100644 --- a/src/main/scala/prci/IOHelper.scala +++ b/src/main/scala/prci/IOHelper.scala @@ -3,7 +3,8 @@ package freechips.rocketchip.prci import chisel3._ -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.diplomacy.lazymodule._ object IOHelper { diff --git a/src/main/scala/prci/ResetCrossingType.scala b/src/main/scala/prci/ResetCrossingType.scala index dd37db2ee9d..0fdaa3b4d6c 100644 --- a/src/main/scala/prci/ResetCrossingType.scala +++ b/src/main/scala/prci/ResetCrossingType.scala @@ -1,8 +1,8 @@ // See LICENSE.SiFive for license details. package freechips.rocketchip.prci -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{CrossingType, HasDomainCrossing, LazyModule} +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ trait HasResetDomainCrossing extends HasDomainCrossing { this: LazyModule => type DomainCrossingType = ResetCrossingType diff --git a/src/main/scala/prci/ResetStretcher.scala b/src/main/scala/prci/ResetStretcher.scala index 747e93281fa..d9d76ab8e4a 100644 --- a/src/main/scala/prci/ResetStretcher.scala +++ b/src/main/scala/prci/ResetStretcher.scala @@ -2,9 +2,10 @@ package freechips.rocketchip.prci import chisel3._ -import chisel3.util.log2Ceil -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, ValName} +import chisel3.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ /** This adapter takes an input reset and stretches it. * @@ -13,7 +14,7 @@ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, ValName} class ResetStretcher(cycles: Int)(implicit p: Parameters) extends LazyModule { val node = ClockAdapterNode()(ValName("reset_stretcher")) require(cycles > 1, s"ResetStretcher only supports cycles > 1 but got ${cycles}") - + override lazy val desiredName = s"ResetStretcher$cycles" lazy val module = new Impl class Impl extends LazyModuleImp(this) { (node.in zip node.out).foreach { case ((in, _), (out, _)) => diff --git a/src/main/scala/prci/ResetSynchronizer.scala b/src/main/scala/prci/ResetSynchronizer.scala index 9bb6c5aea31..c66ce4576a7 100644 --- a/src/main/scala/prci/ResetSynchronizer.scala +++ b/src/main/scala/prci/ResetSynchronizer.scala @@ -1,9 +1,11 @@ // See LICENSE for license details. package freechips.rocketchip.prci -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util.{ResetCatchAndSync} +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.util.ResetCatchAndSync /** * Synchronizes the reset of a diplomatic clock-reset pair to its accompanying clock. diff --git a/src/main/scala/prci/ResetWrangler.scala b/src/main/scala/prci/ResetWrangler.scala index 3f59bc3d183..59b289bc3e6 100644 --- a/src/main/scala/prci/ResetWrangler.scala +++ b/src/main/scala/prci/ResetWrangler.scala @@ -4,8 +4,9 @@ package freechips.rocketchip.prci import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.util.{AsyncResetReg, ResetCatchAndSync} class ResetWrangler(debounceNs: Double = 100000)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/prci/TestClockSource.scala b/src/main/scala/prci/TestClockSource.scala index 440c77f893e..6889908b0d2 100644 --- a/src/main/scala/prci/TestClockSource.scala +++ b/src/main/scala/prci/TestClockSource.scala @@ -1,10 +1,11 @@ package freechips.rocketchip.prci import chisel3._ -import chisel3.util.HasBlackBoxInline +import chisel3.util._ import chisel3.experimental.DoubleParam -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ class ClockSourceIO extends Bundle { val power = Input(Bool()) diff --git a/src/main/scala/prci/package.scala b/src/main/scala/prci/package.scala index e427add8d43..872a05d05d3 100644 --- a/src/main/scala/prci/package.scala +++ b/src/main/scala/prci/package.scala @@ -2,15 +2,21 @@ package freechips.rocketchip -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ +import freechips.rocketchip.diplomacy.{BufferParams} package object prci { type ClockInwardNode = InwardNodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] type ClockOutwardNode = OutwardNodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] type ClockNode = NodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle, ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] + + type ClockGroupNode = NodeHandle[ClockGroupSourceParameters, ClockGroupSinkParameters, ClockGroupEdgeParameters, ClockGroupBundle, ClockGroupSourceParameters, ClockGroupSinkParameters, ClockGroupEdgeParameters, ClockGroupBundle] + def asyncMux[T](xType: ClockCrossingType, async: T, notasync: T): T = xType match { case _: AsynchronousCrossing => async case _ => notasync } + + implicit def noCrossing(value: NoCrossing.type): ClockCrossingType = SynchronousCrossing(BufferParams.none) } diff --git a/src/main/scala/regmapper/RegMapper.scala b/src/main/scala/regmapper/RegMapper.scala index 78361ef9406..2e00c77005a 100644 --- a/src/main/scala/regmapper/RegMapper.scala +++ b/src/main/scala/regmapper/RegMapper.scala @@ -4,13 +4,13 @@ package freechips.rocketchip.regmapper import chisel3._ import chisel3.experimental.SourceInfo -import chisel3.util.{DecoupledIO, Decoupled, Queue, Cat, FillInterleaved, UIntToOH} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property +import chisel3.util._ -// A bus agnostic register interface to a register-based device +import freechips.rocketchip.diplomacy.AddressDecoder + +import freechips.rocketchip.util.{BundleFieldBase, BundleMap, MuxSeq, ReduceOthers, property} +// A bus agnostic register interface to a register-based device case class RegMapperParams(indexBits: Int, maskBits: Int, extraFields: Seq[BundleFieldBase] = Nil) class RegMapperInput(val params: RegMapperParams) extends Bundle @@ -67,7 +67,13 @@ object RegMapper val depth = concurrency require (depth >= 0) require (!pipelined || depth > 0, "Register-based device with request/response handshaking needs concurrency > 0") - val back = if (depth > 0) Queue(front, depth) else front + val back = if (depth > 0) { + val front_q = Module(new Queue(new RegMapperInput(inParams), depth) { + override def desiredName = s"Queue${depth}_${front.bits.typeName}_i${inParams.indexBits}_m${inParams.maskBits}" + }) + front_q.io.enq <> front + front_q.io.deq + } else front // Convert to and from Bits def toBits(x: Int, tail: List[Boolean] = List.empty): List[Boolean] = diff --git a/src/main/scala/regmapper/RegisterRouter.scala b/src/main/scala/regmapper/RegisterRouter.scala index 0bd43a7fd06..083a1d09dfb 100644 --- a/src/main/scala/regmapper/RegisterRouter.scala +++ b/src/main/scala/regmapper/RegisterRouter.scala @@ -3,9 +3,16 @@ package freechips.rocketchip.regmapper import chisel3._ -import chisel3.util.{isPow2} -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{Description, Device, SimpleDevice, ResourceBindings, ResourceValue} +import freechips.rocketchip.prci.{HasClockDomainCrossing} + /** Parameters which apply to any RegisterRouter. */ case class RegisterRouterParams( diff --git a/src/main/scala/regmapper/Test.scala b/src/main/scala/regmapper/Test.scala index 57c5c7ec583..0faedd84cfb 100644 --- a/src/main/scala/regmapper/Test.scala +++ b/src/main/scala/regmapper/Test.scala @@ -3,10 +3,12 @@ package freechips.rocketchip.regmapper import chisel3._ -import chisel3.util.{Cat, log2Ceil} -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.LazyModuleImp -import freechips.rocketchip.util.{Pow2ClockDivider} +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.util.Pow2ClockDivider object LFSR16Seed { diff --git a/src/main/scala/resources/AddressMapEntry.scala b/src/main/scala/resources/AddressMapEntry.scala new file mode 100644 index 00000000000..27ba067ad56 --- /dev/null +++ b/src/main/scala/resources/AddressMapEntry.scala @@ -0,0 +1,21 @@ +package freechips.rocketchip.resources + +import freechips.rocketchip.diplomacy.{AddressRange} + +case class AddressMapEntry(range: AddressRange, permissions: ResourcePermissions, names: Seq[String]) { + val ResourcePermissions(r, w, x, c, a) = permissions + + def toString(aw: Int) = s"\t%${aw}x - %${aw}x %c%c%c%c%c %s".format( + range.base, + range.base+range.size, + if (a) 'A' else ' ', + if (r) 'R' else ' ', + if (w) 'W' else ' ', + if (x) 'X' else ' ', + if (c) 'C' else ' ', + names.mkString(", ")) + + def toJSON = s"""{"base":[${range.base}],"size":[${range.size}],""" + + s""""r":[$r],"w":[$w],"x":[$x],"c":[$c],"a":[$a],""" + + s""""names":[${names.map('"'+_+'"').mkString(",")}]}""" +} diff --git a/src/main/scala/diplomacy/DeviceTree.scala b/src/main/scala/resources/DeviceTree.scala similarity index 98% rename from src/main/scala/diplomacy/DeviceTree.scala rename to src/main/scala/resources/DeviceTree.scala index 05ccdbb5b91..3c9e04384fc 100644 --- a/src/main/scala/diplomacy/DeviceTree.scala +++ b/src/main/scala/resources/DeviceTree.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.resources import org.chipsalliance.cde.config.Field import sys.process._ import java.io.{ByteArrayInputStream, ByteArrayOutputStream} +import freechips.rocketchip.diplomacy.{AddressRange} case object DTSModel extends Field[String] case object DTSCompat extends Field[Seq[String]] // -dev, -soc diff --git a/src/main/scala/diplomacy/FixedClockResource.scala b/src/main/scala/resources/FixedClockResource.scala similarity index 94% rename from src/main/scala/diplomacy/FixedClockResource.scala rename to src/main/scala/resources/FixedClockResource.scala index 2ae3ee9f236..d0c39ef85bd 100644 --- a/src/main/scala/diplomacy/FixedClockResource.scala +++ b/src/main/scala/resources/FixedClockResource.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.resources class FixedClockResource(val name: String, val freqMHz: Double, val prefix: String = "soc/") { diff --git a/src/main/scala/diplomacy/JSON.scala b/src/main/scala/resources/JSON.scala similarity index 95% rename from src/main/scala/diplomacy/JSON.scala rename to src/main/scala/resources/JSON.scala index 0ab4c0a909c..3a656615e6c 100644 --- a/src/main/scala/diplomacy/JSON.scala +++ b/src/main/scala/resources/JSON.scala @@ -1,8 +1,9 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.resources import scala.collection.immutable.SortedMap +import freechips.rocketchip.diplomacy.{AddressRange} object JSON { diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/resources/Resources.scala similarity index 96% rename from src/main/scala/diplomacy/Resources.scala rename to src/main/scala/resources/Resources.scala index 4dc59d95304..41d042f4907 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/resources/Resources.scala @@ -1,11 +1,13 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.resources import chisel3.util.log2Ceil import scala.collection.immutable.{ListMap, SortedMap} import scala.collection.mutable.HashMap +import freechips.rocketchip.diplomacy.{AddressSet, AddressRange} +import org.chipsalliance.diplomacy.lazymodule.{LazyModule} sealed trait ResourceValue @@ -275,12 +277,12 @@ trait BindingScope BindingScope.add(this) private val parentScope = BindingScope.find(parent) - protected[diplomacy] var resourceBindingFns: Seq[() => Unit] = Nil // callback functions to resolve resource binding during elaboration - protected[diplomacy] var resourceBindings: Seq[(Resource, Option[Device], ResourceValue)] = Nil + protected[resources] var resourceBindingFns: Seq[() => Unit] = Nil // callback functions to resolve resource binding during elaboration + protected[resources] var resourceBindings: Seq[(Resource, Option[Device], ResourceValue)] = Nil private case class ExpandedValue(path: Seq[String], labels: Seq[String], value: Seq[ResourceValue]) private lazy val eval: Unit = { - require (!LazyModule.scope.isDefined, "May not evaluate binding while still constructing LazyModules") + require (!LazyModule.getScope.isDefined, "May not evaluate binding while still constructing LazyModules") parentScope.foreach { _.eval } resourceBindings = parentScope.map(_.resourceBindings).getOrElse(Nil) BindingScope.active = Some(this) @@ -387,10 +389,10 @@ trait BindingScope object BindingScope { - protected[diplomacy] var active: Option[BindingScope] = None - protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.scope): Option[BindingScope] = m.flatMap { - case x: BindingScope => find(x.parent).orElse(Some(x)) - case x => find(x.parent) + protected[resources] var active: Option[BindingScope] = None + protected[resources] def find(m: Option[LazyModule] = LazyModule.getScope): Option[BindingScope] = m.flatMap { + case x: BindingScope => find(x.getParent).orElse(Some(x)) + case x => find(x.getParent) } var bindingScopes = new collection.mutable.ArrayBuffer[BindingScope]() diff --git a/src/main/scala/diplomacy/SRAM.scala b/src/main/scala/resources/SRAM.scala similarity index 94% rename from src/main/scala/diplomacy/SRAM.scala rename to src/main/scala/resources/SRAM.scala index 205fba914d0..8fc3c16e0d8 100644 --- a/src/main/scala/diplomacy/SRAM.scala +++ b/src/main/scala/resources/SRAM.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package freechips.rocketchip.diplomacy +package freechips.rocketchip.resources import chisel3._ import chisel3.util.log2Ceil import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.util.{DescribedSRAM, Code} +import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} abstract class DiplomaticSRAM( val address: AddressSet, diff --git a/src/main/scala/resources/package.scala b/src/main/scala/resources/package.scala new file mode 100644 index 00000000000..d2416826427 --- /dev/null +++ b/src/main/scala/resources/package.scala @@ -0,0 +1,29 @@ +package freechips.rocketchip + +package object resources { + type PropertyOption = Option[(String, Seq[ResourceValue])] + type PropertyMap = Iterable[(String, Seq[ResourceValue])] + + implicit class BigIntHexContext(private val sc: StringContext) extends AnyVal { + def x(args: Any*): BigInt = { + val orig = sc.s(args: _*) + BigInt(orig.replace("_", ""), 16) + } + } + + implicit class IntToProperty(x: Int) { + def asProperty: Seq[ResourceValue] = Seq(ResourceInt(BigInt(x))) + } + + implicit class BigIntToProperty(x: BigInt) { + def asProperty: Seq[ResourceValue] = Seq(ResourceInt(x)) + } + + implicit class StringToProperty(x: String) { + def asProperty: Seq[ResourceValue] = Seq(ResourceString(x)) + } + + implicit class DeviceToProperty(x: Device) { + def asProperty: Seq[ResourceValue] = Seq(ResourceReference(x.label)) + } +} diff --git a/src/main/scala/rocket/ALU.scala b/src/main/scala/rocket/ALU.scala index 20c2bdffeb3..96cbc98aa58 100644 --- a/src/main/scala/rocket/ALU.scala +++ b/src/main/scala/rocket/ALU.scala @@ -4,13 +4,14 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.{BitPat, Fill, Cat, Reverse} +import chisel3.util.{BitPat, Fill, Cat, Reverse, PriorityEncoderOH, PopCount, MuxLookup} import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tile.CoreModule +import freechips.rocketchip.util._ -class ALUFN { - val SZ_ALU_FN = 4 - def FN_X = BitPat("b????") +object ALU { + val SZ_ALU_FN = 5 + def FN_X = BitPat("b?????") def FN_ADD = 0.U def FN_SL = 1.U def FN_SEQ = 2.U @@ -27,6 +28,20 @@ class ALUFN { def FN_SGE = 13.U def FN_SLTU = 14.U def FN_SGEU = 15.U + def FN_UNARY = 16.U + def FN_ROL = 17.U + def FN_ROR = 18.U + def FN_BEXT = 19.U + + def FN_ANDN = 24.U + def FN_ORN = 25.U + def FN_XNOR = 26.U + + def FN_MAX = 28.U + def FN_MIN = 29.U + def FN_MAXU = 30.U + def FN_MINU = 31.U + def FN_MAXMIN = BitPat("b111??") // Mul/div reuse some integer FNs def FN_DIV = FN_XOR @@ -41,21 +56,22 @@ class ALUFN { def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0) def isSub(cmd: UInt) = cmd(3) - def isCmp(cmd: UInt) = cmd >= FN_SLT + def isCmp(cmd: UInt) = (cmd >= FN_SLT && cmd <= FN_SGEU) + def isMaxMin(cmd: UInt) = (cmd >= FN_MAX && cmd <= FN_MINU) def cmpUnsigned(cmd: UInt) = cmd(1) def cmpInverted(cmd: UInt) = cmd(0) def cmpEq(cmd: UInt) = !cmd(3) + def shiftReverse(cmd: UInt) = !cmd.isOneOf(FN_SR, FN_SRA, FN_ROR, FN_BEXT) + def bwInvRs2(cmd: UInt) = cmd.isOneOf(FN_ANDN, FN_ORN, FN_XNOR) } -object ALUFN { - def apply() = new ALUFN -} +import ALU._ -abstract class AbstractALU[T <: ALUFN](val aluFn: T)(implicit p: Parameters) extends CoreModule()(p) { +abstract class AbstractALU(implicit p: Parameters) extends CoreModule()(p) { val io = IO(new Bundle { val dw = Input(UInt(SZ_DW.W)) - val fn = Input(UInt(aluFn.SZ_ALU_FN.W)) + val fn = Input(UInt(SZ_ALU_FN.W)) val in2 = Input(UInt(xLen.W)) val in1 = Input(UInt(xLen.W)) val out = Output(UInt(xLen.W)) @@ -64,50 +80,97 @@ abstract class AbstractALU[T <: ALUFN](val aluFn: T)(implicit p: Parameters) ext }) } -class ALU(implicit p: Parameters) extends AbstractALU(new ALUFN)(p) { +class ALU(implicit p: Parameters) extends AbstractALU()(p) { // ADD, SUB - val in2_inv = Mux(aluFn.isSub(io.fn), ~io.in2, io.in2) + val in2_inv = Mux(isSub(io.fn), ~io.in2, io.in2) val in1_xor_in2 = io.in1 ^ in2_inv - io.adder_out := io.in1 + in2_inv + aluFn.isSub(io.fn) + val in1_and_in2 = io.in1 & in2_inv + io.adder_out := io.in1 + in2_inv + isSub(io.fn) // SLT, SLTU val slt = Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1), - Mux(aluFn.cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))) - io.cmp_out := aluFn.cmpInverted(io.fn) ^ Mux(aluFn.cmpEq(io.fn), in1_xor_in2 === 0.U, slt) + Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))) + io.cmp_out := cmpInverted(io.fn) ^ Mux(cmpEq(io.fn), in1_xor_in2 === 0.U, slt) // SLL, SRL, SRA val (shamt, shin_r) = if (xLen == 32) (io.in2(4,0), io.in1) else { require(xLen == 64) - val shin_hi_32 = Fill(32, aluFn.isSub(io.fn) && io.in1(31)) + val shin_hi_32 = Fill(32, isSub(io.fn) && io.in1(31)) val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32) val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0)) (shamt, Cat(shin_hi, io.in1(31,0))) } - val shin = Mux(io.fn === aluFn.FN_SR || io.fn === aluFn.FN_SRA, shin_r, Reverse(shin_r)) - val shout_r = (Cat(aluFn.isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0) + val shin = Mux(shiftReverse(io.fn), Reverse(shin_r), shin_r) + val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0) val shout_l = Reverse(shout_r) - val shout = Mux(io.fn === aluFn.FN_SR || io.fn === aluFn.FN_SRA, shout_r, 0.U) | - Mux(io.fn === aluFn.FN_SL, shout_l, 0.U) + val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA || io.fn === FN_BEXT, shout_r, 0.U) | + Mux(io.fn === FN_SL, shout_l, 0.U) // CZEQZ, CZNEZ val in2_not_zero = io.in2.orR val cond_out = Option.when(usingConditionalZero)( - Mux((io.fn === aluFn.FN_CZEQZ && in2_not_zero) || (io.fn === aluFn.FN_CZNEZ && !in2_not_zero), io.in1, 0.U) + Mux((io.fn === FN_CZEQZ && in2_not_zero) || (io.fn === FN_CZNEZ && !in2_not_zero), io.in1, 0.U) ) // AND, OR, XOR - val logic = Mux(io.fn === aluFn.FN_XOR || io.fn === aluFn.FN_OR, in1_xor_in2, 0.U) | - Mux(io.fn === aluFn.FN_OR || io.fn === aluFn.FN_AND, io.in1 & io.in2, 0.U) + val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR || io.fn === FN_ORN || io.fn === FN_XNOR, in1_xor_in2, 0.U) | + Mux(io.fn === FN_OR || io.fn === FN_AND || io.fn === FN_ORN || io.fn === FN_ANDN, in1_and_in2, 0.U) - val shift_logic = (aluFn.isCmp (io.fn) && slt) | logic | shout + val bext_mask = Mux(coreParams.useZbs.B && io.fn === FN_BEXT, 1.U, ~(0.U(xLen.W))) + val shift_logic = (isCmp (io.fn) && slt) | logic | (shout & bext_mask) val shift_logic_cond = cond_out match { case Some(co) => shift_logic | co case _ => shift_logic } - val out = Mux(io.fn === aluFn.FN_ADD || io.fn === aluFn.FN_SUB, io.adder_out, shift_logic_cond) + + // CLZ, CTZ, CPOP + val tz_in = MuxLookup((io.dw === DW_32) ## !io.in2(0), 0.U)(Seq( + 0.U -> io.in1, + 1.U -> Reverse(io.in1), + 2.U -> 1.U ## io.in1(31,0), + 3.U -> 1.U ## Reverse(io.in1(31,0)) + )) + val popc_in = Mux(io.in2(1), + Mux(io.dw === DW_32, io.in1(31,0), io.in1), + PriorityEncoderOH(1.U ## tz_in) - 1.U)(xLen-1,0) + val count = PopCount(popc_in) + val in1_bytes = io.in1.asTypeOf(Vec(xLen / 8, UInt(8.W))) + val orcb = VecInit(in1_bytes.map(b => Fill(8, b =/= 0.U))).asUInt + val rev8 = VecInit(in1_bytes.reverse).asUInt + val unary = MuxLookup(io.in2(11,0), count)(Seq( + 0x287.U -> orcb, + (if (xLen == 32) 0x698 else 0x6b8).U -> rev8, + 0x080.U -> io.in1(15,0), + 0x604.U -> Fill(xLen-8, io.in1(7)) ## io.in1(7,0), + 0x605.U -> Fill(xLen-16, io.in1(15)) ## io.in1(15,0) + )) + + // MAX, MIN, MAXU, MINU + val maxmin_out = Mux(io.cmp_out, io.in2, io.in1) + + // ROL, ROR + val rot_shamt = Mux(io.dw === DW_32, 32.U, xLen.U) - shamt + val rotin = Mux(io.fn(0), shin_r, Reverse(shin_r)) + val rotout_r = (rotin >> rot_shamt)(xLen-1,0) + val rotout_l = Reverse(rotout_r) + val rotout = Mux(io.fn(0), rotout_r, rotout_l) | Mux(io.fn(0), shout_l, shout_r) + + val out = MuxLookup(io.fn, shift_logic_cond)(Seq( + FN_ADD -> io.adder_out, + FN_SUB -> io.adder_out + ) ++ (if (coreParams.useZbb) Seq( + FN_UNARY -> unary, + FN_MAX -> maxmin_out, + FN_MIN -> maxmin_out, + FN_MAXU -> maxmin_out, + FN_MINU -> maxmin_out, + FN_ROL -> rotout, + FN_ROR -> rotout, + ) else Nil)) + io.out := out if (xLen > 32) { diff --git a/src/main/scala/rocket/AMOALU.scala b/src/main/scala/rocket/AMOALU.scala index 0aff648446e..47295d18db0 100644 --- a/src/main/scala/rocket/AMOALU.scala +++ b/src/main/scala/rocket/AMOALU.scala @@ -10,6 +10,7 @@ import org.chipsalliance.cde.config.Parameters class StoreGen(typ: UInt, addr: UInt, dat: UInt, maxSize: Int) { val size = Wire(UInt(log2Up(log2Up(maxSize)+1).W)) size := typ + val dat_padded = dat.pad(maxSize*8) def misaligned: Bool = (addr & ((1.U << size) - 1.U)(log2Up(maxSize)-1,0)).orR @@ -24,8 +25,8 @@ class StoreGen(typ: UInt, addr: UInt, dat: UInt, maxSize: Int) { } protected def genData(i: Int): UInt = - if (i >= log2Up(maxSize)) dat - else Mux(size === i.U, Fill(1 << (log2Up(maxSize)-i), dat((8 << i)-1,0)), genData(i+1)) + if (i >= log2Up(maxSize)) dat_padded + else Mux(size === i.U, Fill(1 << (log2Up(maxSize)-i), dat_padded((8 << i)-1,0)), genData(i+1)) def data = genData(0) def wordData = genData(2) diff --git a/src/main/scala/rocket/BTB.scala b/src/main/scala/rocket/BTB.scala index 25b5b359ded..75126dd121b 100644 --- a/src/main/scala/rocket/BTB.scala +++ b/src/main/scala/rocket/BTB.scala @@ -5,7 +5,6 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ -import chisel3.internal.InstanceId import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.subsystem.CacheBlockBytes import freechips.rocketchip.tile.HasCoreParameters diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 67812022773..407b1e988be 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -245,6 +245,7 @@ class CSRDecodeIO(implicit p: Parameters) extends CoreBundle { val fp_illegal = Output(Bool()) val vector_illegal = Output(Bool()) val fp_csr = Output(Bool()) + val vector_csr = Output(Bool()) val rocc_illegal = Output(Bool()) val read_illegal = Output(Bool()) val write_illegal = Output(Bool()) @@ -254,10 +255,10 @@ class CSRDecodeIO(implicit p: Parameters) extends CoreBundle { val virtual_system_illegal = Output(Bool()) } -class CSRFileIO(implicit p: Parameters) extends CoreBundle +class CSRFileIO(hasBeu: Boolean)(implicit p: Parameters) extends CoreBundle with HasCoreParameters { val ungated_clock = Input(Clock()) - val interrupts = Input(new CoreInterrupts()) + val interrupts = Input(new CoreInterrupts(hasBeu)) val hartid = Input(UInt(hartIdLen.W)) val rw = new Bundle { val addr = Input(UInt(CSR.ADDRSZ.W)) @@ -286,6 +287,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle val pc = Input(UInt(vaddrBitsExtended.W)) val tval = Input(UInt(vaddrBitsExtended.W)) val htval = Input(UInt(((maxSVAddrBits + 1) min xLen).W)) + val mhtinst_read_pseudo = Input(Bool()) val gva = Input(Bool()) val time = Output(UInt(xLen.W)) val fcsr_rm = Output(Bits(FPConstants.RM_SZ.W)) @@ -375,10 +377,11 @@ class VType(implicit p: Parameters) extends CoreBundle { class CSRFile( perfEventSets: EventSets = new EventSets(Seq()), customCSRs: Seq[CustomCSR] = Nil, - roccCSRs: Seq[CustomCSR] = Nil)(implicit p: Parameters) + roccCSRs: Seq[CustomCSR] = Nil, + hasBeu: Boolean = false)(implicit p: Parameters) extends CoreModule()(p) with HasCoreParameters { - val io = IO(new CSRFileIO { + val io = IO(new CSRFileIO(hasBeu) { val customCSRs = Vec(CSRFile.this.customCSRs.size, new CustomCSRIO) val roccCSRs = Vec(CSRFile.this.roccCSRs.size, new CustomCSRIO) }) @@ -578,6 +581,12 @@ class CSRFile( val reg_vxsat = usingVector.option(Reg(Bool())) val reg_vxrm = usingVector.option(Reg(UInt(io.vector.get.vxrm.getWidth.W))) + val reg_mtinst_read_pseudo = Reg(Bool()) + val reg_htinst_read_pseudo = Reg(Bool()) + // XLEN=32: 0x00002000 + // XLEN=64: 0x00003000 + val Seq(read_mtinst, read_htinst) = Seq(reg_mtinst_read_pseudo, reg_htinst_read_pseudo).map(r => Cat(r, (xLen == 32).option(0.U).getOrElse(r), 0.U(12.W))) + val reg_mcountinhibit = RegInit(0.U((CSR.firstHPM + nPerfCounters).W)) io.inhibit_cycle := reg_mcountinhibit(0) val reg_instret = WideCounter(64, io.retire, inhibit = reg_mcountinhibit(2)) @@ -627,7 +636,7 @@ class CSRFile( (if (usingAtomics) "A" else "") + (if (fLen >= 32) "F" else "") + (if (fLen >= 64) "D" else "") + - (if (usingVector) "V" else "") + + (if (coreParams.hasV) "V" else "") + (if (usingCompressed) "C" else "") val isaString = (if (coreParams.useRVE) "E" else "I") + isaMaskString + @@ -797,7 +806,7 @@ class CSRFile( val reg_rocc = roccCSRs.zip(io.roccCSRs).map(t => generateCustomCSR(t._1, t._2)) if (usingHypervisor) { - read_mapping += CSRs.mtinst -> 0.U + read_mapping += CSRs.mtinst -> read_mtinst read_mapping += CSRs.mtval2 -> reg_mtval2 val read_hstatus = io.hstatus.asUInt.extract(xLen-1,0) @@ -813,7 +822,7 @@ class CSRFile( read_mapping += CSRs.hgeie -> 0.U read_mapping += CSRs.hgeip -> 0.U read_mapping += CSRs.htval -> reg_htval - read_mapping += CSRs.htinst -> 0.U + read_mapping += CSRs.htinst -> read_htinst read_mapping += CSRs.henvcfg -> reg_henvcfg.asUInt if (xLen == 32) read_mapping += CSRs.henvcfgh -> (reg_henvcfg.asUInt >> 32) @@ -906,6 +915,7 @@ class CSRFile( io_dec.fp_illegal := io.status.fs === 0.U || reg_mstatus.v && reg_vsstatus.fs === 0.U || !reg_misa('f'-'a') io_dec.vector_illegal := io.status.vs === 0.U || reg_mstatus.v && reg_vsstatus.vs === 0.U || !reg_misa('v'-'a') io_dec.fp_csr := decodeFast(fp_csrs.keys.toList) + io_dec.vector_csr := decodeFast(vector_csrs.keys.toList) io_dec.rocc_illegal := io.status.xs === 0.U || reg_mstatus.v && reg_vsstatus.xs === 0.U || !reg_misa('x'-'a') val csr_addr_legal = reg_mstatus.prv >= CSR.mode(addr) || usingHypervisor.B && !reg_mstatus.v && reg_mstatus.prv === PRV.S.U && CSR.mode(addr) === PRV.H.U @@ -949,6 +959,7 @@ class CSRFile( Mux(insn_call, Causes.user_ecall.U + Mux(reg_mstatus.prv(0) && reg_mstatus.v, PRV.H.U, reg_mstatus.prv), Mux[UInt](insn_break, Causes.breakpoint.U, io.cause)) val cause_lsbs = cause(log2Ceil(1 + CSR.busErrorIntCause)-1, 0) + val cause_deleg_lsbs = cause(log2Ceil(xLen)-1,0) val causeIsDebugInt = cause(xLen-1) && cause_lsbs === CSR.debugIntCause.U val causeIsDebugTrigger = !cause(xLen-1) && cause_lsbs === CSR.debugTriggerCause.U val causeIsDebugBreak = !cause(xLen-1) && insn_break && Cat(reg_dcsr.ebreakm, reg_dcsr.ebreakh, reg_dcsr.ebreaks, reg_dcsr.ebreaku)(reg_mstatus.prv) @@ -956,8 +967,8 @@ class CSRFile( val debugEntry = p(DebugModuleKey).map(_.debugEntry).getOrElse(BigInt(0x800)) val debugException = p(DebugModuleKey).map(_.debugException).getOrElse(BigInt(0x808)) val debugTVec = Mux(reg_debug, Mux(insn_break, debugEntry.U, debugException.U), debugEntry.U) - val delegate = usingSupervisor.B && reg_mstatus.prv <= PRV.S.U && Mux(cause(xLen-1), read_mideleg(cause_lsbs), read_medeleg(cause_lsbs)) - val delegateVS = reg_mstatus.v && delegate && Mux(cause(xLen-1), read_hideleg(cause_lsbs), read_hedeleg(cause_lsbs)) + val delegate = usingSupervisor.B && reg_mstatus.prv <= PRV.S.U && Mux(cause(xLen-1), read_mideleg(cause_deleg_lsbs), read_medeleg(cause_deleg_lsbs)) + val delegateVS = reg_mstatus.v && delegate && Mux(cause(xLen-1), read_hideleg(cause_deleg_lsbs), read_hedeleg(cause_deleg_lsbs)) def mtvecBaseAlign = 2 def mtvecInterruptAlign = { require(reg_mip.getWidth <= xLen) @@ -1060,6 +1071,7 @@ class CSRFile( reg_scause := cause reg_stval := tval reg_htval := io.htval + reg_htinst_read_pseudo := io.mhtinst_read_pseudo reg_mstatus.spie := reg_mstatus.sie reg_mstatus.spp := reg_mstatus.prv reg_mstatus.sie := false.B @@ -1072,6 +1084,7 @@ class CSRFile( reg_mcause := cause reg_mtval := tval reg_mtval2 := io.htval + reg_mtinst_read_pseudo := io.mhtinst_read_pseudo reg_mstatus.mpie := reg_mstatus.mie reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv) reg_mstatus.mie := false.B @@ -1397,6 +1410,10 @@ class CSRFile( when (decoded_addr(CSRs.htval)) { reg_htval := wdata } when (decoded_addr(CSRs.mtval2)) { reg_mtval2 := wdata } + val write_mhtinst_read_pseudo = wdata(13) && (xLen == 32).option(true.B).getOrElse(wdata(12)) + when(decoded_addr(CSRs.mtinst)) { reg_mtinst_read_pseudo := write_mhtinst_read_pseudo } + when(decoded_addr(CSRs.htinst)) { reg_htinst_read_pseudo := write_mhtinst_read_pseudo } + when (decoded_addr(CSRs.vsstatus)) { val new_vsstatus = wdata.asTypeOf(new MStatus()) reg_vsstatus.sie := new_vsstatus.sie diff --git a/src/main/scala/rocket/Configs.scala b/src/main/scala/rocket/Configs.scala new file mode 100644 index 00000000000..a8f18cc2942 --- /dev/null +++ b/src/main/scala/rocket/Configs.scala @@ -0,0 +1,334 @@ +package freechips.rocketchip.rocket + +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.prci.{SynchronousCrossing, AsynchronousCrossing, RationalCrossing, ClockCrossingType} +import freechips.rocketchip.subsystem.{TilesLocated, NumTiles, HierarchicalLocation, RocketCrossingParams, SystemBusKey, CacheBlockBytes, RocketTileAttachParams, InSubsystem, InCluster, HierarchicalElementMasterPortParams, HierarchicalElementSlavePortParams, CBUS, CCBUS, ClustersLocated, TileAttachConfig, CloneTileAttachParams} +import freechips.rocketchip.tile.{RocketTileParams, RocketTileBoundaryBufferParams, FPUParams} +import scala.reflect.ClassTag + +// All the user-level bells and whistles +class WithNHugeCores( + n: Int, + location: HierarchicalLocation, + crossing: RocketCrossingParams, +) extends Config((site, here, up) => { + case TilesLocated(`location`) => { + val prev = up(TilesLocated(`location`), site) + val idOffset = up(NumTiles) + val big = RocketTileParams( + core = RocketCoreParams( + mulDiv = Some(MulDivParams( + mulUnroll = 8, + mulEarlyOut = true, + divEarlyOut = true, + )), + useZba = true, + useZbb = true, + useZbs = true, + fpu = Some(FPUParams(minFLen = 16))), + dcache = Some(DCacheParams( + nSets = 64, + nWays = 8, + rowBits = site(SystemBusKey).beatBits, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes))), + icache = Some(ICacheParams( + nSets = 64, + nWays = 8, + rowBits = site(SystemBusKey).beatBits, + blockBytes = site(CacheBlockBytes)))) + List.tabulate(n)(i => RocketTileAttachParams( + big.copy(tileId = i + idOffset), + crossing + )) ++ prev + } + case NumTiles => up(NumTiles) + n +}) { + def this(n: Int, location: HierarchicalLocation = InSubsystem) = this(n, location, RocketCrossingParams( + master = HierarchicalElementMasterPortParams.locationDefault(location), + slave = HierarchicalElementSlavePortParams.locationDefault(location), + mmioBaseAddressPrefixWhere = location match { + case InSubsystem => CBUS + case InCluster(clusterId) => CCBUS(clusterId) + } + )) +} + +class WithNBigCores( + n: Int, + location: HierarchicalLocation, + crossing: RocketCrossingParams, +) extends Config((site, here, up) => { + case TilesLocated(`location`) => { + val prev = up(TilesLocated(`location`), site) + val idOffset = up(NumTiles) + val big = RocketTileParams( + core = RocketCoreParams(mulDiv = Some(MulDivParams( + mulUnroll = 8, + mulEarlyOut = true, + divEarlyOut = true))), + dcache = Some(DCacheParams( + rowBits = site(SystemBusKey).beatBits, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes))), + icache = Some(ICacheParams( + rowBits = site(SystemBusKey).beatBits, + blockBytes = site(CacheBlockBytes)))) + List.tabulate(n)(i => RocketTileAttachParams( + big.copy(tileId = i + idOffset), + crossing + )) ++ prev + } + case NumTiles => up(NumTiles) + n +}) { + def this(n: Int, location: HierarchicalLocation = InSubsystem) = this(n, location, RocketCrossingParams( + master = HierarchicalElementMasterPortParams.locationDefault(location), + slave = HierarchicalElementSlavePortParams.locationDefault(location), + mmioBaseAddressPrefixWhere = location match { + case InSubsystem => CBUS + case InCluster(clusterId) => CCBUS(clusterId) + } + )) +} + +class WithNMedCores( + n: Int, + crossing: RocketCrossingParams = RocketCrossingParams(), +) extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => { + val prev = up(TilesLocated(InSubsystem), site) + val idOffset = up(NumTiles) + val med = RocketTileParams( + core = RocketCoreParams(fpu = None), + btb = None, + dcache = Some(DCacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 64, + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes))), + icache = Some(ICacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 64, + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + blockBytes = site(CacheBlockBytes)))) + List.tabulate(n)(i => RocketTileAttachParams( + med.copy(tileId = i + idOffset), + crossing + )) ++ prev + } + case NumTiles => up(NumTiles) + n +}) + +class WithNSmallCores( + n: Int, + crossing: RocketCrossingParams = RocketCrossingParams() +) extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => { + val prev = up(TilesLocated(InSubsystem), site) + val idOffset = up(NumTiles) + val small = RocketTileParams( + core = RocketCoreParams(useVM = false, fpu = None), + btb = None, + dcache = Some(DCacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 64, + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes))), + icache = Some(ICacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 64, + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + blockBytes = site(CacheBlockBytes)))) + List.tabulate(n)(i => RocketTileAttachParams( + small.copy(tileId = i + idOffset), + crossing + )) ++ prev + } + case NumTiles => up(NumTiles) + n +}) + +class With1TinyCore extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => { + val tiny = RocketTileParams( + core = RocketCoreParams( + xLen = 32, + pgLevels = 2, // sv32 + useVM = false, + fpu = None, + mulDiv = Some(MulDivParams(mulUnroll = 8))), + btb = None, + dcache = Some(DCacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 256, // 16Kb scratchpad + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + nMSHRs = 0, + blockBytes = site(CacheBlockBytes), + scratch = Some(0x80000000L))), + icache = Some(ICacheParams( + rowBits = site(SystemBusKey).beatBits, + nSets = 64, + nWays = 1, + nTLBSets = 1, + nTLBWays = 4, + blockBytes = site(CacheBlockBytes))) + ) + List(RocketTileAttachParams( + tiny, + RocketCrossingParams( + crossingType = SynchronousCrossing(), + master = HierarchicalElementMasterPortParams()) + )) + } + case NumTiles => 1 + case ClustersLocated(_) => Nil +}) + +class RocketTileAttachConfig(f: RocketTileAttachParams => RocketTileAttachParams) extends TileAttachConfig[RocketTileAttachParams](f) + +class RocketTileConfig(f: RocketTileParams => RocketTileParams) extends RocketTileAttachConfig(tp => tp.copy( + tileParams = f(tp.tileParams) +)) + +class RocketCrossingConfig(f: RocketCrossingParams => RocketCrossingParams) extends RocketTileAttachConfig(tp => tp.copy( + crossingParams = f(tp.crossingParams) +)) + +class RocketCoreConfig(f: RocketCoreParams => RocketCoreParams) extends RocketTileConfig(tp => tp.copy( + core = f(tp.core) +)) + +class RocketICacheConfig(f: ICacheParams => ICacheParams) extends RocketTileConfig(tp => tp.copy( + icache = tp.icache.map(ic => f(ic)) +)) + +class RocketDCacheConfig(f: DCacheParams => DCacheParams) extends RocketTileConfig(tp => tp.copy( + dcache = tp.dcache.map(dc => f(dc)) +)) + +class WithL1ICacheSets(sets: Int) extends RocketICacheConfig(_.copy(nSets=sets)) +class WithL1ICacheWays(ways: Int) extends RocketICacheConfig(_.copy(nWays=ways)) +class WithL1ICacheECC(dataECC: String, tagECC: String) extends RocketICacheConfig(_.copy(dataECC = Some(dataECC), tagECC = Some(tagECC))) +class WithL1ICacheRowBits(n: Int) extends RocketICacheConfig(_.copy(rowBits = n)) +class WithL1ICacheTLBSets(sets: Int) extends RocketICacheConfig(_.copy(nTLBSets = sets)) +class WithL1ICacheTLBWays(ways: Int) extends RocketICacheConfig(_.copy(nTLBWays = ways)) +class WithL1ICacheTLBBasePageSectors(sectors: Int) extends RocketICacheConfig(_.copy(nTLBBasePageSectors = sectors)) +class WithL1ICacheTLBSuperpages(superpages: Int) extends RocketICacheConfig(_.copy(nTLBSuperpages = superpages)) +class WithL1ICacheBlockBytes(bytes: Int = 64) extends RocketICacheConfig(_.copy(blockBytes = bytes)) + +class WithL1DCacheSets(sets: Int) extends RocketDCacheConfig(_.copy(nSets=sets)) +class WithL1DCacheWays(ways: Int) extends RocketDCacheConfig(_.copy(nWays=ways)) +class WithL1DCacheECC(dataECC: String, tagECC: String) extends RocketDCacheConfig(_.copy(dataECC = Some(dataECC), tagECC = Some(tagECC))) +class WithL1DCacheRowBits(n: Int) extends RocketDCacheConfig(_.copy(rowBits = n)) +class WithL1DCacheTLBSets(sets: Int) extends RocketDCacheConfig(_.copy(nTLBSets = sets)) +class WithL1DCacheTLBWays(ways: Int) extends RocketDCacheConfig(_.copy(nTLBWays = ways)) +class WithL1DCacheTLBBasePageSectors(sectors: Int) extends RocketDCacheConfig(_.copy(nTLBBasePageSectors = sectors)) +class WithL1DCacheTLBSuperpages(superpages: Int) extends RocketDCacheConfig(_.copy(nTLBSuperpages = superpages)) +class WithL1DCacheBlockBytes(bytes: Int = 64) extends RocketDCacheConfig(_.copy(blockBytes = bytes)) +class WithL1DCacheNonblocking(nMSHRs: Int) extends RocketDCacheConfig(_.copy(nMSHRs = nMSHRs)) +class WithL1DCacheClockGating extends RocketDCacheConfig(_.copy(clockGate = true)) +class WithL1DCacheDTIMAddress(address: BigInt) extends RocketDCacheConfig(_.copy(scratch = Some(address))) + +class WithScratchpadsOnly extends RocketTileConfig(tp => tp.copy( + core = tp.core.copy(useVM = false), + dcache = tp.dcache.map(_.copy( + nSets = 256, // 16Kb scratchpad + nWays = 1, + scratch = Some(0x80000000L))) +)) + +class WithCacheRowBits(n: Int) extends RocketTileConfig(tp => tp.copy( + dcache = tp.dcache.map(_.copy(rowBits = n)), + icache = tp.icache.map(_.copy(rowBits = n)) +)) + +class WithBEU(addr: BigInt) extends RocketTileConfig(_.copy(beuAddr = Some(addr))) +class WithBoundaryBuffers(buffers: Option[RocketTileBoundaryBufferParams] = Some(RocketTileBoundaryBufferParams(true))) extends RocketTileConfig(_.copy(boundaryBuffers = buffers)) + +class WithRV32 extends RocketCoreConfig(c => c.copy( + xLen = 32, + pgLevels = 2, // sv32 + fpu = c.fpu.map(_.copy(fLen = 32)), + mulDiv = Some(MulDivParams(mulUnroll = 8)) +)) + +class WithoutVM extends RocketCoreConfig(_.copy(useVM = false)) +class WithCFlushEnabled extends RocketCoreConfig(_.copy(haveCFlush = true)) +class WithNBreakpoints(hwbp: Int) extends RocketCoreConfig(_.copy(nBreakpoints = hwbp)) +class WithHypervisor(hext: Boolean = true) extends RocketCoreConfig(_.copy(useHypervisor = hext)) +class WithCease(enable: Boolean = true) extends RocketCoreConfig(_.copy(haveCease = enable)) +class WithCoreClockGatingEnabled extends RocketCoreConfig(_.copy(clockGate = true)) +class WithPgLevels(n: Int) extends RocketCoreConfig(_.copy(pgLevels = n)) +class WithZba extends RocketCoreConfig(_.copy(useZba = true)) +class WithZbb extends RocketCoreConfig(_.copy(useZbb = true)) +class WithZbs extends RocketCoreConfig(_.copy(useZbs = true)) +class WithB extends RocketCoreConfig(_.copy(useZba = true, useZbb = true, useZbs = true)) +class WithSV48 extends WithPgLevels(4) +class WithSV39 extends WithPgLevels(3) + +// Simulation-only configs +class WithNoSimulationTimeout extends RocketCoreConfig(_.copy(haveSimTimeout = false)) +class WithDebugROB(enable: Boolean = true, size: Int = 0) extends RocketCoreConfig(_.copy(debugROB = Option.when(enable)(DebugROBParams(size)))) + +// FPU configs +class WithoutFPU extends RocketCoreConfig(_.copy(fpu = None)) +class WithFP16 extends RocketCoreConfig(c => c.copy(fpu = c.fpu.map(_.copy(minFLen = 16)))) +class WithFPUWithoutDivSqrt extends RocketCoreConfig(c => c.copy(fpu = c.fpu.map(_.copy(divSqrt = false)))) + +// mul-div configs +class WithFastMulDiv extends RocketCoreConfig(c => c.copy(mulDiv = Some( + MulDivParams(mulUnroll = 8, mulEarlyOut = c.xLen > 32, divEarlyOut = true) +))) +class WithCustomFastMulDiv(mUnroll: Int = 8, mEarlyOut: Boolean = true, dUnroll: Int = 1, dEarlyOut: Boolean = true, dEarlyOutGranularity: Int = 1) extends RocketCoreConfig(_.copy(mulDiv = Some( + MulDivParams(mulUnroll = mUnroll, mulEarlyOut = mEarlyOut, divUnroll = dUnroll, divEarlyOut = dEarlyOut, divEarlyOutGranularity = dEarlyOutGranularity) +))) +class WithoutMulDiv extends RocketCoreConfig(_.copy(mulDiv = None)) + +// Branch-prediction configs +class WithDefaultBtb extends RocketTileConfig(t => t.copy(btb = Some(BTBParams()))) +class WithNoBtb extends RocketTileConfig(_.copy(btb = None)) + +// Tile CDC configs +class WithCDC(crossingType: ClockCrossingType = SynchronousCrossing()) extends RocketCrossingConfig(_.copy(crossingType = crossingType)) +class WithSeperateClockReset extends RocketCrossingConfig(_.copy(forceSeparateClockReset = true)) +class WithSynchronousCDCs extends WithCDC(SynchronousCrossing()) +class WithAsynchronousCDCs(depth: Int, sync: Int) extends WithCDC(AsynchronousCrossing(depth, sync)) +class WithRationalCDCs extends WithCDC(RationalCrossing()) + + + +class WithCloneRocketTiles( + n: Int = 1, + cloneTileId: Int = 0, + location: HierarchicalLocation = InSubsystem, + cloneLocation: HierarchicalLocation = InSubsystem +) extends Config((site, here, up) => { + case TilesLocated(`location`) => { + val prev = up(TilesLocated(location), site) + val idOffset = up(NumTiles) + val tileAttachParams = up(TilesLocated(cloneLocation)).find(_.tileParams.tileId == cloneTileId) + .get.asInstanceOf[RocketTileAttachParams] + (0 until n).map { i => + CloneTileAttachParams(cloneTileId, tileAttachParams.copy( + tileParams = tileAttachParams.tileParams.copy(tileId = i + idOffset) + )) + } ++ prev + } + case NumTiles => up(NumTiles) + n +}) + diff --git a/src/main/scala/rocket/Consts.scala b/src/main/scala/rocket/Consts.scala index 66e45f733ba..10f5201a365 100644 --- a/src/main/scala/rocket/Consts.scala +++ b/src/main/scala/rocket/Consts.scala @@ -22,6 +22,7 @@ trait ScalarOpConstants { def A1_ZERO = 0.U(2.W) def A1_RS1 = 1.U(2.W) def A1_PC = 2.U(2.W) + def A1_RS1SHL = 3.U(2.W) def IMM_X = BitPat("b???") def IMM_S = 0.U(3.W) @@ -31,11 +32,14 @@ trait ScalarOpConstants { def IMM_I = 4.U(3.W) def IMM_Z = 5.U(3.W) - def A2_X = BitPat("b??") - def A2_ZERO = 0.U(2.W) - def A2_SIZE = 1.U(2.W) - def A2_RS2 = 2.U(2.W) - def A2_IMM = 3.U(2.W) + def A2_X = BitPat("b???") + def A2_ZERO = 0.U(3.W) + def A2_SIZE = 1.U(3.W) + def A2_RS2 = 2.U(3.W) + def A2_IMM = 3.U(3.W) + def A2_RS2OH = 4.U(3.W) + def A2_IMMOH = 5.U(3.W) + def X = BitPat("b?") def N = BitPat("b0") diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 308392acad1..edbd7328277 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -4,16 +4,24 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ -import freechips.rocketchip.amba._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tile.{CoreBundle, LookupByHartId} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property -import chisel3.{DontCare, WireInit, dontTouch, withClock} import chisel3.experimental.SourceInfo -import TLMessages._ + +import org.chipsalliance.cde.config._ + +import freechips.rocketchip.amba.AMBAProt +import freechips.rocketchip.diplomacy.{BufferParams} +import freechips.rocketchip.prci.{ClockCrossingType, RationalCrossing, SynchronousCrossing, AsynchronousCrossing, CreditedCrossing} +import freechips.rocketchip.tile.{CoreBundle, LookupByHartId} +import freechips.rocketchip.tilelink.{TLFIFOFixer,ClientMetadata, TLBundleA, TLAtomics, TLBundleB, TLPermissions} +import freechips.rocketchip.tilelink.TLMessages.{AccessAck, HintAck, AccessAckData, Grant, GrantData, ReleaseAck} +import freechips.rocketchip.util.{CanHaveErrors, ClockGate, IdentityCode, ReplacementPolicy, DescribedSRAM, property} + +import freechips.rocketchip.util.BooleanToAugmentedBoolean +import freechips.rocketchip.util.UIntToAugmentedUInt +import freechips.rocketchip.util.UIntIsOneOf +import freechips.rocketchip.util.IntToAugmentedInt +import freechips.rocketchip.util.SeqToAugmentedSeq +import freechips.rocketchip.util.SeqBoolBitwiseOps // TODO: delete this trait once deduplication is smart enough to avoid globally inlining matching circuits trait InlineInstance { self: chisel3.experimental.BaseModule => @@ -52,7 +60,7 @@ class DCacheDataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) { val data_arrays = Seq.tabulate(rowBits / subWordBits) { i => DescribedSRAM( - name = s"data_arrays_${i}", + name = s"${tileParams.baseName}_dcache_data_arrays_${i}", desc = "DCache Data Array", size = nSets * cacheBlockBytes / rowBytes, data = Vec(nWays * (subWordBits / eccBits), UInt(encBits.W)) @@ -86,13 +94,11 @@ class DCache(staticIdForMetadataUseOnly: Int, val crossing: ClockCrossingType)(i class DCacheTLBPort(implicit p: Parameters) extends CoreBundle()(p) { val req = Flipped(Decoupled(new TLBReq(coreDataBytes.log2))) - val s1_resp = Output(new TLBResp) + val s1_resp = Output(new TLBResp(coreDataBytes.log2)) val s2_kill = Input(Bool()) } class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { - val tlb_port = IO(new DCacheTLBPort) - val tECC = cacheParams.tagCode val dECC = cacheParams.dataCode require(subWordBits % eccBits == 0, "subWordBits must be a multiple of eccBits") @@ -115,10 +121,21 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { // tags val replacer = ReplacementPolicy.fromString(cacheParams.replacementPolicy, nWays) + + /** Metadata Arbiter: + * 0: Tag update on reset + * 1: Tag update on ECC error + * 2: Tag update on hit + * 3: Tag update on refill + * 4: Tag update on release + * 5: Tag update on flush + * 6: Tag update on probe + * 7: Tag update on CPU request + */ val metaArb = Module(new Arbiter(new DCacheMetadataReq, 8) with InlineInstance) val tag_array = DescribedSRAM( - name = "tag_array", + name = s"${tileParams.baseName}_dcache_tag_array", desc = "DCache Tag Array", size = nSets, data = Vec(nWays, chiselTypeOf(metaArb.io.out.bits.data)) @@ -126,6 +143,12 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { // data val data = Module(new DCacheDataArray) + /** Data Arbiter + * 0: data from pending store buffer + * 1: data from TL-D refill + * 2: release to TL-A + * 3: hit path to CPU + */ val dataArb = Module(new Arbiter(new DCacheDataReq, 4) with InlineInstance) dataArb.io.in.tail.foreach(_.bits.wdata := dataArb.io.in.head.bits.wdata) // tie off write ports by default data.io.req.bits <> dataArb.io.out.bits @@ -162,7 +185,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_nack = WireDefault(false.B) val s1_valid_masked = s1_valid && !io.cpu.s1_kill val s1_valid_not_nacked = s1_valid && !s1_nack - val s1_tlb_req_valid = RegNext(tlb_port.req.fire, false.B) + val s1_tlb_req_valid = RegNext(io.tlb_port.req.fire, false.B) val s2_tlb_req_valid = RegNext(s1_tlb_req_valid, false.B) val s0_clk_en = metaArb.io.out.valid && !metaArb.io.out.bits.write @@ -173,8 +196,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_req = RegEnable(s0_req, s0_clk_en) val s1_vaddr = Cat(s1_req.idx.getOrElse(s1_req.addr) >> tagLSB, s1_req.addr(tagLSB-1, 0)) - val s0_tlb_req = WireInit(tlb_port.req.bits) - when (!tlb_port.req.fire) { + val s0_tlb_req = WireInit(io.tlb_port.req.bits) + when (!io.tlb_port.req.fire) { s0_tlb_req.passthrough := s0_req.phys s0_tlb_req.vaddr := s0_req.addr s0_tlb_req.size := s0_req.size @@ -182,7 +205,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { s0_tlb_req.prv := s0_req.dprv s0_tlb_req.v := s0_req.dv } - val s1_tlb_req = RegEnable(s0_tlb_req, s0_clk_en || tlb_port.req.valid) + val s1_tlb_req = RegEnable(s0_tlb_req, s0_clk_en || io.tlb_port.req.valid) val s1_read = isRead(s1_req.cmd) val s1_write = isWrite(s1_req.cmd) @@ -246,7 +269,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { // address translation val s1_cmd_uses_tlb = s1_readwrite || s1_flush_line || s1_req.cmd === M_WOK io.ptw <> tlb.io.ptw - tlb.io.kill := io.cpu.s2_kill || s2_tlb_req_valid && tlb_port.s2_kill + tlb.io.kill := io.cpu.s2_kill || s2_tlb_req_valid && io.tlb_port.s2_kill tlb.io.req.valid := s1_tlb_req_valid || s1_valid && !io.cpu.s1_kill && s1_cmd_uses_tlb tlb.io.req.bits := s1_tlb_req when (!tlb.io.req.ready && !tlb.io.ptw.resp.valid && !io.cpu.req.bits.phys) { io.cpu.req.ready := false.B } @@ -260,8 +283,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { tlb.io.sfence.bits.hv := s1_req.cmd === M_HFENCEV tlb.io.sfence.bits.hg := s1_req.cmd === M_HFENCEG - tlb_port.req.ready := clock_en_reg - tlb_port.s1_resp := tlb.io.resp + io.tlb_port.req.ready := clock_en_reg + io.tlb_port.s1_resp := tlb.io.resp when (s1_tlb_req_valid && s1_valid && !(s1_req.phys && s1_req.no_xcpt)) { s1_nack := true.B } pma_checker.io <> DontCare @@ -561,7 +584,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val put = edge.Put(a_source, access_address, a_size, a_data)._2 val putpartial = edge.Put(a_source, access_address, a_size, a_data, a_mask)._2 val atomics = if (edge.manager.anySupportLogical) { - MuxLookup(s2_req.cmd, WireDefault(0.U.asTypeOf(new TLBundleA(edge.bundle))), Array( + MuxLookup(s2_req.cmd, WireDefault(0.U.asTypeOf(new TLBundleA(edge.bundle))))(Array( M_XA_SWAP -> edge.Logical(a_source, access_address, a_size, a_data, TLAtomics.SWAP)._2, M_XA_XOR -> edge.Logical(a_source, access_address, a_size, a_data, TLAtomics.XOR) ._2, M_XA_OR -> edge.Logical(a_source, access_address, a_size, a_data, TLAtomics.OR) ._2, @@ -904,6 +927,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_isSlavePortAccess = s1_req.no_xcpt val s2_isSlavePortAccess = s2_req.no_xcpt io.cpu.ordered := !(s1_valid && !s1_isSlavePortAccess || s2_valid && !s2_isSlavePortAccess || cached_grant_wait || uncachedInFlight.asUInt.orR) + io.cpu.store_pending := (cached_grant_wait && isWrite(s2_req.cmd)) || uncachedInFlight.asUInt.orR val s1_xcpt_valid = tlb.io.req.valid && !s1_isSlavePortAccess && !s1_nack io.cpu.s2_xcpt := Mux(RegNext(s1_xcpt_valid), s2_tlb_xcpt, 0.U.asTypeOf(s2_tlb_xcpt)) @@ -1039,7 +1063,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { metaArb.io.out.valid || // subsumes resetting || flushing s1_probe || s2_probe || s1_valid || s2_valid || - tlb_port.req.valid || + io.tlb_port.req.valid || s1_tlb_req_valid || s2_tlb_req_valid || pstore1_held || pstore2_valid || release_state =/= s_ready || diff --git a/src/main/scala/rocket/DebugROB.scala b/src/main/scala/rocket/DebugROB.scala index 1740b8c073a..39dec03a78c 100644 --- a/src/main/scala/rocket/DebugROB.scala +++ b/src/main/scala/rocket/DebugROB.scala @@ -8,7 +8,9 @@ import chisel3.util._ import chisel3.experimental.{IntParam} import org.chipsalliance.cde.config.{Parameters} import freechips.rocketchip.tile.{HasCoreParameters} +import freechips.rocketchip.util.DecoupledHelper +case class DebugROBParams(size: Int) class WidenedTracedInstruction extends Bundle { val valid = Bool() @@ -27,7 +29,6 @@ class WidenedTracedInstruction extends Bundle { // These is not synthesizable, they use a C++ blackbox to implement the // write-back reordering class DebugROBPushTrace(implicit val p: Parameters) extends BlackBox with HasBlackBoxResource with HasCoreParameters { - require(traceHasWdata && (vLen max xLen) <= 512) val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) @@ -43,7 +44,6 @@ class DebugROBPushTrace(implicit val p: Parameters) extends BlackBox with HasBla class DebugROBPushWb(implicit val p: Parameters) extends BlackBox with HasBlackBoxResource with HasCoreParameters { - require(traceHasWdata && (vLen max xLen) <= 512) val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) @@ -57,7 +57,6 @@ class DebugROBPushWb(implicit val p: Parameters) extends BlackBox } class DebugROBPopTrace(implicit val p: Parameters) extends BlackBox with HasBlackBoxResource with HasCoreParameters { - require(traceHasWdata && (vLen max xLen) <= 512) val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) @@ -102,3 +101,92 @@ object DebugROB { debug_rob_push_wb.io.wb_data := data } } + +class TaggedInstruction(val nXPR: Int)(implicit val p: Parameters) extends Bundle { + val insn = new TracedInstruction + val tag = UInt(log2Up(nXPR + 1).W) + val waiting = Bool() +} + +class TaggedWbData(implicit val p: Parameters) extends Bundle with HasCoreParameters { + val valid = Bool() + val data = UInt(xLen.W) +} + +class HardDebugROB(val traceRatio: Int, val nXPR: Int)(implicit val p: Parameters) + extends Module with HasCoreParameters +{ + val io = IO(new Bundle { + val i_insn = Input(new TracedInstruction) + val should_wb = Input(Bool()) + val has_wb = Input(Bool()) + val tag = Input(UInt(log2Up(nXPR + 1).W)) + + val wb_val = Input(Bool()) + val wb_tag = Input(UInt(log2Up(nXPR + 1).W)) + val wb_data = Input(UInt(xLen.W)) + + val o_insn = Output(new TracedInstruction) + }) + + val iq = Module(new Queue(new TaggedInstruction(nXPR), traceRatio * nXPR, flow = true)) + + // No backpressure + assert(iq.io.enq.ready) + + iq.io.enq.valid := io.i_insn.valid || io.i_insn.exception || io.i_insn.interrupt + iq.io.enq.bits.insn := io.i_insn + iq.io.enq.bits.tag := io.tag + iq.io.enq.bits.waiting := io.should_wb && !io.has_wb + + val wb_q = Seq.fill(nXPR)(Reg(new TaggedWbData)) + + for (i <- 0 until nXPR) { + when (io.wb_val && i.U === io.wb_tag) { + assert(wb_q(i).valid === false.B) + wb_q(i).valid := true.B + wb_q(i).data := io.wb_data + } + } + + val tag_matches = Seq.fill(nXPR)(Wire(Bool())) + for (i <- 0 until nXPR) { + val is_match = iq.io.deq.bits.waiting && + (iq.io.deq.bits.tag === i.U) && + wb_q(i).valid + when (is_match) { + tag_matches(i) := true.B + } .otherwise { + tag_matches(i) := false.B + } + } + + val tag_match = tag_matches.reduce(_ || _) + val vinsn_rdy = !iq.io.deq.bits.waiting || + (iq.io.deq.bits.tag >= nXPR.U) || // not integer instruction + tag_match + val maybeFire = Mux(iq.io.deq.bits.insn.valid, vinsn_rdy, true.B) + val fireTrace = DecoupledHelper( + iq.io.deq.valid, + maybeFire) + + iq.io.deq.ready := fireTrace.fire(iq.io.deq.valid) + io.o_insn := iq.io.deq.bits.insn + io.o_insn.valid := iq.io.deq.fire && iq.io.deq.bits.insn.valid + + for (i <- 0 until nXPR) { + when (tag_match && fireTrace.fire() && i.U === iq.io.deq.bits.tag) { + io.o_insn.wdata.get := wb_q(i).data + wb_q(i).valid := false.B + } + } + + val qcnt = RegInit(0.U(64.W)) + when (iq.io.enq.fire && !iq.io.deq.fire) { + qcnt := qcnt + 1.U + } .elsewhen (!iq.io.enq.fire && iq.io.deq.fire) { + qcnt := qcnt - 1.U + } .otherwise { + qcnt := qcnt + } +} diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index f6c0ad52b68..8156e51c475 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -5,14 +5,17 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ -import chisel3.{withClock,withReset} import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.tilelink.{TLWidthWidget} -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.tile.{CoreBundle, BaseTile} +import freechips.rocketchip.tilelink.{TLWidthWidget, TLEdgeOut} +import freechips.rocketchip.util.{ClockGate, ShiftQueue, property} + +import freechips.rocketchip.util.UIntToAugmentedUInt class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) { val pc = UInt(vaddrBitsExtended.W) @@ -52,6 +55,7 @@ class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) { val sfence = Valid(new SFenceReq) val resp = Flipped(Decoupled(new FrontendResp)) val gpa = Flipped(Valid(UInt(vaddrBitsExtended.W))) + val gpa_is_pte = Input(Bool()) val btb_update = Valid(new BTBUpdate) val bht_update = Valid(new BHTUpdate) val ras_update = Valid(new RASUpdate) @@ -61,9 +65,9 @@ class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) { val progress = Output(Bool()) } -class Frontend(val icacheParams: ICacheParams, staticIdForMetadataUseOnly: Int)(implicit p: Parameters) extends LazyModule { +class Frontend(val icacheParams: ICacheParams, tileId: Int)(implicit p: Parameters) extends LazyModule { lazy val module = new FrontendModule(this) - val icache = LazyModule(new ICache(icacheParams, staticIdForMetadataUseOnly)) + val icache = LazyModule(new ICache(icacheParams, tileId)) val masterNode = icache.masterNode val slaveNode = icache.slaveNode val resetVectorSinkNode = BundleBridgeSink[UInt](Some(() => UInt(masterNode.edges.out.head.bundle.addressBits.W))) @@ -80,7 +84,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) with HasL1ICacheParameters { val io = IO(new FrontendBundle(outer)) val io_reset_vector = outer.resetVectorSinkNode.bundle - implicit val edge = outer.masterNode.edges.out(0) + implicit val edge: TLEdgeOut = outer.masterNode.edges.out(0) val icache = outer.icache.module require(fetchWidth*coreInstBytes == outer.icacheParams.fetchBytes) @@ -240,7 +244,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) val rvcBranch = bits === Instructions.C_BEQZ || bits === Instructions.C_BNEZ val rvcJAL = (xLen == 32).B && bits === Instructions32.C_JAL val rvcJump = bits === Instructions.C_J || rvcJAL - val rvcImm = Mux(bits(14), new RVCDecoder(bits, xLen).bImm.asSInt, new RVCDecoder(bits, xLen).jImm.asSInt) + val rvcImm = Mux(bits(14), new RVCDecoder(bits, xLen, fLen).bImm.asSInt, new RVCDecoder(bits, xLen, fLen).jImm.asSInt) val rvcJR = bits === Instructions.C_MV && bits(6,2) === 0.U val rvcReturn = rvcJR && BitPat("b00?01") === bits(11,7) val rvcJALR = bits === Instructions.C_ADD && bits(6,2) === 0.U @@ -348,9 +352,11 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) // supply guest physical address to commit stage val gpa_valid = Reg(Bool()) val gpa = Reg(UInt(vaddrBitsExtended.W)) + val gpa_is_pte = Reg(Bool()) when (fq.io.enq.fire && s2_tlb_resp.gf.inst) { when (!gpa_valid) { gpa := s2_tlb_resp.gpa + gpa_is_pte := s2_tlb_resp.gpa_is_pte } gpa_valid := true.B } @@ -359,6 +365,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) } io.cpu.gpa.valid := gpa_valid io.cpu.gpa.bits := gpa + io.cpu.gpa_is_pte := gpa_is_pte // performance events io.cpu.perf.acquire := icache.io.perf.acquire @@ -383,7 +390,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) /** Mix-ins for constructing tiles that have an ICache-based pipeline frontend */ trait HasICacheFrontend extends CanHavePTW { this: BaseTile => val module: HasICacheFrontendModule - val frontend = LazyModule(new Frontend(tileParams.icache.get, staticIdForMetadataUseOnly)) + val frontend = LazyModule(new Frontend(tileParams.icache.get, tileId)) tlMasterXbar.node := TLWidthWidget(tileParams.icache.get.rowBits/8) := frontend.masterNode connectTLSlave(frontend.slaveNode, tileParams.core.fetchBytes) frontend.icache.hartIdSinkNodeOpt.foreach { _ := hartIdNexusNode } diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index 7360ab89fc0..29333c13fa3 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -3,15 +3,21 @@ package freechips.rocketchip.rocket -import chisel3._ -import chisel3.util.{isPow2,log2Ceil,log2Up,Decoupled,Valid} -import chisel3.dontTouch -import freechips.rocketchip.amba._ -import org.chipsalliance.cde.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import chisel3.{dontTouch, _} +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.AMBAProtField +import freechips.rocketchip.diplomacy.{IdRange, TransferSizes, RegionType} +import freechips.rocketchip.tile.{L1CacheParams, HasL1CacheParameters, HasCoreParameters, CoreBundle, HasNonDiplomaticTileParameters, BaseTile, HasTileParameters} +import freechips.rocketchip.tilelink.{TLMasterParameters, TLClientNode, TLMasterPortParameters, TLEdgeOut, TLWidthWidget, TLFIFOFixer, ClientMetadata} +import freechips.rocketchip.util.{Code, RandomReplacement, ParameterizedBundle} + +import freechips.rocketchip.util.{BooleanToAugmentedBoolean, IntToAugmentedInt} + import scala.collection.mutable.ListBuffer case class DCacheParams( @@ -119,6 +125,7 @@ trait HasCoreData extends HasCoreParameters { class HellaCacheReqInternal(implicit p: Parameters) extends CoreBundle()(p) with HasCoreMemOp { val phys = Bool() + val no_resp = Bool() // The dcache may omit generating a response for this request val no_alloc = Bool() val no_xcpt = Bool() } @@ -180,6 +187,7 @@ class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) { val s2_gpa_is_pte = Input(Bool()) val uncached_resp = tileParams.dcache.get.separateUncachedResp.option(Flipped(Decoupled(new HellaCacheResp))) val ordered = Input(Bool()) + val store_pending = Input(Bool()) // there is a store in a store buffer somewhere val perf = Input(new HellaCachePerfEvents()) val keep_clock_enabled = Output(Bool()) // should D$ avoid clock-gating itself? @@ -188,17 +196,17 @@ class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) { /** Base classes for Diplomatic TL2 HellaCaches */ -abstract class HellaCache(staticIdForMetadataUseOnly: Int)(implicit p: Parameters) extends LazyModule +abstract class HellaCache(tileId: Int)(implicit p: Parameters) extends LazyModule with HasNonDiplomaticTileParameters { protected val cfg = tileParams.dcache.get protected def cacheClientParameters = cfg.scratch.map(x => Seq()).getOrElse(Seq(TLMasterParameters.v1( - name = s"Core ${staticIdForMetadataUseOnly} DCache", + name = s"Core ${tileId} DCache", sourceId = IdRange(0, 1 max cfg.nMSHRs), supportsProbe = TransferSizes(cfg.blockBytes, cfg.blockBytes)))) protected def mmioClientParameters = Seq(TLMasterParameters.v1( - name = s"Core ${staticIdForMetadataUseOnly} DCache MMIO", + name = s"Core ${tileId} DCache MMIO", sourceId = IdRange(firstMMIO, firstMMIO + cfg.nMMIOs), requestFifo = true)) @@ -221,17 +229,18 @@ abstract class HellaCache(staticIdForMetadataUseOnly: Int)(implicit p: Parameter require(!tileParams.core.haveCFlush || cfg.scratch.isEmpty, "CFLUSH_D_L1 instruction requires a D$") } -class HellaCacheBundle(val outer: HellaCache)(implicit p: Parameters) extends CoreBundle()(p) { - val cpu = Flipped((new HellaCacheIO)) +class HellaCacheBundle(implicit p: Parameters) extends CoreBundle()(p) { + val cpu = Flipped(new HellaCacheIO) val ptw = new TLBPTWIO() val errors = new DCacheErrors + val tlb_port = new DCacheTLBPort } class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) with HasL1HellaCacheParameters { - implicit val edge = outer.node.edges.out(0) + implicit val edge: TLEdgeOut = outer.node.edges.out(0) val (tl_out, _) = outer.node.out(0) - val io = IO(new HellaCacheBundle(outer)) + val io = IO(new HellaCacheBundle) val io_hartid = outer.hartIdSinkNodeOpt.map(_.bundle) val io_mmio_address_prefix = outer.mmioAddressPrefixSinkNodeOpt.map(_.bundle) dontTouch(io.cpu.resp) // Users like to monitor these fields even if the core ignores some signals @@ -254,9 +263,9 @@ case object BuildHellaCache extends Field[BaseTile => Parameters => HellaCache]( object HellaCacheFactory { def apply(tile: BaseTile)(p: Parameters): HellaCache = { if (tile.tileParams.dcache.get.nMSHRs == 0) - new DCache(tile.staticIdForMetadataUseOnly, tile.crossing)(p) + new DCache(tile.tileId, tile.crossing)(p) else - new NonBlockingDCache(tile.staticIdForMetadataUseOnly)(p) + new NonBlockingDCache(tile.tileId)(p) } } @@ -272,10 +281,7 @@ trait HasHellaCache { this: BaseTile => dcache.hartIdSinkNodeOpt.map { _ := hartIdNexusNode } dcache.mmioAddressPrefixSinkNodeOpt.map { _ := mmioAddressPrefixNexusNode } InModuleBody { - dcache.module match { - case module: DCacheModule => module.tlb_port := DontCare - case other => other - } + dcache.module.io.tlb_port := DontCare } } diff --git a/src/main/scala/rocket/HellaCacheArbiter.scala b/src/main/scala/rocket/HellaCacheArbiter.scala index 4b9fc08f4cb..cdc287d5043 100644 --- a/src/main/scala/rocket/HellaCacheArbiter.scala +++ b/src/main/scala/rocket/HellaCacheArbiter.scala @@ -63,6 +63,7 @@ class HellaCacheArbiter(n: Int)(implicit p: Parameters) extends Module io.requestor(i).s2_gpa := io.mem.s2_gpa io.requestor(i).s2_gpa_is_pte := io.mem.s2_gpa_is_pte io.requestor(i).ordered := io.mem.ordered + io.requestor(i).store_pending := io.mem.store_pending io.requestor(i).perf := io.mem.perf io.requestor(i).s2_nack := io.mem.s2_nack && s2_id === i.U io.requestor(i).s2_nack_cause_raw := io.mem.s2_nack_cause_raw diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index 3090ca4f99d..d3bf3c2119f 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -3,18 +3,26 @@ package freechips.rocketchip.rocket -import chisel3._ -import chisel3.util.{Cat, Decoupled, Mux1H, OHToUInt, RegEnable, Valid, isPow2, log2Ceil, log2Up, PopCount} -import freechips.rocketchip.amba._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util.{DescribedSRAM, _} -import freechips.rocketchip.util.property -import chisel3.experimental.SourceInfo -import chisel3.dontTouch +import chisel3.{dontTouch, _} +import chisel3.util._ import chisel3.util.random.LFSR +import chisel3.experimental.SourceInfo + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} +import freechips.rocketchip.diplomacy.{IdRange, AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{SimpleDevice, ResourceBindings, Binding, ResourceAddress, Description, ResourceString, ResourceValue} +import freechips.rocketchip.tile.{L1CacheParams, HasL1CacheParameters, HasCoreParameters, CoreBundle, TileKey, LookupByHartId} +import freechips.rocketchip.tilelink.{TLClientNode, TLMasterPortParameters, TLManagerNode, TLSlavePortParameters, TLSlaveParameters, TLMasterParameters, TLHints} +import freechips.rocketchip.util.{Code, CanHaveErrors, DescribedSRAM, RandomReplacement, Split, IdentityCode, property} + +import freechips.rocketchip.util.BooleanToAugmentedBoolean +import freechips.rocketchip.util.UIntToAugmentedUInt +import freechips.rocketchip.util.SeqToAugmentedSeq +import freechips.rocketchip.util.OptionUIntToAugmentedOptionUInt /** Parameter of [[ICache]]. * @@ -410,7 +418,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) * content with `refillError ## tag[19:0]` after ECC * */ val tag_array = DescribedSRAM( - name = "tag_array", + name = s"${tileParams.baseName}_icache_tag_array", desc = "ICache Tag Array", size = nSets, data = Vec(nWays, UInt(tECC.width(1 + tagBits).W)) @@ -497,7 +505,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) // @todo Accessing ITIM correspond address will be able to read cacheline? // is this desired behavior? addrInScratchpad(io.s1_paddr) && scratchpadWay(io.s1_paddr) === i.U) - val s1_vb = vb_array(Cat(i.U, s1_idx)) && !s1_slaveValid + val s1_vb = vb_array(Cat(i.U, s1_idx).pad(log2Ceil(nSets*nWays))) && !s1_slaveValid val enc_tag = tECC.decode(tag_rdata(i)) /** [[tl_error]] ECC error bit. * [[tag]] of [[tag_array]] access. @@ -544,7 +552,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) val data_arrays = Seq.tabulate(tl_out.d.bits.data.getWidth / wordBits) { i => DescribedSRAM( - name = s"data_arrays_${i}", + name = s"${tileParams.baseName}_icache_data_arrays_${i}", desc = "ICache Data Array", size = nSets * refillCycles, data = Vec(nWays, UInt(dECC.width(wordBits).W)) diff --git a/src/main/scala/rocket/IDecode.scala b/src/main/scala/rocket/IDecode.scala index 86ee7eef58a..e61d11dd26a 100644 --- a/src/main/scala/rocket/IDecode.scala +++ b/src/main/scala/rocket/IDecode.scala @@ -9,13 +9,14 @@ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.util._ import Instructions._ import CustomInstructions._ +import ALU._ abstract trait DecodeConstants { val table: Array[(BitPat, List[BitPat])] } -class IntCtrlSigs(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends Bundle { +class IntCtrlSigs(implicit val p: Parameters) extends Bundle { val legal = Bool() val fp = Bool() @@ -29,7 +30,7 @@ class IntCtrlSigs(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends Bu val sel_alu1 = Bits(A1_X.getWidth.W) val sel_imm = Bits(IMM_X.getWidth.W) val alu_dw = Bool() - val alu_fn = Bits(aluFn.FN_X.getWidth.W) + val alu_fn = Bits(FN_X.getWidth.W) val mem = Bool() val mem_cmd = Bits(M_SZ.W) val rfs1 = Bool() @@ -44,17 +45,18 @@ class IntCtrlSigs(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends Bu val fence = Bool() val amo = Bool() val dp = Bool() + val vec = Bool() def default: List[BitPat] = - // jal renf1 fence.i - // val | jalr | renf2 | - // | fp_val| | renx2 | | renf3 | - // | | rocc| | | renx1 s_alu1 mem_val | | | wfd | - // | | | br| | | | s_alu2 | imm dw alu | mem_cmd | | | | mul | - // | | | | | | | | | | | | | | | | | | | | div | fence - // | | | | | | | | | | | | | | | | | | | | | wxd | | amo - // | | | | | | | | | | | | | | | | | | | | | | | | | dp - List(N,X,X,X,X,X,X,X, A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, X,X,X,X,X,X,X,CSR.X,X,X,X,X) + // jal renf1 fence.i + // val | jalr | renf2 | + // | fp_val| | renx2 | | renf3 | + // | | rocc| | | renx1 s_alu1 mem_val | | | wfd | + // | | | br| | | | s_alu2 | imm dw alu | mem_cmd | | | | mul | + // | | | | | | | | | | | | | | | | | | | | div | fence + // | | | | | | | | | | | | | | | | | | | | | wxd | | amo + // | | | | | | | | | | | | | | | | | | | | | | | | | dp + List(N,X,X,X,X,X,X,X, A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, X,X,X,X,X,X,X,CSR.X,X,X,X,X) def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = { val decoder = DecodeLogic(inst, default, table) @@ -66,398 +68,486 @@ class IntCtrlSigs(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends Bu } } -class IDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class IDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - BNE-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SNE, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - BEQ-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SEQ, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - BLT-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SLT, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - BLTU-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SLTU, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - BGE-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SGE, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - BGEU-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,aluFn.FN_SGEU, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - - JAL-> List(Y,N,N,N,Y,N,N,N,A2_SIZE,A1_PC, IMM_UJ,DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - JALR-> List(Y,N,N,N,N,Y,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - AUIPC-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_PC, IMM_U, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - - LB-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - LH-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - LW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - LBU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - LHU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SB-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - SH-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - SW-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - - LUI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_U, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - ADDI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLTI -> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SLT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLTIU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SLTU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - ANDI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_AND, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - ORI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_OR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - XORI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_XOR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - ADD-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SUB-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SUB, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLT-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SLT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLTU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SLTU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - AND-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_AND, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - OR-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_OR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - XOR-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_XOR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRA-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - - FENCE-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.N,N,Y,N,N), - - ECALL-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - EBREAK-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - MRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - WFI-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - CSRRW-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.W,N,N,N,N), - CSRRS-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.S,N,N,N,N), - CSRRC-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.C,N,N,N,N), - CSRRWI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.W,N,N,N,N), - CSRRSI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.S,N,N,N,N), - CSRRCI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.C,N,N,N,N)) + BNE-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SNE, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + BEQ-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SEQ, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + BLT-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SLT, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + BLTU-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SLTU, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + BGE-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SGE, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + BGEU-> List(Y,N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_XPR,FN_SGEU, N,M_X, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + + JAL-> List(Y,N,N,N,Y,N,N,N,A2_SIZE,A1_PC, IMM_UJ,DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + JALR-> List(Y,N,N,N,N,Y,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + AUIPC-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_PC, IMM_U, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + + LB-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + LH-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + LW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + LBU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + LHU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SB-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + SH-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + SW-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + + LUI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_U, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ADDI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLTI -> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SLT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLTIU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SLTU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ANDI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_AND, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ORI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_OR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + XORI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_XOR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ADD-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SUB-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SUB, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLT-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SLT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLTU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SLTU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + AND-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_AND, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + OR-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_OR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + XOR-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_XOR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRA-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + + FENCE-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.N,N,Y,N,N), + + ECALL-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + EBREAK-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + MRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + WFI-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + CSRRW-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.W,N,N,N,N), + CSRRS-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.S,N,N,N,N), + CSRRC-> List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.C,N,N,N,N), + CSRRWI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.W,N,N,N,N), + CSRRSI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.S,N,N,N,N), + CSRRCI-> List(Y,N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.C,N,N,N,N)) } -class CeaseDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class CeaseDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - CEASE-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + CEASE-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class FenceIDecode(flushDCache: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class FenceIDecode(flushDCache: Boolean)(implicit val p: Parameters) extends DecodeConstants { private val (v, cmd) = if (flushDCache) (Y, BitPat(M_FLUSH_ALL)) else (N, M_X) val table: Array[(BitPat, List[BitPat])] = Array( - FENCE_I-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, v,cmd, N,N,N,N,N,N,N,CSR.N,Y,Y,N,N)) + FENCE_I-> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, v,cmd, N,N,N,N,N,N,N,CSR.N,Y,Y,N,N)) } -class ConditionalZeroDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class ConditionalZeroDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - CZERO_EQZ-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_CZEQZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CZERO_NEZ-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_CZNEZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) + CZERO_EQZ-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_CZEQZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CZERO_NEZ-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_CZNEZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) } -class CFlushDecode(supportsFlushLine: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class CFlushDecode(supportsFlushLine: Boolean)(implicit val p: Parameters) extends DecodeConstants { private def zapRs1(x: BitPat) = if (supportsFlushLine) x else BitPat(x.value.U) val table: Array[(BitPat, List[BitPat])] = Array( zapRs1(CFLUSH_D_L1)-> - List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_FLUSH_ALL,N,N,N,N,N,N,N,CSR.I,N,N,N,N), + List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_FLUSH_ALL,N,N,N,N,N,N,N,CSR.I,N,N,N,N), zapRs1(CDISCARD_D_L1)-> - List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_FLUSH_ALL,N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + List(Y,N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_FLUSH_ALL,N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class SVMDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class SVMDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - SFENCE_VMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_SFENCE, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + SFENCE_VMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_SFENCE, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class SDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class SDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - SRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + SRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class HypervisorDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class HypervisorDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - HFENCE_VVMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_HFENCEV, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - HFENCE_GVMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_HFENCEG, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + HFENCE_VVMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_HFENCEV, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + HFENCE_GVMA->List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_HFENCEG, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - HLV_B -> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLV_BU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLV_H -> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLV_HU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLVX_HU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_HLVX, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLV_W-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HLVX_WU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_HLVX, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLV_B -> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLV_BU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLV_H -> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLV_HU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLVX_HU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_HLVX, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLV_W-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HLVX_WU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_HLVX, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HSV_B-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - HSV_H-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - HSV_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + HSV_B-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + HSV_H-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + HSV_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class DebugDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class DebugDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - DRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + DRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class NMIDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class NMIDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - MNRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) + MNRET-> List(Y,N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,N,CSR.I,N,N,N,N)) } -class I32Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class I32Decode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( Instructions32.SLLI-> - List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), Instructions32.SRLI-> - List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), Instructions32.SRAI-> - List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) + List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) } -class I64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class I64Decode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - LD-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - LWU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SD-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), - - SLLI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRLI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRAI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - - ADDIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLLIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,aluFn.FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRLIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,aluFn.FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRAIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,aluFn.FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - ADDW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,aluFn.FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SUBW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,aluFn.FN_SUB, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SLLW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,aluFn.FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRLW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,aluFn.FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - SRAW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,aluFn.FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) + LD-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + LWU-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SD-> List(Y,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.N,N,N,N,N), + + SLLI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRLI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRAI-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + + ADDIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLLIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRLIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRAIW-> List(Y,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ADDW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SUBW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SUB, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLLW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRLW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SRAW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SRA, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) } -class Hypervisor64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class Hypervisor64Decode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - HLV_D-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), - HSV_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, aluFn.FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), - HLV_WU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, aluFn.FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N)) + HLV_D-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N), + HSV_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_I, DW_XPR, FN_ADD, Y,M_XWR, N,N,N,N,N,N,N,CSR.I,N,N,N,N), + HLV_WU-> List(Y,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR, FN_ADD, Y,M_XRD, N,N,N,N,N,N,Y,CSR.I,N,N,N,N)) } -class MDecode(pipelinedMul: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class MDecode(pipelinedMul: Boolean)(implicit val p: Parameters) extends DecodeConstants { val M = if (pipelinedMul) Y else N val D = if (pipelinedMul) N else Y val table: Array[(BitPat, List[BitPat])] = Array( - MUL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_MUL, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), - MULH-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_MULH, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), - MULHU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_MULHU, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), - MULHSU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_MULHSU,N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), - - DIV-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_DIV, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - DIVU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_DIVU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - REM-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_REM, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - REMU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_REMU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N)) + MUL-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MUL, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), + MULH-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULH, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), + MULHU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULHU, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), + MULHSU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULHSU,N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), + + DIV-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_DIV, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + DIVU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_DIVU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + REM-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_REM, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + REMU-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_REMU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N)) } -class M64Decode(pipelinedMul: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +class M64Decode(pipelinedMul: Boolean)(implicit val p: Parameters) extends DecodeConstants { val M = if (pipelinedMul) Y else N val D = if (pipelinedMul) N else Y val table: Array[(BitPat, List[BitPat])] = Array( - MULW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, aluFn.FN_MUL, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), - - DIVW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, aluFn.FN_DIV, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - DIVUW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, aluFn.FN_DIVU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - REMW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, aluFn.FN_REM, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), - REMUW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, aluFn.FN_REMU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N)) -} - -class ADecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - AMOADD_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_ADD, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOXOR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_XOR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOSWAP_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_SWAP, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOAND_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_AND, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOOR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_OR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMIN_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MIN, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMINU_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MINU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMAX_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MAX, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMAXU_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MAXU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - - LR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XLR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - SC_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XSC, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N)) -} - -class A64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - AMOADD_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_ADD, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOSWAP_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_SWAP, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOXOR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_XOR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOAND_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_AND, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOOR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_OR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMIN_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MIN, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMINU_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MINU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMAX_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MAX, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - AMOMAXU_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XA_MAXU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - - LR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XLR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), - SC_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, Y,M_XSC, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N)) -} - -class HDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FCVT_S_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_H_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FSGNJ_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSGNJX_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSGNJN_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMIN_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMAX_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMUL_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FMSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FNMADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FNMSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FCLASS_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FMV_X_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_W_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_WU_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FEQ_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FLT_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FLE_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FMV_H_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_H_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_H_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FLH-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FSH-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,N), - FDIV_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSQRT_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N)) -} - -class FDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants + MULW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_MUL, N,M_X, N,N,N,N,M,D,Y,CSR.N,N,N,N,N), + + DIVW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_DIV, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + DIVUW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_DIVU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + REMW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_REM, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N), + REMUW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_REMU, N,M_X, N,N,N,N,N,Y,Y,CSR.N,N,N,N,N)) +} + +class ADecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + AMOADD_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_ADD, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOXOR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_XOR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOSWAP_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_SWAP, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOAND_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_AND, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOOR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_OR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMIN_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MIN, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMINU_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MINU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMAX_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAX, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMAXU_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAXU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + + LR_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XLR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + SC_W-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XSC, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N)) +} + +class A64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + AMOADD_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_ADD, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOSWAP_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_SWAP, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOXOR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_XOR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOAND_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_AND, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOOR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_OR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMIN_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MIN, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMINU_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MINU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMAX_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAX, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + AMOMAXU_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAXU, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + + LR_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XLR, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N), + SC_D-> List(Y,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XSC, N,N,N,N,N,N,Y,CSR.N,N,N,Y,N)) +} + +class HDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FCVT_S_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_H_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FSGNJ_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSGNJX_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSGNJN_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMIN_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMAX_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMUL_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FMSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FNMADD_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FNMSUB_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FCLASS_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FMV_X_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_W_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_WU_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FEQ_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FLT_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FLE_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FMV_H_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_H_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_H_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FLH-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FSH-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,N), + FDIV_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSQRT_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N)) +} + +class FDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FSGNJ_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSGNJX_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSGNJN_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMIN_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMAX_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMUL_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FMADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FMSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FNMADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FNMSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), + FCLASS_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FMV_X_W-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_W_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_WU_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FEQ_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FLT_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FLE_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), + FMV_W_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_S_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_S_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FLW-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FSW-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,N), + FDIV_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), + FSQRT_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N)) +} + +class DDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FCVT_S_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FCVT_D_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSGNJ_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSGNJX_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSGNJN_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FMIN_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FMAX_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FMUL_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FMADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), + FMSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), + FNMADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), + FNMSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), + FCLASS_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FCVT_W_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FCVT_WU_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FEQ_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), + FLT_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), + FLE_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), + FCVT_D_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FCVT_D_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FLD-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSD-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,Y), + FDIV_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), + FSQRT_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y)) +} + +class HDDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FCVT_D_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FCVT_H_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y)) +} + +class H64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FCVT_L_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_LU_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_H_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_H_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N)) +} + +class F64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FCVT_L_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_LU_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), + FCVT_S_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), + FCVT_S_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N)) +} + +class D64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + FMV_X_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FCVT_L_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FCVT_LU_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), + FMV_D_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FCVT_D_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), + FCVT_D_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y)) +} + +class VCFGDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + VSETVLI -> List(Y,N,N,N,N,N,N,Y,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + VSETIVLI -> List(Y,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + VSETVL -> List(Y,N,N,N,N,N,Y,Y,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) +} + +class ZbaDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + SH1ADD -> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X,DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SH2ADD -> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X,DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SH3ADD -> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X,DW_XPR,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class Zba64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + SH1ADD_UW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X, DW_64,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SH2ADD_UW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X, DW_64,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SH3ADD_UW-> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X, DW_64,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ADD_UW -> List(Y,N,N,N,N,N,Y,Y,A2_RS2,A1_RS1SHL,IMM_X, DW_64,FN_ADD, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SLLI_UW -> List(Y,N,N,N,N,N,Y,Y,A2_IMM,A1_RS1SHL,IMM_I, DW_64,FN_SL , N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class ZbbDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + ANDN -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_ANDN, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ORN -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_ORN, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + XNOR -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_XNOR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CLZ -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CPOP -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CTZ -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + MAX -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_MAX, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + MAXU -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_MAXU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + MIN -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_MIN, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + MINU -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_MINU, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ORC_B -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ROL -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_ROL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ROR -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_ROR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + RORI -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_ROR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SEXT_B -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + SEXT_H -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class Zbb64Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + REV8 -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CTZW -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_32 ,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CLZW -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_32 ,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CPOPW -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_32 ,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ROLW -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_32 ,FN_ROL, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + RORW -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_32 ,FN_ROR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + RORIW -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_32 ,FN_ROR, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ZEXT_H -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class Zbb32Decode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + Instructions32.REV8 -> + List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + Instructions32.ZEXT_H -> + List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_UNARY, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class ZbsDecode(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + BCLR -> List(Y,N,N,N,N,N,Y,Y,A2_RS2OH ,A1_RS1,IMM_X,DW_XPR,FN_ANDN, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BCLRI -> List(Y,N,N,N,N,N,N,Y,A2_IMMOH ,A1_RS1,IMM_I,DW_XPR,FN_ANDN, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BEXT -> List(Y,N,N,N,N,N,Y,Y,A2_RS2 ,A1_RS1,IMM_X,DW_XPR,FN_BEXT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BEXTI -> List(Y,N,N,N,N,N,N,Y,A2_IMM ,A1_RS1,IMM_I,DW_XPR,FN_BEXT, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BINV -> List(Y,N,N,N,N,N,Y,Y,A2_RS2OH ,A1_RS1,IMM_X,DW_XPR,FN_XOR , N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BINVI -> List(Y,N,N,N,N,N,N,Y,A2_IMMOH ,A1_RS1,IMM_I,DW_XPR,FN_XOR , N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BSET -> List(Y,N,N,N,N,N,Y,Y,A2_RS2OH ,A1_RS1,IMM_X,DW_XPR,FN_OR , N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + BSETI -> List(Y,N,N,N,N,N,N,Y,A2_IMMOH ,A1_RS1,IMM_I,DW_XPR,FN_OR , N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + ) +} + +class RoCCDecode(implicit val p: Parameters) extends DecodeConstants { val table: Array[(BitPat, List[BitPat])] = Array( - FSGNJ_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSGNJX_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSGNJN_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMIN_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMAX_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMUL_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FMADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FMSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FNMADD_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FNMSUB_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,N), - FCLASS_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FMV_X_W-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_W_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_WU_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FEQ_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FLT_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FLE_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,N), - FMV_W_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_S_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_S_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FLW-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FSW-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,N), - FDIV_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N), - FSQRT_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,N)) -} - -class DDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FCVT_S_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FCVT_D_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSGNJ_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSGNJX_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSGNJN_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FMIN_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FMAX_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FMUL_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FMADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), - FMSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), - FNMADD_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), - FNMSUB_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,Y,Y,N,N,N,CSR.N,N,N,N,Y), - FCLASS_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FCVT_W_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FCVT_WU_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FEQ_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), - FLT_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), - FLE_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,N,N,N,Y,CSR.N,N,N,N,Y), - FCVT_D_W-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FCVT_D_WU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FLD-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,aluFn.FN_ADD, Y,M_XRD, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSD-> List(Y,Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,aluFn.FN_ADD, Y,M_XWR, N,Y,N,N,N,N,N,CSR.N,N,N,N,Y), - FDIV_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y), - FSQRT_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,Y,N,Y,N,N,N,CSR.N,N,N,N,Y)) -} - -class HDDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FCVT_D_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FCVT_H_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,Y,N,N,N,CSR.N,N,N,N,Y)) -} - -class H64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FCVT_L_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_LU_H-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_H_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_H_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N)) -} - -class F64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FCVT_L_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_LU_S-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,N), - FCVT_S_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N), - FCVT_S_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,N)) -} - -class D64Decode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - FMV_X_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FCVT_L_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FCVT_LU_D-> List(Y,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, N,M_X, Y,N,N,N,N,N,Y,CSR.N,N,N,N,Y), - FMV_D_X-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FCVT_D_L-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y), - FCVT_D_LU-> List(Y,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, aluFn.FN_X, N,M_X, N,N,N,Y,N,N,N,CSR.N,N,N,N,Y)) -} - -class RoCCDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants -{ - val table: Array[(BitPat, List[BitPat])] = Array( - CUSTOM0-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM0_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM0_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM0_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM0_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM0_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM1-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM1_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM1_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM1_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM1_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM1_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM2-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM2_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM2_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM2_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM2_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM2_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM3-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM3_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM3_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), - CUSTOM3_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM3_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), - CUSTOM3_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,aluFn.FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) + CUSTOM0-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM0_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM0_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM0_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM0_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM0_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM1-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM1_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM1_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM1_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM1_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM1_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM2-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM2_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM2_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM2_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM2_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM2_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM3-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM3_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM3_RS1_RS2-> List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,N,CSR.N,N,N,N,N), + CUSTOM3_RD-> List(Y,N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM3_RD_RS1-> List(Y,N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CUSTOM3_RD_RS1_RS2->List(Y,N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X,N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) } diff --git a/src/main/scala/rocket/Multiplier.scala b/src/main/scala/rocket/Multiplier.scala index fd571024d63..081dd0c841f 100644 --- a/src/main/scala/rocket/Multiplier.scala +++ b/src/main/scala/rocket/Multiplier.scala @@ -7,8 +7,10 @@ import chisel3._ import chisel3.util.{Cat, log2Up, log2Ceil, log2Floor, Log2, Decoupled, Enum, Fill, Valid, Pipe} import freechips.rocketchip.util._ -class MultiplierReq(dataBits: Int, tagBits: Int, aluFn: ALUFN = new ALUFN) extends Bundle { - val fn = Bits(aluFn.SZ_ALU_FN.W) +import ALU._ + +class MultiplierReq(dataBits: Int, tagBits: Int) extends Bundle { + val fn = Bits(SZ_ALU_FN.W) val dw = Bits(SZ_DW.W) val in1 = Bits(dataBits.W) val in2 = Bits(dataBits.W) @@ -17,11 +19,12 @@ class MultiplierReq(dataBits: Int, tagBits: Int, aluFn: ALUFN = new ALUFN) exten class MultiplierResp(dataBits: Int, tagBits: Int) extends Bundle { val data = Bits(dataBits.W) + val full_data = Bits((2*dataBits).W) val tag = UInt(tagBits.W) } -class MultiplierIO(val dataBits: Int, val tagBits: Int, aluFn: ALUFN = new ALUFN) extends Bundle { - val req = Flipped(Decoupled(new MultiplierReq(dataBits, tagBits, aluFn))) +class MultiplierIO(val dataBits: Int, val tagBits: Int) extends Bundle { + val req = Flipped(Decoupled(new MultiplierReq(dataBits, tagBits))) val kill = Input(Bool()) val resp = Decoupled(new MultiplierResp(dataBits, tagBits)) } @@ -34,12 +37,12 @@ case class MulDivParams( divEarlyOutGranularity: Int = 1 ) -class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32, aluFn: ALUFN = new ALUFN) extends Module { +class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { private def minDivLatency = (cfg.divUnroll > 0).option(if (cfg.divEarlyOut) 3 else 1 + w/cfg.divUnroll) private def minMulLatency = (cfg.mulUnroll > 0).option(if (cfg.mulEarlyOut) 2 else w/cfg.mulUnroll) def minLatency: Int = (minDivLatency ++ minMulLatency).min - val io = IO(new MultiplierIO(width, log2Up(nXpr), aluFn)) + val io = IO(new MultiplierIO(width, log2Up(nXpr))) val w = io.req.bits.in1.getWidth val mulw = if (cfg.mulUnroll == 0) w else (w + cfg.mulUnroll - 1) / cfg.mulUnroll * cfg.mulUnroll val fastMulW = if (cfg.mulUnroll == 0) false else w/2 > cfg.mulUnroll && w % (2*cfg.mulUnroll) == 0 @@ -58,15 +61,15 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32, aluFn: ALUFN = new A val remainder = Reg(Bits((2*mulw+2).W)) // div only needs 2*w+1 bits val mulDecode = List( - aluFn.FN_MUL -> List(Y, N, X, X), - aluFn.FN_MULH -> List(Y, Y, Y, Y), - aluFn.FN_MULHU -> List(Y, Y, N, N), - aluFn.FN_MULHSU -> List(Y, Y, Y, N)) + FN_MUL -> List(Y, N, X, X), + FN_MULH -> List(Y, Y, Y, Y), + FN_MULHU -> List(Y, Y, N, N), + FN_MULHSU -> List(Y, Y, Y, N)) val divDecode = List( - aluFn.FN_DIV -> List(N, N, Y, Y), - aluFn.FN_REM -> List(N, Y, Y, Y), - aluFn.FN_DIVU -> List(N, N, N, N), - aluFn.FN_REMU -> List(N, Y, N, N)) + FN_DIV -> List(N, N, Y, Y), + FN_REM -> List(N, Y, Y, Y), + FN_DIVU -> List(N, N, N, N), + FN_REMU -> List(N, Y, N, N)) val cmdMul :: cmdHi :: lhsSigned :: rhsSigned :: Nil = DecodeLogic(io.req.bits.fn, List(X, X, X, X), (if (cfg.divUnroll != 0) divDecode else Nil) ++ (if (cfg.mulUnroll != 0) mulDecode else Nil)).map(_.asBool) @@ -175,23 +178,24 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32, aluFn: ALUFN = new A io.resp.bits.tag := req.tag io.resp.bits.data := Cat(hiOut, loOut) + io.resp.bits.full_data := Cat(remainder(2*w, w+1), remainder(w-1, 0)) io.resp.valid := (state === s_done_mul || state === s_done_div) io.req.ready := state === s_ready } -class PipelinedMultiplier(width: Int, latency: Int, nXpr: Int = 32, aluFn: ALUFN = new ALUFN) extends Module with ShouldBeRetimed { +class PipelinedMultiplier(width: Int, latency: Int, nXpr: Int = 32) extends Module with ShouldBeRetimed { val io = IO(new Bundle { - val req = Flipped(Valid(new MultiplierReq(width, log2Ceil(nXpr), aluFn))) + val req = Flipped(Valid(new MultiplierReq(width, log2Ceil(nXpr)))) val resp = Valid(new MultiplierResp(width, log2Ceil(nXpr))) }) val in = Pipe(io.req) val decode = List( - aluFn.FN_MUL -> List(N, X, X), - aluFn.FN_MULH -> List(Y, Y, Y), - aluFn.FN_MULHU -> List(Y, N, N), - aluFn.FN_MULHSU -> List(Y, Y, N)) + FN_MUL -> List(N, X, X), + FN_MULH -> List(Y, Y, Y), + FN_MULHU -> List(Y, N, N), + FN_MULHSU -> List(Y, Y, N)) val cmdHi :: lhsSigned :: rhsSigned :: Nil = DecodeLogic(in.bits.fn, List(X, X, X), decode).map(_.asBool) val cmdHalf = (width > 32).B && in.bits.dw === DW_32 @@ -205,4 +209,5 @@ class PipelinedMultiplier(width: Int, latency: Int, nXpr: Int = 32, aluFn: ALUFN io.resp.valid := resp.valid io.resp.bits.tag := resp.bits.tag io.resp.bits.data := Pipe(in.valid, muxed, latency-1).bits + io.resp.bits.full_data := Pipe(in.valid, prod, latency-1).bits.asUInt } diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index f9161dd5d51..a0f9f72b91b 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -56,6 +56,7 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa val mem_access = Decoupled(new TLBundleA(edge.bundle)) val mem_ack = Flipped(Valid(new TLBundleD(edge.bundle))) val replay_next = Output(Bool()) + val store_pending = Output(Bool()) }) def beatOffset(addr: UInt) = addr.extract(beatOffBits - 1, wordOffBits) @@ -68,7 +69,7 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa val req = Reg(new HellaCacheReq) val grant_word = Reg(UInt(wordBits.W)) - val s_idle :: s_mem_access :: s_mem_ack :: s_resp :: Nil = Enum(4) + val s_idle :: s_mem_access :: s_mem_ack :: s_resp_1 :: s_resp_2 :: Nil = Enum(5) val state = RegInit(s_idle) io.req.ready := (state === s_idle) @@ -82,7 +83,7 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa val get = edge.Get(a_source, a_address, a_size)._2 val put = edge.Put(a_source, a_address, a_size, a_data)._2 val atomics = if (edge.manager.anySupportLogical) { - MuxLookup(req.cmd, (0.U).asTypeOf(new TLBundleA(edge.bundle)), Array( + MuxLookup(req.cmd, (0.U).asTypeOf(new TLBundleA(edge.bundle)))(Array( M_XA_SWAP -> edge.Logical(a_source, a_address, a_size, a_data, TLAtomics.SWAP)._2, M_XA_XOR -> edge.Logical(a_source, a_address, a_size, a_data, TLAtomics.XOR) ._2, M_XA_OR -> edge.Logical(a_source, a_address, a_size, a_data, TLAtomics.OR) ._2, @@ -102,8 +103,8 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa io.mem_access.valid := (state === s_mem_access) io.mem_access.bits := Mux(isAMO(req.cmd), atomics, Mux(isRead(req.cmd), get, put)) - io.replay_next := (state === s_mem_ack) || io.resp.valid && !io.resp.ready - io.resp.valid := (state === s_resp) + io.replay_next := state === s_resp_1 || (state === s_resp_2 && !io.resp.ready) + io.resp.valid := state === s_resp_2 io.resp.bits.addr := req.addr io.resp.bits.idx.foreach(_ := req.idx.get) io.resp.bits.tag := req.tag @@ -119,6 +120,7 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa io.resp.bits.data_word_bypass := loadgen.wordData io.resp.bits.store_data := req.data io.resp.bits.replay := true.B + io.store_pending := state =/= s_idle && isWrite(req.cmd) when (io.req.fire) { req := io.req.bits @@ -130,12 +132,16 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa } when (state === s_mem_ack && io.mem_ack.valid) { - state := s_resp + state := Mux(req.no_resp || !isRead(req.cmd), s_idle, s_resp_1) when (isRead(req.cmd)) { grant_word := wordFromBeat(req.addr, io.mem_ack.bits.data) } } + when (state === s_resp_1) { + state := s_resp_2 + } + when (io.resp.fire) { state := s_idle } @@ -331,6 +337,7 @@ class MSHRFile(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCacheModu val probe_rdy = Output(Bool()) val fence_rdy = Output(Bool()) val replay_next = Output(Bool()) + val store_pending = Output(Bool()) }) // determine if the request is cacheable or not @@ -439,6 +446,8 @@ class MSHRFile(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCacheModu TLArbiter.lowestFromSeq(edge, io.mem_acquire, mshrs.map(_.io.mem_acquire) ++ mmios.map(_.io.mem_access)) TLArbiter.lowestFromSeq(edge, io.mem_finish, mshrs.map(_.io.mem_finish)) + io.store_pending := sdq_val =/= 0.U || mmios.map(_.io.store_pending).orR + io.resp <> resp_arb.io.out io.req.ready := Mux(!cacheable, mmio_rdy, @@ -716,8 +725,11 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule val prober = Module(new ProbeUnit) val mshrs = Module(new MSHRFile) + io.tlb_port.req.ready := true.B io.cpu.req.ready := true.B val s1_valid = RegNext(io.cpu.req.fire, false.B) + val s1_tlb_req_valid = RegNext(io.tlb_port.req.fire, false.B) + val s1_tlb_req = RegEnable(io.tlb_port.req.bits, io.tlb_port.req.fire) val s1_req = Reg(new HellaCacheReq) val s1_valid_masked = s1_valid && !io.cpu.s1_kill val s1_replay = RegInit(false.B) @@ -725,6 +737,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule val s1_sfence = s1_req.cmd === M_SFENCE val s2_valid = RegNext(s1_valid_masked && !s1_sfence, false.B) && !io.cpu.s2_xcpt.asUInt.orR + val s2_tlb_req_valid = RegNext(s1_tlb_req_valid, false.B) val s2_req = Reg(new HellaCacheReq) val s2_replay = RegNext(s1_replay, false.B) && s2_req.cmd =/= M_FLUSH_ALL val s2_recycle = Wire(Bool()) @@ -751,6 +764,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule dtlb.io.req.bits.cmd := s1_req.cmd dtlb.io.req.bits.prv := s1_req.dprv dtlb.io.req.bits.v := s1_req.dv + when (s1_tlb_req_valid) { dtlb.io.req.bits := s1_tlb_req } when (!dtlb.io.req.ready && !io.cpu.req.bits.phys) { io.cpu.req.ready := false.B } dtlb.io.sfence.valid := s1_valid && !io.cpu.s1_kill && s1_sfence @@ -778,13 +792,16 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule when (s2_recycle) { s1_req := s2_req } - val s1_addr = dtlb.io.resp.paddr + val s1_addr = Mux(s1_req.phys, s1_req.addr, dtlb.io.resp.paddr) + + io.tlb_port.s1_resp := dtlb.io.resp when (s1_clk_en) { s2_req.size := s1_req.size s2_req.signed := s1_req.signed s2_req.phys := s1_req.phys s2_req.addr := s1_addr + s2_req.no_resp := s1_req.no_resp when (s1_write) { s2_req.data := Mux(s1_replay, mshrs.io.replay.bits.data, io.cpu.s1_data.data) } @@ -990,7 +1007,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule amoalu.io.rhs := s2_req.data // nack it like it's hot - val s1_nack = dtlb.io.req.valid && dtlb.io.resp.miss || io.cpu.s2_nack || + val s1_nack = dtlb.io.req.valid && dtlb.io.resp.miss || io.cpu.s2_nack || s1_tlb_req_valid || s1_req.addr(idxMSB,idxLSB) === prober.io.meta_write.bits.idx && !prober.io.req.ready val s2_nack_hit = RegEnable(s1_nack, s1_valid || s1_replay) when (s2_nack_hit) { mshrs.io.req.valid := false.B } @@ -1039,6 +1056,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule io.cpu.resp.bits.data_word_bypass := loadgen.wordData io.cpu.resp.bits.data_raw := s2_data_word io.cpu.ordered := mshrs.io.fence_rdy && !s1_valid && !s2_valid + io.cpu.store_pending := mshrs.io.store_pending io.cpu.replay_next := (s1_replay && s1_read) || mshrs.io.replay_next val s1_xcpt_valid = dtlb.io.req.valid && !s1_nack diff --git a/src/main/scala/rocket/PMA.scala b/src/main/scala/rocket/PMA.scala new file mode 100644 index 00000000000..b2144e6b38a --- /dev/null +++ b/src/main/scala/rocket/PMA.scala @@ -0,0 +1,49 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.rocket + +import chisel3._ +import chisel3.util._ +import chisel3.experimental.SourceInfo + +import org.chipsalliance.cde.config._ + +import freechips.rocketchip.devices.debug.DebugModuleKey +import freechips.rocketchip.diplomacy.RegionType +import freechips.rocketchip.subsystem.CacheBlockBytes +import freechips.rocketchip.tile.{CoreModule, CoreBundle} +import freechips.rocketchip.tilelink.{TLSlavePortParameters, TLManagerParameters} + +class PMAChecker(manager: TLSlavePortParameters)(implicit p: Parameters) extends CoreModule()(p) { + val io = IO(new Bundle { + val paddr = Input(UInt()) + + val resp = Output(new Bundle { + val cacheable = Bool() + val r = Bool() + val w = Bool() + val pp = Bool() + val al = Bool() + val aa = Bool() + val x = Bool() + val eff = Bool() + }) + }) + + // PMA + // check exist a slave can consume this address. + val legal_address = manager.findSafe(io.paddr).reduce(_||_) + // check utility to help check SoC property. + def fastCheck(member: TLManagerParameters => Boolean) = + legal_address && manager.fastProperty(io.paddr, member, (b:Boolean) => b.B) + + io.resp.cacheable := fastCheck(_.supportsAcquireB) + io.resp.r := fastCheck(_.supportsGet) + io.resp.w := fastCheck(_.supportsPutFull) + io.resp.pp := fastCheck(_.supportsPutPartial) + io.resp.al := fastCheck(_.supportsLogical) + io.resp.aa := fastCheck(_.supportsArithmetic) + io.resp.x := fastCheck(_.executable) + io.resp.eff := fastCheck(Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains _.regionType) +} diff --git a/src/main/scala/rocket/PMP.scala b/src/main/scala/rocket/PMP.scala index 11fe95d9e0b..2ccd58ce822 100644 --- a/src/main/scala/rocket/PMP.scala +++ b/src/main/scala/rocket/PMP.scala @@ -142,6 +142,7 @@ class PMPHomogeneityChecker(pmps: Seq[PMP])(implicit p: Parameters) { class PMPChecker(lgMaxSize: Int)(implicit val p: Parameters) extends Module with HasCoreParameters { + override def desiredName = s"PMPChecker_s${lgMaxSize}" val io = IO(new Bundle { val prv = Input(UInt(PRV.SZ.W)) val pmp = Input(Vec(nPMPs, new PMP)) diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index 91b9a7bb2f1..872b143e24c 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -522,6 +522,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( io.mem.req.bits.dprv := PRV.S.U // PTW accesses are S-mode by definition io.mem.req.bits.dv := do_both_stages && !stage2 io.mem.req.bits.tag := DontCare + io.mem.req.bits.no_resp := false.B io.mem.req.bits.no_alloc := DontCare io.mem.req.bits.no_xcpt := DontCare io.mem.req.bits.data := DontCare @@ -540,7 +541,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( require(TLBPageLookup.homogeneous(edge.manager.managers, pgSize), s"All memory regions must be $pgSize-byte aligned") true.B } else { - TLBPageLookup(edge.manager.managers, xLen, p(CacheBlockBytes), pgSize)(r_pte.ppn << pgIdxBits).homogeneous + TLBPageLookup(edge.manager.managers, xLen, p(CacheBlockBytes), pgSize, xLen/8)(r_pte.ppn << pgIdxBits).homogeneous } } val pmaHomogeneous = pmaPgLevelHomogeneous(count) @@ -694,7 +695,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( when (do_both_stages && !stage2) { do_switch := true.B } count := count + 1.U }.otherwise { - val gf = stage2 && !stage2_final && !pte.ur() + val gf = (stage2 && !stage2_final && !pte.ur()) || (pte.leaf() && pte.reserved_for_future === 0.U && invalid_gpa) val ae = pte.v && invalid_paddr val pf = pte.v && pte.reserved_for_future =/= 0.U val success = pte.v && !ae && !pf && !gf @@ -722,7 +723,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( } resp_ae_ptw := ae && count < (pgLevels-1).U && pte.table() - resp_ae_final := ae + resp_ae_final := ae && pte.leaf() resp_pf := pf && !stage2 resp_gf := gf || (pf && stage2) resp_hr := !stage2 || (!pf && !gf && pte.ur()) diff --git a/src/main/scala/rocket/RVC.scala b/src/main/scala/rocket/RVC.scala index cc54c293558..c9252c086cf 100644 --- a/src/main/scala/rocket/RVC.scala +++ b/src/main/scala/rocket/RVC.scala @@ -16,7 +16,7 @@ class ExpandedInstruction extends Bundle { val rs3 = UInt(5.W) } -class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) { +class RVCDecoder(x: UInt, xLen: Int, fLen: Int, useAddiForMv: Boolean = false) { def inst(bits: UInt, rd: UInt = x(11,7), rs1: UInt = x(19,15), rs2: UInt = x(24,20), rs3: UInt = x(31,27)) = { val res = Wire(new ExpandedInstruction) res.bits := bits @@ -153,6 +153,38 @@ class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) { val s = q0 ++ q1 ++ q2 ++ q3 s(Cat(x(1,0), x(15,13))) } + + def q0_ill = { + def allz = !(x(12, 2).orR) + def fld = if (fLen >= 64) false.B else true.B + def flw32 = if (xLen == 64 || fLen >= 32) false.B else true.B + def fsd = if (fLen >= 64) false.B else true.B + def fsw32 = if (xLen == 64 || fLen >= 32) false.B else true.B + Seq(allz, fld, false.B, flw32, true.B, fsd, false.B, fsw32) + } + + def q1_ill = { + def rd0 = if (xLen == 32) false.B else rd === 0.U + def immz = !(x(12) | x(6, 2).orR) + def arith_res = x(12, 10).andR && (if (xLen == 32) true.B else x(6) === 1.U) + Seq(false.B, rd0, false.B, immz, arith_res, false.B, false.B, false.B) + } + + def q2_ill = { + def fldsp = if (fLen >= 64) false.B else true.B + def rd0 = rd === 0.U + def flwsp = if (xLen == 64) rd0 else if (fLen >= 32) false.B else true.B + def jr_res = !(x(12 ,2).orR) + def fsdsp = if (fLen >= 64) false.B else true.B + def fswsp32 = if (xLen == 64) false.B else if (fLen >= 32) false.B else true.B + Seq(false.B, fldsp, rd0, flwsp, jr_res, fsdsp, false.B, fswsp32) + } + def q3_ill = Seq.fill(8)(false.B) + + def ill = { + val s = q0_ill ++ q1_ill ++ q2_ill ++ q3_ill + s(Cat(x(1,0), x(15,13))) + } } class RVCExpander(useAddiForMv: Boolean = false)(implicit val p: Parameters) extends Module with HasCoreParameters { @@ -160,13 +192,17 @@ class RVCExpander(useAddiForMv: Boolean = false)(implicit val p: Parameters) ext val in = Input(UInt(32.W)) val out = Output(new ExpandedInstruction) val rvc = Output(Bool()) + val ill = Output(Bool()) }) if (usingCompressed) { io.rvc := io.in(1,0) =/= 3.U - io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv).decode + val decoder = new RVCDecoder(io.in, xLen, fLen, useAddiForMv) + io.out := decoder.decode + io.ill := decoder.ill } else { io.rvc := false.B - io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv).passthrough + io.out := new RVCDecoder(io.in, xLen, fLen, useAddiForMv).passthrough + io.ill := false.B // only used for RVC } } diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 65f8c73234a..1491a4143e1 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -13,6 +13,8 @@ import freechips.rocketchip.util.property import scala.collection.mutable.ArrayBuffer case class RocketCoreParams( + xLen: Int = 64, + pgLevels: Int = 3, // sv39 default bootFreqHz: BigInt = 0, useVM: Boolean = true, useUser: Boolean = false, @@ -24,6 +26,9 @@ case class RocketCoreParams( useCompressed: Boolean = true, useRVE: Boolean = false, useConditionalZero: Boolean = false, + useZba: Boolean = false, + useZbb: Boolean = false, + useZbs: Boolean = false, nLocalInterrupts: Int = 0, useNMI: Boolean = false, nBreakpoints: Int = 1, @@ -48,9 +53,10 @@ case class RocketCoreParams( mimpid: Int = 0x20181004, // release date in BCD mulDiv: Option[MulDivParams] = Some(MulDivParams()), fpu: Option[FPUParams] = Some(FPUParams()), - debugROB: Boolean = false, // if enabled, uses a C++ debug ROB to generate trace-with-wdata + debugROB: Option[DebugROBParams] = None, // if size < 1, SW ROB, else HW ROB haveCease: Boolean = true, // non-standard CEASE instruction - haveSimTimeout: Boolean = true // add plusarg for simulation timeout + haveSimTimeout: Boolean = true, // add plusarg for simulation timeout + vector: Option[RocketCoreVectorParams] = None ) extends CoreParams { val lgPauseCycles = 5 val haveFSDirty = false @@ -61,7 +67,15 @@ case class RocketCoreParams( val retireWidth: Int = 1 val instBits: Int = if (useCompressed) 16 else 32 val lrscCycles: Int = 80 // worst case is 14 mispredicted branches + slop - val traceHasWdata: Boolean = false // ooo wb, so no wdata in trace + val traceHasWdata: Boolean = debugROB.isDefined // ooo wb, so no wdata in trace + override val useVector = vector.isDefined + override val vectorUseDCache = vector.map(_.useDCache).getOrElse(false) + override def vLen = vector.map(_.vLen).getOrElse(0) + override def eLen = vector.map(_.eLen).getOrElse(0) + override def vfLen = vector.map(_.vfLen).getOrElse(0) + override def vfh = vector.map(_.vfh).getOrElse(false) + override def vExts = vector.map(_.vExts).getOrElse(Nil) + override def vMemDataBits = vector.map(_.vMemDataBits).getOrElse(0) override val customIsaExt = Option.when(haveCease)("xrocket") // CEASE instruction override def minFLen: Int = fpu.map(_.minFLen).getOrElse(32) override def customCSRs(implicit p: Parameters) = new RocketCustomCSRs @@ -75,8 +89,6 @@ trait HasRocketCoreParameters extends HasCoreParameters { val mulDivParams = rocketParams.mulDiv.getOrElse(MulDivParams()) // TODO ask andrew about this - val aluFn = new ALUFN - require(!fastLoadByte || fastLoadWord) require(!rocketParams.haveFSDirty, "rocket doesn't support setting fs dirty from outside, please disable haveFSDirty") } @@ -112,10 +124,37 @@ class RocketCustomCSRs(implicit p: Parameters) extends CustomCSRs with HasRocket override def decls = super.decls :+ marchid :+ mvendorid :+ mimpid } +class CoreInterrupts(val hasBeu: Boolean)(implicit p: Parameters) extends TileInterrupts()(p) { + val buserror = Option.when(hasBeu)(Bool()) +} + +trait HasRocketCoreIO extends HasRocketCoreParameters { + implicit val p: Parameters + def nTotalRoCCCSRs: Int + val io = IO(new CoreBundle()(p) { + val hartid = Input(UInt(hartIdLen.W)) + val reset_vector = Input(UInt(resetVectorLen.W)) + val interrupts = Input(new CoreInterrupts(tileParams.asInstanceOf[RocketTileParams].beuAddr.isDefined)) + val imem = new FrontendIO + val dmem = new HellaCacheIO + val ptw = Flipped(new DatapathPTWIO()) + val fpu = Flipped(new FPUCoreIO()) + val rocc = Flipped(new RoCCCoreIO(nTotalRoCCCSRs)) + val trace = Output(new TraceBundle) + val bpwatch = Output(Vec(coreParams.nBreakpoints, new BPWatch(coreParams.retireWidth))) + val cease = Output(Bool()) + val wfi = Output(Bool()) + val traceStall = Input(Bool()) + val vector = if (usingVector) Some(Flipped(new VectorCoreIO)) else None + }) +} + + class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) with HasRocketCoreParameters - with HasCoreIO { + with HasRocketCoreIO { def nTotalRoCCCSRs = tile.roccCSRs.flatten.size + import ALU._ val clock_en_reg = RegInit(true.B) val long_latency_stall = Reg(Bool()) @@ -143,8 +182,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) ("jal", () => id_ctrl.jal), ("jalr", () => id_ctrl.jalr)) ++ (if (!usingMulDiv) Seq() else Seq( - ("mul", () => if (pipelinedMul) id_ctrl.mul else id_ctrl.div && (id_ctrl.alu_fn & aluFn.FN_DIV) =/= aluFn.FN_DIV), - ("div", () => if (pipelinedMul) id_ctrl.div else id_ctrl.div && (id_ctrl.alu_fn & aluFn.FN_DIV) === aluFn.FN_DIV))) + ("mul", () => if (pipelinedMul) id_ctrl.mul else id_ctrl.div && (id_ctrl.alu_fn & FN_DIV) =/= FN_DIV), + ("div", () => if (pipelinedMul) id_ctrl.div else id_ctrl.div && (id_ctrl.alu_fn & FN_DIV) === FN_DIV))) ++ (if (!usingFPU) Seq() else Seq( ("fp load", () => id_ctrl.fp && io.fpu.dec.ldst && io.fpu.dec.wen), ("fp store", () => id_ctrl.fp && io.fpu.dec.ldst && !io.fpu.dec.wen), @@ -177,29 +216,33 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val pipelinedMul = usingMulDiv && mulDivParams.mulUnroll == xLen val decode_table = { - (if (usingMulDiv) new MDecode(pipelinedMul, aluFn) +: (xLen > 32).option(new M64Decode(pipelinedMul, aluFn)).toSeq else Nil) ++: - (if (usingAtomics) new ADecode(aluFn) +: (xLen > 32).option(new A64Decode(aluFn)).toSeq else Nil) ++: - (if (fLen >= 32) new FDecode(aluFn) +: (xLen > 32).option(new F64Decode(aluFn)).toSeq else Nil) ++: - (if (fLen >= 64) new DDecode(aluFn) +: (xLen > 32).option(new D64Decode(aluFn)).toSeq else Nil) ++: - (if (minFLen == 16) new HDecode(aluFn) +: (xLen > 32).option(new H64Decode(aluFn)).toSeq ++: (fLen >= 64).option(new HDDecode(aluFn)).toSeq else Nil) ++: - (usingRoCC.option(new RoCCDecode(aluFn))) ++: - (if (xLen == 32) new I32Decode(aluFn) else new I64Decode(aluFn)) +: - (usingVM.option(new SVMDecode(aluFn))) ++: - (usingSupervisor.option(new SDecode(aluFn))) ++: - (usingHypervisor.option(new HypervisorDecode(aluFn))) ++: - ((usingHypervisor && (xLen == 64)).option(new Hypervisor64Decode(aluFn))) ++: - (usingDebug.option(new DebugDecode(aluFn))) ++: - (usingNMI.option(new NMIDecode(aluFn))) ++: - (usingConditionalZero.option(new ConditionalZeroDecode(aluFn))) ++: - Seq(new FenceIDecode(tile.dcache.flushOnFenceI, aluFn)) ++: - coreParams.haveCFlush.option(new CFlushDecode(tile.dcache.canSupportCFlushLine, aluFn)) ++: - rocketParams.haveCease.option(new CeaseDecode(aluFn)) ++: - Seq(new IDecode(aluFn)) + (if (usingMulDiv) new MDecode(pipelinedMul) +: (xLen > 32).option(new M64Decode(pipelinedMul)).toSeq else Nil) ++: + (if (usingAtomics) new ADecode +: (xLen > 32).option(new A64Decode).toSeq else Nil) ++: + (if (fLen >= 32) new FDecode +: (xLen > 32).option(new F64Decode).toSeq else Nil) ++: + (if (fLen >= 64) new DDecode +: (xLen > 32).option(new D64Decode).toSeq else Nil) ++: + (if (minFLen == 16) new HDecode +: (xLen > 32).option(new H64Decode).toSeq ++: (fLen >= 64).option(new HDDecode).toSeq else Nil) ++: + (usingRoCC.option(new RoCCDecode)) ++: + (if (xLen == 32) new I32Decode else new I64Decode) +: + (usingVM.option(new SVMDecode)) ++: + (usingSupervisor.option(new SDecode)) ++: + (usingHypervisor.option(new HypervisorDecode)) ++: + ((usingHypervisor && (xLen == 64)).option(new Hypervisor64Decode)) ++: + (usingDebug.option(new DebugDecode)) ++: + (usingNMI.option(new NMIDecode)) ++: + (usingConditionalZero.option(new ConditionalZeroDecode)) ++: + Seq(new FenceIDecode(tile.dcache.flushOnFenceI)) ++: + coreParams.haveCFlush.option(new CFlushDecode(tile.dcache.canSupportCFlushLine)) ++: + rocketParams.haveCease.option(new CeaseDecode) ++: + usingVector.option(new VCFGDecode) ++: + (if (coreParams.useZba) new ZbaDecode +: (xLen > 32).option(new Zba64Decode).toSeq else Nil) ++: + (if (coreParams.useZbb) Seq(new ZbbDecode, if (xLen == 32) new Zbb32Decode else new Zbb64Decode) else Nil) ++: + coreParams.useZbs.option(new ZbsDecode) ++: + Seq(new IDecode) } flatMap(_.table) - val ex_ctrl = Reg(new IntCtrlSigs(aluFn)) - val mem_ctrl = Reg(new IntCtrlSigs(aluFn)) - val wb_ctrl = Reg(new IntCtrlSigs(aluFn)) + val ex_ctrl = Reg(new IntCtrlSigs) + val mem_ctrl = Reg(new IntCtrlSigs) + val wb_ctrl = Reg(new IntCtrlSigs) val ex_reg_xcpt_interrupt = Reg(Bool()) val ex_reg_valid = Reg(Bool()) @@ -216,6 +259,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ex_reg_inst = Reg(Bits()) val ex_reg_raw_inst = Reg(UInt()) val ex_reg_wphit = Reg(Vec(nBreakpoints, Bool())) + val ex_reg_set_vconfig = Reg(Bool()) val mem_reg_xcpt_interrupt = Reg(Bool()) val mem_reg_valid = Reg(Bool()) @@ -228,6 +272,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val mem_reg_slow_bypass = Reg(Bool()) val mem_reg_load = Reg(Bool()) val mem_reg_store = Reg(Bool()) + val mem_reg_set_vconfig = Reg(Bool()) val mem_reg_sfence = Reg(Bool()) val mem_reg_pc = Reg(UInt()) val mem_reg_inst = Reg(Bits()) @@ -245,6 +290,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val wb_reg_replay = Reg(Bool()) val wb_reg_flush_pipe = Reg(Bool()) val wb_reg_cause = Reg(UInt()) + val wb_reg_set_vconfig = Reg(Bool()) val wb_reg_sfence = Reg(Bool()) val wb_reg_pc = Reg(UInt()) val wb_reg_mem_size = Reg(UInt()) @@ -272,7 +318,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) require(decodeWidth == 1 /* TODO */ && retireWidth == decodeWidth) require(!(coreParams.useRVE && coreParams.fpu.nonEmpty), "Can't select both RVE and floating-point") require(!(coreParams.useRVE && coreParams.useHypervisor), "Can't select both RVE and Hypervisor") - val id_ctrl = Wire(new IntCtrlSigs(aluFn)).decode(id_inst(0), decode_table) + val id_ctrl = Wire(new IntCtrlSigs).decode(id_inst(0), decode_table) + val lgNXRegs = if (coreParams.useRVE) 4 else 5 val regAddrMask = (1 << lgNXRegs) - 1 @@ -291,17 +338,51 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ctrl_killd = Wire(Bool()) val id_npc = (ibuf.io.pc.asSInt + ImmGen(IMM_UJ, id_inst(0))).asUInt - val csr = Module(new CSRFile(perfEvents, coreParams.customCSRs.decls, tile.roccCSRs.flatten)) + val csr = Module(new CSRFile(perfEvents, coreParams.customCSRs.decls, tile.roccCSRs.flatten, tile.rocketParams.beuAddr.isDefined)) val id_csr_en = id_ctrl.csr.isOneOf(CSR.S, CSR.C, CSR.W) val id_system_insn = id_ctrl.csr === CSR.I val id_csr_ren = id_ctrl.csr.isOneOf(CSR.S, CSR.C) && id_expanded_inst(0).rs1 === 0.U val id_csr = Mux(id_system_insn && id_ctrl.mem, CSR.N, Mux(id_csr_ren, CSR.R, id_ctrl.csr)) val id_csr_flush = id_system_insn || (id_csr_en && !id_csr_ren && csr.io.decode(0).write_flush) + val id_set_vconfig = Seq(Instructions.VSETVLI, Instructions.VSETIVLI, Instructions.VSETVL).map(_ === id_inst(0)).orR && usingVector.B + + id_ctrl.vec := false.B + if (usingVector) { + val v_decode = rocketParams.vector.get.decoder(p) + v_decode.io.inst := id_inst(0) + v_decode.io.vconfig := csr.io.vector.get.vconfig + when (v_decode.io.legal) { + id_ctrl.legal := !csr.io.vector.get.vconfig.vtype.vill + id_ctrl.fp := v_decode.io.fp + id_ctrl.rocc := false.B + id_ctrl.branch := false.B + id_ctrl.jal := false.B + id_ctrl.jalr := false.B + id_ctrl.rxs2 := v_decode.io.read_rs2 + id_ctrl.rxs1 := v_decode.io.read_rs1 + id_ctrl.mem := false.B + id_ctrl.rfs1 := v_decode.io.read_frs1 + id_ctrl.rfs2 := false.B + id_ctrl.rfs3 := false.B + id_ctrl.wfd := v_decode.io.write_frd + id_ctrl.mul := false.B + id_ctrl.div := false.B + id_ctrl.wxd := v_decode.io.write_rd + id_ctrl.csr := CSR.N + id_ctrl.fence_i := false.B + id_ctrl.fence := false.B + id_ctrl.amo := false.B + id_ctrl.dp := false.B + id_ctrl.vec := true.B + } + } + val id_illegal_insn = !id_ctrl.legal || (id_ctrl.mul || id_ctrl.div) && !csr.io.status.isa('m'-'a') || id_ctrl.amo && !csr.io.status.isa('a'-'a') || - id_ctrl.fp && (csr.io.decode(0).fp_illegal || io.fpu.illegal_rm) || + id_ctrl.fp && (csr.io.decode(0).fp_illegal || (io.fpu.illegal_rm && !id_ctrl.vec)) || + (id_ctrl.vec) && (csr.io.decode(0).vector_illegal || csr.io.vector.map(_.vconfig.vtype.vill).getOrElse(false.B)) || id_ctrl.dp && !csr.io.status.isa('d'-'a') || ibuf.io.inst(0).bits.rvc && !csr.io.status.isa('c'-'a') || id_raddr2_illegal && id_ctrl.rxs2 || @@ -324,7 +405,10 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_rocc_busy = usingRoCC.B && (io.rocc.busy || ex_reg_valid && ex_ctrl.rocc || mem_reg_valid && mem_ctrl.rocc || wb_reg_valid && wb_ctrl.rocc) - val id_do_fence = WireDefault(id_rocc_busy && id_ctrl.fence || + val id_csr_rocc_write = tile.roccCSRs.flatten.map(_.id.U === id_inst(0)(31,20)).orR && id_csr_en && !id_csr_ren + val id_vec_busy = io.vector.map(v => v.backend_busy || v.trap_check_busy).getOrElse(false.B) + val id_do_fence = WireDefault(id_rocc_busy && (id_ctrl.fence || id_csr_rocc_write) || + id_vec_busy && id_ctrl.fence || id_mem_busy && (id_ctrl.amo && id_amo_rl || id_ctrl.fence_i || id_reg_fence && (id_ctrl.mem || id_ctrl.rocc))) val bpu = Module(new BreakpointUnit(nBreakpoints)) @@ -384,24 +468,47 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ex_rs = for (i <- 0 until id_raddr.size) yield Mux(ex_reg_rs_bypass(i), bypass_mux(ex_reg_rs_lsb(i)), Cat(ex_reg_rs_msb(i), ex_reg_rs_lsb(i))) val ex_imm = ImmGen(ex_ctrl.sel_imm, ex_reg_inst) - val ex_op1 = MuxLookup(ex_ctrl.sel_alu1, 0.S, Seq( + val ex_rs1shl = Mux(ex_reg_inst(3), ex_rs(0)(31,0), ex_rs(0)) << ex_reg_inst(14,13) + val ex_op1 = MuxLookup(ex_ctrl.sel_alu1, 0.S)(Seq( A1_RS1 -> ex_rs(0).asSInt, - A1_PC -> ex_reg_pc.asSInt)) - val ex_op2 = MuxLookup(ex_ctrl.sel_alu2, 0.S, Seq( + A1_PC -> ex_reg_pc.asSInt, + A1_RS1SHL -> (if (rocketParams.useZba) ex_rs1shl.asSInt else 0.S) + )) + val ex_op2_oh = UIntToOH(Mux(ex_ctrl.sel_alu2(0), (ex_reg_inst >> 20).asUInt, ex_rs(1))(log2Ceil(xLen)-1,0)).asSInt + val ex_op2 = MuxLookup(ex_ctrl.sel_alu2, 0.S)(Seq( A2_RS2 -> ex_rs(1).asSInt, A2_IMM -> ex_imm, - A2_SIZE -> Mux(ex_reg_rvc, 2.S, 4.S))) - - val alu = Module(aluFn match { - case _: ALUFN => new ALU - }) + A2_SIZE -> Mux(ex_reg_rvc, 2.S, 4.S), + ) ++ (if (coreParams.useZbs) Seq( + A2_RS2OH -> ex_op2_oh, + A2_IMMOH -> ex_op2_oh, + ) else Nil)) + + val (ex_new_vl, ex_new_vconfig) = if (usingVector) { + val ex_new_vtype = VType.fromUInt(MuxCase(ex_rs(1), Seq( + ex_reg_inst(31,30).andR -> ex_reg_inst(29,20), + !ex_reg_inst(31) -> ex_reg_inst(30,20)))) + val ex_avl = Mux(ex_ctrl.rxs1, + Mux(ex_reg_inst(19,15) === 0.U, + Mux(ex_reg_inst(11,7) === 0.U, csr.io.vector.get.vconfig.vl, ex_new_vtype.vlMax), + ex_rs(0) + ), + ex_reg_inst(19,15)) + val ex_new_vl = ex_new_vtype.vl(ex_avl, csr.io.vector.get.vconfig.vl, false.B, false.B, false.B) + val ex_new_vconfig = Wire(new VConfig) + ex_new_vconfig.vtype := ex_new_vtype + ex_new_vconfig.vl := ex_new_vl + (Some(ex_new_vl), Some(ex_new_vconfig)) + } else { (None, None) } + + val alu = Module(new ALU) alu.io.dw := ex_ctrl.alu_dw alu.io.fn := ex_ctrl.alu_fn alu.io.in2 := ex_op2.asUInt alu.io.in1 := ex_op1.asUInt // multiplier and divider - val div = Module(new MulDiv(if (pipelinedMul) mulDivParams.copy(mulUnroll = 0) else mulDivParams, width = xLen, aluFn = aluFn)) + val div = Module(new MulDiv(if (pipelinedMul) mulDivParams.copy(mulUnroll = 0) else mulDivParams, width = xLen)) div.io.req.valid := ex_reg_valid && ex_ctrl.div div.io.req.bits.dw := ex_ctrl.alu_dw div.io.req.bits.fn := ex_ctrl.alu_fn @@ -409,7 +516,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) div.io.req.bits.in2 := ex_rs(1) div.io.req.bits.tag := ex_waddr val mul = pipelinedMul.option { - val m = Module(new PipelinedMultiplier(xLen, 2, aluFn = aluFn)) + val m = Module(new PipelinedMultiplier(xLen, 2)) m.io.req.valid := ex_reg_valid && ex_ctrl.mul m.io.req.bits := div.io.req.bits m @@ -427,7 +534,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) when (id_ctrl.fence && id_fence_succ === 0.U) { id_reg_pause := true.B } when (id_fence_next) { id_reg_fence := true.B } when (id_xcpt) { // pass PC down ALU writeback pipeline for badaddr - ex_ctrl.alu_fn := aluFn.FN_ADD + ex_ctrl.alu_fn := FN_ADD ex_ctrl.alu_dw := DW_XPR ex_ctrl.sel_alu1 := A1_RS1 // badaddr := instruction ex_ctrl.sel_alu2 := A2_ZERO @@ -481,13 +588,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) ex_reg_pc := ibuf.io.pc ex_reg_btb_resp := ibuf.io.btb_resp ex_reg_wphit := bpu.io.bpwatch.map { bpw => bpw.ivalid(0) } + ex_reg_set_vconfig := id_set_vconfig && !id_xcpt } // replay inst in ex stage? val ex_pc_valid = ex_reg_valid || ex_reg_replay || ex_reg_xcpt_interrupt val wb_dcache_miss = wb_ctrl.mem && !io.dmem.resp.valid val replay_ex_structural = ex_ctrl.mem && !io.dmem.req.ready || - ex_ctrl.div && !div.io.req.ready + ex_ctrl.div && !div.io.req.ready || + ex_ctrl.vec && !io.vector.map(_.ex.ready).getOrElse(true.B) val replay_ex_load_use = wb_dcache_miss && ex_reg_load_use val replay_ex = ex_reg_replay || (ex_reg_valid && (replay_ex_structural || replay_ex_load_use)) val ctrl_killx = take_pc_mem_wb || replay_ex || !ex_reg_valid @@ -538,6 +647,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) mem_reg_flush_pipe := ex_reg_flush_pipe mem_reg_slow_bypass := ex_slow_bypass mem_reg_wphit := ex_reg_wphit + mem_reg_set_vconfig := ex_reg_set_vconfig mem_reg_cause := ex_cause mem_reg_inst := ex_reg_inst @@ -546,13 +656,17 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) mem_reg_hls_or_dv := io.dmem.req.bits.dv mem_reg_pc := ex_reg_pc // IDecode ensured they are 1H - mem_reg_wdata := alu.io.out + mem_reg_wdata := Mux(ex_reg_set_vconfig, ex_new_vl.getOrElse(alu.io.out), alu.io.out) mem_br_taken := alu.io.cmp_out + when (ex_ctrl.rxs2 && (ex_ctrl.mem || ex_ctrl.rocc || ex_sfence)) { val size = Mux(ex_ctrl.rocc, log2Ceil(xLen/8).U, ex_reg_mem_size) mem_reg_rs2 := new StoreGen(size, 0.U, ex_rs(1), coreDataBytes).data } + if (usingVector) { when (ex_reg_set_vconfig) { + mem_reg_rs2 := ex_new_vconfig.get.asUInt + } } when (ex_ctrl.jalr && csr.io.status.debug) { // flush I$ on D-mode JALR to effect uncached fetch without D$ flush mem_ctrl.fence_i := true.B @@ -580,21 +694,23 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val dcache_kill_mem = mem_reg_valid && mem_ctrl.wxd && io.dmem.replay_next // structural hazard on writeback port val fpu_kill_mem = mem_reg_valid && mem_ctrl.fp && io.fpu.nack_mem - val replay_mem = dcache_kill_mem || mem_reg_replay || fpu_kill_mem + val vec_kill_mem = mem_reg_valid && mem_ctrl.mem && io.vector.map(_.mem.block_mem).getOrElse(false.B) + val vec_kill_all = mem_reg_valid && io.vector.map(_.mem.block_all).getOrElse(false.B) + val replay_mem = dcache_kill_mem || mem_reg_replay || fpu_kill_mem || vec_kill_mem || vec_kill_all val killm_common = dcache_kill_mem || take_pc_wb || mem_reg_xcpt || !mem_reg_valid div.io.kill := killm_common && RegNext(div.io.req.fire) - val ctrl_killm = killm_common || mem_xcpt || fpu_kill_mem + val ctrl_killm = killm_common || mem_xcpt || fpu_kill_mem || vec_kill_mem // writeback stage wb_reg_valid := !ctrl_killm wb_reg_replay := replay_mem && !take_pc_wb - wb_reg_xcpt := mem_xcpt && !take_pc_wb + wb_reg_xcpt := mem_xcpt && !take_pc_wb && !io.vector.map(_.mem.block_all).getOrElse(false.B) wb_reg_flush_pipe := !ctrl_killm && mem_reg_flush_pipe when (mem_pc_valid) { wb_ctrl := mem_ctrl wb_reg_sfence := mem_reg_sfence wb_reg_wdata := Mux(!mem_reg_xcpt && mem_ctrl.fp && mem_ctrl.wxd, io.fpu.toint_data, mem_int_wdata) - when (mem_ctrl.rocc || mem_reg_sfence) { + when (mem_ctrl.rocc || mem_reg_sfence || mem_reg_set_vconfig) { wb_reg_rs2 := mem_reg_rs2 } wb_reg_cause := mem_cause @@ -606,7 +722,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) wb_reg_hfence_g := mem_ctrl.mem_cmd === M_HFENCEG wb_reg_pc := mem_reg_pc wb_reg_wphit := mem_reg_wphit | bpu.io.bpwatch.map { bpw => (bpw.rvalid(0) && mem_reg_load) || (bpw.wvalid(0) && mem_reg_store) } - + wb_reg_set_vconfig := mem_reg_set_vconfig } val (wb_xcpt, wb_cause) = checkExceptions(List( @@ -637,11 +753,12 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val wb_pc_valid = wb_reg_valid || wb_reg_replay || wb_reg_xcpt val wb_wxd = wb_reg_valid && wb_ctrl.wxd - val wb_set_sboard = wb_ctrl.div || wb_dcache_miss || wb_ctrl.rocc + val wb_set_sboard = wb_ctrl.div || wb_dcache_miss || wb_ctrl.rocc || wb_ctrl.vec val replay_wb_common = io.dmem.s2_nack || wb_reg_replay val replay_wb_rocc = wb_reg_valid && wb_ctrl.rocc && !io.rocc.cmd.ready val replay_wb_csr: Bool = wb_reg_valid && csr.io.rw_stall - val replay_wb = replay_wb_common || replay_wb_rocc || replay_wb_csr + val replay_wb_vec = wb_reg_valid && io.vector.map(_.wb.replay).getOrElse(false.B) + val replay_wb = replay_wb_common || replay_wb_rocc || replay_wb_csr || replay_wb_vec take_pc_wb := replay_wb || wb_xcpt || csr.io.eret || wb_reg_flush_pipe // writeback arbitration @@ -651,30 +768,46 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val dmem_resp_valid = io.dmem.resp.valid && io.dmem.resp.bits.has_data val dmem_resp_replay = dmem_resp_valid && io.dmem.resp.bits.replay - div.io.resp.ready := !wb_wxd - val ll_wdata = WireDefault(div.io.resp.bits.data) - val ll_waddr = WireDefault(div.io.resp.bits.tag) - val ll_wen = WireDefault(div.io.resp.fire) + class LLWB extends Bundle { + val data = UInt(xLen.W) + val tag = UInt(5.W) + } + + val ll_arb = Module(new Arbiter(new LLWB, 3)) // div, rocc, vec + ll_arb.io.in.foreach(_.valid := false.B) + ll_arb.io.in.foreach(_.bits := DontCare) + val ll_wdata = WireInit(ll_arb.io.out.bits.data) + val ll_waddr = WireInit(ll_arb.io.out.bits.tag) + val ll_wen = WireInit(ll_arb.io.out.fire) + ll_arb.io.out.ready := !wb_wxd + + div.io.resp.ready := ll_arb.io.in(0).ready + ll_arb.io.in(0).valid := div.io.resp.valid + ll_arb.io.in(0).bits.data := div.io.resp.bits.data + ll_arb.io.in(0).bits.tag := div.io.resp.bits.tag + if (usingRoCC) { - io.rocc.resp.ready := !wb_wxd - when (io.rocc.resp.fire) { - div.io.resp.ready := false.B - ll_wdata := io.rocc.resp.bits.data - ll_waddr := io.rocc.resp.bits.rd - ll_wen := true.B - } + io.rocc.resp.ready := ll_arb.io.in(1).ready + ll_arb.io.in(1).valid := io.rocc.resp.valid + ll_arb.io.in(1).bits.data := io.rocc.resp.bits.data + ll_arb.io.in(1).bits.tag := io.rocc.resp.bits.rd } else { // tie off RoCC io.rocc.resp.ready := false.B io.rocc.mem.req.ready := false.B } + + io.vector.map { v => + v.resp.ready := Mux(v.resp.bits.fp, !(dmem_resp_valid && dmem_resp_fpu), ll_arb.io.in(2).ready) + ll_arb.io.in(2).valid := v.resp.valid && !v.resp.bits.fp + ll_arb.io.in(2).bits.data := v.resp.bits.data + ll_arb.io.in(2).bits.tag := v.resp.bits.rd + } // Dont care mem since not all RoCC need accessing memory io.rocc.mem := DontCare when (dmem_resp_replay && dmem_resp_xpu) { - div.io.resp.ready := false.B - if (usingRoCC) - io.rocc.resp.ready := false.B + ll_arb.io.out.ready := false.B ll_waddr := dmem_resp_waddr ll_wen := true.B } @@ -700,11 +833,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) csr.io.interrupts := io.interrupts csr.io.hartid := io.hartid io.fpu.fcsr_rm := csr.io.fcsr_rm - csr.io.fcsr_flags := io.fpu.fcsr_flags + val vector_fcsr_flags = io.vector.map(_.set_fflags.bits).getOrElse(0.U(5.W)) + val vector_fcsr_flags_valid = io.vector.map(_.set_fflags.valid).getOrElse(false.B) + csr.io.fcsr_flags.valid := io.fpu.fcsr_flags.valid | vector_fcsr_flags_valid + csr.io.fcsr_flags.bits := (io.fpu.fcsr_flags.bits & Fill(5, io.fpu.fcsr_flags.valid)) | (vector_fcsr_flags & Fill(5, vector_fcsr_flags_valid)) io.fpu.time := csr.io.time(31,0) io.fpu.hartid := io.hartid csr.io.rocc_interrupt := io.rocc.interrupt csr.io.pc := wb_reg_pc + val tval_dmem_addr = !wb_reg_xcpt val tval_any_addr = tval_dmem_addr || wb_reg_cause.isOneOf(Causes.breakpoint.U, Causes.fetch_access.U, Causes.fetch_page_fault.U, Causes.fetch_guest_page_fault.U) @@ -712,7 +849,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val tval_valid = wb_xcpt && (tval_any_addr || tval_inst) csr.io.gva := wb_xcpt && (tval_any_addr && csr.io.status.v || tval_dmem_addr && wb_reg_hls_or_dv) csr.io.tval := Mux(tval_valid, encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata), 0.U) - csr.io.htval := { + val (htval, mhtinst_read_pseudo) = { val htval_valid_imem = wb_reg_xcpt && wb_reg_cause === Causes.fetch_guest_page_fault.U val htval_imem = Mux(htval_valid_imem, io.imem.gpa.bits, 0.U) assert(!htval_valid_imem || io.imem.gpa.valid) @@ -720,8 +857,47 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val htval_valid_dmem = wb_xcpt && tval_dmem_addr && io.dmem.s2_xcpt.gf.asUInt.orR && !io.dmem.s2_xcpt.pf.asUInt.orR val htval_dmem = Mux(htval_valid_dmem, io.dmem.s2_gpa, 0.U) - (htval_dmem | htval_imem) >> hypervisorExtraAddrBits + val htval = (htval_dmem | htval_imem) >> hypervisorExtraAddrBits + // read pseudoinstruction if a guest-page fault is caused by an implicit memory access for VS-stage address translation + val mhtinst_read_pseudo = (io.imem.gpa_is_pte && htval_valid_imem) || (io.dmem.s2_gpa_is_pte && htval_valid_dmem) + (htval, mhtinst_read_pseudo) + } + + csr.io.vector.foreach { v => + v.set_vconfig.valid := wb_reg_set_vconfig && wb_reg_valid + v.set_vconfig.bits := wb_reg_rs2.asTypeOf(new VConfig) + v.set_vs_dirty := wb_valid && wb_ctrl.vec + v.set_vstart.valid := wb_valid && wb_reg_set_vconfig + v.set_vstart.bits := 0.U } + + io.vector.foreach { v => + when (v.wb.retire || v.wb.xcpt || wb_ctrl.vec) { + csr.io.pc := v.wb.pc + csr.io.retire := v.wb.retire + csr.io.inst(0) := v.wb.inst + when (v.wb.xcpt && !wb_reg_xcpt) { + wb_xcpt := true.B + wb_cause := v.wb.cause + csr.io.tval := v.wb.tval + } + } + v.wb.store_pending := io.dmem.store_pending + v.wb.vxrm := csr.io.vector.get.vxrm + v.wb.frm := csr.io.fcsr_rm + csr.io.vector.get.set_vxsat := v.set_vxsat + when (v.set_vconfig.valid) { + csr.io.vector.get.set_vconfig.valid := true.B + csr.io.vector.get.set_vconfig.bits := v.set_vconfig.bits + } + when (v.set_vstart.valid) { + csr.io.vector.get.set_vstart.valid := true.B + csr.io.vector.get.set_vstart.bits := v.set_vstart.bits + } + } + + csr.io.htval := htval + csr.io.mhtinst_read_pseudo := mhtinst_read_pseudo io.ptw.ptbr := csr.io.ptbr io.ptw.hgatp := csr.io.hgatp io.ptw.vsatp := csr.io.vsatp @@ -733,21 +909,51 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) csr.io.rw.addr := wb_reg_inst(31,20) csr.io.rw.cmd := CSR.maskCmd(wb_reg_valid, wb_ctrl.csr) csr.io.rw.wdata := wb_reg_wdata + + io.rocc.csrs <> csr.io.roccCSRs io.trace.time := csr.io.time io.trace.insns := csr.io.trace - if (rocketParams.debugROB) { - val csr_trace_with_wdata = WireInit(csr.io.trace(0)) - csr_trace_with_wdata.wdata.get := rf_wdata - DebugROB.pushTrace(clock, reset, - io.hartid, csr_trace_with_wdata, - (wb_ctrl.wfd || (wb_ctrl.wxd && wb_waddr =/= 0.U)) && !csr.io.trace(0).exception, - wb_ctrl.wxd && wb_wen && !wb_set_sboard, - wb_waddr + Mux(wb_ctrl.wfd, 32.U, 0.U)) - - io.trace.insns(0) := DebugROB.popTrace(clock, reset, io.hartid) - - DebugROB.pushWb(clock, reset, io.hartid, ll_wen, rf_waddr, rf_wdata) + if (rocketParams.debugROB.isDefined) { + val sz = rocketParams.debugROB.get.size + if (sz < 1) { // use unsynthesizable ROB + val csr_trace_with_wdata = WireInit(csr.io.trace(0)) + csr_trace_with_wdata.wdata.get := rf_wdata + val should_wb = WireInit((wb_ctrl.wfd || (wb_ctrl.wxd && wb_waddr =/= 0.U)) && !csr.io.trace(0).exception) + val has_wb = WireInit(wb_ctrl.wxd && wb_wen && !wb_set_sboard) + val wb_addr = WireInit(wb_waddr + Mux(wb_ctrl.wfd, 32.U, 0.U)) + + io.vector.foreach { v => when (v.wb.retire) { + should_wb := v.wb.rob_should_wb + has_wb := false.B + wb_addr := Cat(v.wb.rob_should_wb_fp, csr_trace_with_wdata.insn(11,7)) + }} + + DebugROB.pushTrace(clock, reset, + io.hartid, csr_trace_with_wdata, + should_wb, has_wb, wb_addr) + + io.trace.insns(0) := DebugROB.popTrace(clock, reset, io.hartid) + + DebugROB.pushWb(clock, reset, io.hartid, ll_wen, rf_waddr, rf_wdata) + } else { // synthesizable ROB (no FPRs) + require(!usingVector, "Synthesizable ROB does not support vector implementations") + val csr_trace_with_wdata = WireInit(csr.io.trace(0)) + csr_trace_with_wdata.wdata.get := rf_wdata + + val debug_rob = Module(new HardDebugROB(sz, 32)) + debug_rob.io.i_insn := csr_trace_with_wdata + debug_rob.io.should_wb := (wb_ctrl.wfd || (wb_ctrl.wxd && wb_waddr =/= 0.U)) && + !csr.io.trace(0).exception + debug_rob.io.has_wb := wb_ctrl.wxd && wb_wen && !wb_set_sboard + debug_rob.io.tag := wb_waddr + Mux(wb_ctrl.wfd, 32.U, 0.U) + + debug_rob.io.wb_val := ll_wen + debug_rob.io.wb_tag := rf_waddr + debug_rob.io.wb_data := rf_wdata + + io.trace.insns(0) := debug_rob.io.o_insn + } } else { io.trace.insns := csr.io.trace } @@ -779,7 +985,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) sboard.set(wb_set_sboard && wb_wen, wb_waddr) // stall for RAW/WAW hazards on CSRs, loads, AMOs, and mul/div in execute stage. - val ex_cannot_bypass = ex_ctrl.csr =/= CSR.N || ex_ctrl.jalr || ex_ctrl.mem || ex_ctrl.mul || ex_ctrl.div || ex_ctrl.fp || ex_ctrl.rocc + val ex_cannot_bypass = ex_ctrl.csr =/= CSR.N || ex_ctrl.jalr || ex_ctrl.mem || ex_ctrl.mul || ex_ctrl.div || ex_ctrl.fp || ex_ctrl.rocc || ex_ctrl.vec val data_hazard_ex = ex_ctrl.wxd && checkHazards(hazard_targets, _ === ex_waddr) val fp_data_hazard_ex = id_ctrl.fp && ex_ctrl.wfd && checkHazards(fp_hazard_targets, _ === ex_waddr) val id_ex_hazard = ex_reg_valid && (data_hazard_ex && ex_cannot_bypass || fp_data_hazard_ex) @@ -788,11 +994,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val mem_mem_cmd_bh = if (fastLoadWord) (!fastLoadByte).B && mem_reg_slow_bypass else true.B - val mem_cannot_bypass = mem_ctrl.csr =/= CSR.N || mem_ctrl.mem && mem_mem_cmd_bh || mem_ctrl.mul || mem_ctrl.div || mem_ctrl.fp || mem_ctrl.rocc + val mem_cannot_bypass = mem_ctrl.csr =/= CSR.N || mem_ctrl.mem && mem_mem_cmd_bh || mem_ctrl.mul || mem_ctrl.div || mem_ctrl.fp || mem_ctrl.rocc || mem_ctrl.vec val data_hazard_mem = mem_ctrl.wxd && checkHazards(hazard_targets, _ === mem_waddr) val fp_data_hazard_mem = id_ctrl.fp && mem_ctrl.wfd && checkHazards(fp_hazard_targets, _ === mem_waddr) val id_mem_hazard = mem_reg_valid && (data_hazard_mem && mem_cannot_bypass || fp_data_hazard_mem) id_load_use := mem_reg_valid && data_hazard_mem && mem_ctrl.mem + val id_vconfig_hazard = id_ctrl.vec && ( + (ex_reg_valid && ex_reg_set_vconfig) || + (mem_reg_valid && mem_reg_set_vconfig) || + (wb_reg_valid && wb_reg_set_vconfig)) // stall for RAW/WAW hazards on load/AMO misses and mul/div in writeback. val data_hazard_wb = wb_ctrl.wxd && checkHazards(hazard_targets, _ === wb_waddr) @@ -801,8 +1011,9 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_stall_fpu = if (usingFPU) { val fp_sboard = new Scoreboard(32) - fp_sboard.set((wb_dcache_miss && wb_ctrl.wfd || io.fpu.sboard_set) && wb_valid, wb_waddr) - fp_sboard.clear(dmem_resp_replay && dmem_resp_fpu, dmem_resp_waddr) + fp_sboard.set(((wb_dcache_miss || wb_ctrl.vec) && wb_ctrl.wfd || io.fpu.sboard_set) && wb_valid, wb_waddr) + val v_ll = io.vector.map(v => v.resp.fire && v.resp.bits.fp).getOrElse(false.B) + fp_sboard.clear((dmem_resp_replay && dmem_resp_fpu) || v_ll, io.fpu.ll_resp_tag) fp_sboard.clear(io.fpu.sboard_clr, io.fpu.sboard_clra) checkHazards(fp_hazard_targets, fp_sboard.read _) @@ -819,8 +1030,10 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ctrl_stalld = id_ex_hazard || id_mem_hazard || id_wb_hazard || id_sboard_hazard || + id_vconfig_hazard || csr.io.singleStep && (ex_reg_valid || mem_reg_valid || wb_reg_valid) || id_csr_en && csr.io.decode(0).fp_csr && !io.fpu.fcsr_rdy || + id_csr_en && csr.io.decode(0).vector_csr && id_vec_busy || id_ctrl.fp && id_stall_fpu || id_ctrl.mem && dcache_blocked || // reduce activity during D$ misses id_ctrl.rocc && rocc_blocked || // reduce activity while RoCC is busy @@ -840,7 +1053,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) mem_npc)) // flush or branch misprediction io.imem.flush_icache := wb_reg_valid && wb_ctrl.fence_i && !io.dmem.s2_nack io.imem.might_request := { - imem_might_request_reg := ex_pc_valid || mem_pc_valid || io.ptw.customCSRs.disableICacheClockGate + imem_might_request_reg := ex_pc_valid || mem_pc_valid || io.ptw.customCSRs.disableICacheClockGate || io.vector.map(_.trap_check_busy).getOrElse(false.B) imem_might_request_reg } io.imem.progress := RegNext(wb_reg_valid && !replay_wb_common) @@ -883,12 +1096,37 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.fpu.killm := killm_common io.fpu.inst := id_inst(0) io.fpu.fromint_data := ex_rs(0) - io.fpu.dmem_resp_val := dmem_resp_valid && dmem_resp_fpu - io.fpu.dmem_resp_data := (if (minFLen == 32) io.dmem.resp.bits.data_word_bypass else io.dmem.resp.bits.data) - io.fpu.dmem_resp_type := io.dmem.resp.bits.size - io.fpu.dmem_resp_tag := dmem_resp_waddr + io.fpu.ll_resp_val := dmem_resp_valid && dmem_resp_fpu + io.fpu.ll_resp_data := (if (minFLen == 32) io.dmem.resp.bits.data_word_bypass else io.dmem.resp.bits.data) + io.fpu.ll_resp_type := io.dmem.resp.bits.size + io.fpu.ll_resp_tag := dmem_resp_waddr io.fpu.keep_clock_enabled := io.ptw.customCSRs.disableCoreClockGate + io.fpu.v_sew := csr.io.vector.map(_.vconfig.vtype.vsew).getOrElse(0.U) + + io.vector.map { v => + when (!(dmem_resp_valid && dmem_resp_fpu)) { + io.fpu.ll_resp_val := v.resp.valid && v.resp.bits.fp + io.fpu.ll_resp_data := v.resp.bits.data + io.fpu.ll_resp_type := v.resp.bits.size + io.fpu.ll_resp_tag := v.resp.bits.rd + } + } + + io.vector.foreach { v => + v.ex.valid := ex_reg_valid && (ex_ctrl.vec || rocketParams.vector.get.issueVConfig.B && ex_reg_set_vconfig) && !ctrl_killx + v.ex.inst := ex_reg_inst + v.ex.vconfig := csr.io.vector.get.vconfig + v.ex.vstart := Mux(mem_reg_valid && mem_ctrl.vec || wb_reg_valid && wb_ctrl.vec, 0.U, csr.io.vector.get.vstart) + v.ex.rs1 := ex_rs(0) + v.ex.rs2 := ex_rs(1) + v.ex.pc := ex_reg_pc + v.mem.frs1 := io.fpu.store_data + v.killm := killm_common + v.status := csr.io.status + } + + io.dmem.req.valid := ex_reg_valid && ex_ctrl.mem val ex_dcache_tag = Cat(ex_waddr, ex_ctrl.fp) require(coreParams.dcacheReqTagBits >= ex_dcache_tag.getWidth) @@ -901,15 +1139,16 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.dmem.req.bits.idx.foreach(_ := io.dmem.req.bits.addr) io.dmem.req.bits.dprv := Mux(ex_reg_hls, csr.io.hstatus.spvp, csr.io.status.dprv) io.dmem.req.bits.dv := ex_reg_hls || csr.io.status.dv + io.dmem.req.bits.no_resp := !isRead(ex_ctrl.mem_cmd) || (!ex_ctrl.fp && ex_waddr === 0.U) io.dmem.req.bits.no_alloc := DontCare io.dmem.req.bits.no_xcpt := DontCare io.dmem.req.bits.data := DontCare io.dmem.req.bits.mask := DontCare - io.dmem.s1_data.data := (if (fLen == 0) mem_reg_rs2 else Mux(mem_ctrl.fp, Fill((xLen max fLen) / fLen, io.fpu.store_data), mem_reg_rs2)) + io.dmem.s1_data.data := (if (fLen == 0) mem_reg_rs2 else Mux(mem_ctrl.fp, Fill(coreDataBits / fLen, io.fpu.store_data), mem_reg_rs2)) io.dmem.s1_data.mask := DontCare - io.dmem.s1_kill := killm_common || mem_ldst_xcpt || fpu_kill_mem + io.dmem.s1_kill := killm_common || mem_ldst_xcpt || fpu_kill_mem || vec_kill_mem io.dmem.s2_kill := false.B // don't let D$ go to sleep if we're probably going to use it soon io.dmem.keep_clock_enabled := ibuf.io.inst(0).valid && id_ctrl.mem && !csr.io.csr_stall @@ -1036,7 +1275,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val rocketImpl = withClock (gated_clock) { new RocketImpl } def checkExceptions(x: Seq[(Bool, UInt)]) = - (x.map(_._1).reduce(_||_), PriorityMux(x)) + (WireInit(x.map(_._1).reduce(_||_)), WireInit(PriorityMux(x))) def coverExceptions(exceptionValid: Bool, cause: UInt, labelPrefix: String, coverCausesLabels: Seq[(Int, String)]): Unit = { for ((coverCause, label) <- coverCausesLabels) { diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index c5b5632f583..8b613aa09de 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -4,10 +4,17 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{SimpleDevice} + +import freechips.rocketchip.tilelink.{TLManagerNode, TLSlavePortParameters, TLSlaveParameters, TLBundleA, TLMessages, TLAtomics} + +import freechips.rocketchip.util.UIntIsOneOf +import freechips.rocketchip.util.DataToAugmentedData /* This adapter converts between diplomatic TileLink and non-diplomatic HellaCacheIO */ class ScratchpadSlavePort(address: Seq[AddressSet], coreDataBytes: Int, usingAtomics: Boolean)(implicit p: Parameters) extends LazyModule { @@ -57,16 +64,16 @@ class ScratchpadSlavePort(address: Seq[AddressSet], coreDataBytes: Int, usingAto def formCacheReq(a: TLBundleA) = { val req = Wire(new HellaCacheReq) - req.cmd := MuxLookup(a.opcode, M_XRD, Array( + req.cmd := MuxLookup(a.opcode, M_XRD)(Array( TLMessages.PutFullData -> M_XWR, TLMessages.PutPartialData -> M_PWR, - TLMessages.ArithmeticData -> MuxLookup(a.param, M_XRD, Array( + TLMessages.ArithmeticData -> MuxLookup(a.param, M_XRD)(Array( TLAtomics.MIN -> M_XA_MIN, TLAtomics.MAX -> M_XA_MAX, TLAtomics.MINU -> M_XA_MINU, TLAtomics.MAXU -> M_XA_MAXU, TLAtomics.ADD -> M_XA_ADD)), - TLMessages.LogicalData -> MuxLookup(a.param, M_XRD, Array( + TLMessages.LogicalData -> MuxLookup(a.param, M_XRD)(Array( TLAtomics.XOR -> M_XA_XOR, TLAtomics.OR -> M_XA_OR, TLAtomics.AND -> M_XA_AND, @@ -89,6 +96,7 @@ class ScratchpadSlavePort(address: Seq[AddressSet], coreDataBytes: Int, usingAto req.tag := 0.U req.phys := true.B req.no_xcpt := true.B + req.no_resp := false.B req.data := 0.U req.no_alloc := false.B req.mask := 0.U diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index c1f04aef73a..8cc4a2c67c9 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -5,18 +5,24 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ +import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.subsystem.CacheBlockBytes +import org.chipsalliance.cde.config._ + +import freechips.rocketchip.devices.debug.DebugModuleKey import freechips.rocketchip.diplomacy.RegionType +import freechips.rocketchip.subsystem.CacheBlockBytes import freechips.rocketchip.tile.{CoreModule, CoreBundle} import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property -import freechips.rocketchip.devices.debug.DebugModuleKey -import chisel3.experimental.SourceInfo +import freechips.rocketchip.util.{OptimizationBarrier, SetAssocLRU, PseudoLRU, PopCountAtLeast, property} + +import freechips.rocketchip.util.BooleanToAugmentedBoolean +import freechips.rocketchip.util.IntToAugmentedInt +import freechips.rocketchip.util.UIntToAugmentedUInt +import freechips.rocketchip.util.UIntIsOneOf +import freechips.rocketchip.util.SeqToAugmentedSeq +import freechips.rocketchip.util.SeqBoolBitwiseOps -case object PgLevels extends Field[Int](2) case object ASIdBits extends Field[Int](0) case object VMIdBits extends Field[Int](0) @@ -65,7 +71,7 @@ class TLBExceptions extends Bundle { val inst = Bool() } -class TLBResp(implicit p: Parameters) extends CoreBundle()(p) { +class TLBResp(lgMaxSize: Int = 3)(implicit p: Parameters) extends CoreBundle()(p) { // lookup responses val miss = Bool() /** physical address */ @@ -86,6 +92,10 @@ class TLBResp(implicit p: Parameters) extends CoreBundle()(p) { val must_alloc = Bool() /** if this address is prefetchable for caches*/ val prefetchable = Bool() + /** size/cmd of request that generated this response*/ + val size = UInt(log2Ceil(lgMaxSize + 1).W) + val cmd = UInt(M_SZ.W) + } class TLBEntryData(implicit p: Parameters) extends CoreBundle()(p) { @@ -306,11 +316,12 @@ case class TLBConfig( * @param edge collect SoC metadata. */ class TLB(instruction: Boolean, lgMaxSize: Int, cfg: TLBConfig)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(p) { + override def desiredName = if (instruction) "ITLB" else "DTLB" val io = IO(new Bundle { /** request from Core */ val req = Flipped(Decoupled(new TLBReq(lgMaxSize))) /** response to Core */ - val resp = Output(new TLBResp()) + val resp = Output(new TLBResp(lgMaxSize)) /** SFence Input */ val sfence = Flipped(Valid(new SFenceReq)) /** IO to PTW */ @@ -407,24 +418,21 @@ class TLB(instruction: Boolean, lgMaxSize: Int, cfg: TLBConfig)(implicit edge: T pmp.io.size := io.req.bits.size pmp.io.pmp := (io.ptw.pmp: Seq[PMP]) pmp.io.prv := mpu_priv - // PMA - // check exist a slave can consume this address. - val legal_address = edge.manager.findSafe(mpu_physaddr).reduce(_||_) - // check utility to help check SoC property. - def fastCheck(member: TLManagerParameters => Boolean) = - legal_address && edge.manager.fastProperty(mpu_physaddr, member, (b:Boolean) => b.B) + + val pma = Module(new PMAChecker(edge.manager)(p)) + pma.io.paddr := mpu_physaddr // todo: using DataScratchpad doesn't support cacheable. - val cacheable = fastCheck(_.supportsAcquireB) && (instruction || !usingDataScratchpad).B - val homogeneous = TLBPageLookup(edge.manager.managers, xLen, p(CacheBlockBytes), BigInt(1) << pgIdxBits)(mpu_physaddr).homogeneous + val cacheable = pma.io.resp.cacheable && (instruction || !usingDataScratchpad).B + val homogeneous = TLBPageLookup(edge.manager.managers, xLen, p(CacheBlockBytes), BigInt(1) << pgIdxBits, 1 << lgMaxSize)(mpu_physaddr).homogeneous // In M mode, if access DM address(debug module program buffer) val deny_access_to_debug = mpu_priv <= PRV.M.U && p(DebugModuleKey).map(dmp => dmp.address.contains(mpu_physaddr)).getOrElse(false.B) - val prot_r = fastCheck(_.supportsGet) && !deny_access_to_debug && pmp.io.r - val prot_w = fastCheck(_.supportsPutFull) && !deny_access_to_debug && pmp.io.w - val prot_pp = fastCheck(_.supportsPutPartial) - val prot_al = fastCheck(_.supportsLogical) - val prot_aa = fastCheck(_.supportsArithmetic) - val prot_x = fastCheck(_.executable) && !deny_access_to_debug && pmp.io.x - val prot_eff = fastCheck(Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains _.regionType) + val prot_r = pma.io.resp.r && !deny_access_to_debug && pmp.io.r + val prot_w = pma.io.resp.w && !deny_access_to_debug && pmp.io.w + val prot_pp = pma.io.resp.pp + val prot_al = pma.io.resp.al + val prot_aa = pma.io.resp.aa + val prot_x = pma.io.resp.x && !deny_access_to_debug && pmp.io.x + val prot_eff = pma.io.resp.eff // hit check val sector_hits = sectored_entries(memIdx).map(_.sectorHit(vpn, priv_v)) @@ -642,6 +650,8 @@ class TLB(instruction: Boolean, lgMaxSize: Int, cfg: TLBConfig)(implicit edge: T io.resp.prefetchable := (prefetchable_array & hits).orR && edge.manager.managers.forall(m => !m.supportsAcquireB || m.supportsHint).B io.resp.miss := do_refill || vsatp_mode_mismatch || tlb_miss || multipleHits io.resp.paddr := Cat(ppn, io.req.bits.vaddr(pgIdxBits-1, 0)) + io.resp.size := io.req.bits.size + io.resp.cmd := io.req.bits.cmd io.resp.gpa_is_pte := vstage1_en && r_gpa_is_pte io.resp.gpa := { val page = Mux(!vstage1_en, Cat(bad_gpa, vpn), r_gpa >> pgIdxBits) diff --git a/src/main/scala/rocket/TLBPermissions.scala b/src/main/scala/rocket/TLBPermissions.scala index e35b85f528a..899bc7c33ca 100644 --- a/src/main/scala/rocket/TLBPermissions.scala +++ b/src/main/scala/rocket/TLBPermissions.scala @@ -3,10 +3,10 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.isPow2 +import chisel3.util._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes, RegionType, AddressDecoder} +import freechips.rocketchip.tilelink.TLManagerParameters case class TLBPermissions( homogeneous: Bool, // if false, the below are undefined @@ -51,13 +51,13 @@ object TLBPageLookup } // Unmapped memory is considered to be inhomogeneous - def apply(managers: Seq[TLManagerParameters], xLen: Int, cacheBlockBytes: Int, pageSize: BigInt): UInt => TLBPermissions = { + def apply(managers: Seq[TLManagerParameters], xLen: Int, cacheBlockBytes: Int, pageSize: BigInt, maxRequestBytes: Int): UInt => TLBPermissions = { require (isPow2(xLen) && xLen >= 8) require (isPow2(cacheBlockBytes) && cacheBlockBytes >= xLen/8) require (isPow2(pageSize) && pageSize >= cacheBlockBytes) val xferSizes = TransferSizes(cacheBlockBytes, cacheBlockBytes) - val allSizes = TransferSizes(1, cacheBlockBytes) + val allSizes = TransferSizes(1, maxRequestBytes) val amoSizes = TransferSizes(4, xLen/8) val permissions = managers.foreach { m => diff --git a/src/main/scala/rocket/VectorUnit.scala b/src/main/scala/rocket/VectorUnit.scala new file mode 100644 index 00000000000..636c0f21332 --- /dev/null +++ b/src/main/scala/rocket/VectorUnit.scala @@ -0,0 +1,102 @@ +package freechips.rocketchip.rocket + +import chisel3._ +import chisel3.util._ +import org.chipsalliance.cde.config._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ + +case class RocketCoreVectorParams( + build: Parameters => RocketVectorUnit, + vLen: Int, + eLen: Int, + vfLen: Int, + vfh: Boolean, + vMemDataBits: Int, + decoder: Parameters => RocketVectorDecoder, + useDCache: Boolean, + issueVConfig: Boolean, + vExts: Seq[String] +) + +class VectorCoreIO(implicit p: Parameters) extends CoreBundle()(p) { + val status = Input(new MStatus) + val ex = new Bundle { + val valid = Input(Bool()) + val ready = Output(Bool()) + val inst = Input(UInt(32.W)) + val pc = Input(UInt(vaddrBitsExtended.W)) + val vconfig = Input(new VConfig) + val vstart = Input(UInt(log2Ceil(maxVLMax).W)) + val rs1 = Input(UInt(xLen.W)) + val rs2 = Input(UInt(xLen.W)) + } + val killm = Input(Bool()) + val mem = new Bundle { + val frs1 = Input(UInt(fLen.W)) + val block_mem = Output(Bool()) + val block_all = Output(Bool()) + } + + val wb = new Bundle { + val store_pending = Input(Bool()) + val replay = Output(Bool()) + val retire = Output(Bool()) + val inst = Output(UInt(32.W)) + val rob_should_wb = Output(Bool()) // debug + val rob_should_wb_fp = Output(Bool()) // debug + val pc = Output(UInt(vaddrBitsExtended.W)) + val xcpt = Output(Bool()) + val cause = Output(UInt(log2Ceil(Causes.all.max).W)) + val tval = Output(UInt(coreMaxAddrBits.W)) + val vxrm = Input(UInt(2.W)) + val frm = Input(UInt(3.W)) + } + + val resp = Decoupled(new Bundle { + val fp = Bool() + val size = UInt(2.W) + val rd = UInt(5.W) + val data = UInt((xLen max fLen).W) + }) + + val set_vstart = Valid(UInt(log2Ceil(maxVLMax).W)) + val set_vxsat = Output(Bool()) + val set_vconfig = Valid(new VConfig) + val set_fflags = Valid(UInt(5.W)) + + val trap_check_busy = Output(Bool()) + val backend_busy = Output(Bool()) +} + +abstract class RocketVectorUnit(implicit p: Parameters) extends LazyModule { + val module: RocketVectorUnitModuleImp + val tlNode: TLNode = TLIdentityNode() + val atlNode: TLNode = TLIdentityNode() +} + +class RocketVectorUnitModuleImp(outer: RocketVectorUnit) extends LazyModuleImp(outer) { + val io = IO(new Bundle { + val core = new VectorCoreIO + val tlb = Flipped(new DCacheTLBPort) + val dmem = new HellaCacheIO + + val fp_req = Decoupled(new FPInput()) + val fp_resp = Flipped(Decoupled(new FPResult())) + }) +} + +abstract class RocketVectorDecoder(implicit p: Parameters) extends CoreModule()(p) { + val io = IO(new Bundle { + val inst = Input(UInt(32.W)) + val vconfig = Input(new VConfig) + val legal = Output(Bool()) + val fp = Output(Bool()) + val read_rs1 = Output(Bool()) + val read_rs2 = Output(Bool()) + val read_frs1 = Output(Bool()) + val write_rd = Output(Bool()) + val write_frd = Output(Bool()) + }) +} diff --git a/src/main/scala/subsystem/Attachable.scala b/src/main/scala/subsystem/Attachable.scala index 7809280a110..9f3f720a04a 100644 --- a/src/main/scala/subsystem/Attachable.scala +++ b/src/main/scala/subsystem/Attachable.scala @@ -2,9 +2,10 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy.{LazyModule, LazyScope} -import freechips.rocketchip.prci.ClockGroupEphemeralNode +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.prci.ClockGroupNode import freechips.rocketchip.tilelink.TLBusWrapper import freechips.rocketchip.util.{Location, LocationMap} @@ -23,13 +24,14 @@ trait LazyScopeWithParameters extends LazyScope { this: LazyModule => /** Layers of hierarchy with this trait contain attachment points for neworks of power, clock, reset, and interrupt resources */ trait HasPRCILocations extends LazyScopeWithParameters { this: LazyModule => - implicit val asyncClockGroupsNode: ClockGroupEphemeralNode + val allClockGroupsNode: ClockGroupNode val ibus: InterruptBusWrapper val anyLocationMap = LocationMap.empty[Any] } /** Layers of hierarchy with this trait contain attachment points for TileLink interfaces */ trait HasTileLinkLocations extends HasPRCILocations { this: LazyModule => + val busContextName: String val tlBusWrapperLocationMap = LocationMap.empty[TLBusWrapper] def locateTLBusWrapper(location: Location[TLBusWrapper]): TLBusWrapper = locateTLBusWrapper(location.name) def locateTLBusWrapper(name: String): TLBusWrapper = tlBusWrapperLocationMap(Location[TLBusWrapper](name)) diff --git a/src/main/scala/subsystem/BankedL2Params.scala b/src/main/scala/subsystem/BankedCoherenceParams.scala similarity index 81% rename from src/main/scala/subsystem/BankedL2Params.scala rename to src/main/scala/subsystem/BankedCoherenceParams.scala index 402dd537804..235cd1eebbd 100644 --- a/src/main/scala/subsystem/BankedL2Params.scala +++ b/src/main/scala/subsystem/BankedCoherenceParams.scala @@ -2,19 +2,27 @@ package freechips.rocketchip.subsystem -import chisel3.util.isPow2 +import chisel3.util._ + import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.devices.tilelink.BuiltInDevices -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.interrupts.IntOutwardNode +import freechips.rocketchip.tilelink.{ + TLBroadcast, HasTLBusParams, BroadcastFilter, TLBusWrapper, TLBusWrapperInstantiationLike, + TLJbar, TLEdge, TLOutwardNode, TLTempNode, TLInwardNode, BankBinder, TLBroadcastParams, + TLBroadcastControlParams, TLBuffer, TLFragmenter, TLNameNode +} +import freechips.rocketchip.util.Location + import CoherenceManagerWrapper._ /** Global cache coherence granularity, which applies to all caches, for now. */ case object CacheBlockBytes extends Field[Int](64) -/** L2 Broadcast Hub configuration */ +/** LLC Broadcast Hub configuration */ case object BroadcastKey extends Field(BroadcastParams()) case class BroadcastParams( @@ -23,10 +31,11 @@ case class BroadcastParams( controlAddress: Option[BigInt] = None, filterFactory: TLBroadcast.ProbeFilterFactory = BroadcastFilter.factory) -/** L2 memory subsystem configuration */ -case object BankedL2Key extends Field(BankedL2Params()) +/** Coherence manager configuration */ +case object SubsystemBankedCoherenceKey extends Field(BankedCoherenceParams()) +case class ClusterBankedCoherenceKey(clusterId: Int) extends Field(BankedCoherenceParams(nBanks=0)) -case class BankedL2Params( +case class BankedCoherenceParams( nBanks: Int = 1, coherenceManager: CoherenceManagerInstantiationFn = broadcastManager ) { diff --git a/src/main/scala/subsystem/BaseSubsystem.scala b/src/main/scala/subsystem/BaseSubsystem.scala index 926e1d22923..e5aaa6242aa 100644 --- a/src/main/scala/subsystem/BaseSubsystem.scala +++ b/src/main/scala/subsystem/BaseSubsystem.scala @@ -2,15 +2,22 @@ package freechips.rocketchip.subsystem +import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressRange} +import freechips.rocketchip.resources.{ + BindingScope, DTS, DTB, ResourceBinding, JSON, ResourceInt, + DTSModel, DTSCompat, DTSTimebase, ResourceString, Resource, + ResourceAnchors, AddressMapEntry} +import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockGroupAggregator, ClockGroupSourceNode, ClockGroupSourceParameters} import freechips.rocketchip.tilelink.TLBusWrapper -import freechips.rocketchip.util._ +import freechips.rocketchip.util.{Location, ElaborationArtefacts, PlusArgArtefacts, RecordMap, Annotated} -case object SubsystemDriveAsyncClockGroupsKey extends Field[Option[ClockGroupDriverParameters]](Some(ClockGroupDriverParameters(1))) -case object AsyncClockGroupsKey extends Field[() => ClockGroupEphemeralNode](() => ClockGroupEphemeralNode()(ValName("clock_sources"))) +case object SubsystemDriveClockGroupsFromIO extends Field[Boolean](true) case class TLNetworkTopologyLocated(where: HierarchicalLocation) extends Field[Seq[CanInstantiateWithinContextThatHasTileLinkLocations with CanConnectWithinContextThatHasTileLinkLocations]] case class TLManagerViewpointLocated(where: HierarchicalLocation) extends Field[Location[TLBusWrapper]](SBUS) @@ -19,22 +26,29 @@ case object InTile extends HierarchicalLocation("InTile") case object InSubsystem extends HierarchicalLocation("InSubsystem") case object InSystem extends HierarchicalLocation("InSystem") -/** BareSubsystem is the root class for creating a subsystem */ -abstract class BareSubsystem(implicit p: Parameters) extends LazyModule with BindingScope { +// HasDts is generating metadatas from Scala, which is not the target for new diplomacy and Property. +// It will be deprecated and removed after we migrate all metadata handling logic to OM Dialect. +trait HasDTS extends LazyModule with BindingScope { lazy val dts = DTS(bindingTree) lazy val dtb = DTB(dts) lazy val json = JSON(bindingTree) } -abstract class BareSubsystemModuleImp[+L <: BareSubsystem](_outer: L) extends LazyModuleImp(_outer) { - val outer = _outer - ElaborationArtefacts.add("graphml", outer.graphML) - ElaborationArtefacts.add("dts", outer.dts) - ElaborationArtefacts.add("json", outer.json) +trait HasDTSImp[+L <: HasDTS] { this: LazyRawModuleImp => + def dtsLM: L + // GraphML should live outside form this trait, but we keep it here until we find an appropriate way to handle metadata + ElaborationArtefacts.add("graphml", dtsLM.graphML) + // PlusArg should be purged out from rocket-chip in a near feature. ElaborationArtefacts.add("plusArgs", PlusArgArtefacts.serialize_cHeader()) - println(outer.dts) + ElaborationArtefacts.add("dts", dtsLM.dts) + ElaborationArtefacts.add("json", dtsLM.json) + println(dtsLM.dts) } +/** BareSubsystem is the root class for creating a subsystem */ +abstract class BareSubsystem(implicit p: Parameters) extends LazyModule +abstract class BareSubsystemModuleImp[+L <: BareSubsystem](_outer: L) extends LazyRawModuleImp(_outer) + trait SubsystemResetScheme case object ResetSynchronous extends SubsystemResetScheme case object ResetAsynchronous extends SubsystemResetScheme @@ -47,11 +61,22 @@ case object SubsystemResetSchemeKey extends Field[SubsystemResetScheme](ResetSyn */ trait HasConfigurablePRCILocations { this: HasPRCILocations => val ibus = LazyModule(new InterruptBusWrapper) - implicit val asyncClockGroupsNode = p(AsyncClockGroupsKey)() - val clock_sources: ModuleValue[RecordMap[ClockBundle]] = - p(SubsystemDriveAsyncClockGroupsKey) - .map(_.drive(asyncClockGroupsNode)) - .getOrElse(InModuleBody { RecordMap[ClockBundle]() }) + val allClockGroupsNode = ClockGroupIdentityNode() + val io_clocks = if (p(SubsystemDriveClockGroupsFromIO)) { + val aggregator = ClockGroupAggregator() + val source = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) + allClockGroupsNode :*= aggregator := source + Some(InModuleBody { + val elements = source.out.map(_._1.member.elements).flatten + val io = IO(Flipped(RecordMap(elements.map { case (name, data) => + name -> data.cloneType + }:_*))) + elements.foreach { case (name, data) => io(name).foreach { data := _ } } + io + }) + } else { + None + } } /** Look up the topology configuration for the TL buses located within this layer of the hierarchy */ @@ -60,36 +85,32 @@ trait HasConfigurableTLNetworkTopology { this: HasTileLinkLocations => // Calling these functions populates tlBusWrapperLocationMap and connects the locations to each other. val topology = p(TLNetworkTopologyLocated(location)) - topology.map(_.instantiate(this)) + topology.foreach(_.instantiate(this)) topology.foreach(_.connect(this)) + def viewpointBus: TLBusWrapper = tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location))) // This is used lazily at DTS binding time to get a view of the network - lazy val topManagers = tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location))).unifyManagers + lazy val topManagers = viewpointBus.unifyManagers } /** Base Subsystem class with no peripheral devices, ports or cores added yet */ abstract class BaseSubsystem(val location: HierarchicalLocation = InSubsystem) (implicit p: Parameters) extends BareSubsystem + with HasDTS with Attachable with HasConfigurablePRCILocations with HasConfigurableTLNetworkTopology { override val module: BaseSubsystemModuleImp[BaseSubsystem] - // TODO must there really always be an "sbus"? - val sbus = tlBusWrapperLocationMap(SBUS) - tlBusWrapperLocationMap.lift(SBUS).map { _.clockGroupNode := asyncClockGroupsNode } + val busContextName = "subsystem" - // TODO: Preserve legacy implicit-clock behavior for IBUS for now. If binding - // a PLIC to the CBUS, ensure it is synchronously coupled to the SBUS. - ibus.clockNode := sbus.fixedClockNode + viewpointBus.clockGroupNode := allClockGroupsNode - // TODO deprecate these public members to see where users are manually hardcoding a particular bus that might actually not exist in a certain dynamic topology - val pbus = tlBusWrapperLocationMap.lift(PBUS).getOrElse(sbus) - val fbus = tlBusWrapperLocationMap.lift(FBUS).getOrElse(sbus) - val mbus = tlBusWrapperLocationMap.lift(MBUS).getOrElse(sbus) - val cbus = tlBusWrapperLocationMap.lift(CBUS).getOrElse(sbus) + // TODO: Preserve legacy implicit-clock behavior for IBUS for now. If binding + // a PLIC to the CBUS, ensure it is synchronously coupled to the SBUS. + ibus.clockNode := viewpointBus.fixedClockNode // Collect information for use in DTS ResourceBinding { @@ -119,9 +140,10 @@ abstract class BaseSubsystem(val location: HierarchicalLocation = InSubsystem) } -abstract class BaseSubsystemModuleImp[+L <: BaseSubsystem](_outer: L) extends BareSubsystemModuleImp(_outer) { +abstract class BaseSubsystemModuleImp[+L <: BaseSubsystem](_outer: L) extends BareSubsystemModuleImp(_outer) with HasDTSImp[L] { + def dtsLM: L = _outer private val mapping: Seq[AddressMapEntry] = Annotated.addressMapping(this, { - outer.collectResourceAddresses.groupBy(_._2).toList.flatMap { case (key, seq) => + dtsLM.collectResourceAddresses.groupBy(_._2).toList.flatMap { case (key, seq) => AddressRange.fromSets(key.address).map { r => AddressMapEntry(r, key.permissions, seq.map(_._1)) } }.sortBy(_.range) }) @@ -129,14 +151,14 @@ abstract class BaseSubsystemModuleImp[+L <: BaseSubsystem](_outer: L) extends Ba Annotated.addressMapping(this, mapping) println("Generated Address Map") - mapping.map(entry => println(entry.toString((outer.sbus.busView.bundle.addressBits-1)/4 + 1))) + mapping.foreach(entry => println(entry.toString((dtsLM.tlBusWrapperLocationMap(p(TLManagerViewpointLocated(dtsLM.location))).busView.bundle.addressBits-1)/4 + 1))) println("") ElaborationArtefacts.add("memmap.json", s"""{"mapping":[${mapping.map(_.toJSON).mkString(",")}]}""") // Confirm that all of memory was described by DTS private val dtsRanges = AddressRange.unify(mapping.map(_.range)) - private val allRanges = AddressRange.unify(outer.topManagers.flatMap { m => AddressRange.fromSets(m.address) }) + private val allRanges = AddressRange.unify(dtsLM.topManagers.flatMap { m => AddressRange.fromSets(m.address) }) if (dtsRanges != allRanges) { println("Address map described by DTS differs from physical implementation:") diff --git a/src/main/scala/subsystem/BusTopology.scala b/src/main/scala/subsystem/BusTopology.scala index 239a016647e..5b3dd7c452a 100644 --- a/src/main/scala/subsystem/BusTopology.scala +++ b/src/main/scala/subsystem/BusTopology.scala @@ -2,9 +2,11 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.Field -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.prci.{ClockCrossingType, NoCrossing, SynchronousCrossing} +import freechips.rocketchip.tilelink.{TLBusWrapper, TLBusWrapperTopology, TLBusWrapperConnection} import freechips.rocketchip.util.Location // These fields control parameters of the five traditional tilelink bus wrappers. @@ -23,12 +25,16 @@ case object MemoryBusKey extends Field[MemoryBusParams] // dynamically-configured topologies. class TLBusWrapperLocation(name: String) extends Location[TLBusWrapper](name) -case object SBUS extends TLBusWrapperLocation("subsystem_sbus") -case object PBUS extends TLBusWrapperLocation("subsystem_pbus") -case object FBUS extends TLBusWrapperLocation("subsystem_fbus") -case object MBUS extends TLBusWrapperLocation("subsystem_mbus") -case object CBUS extends TLBusWrapperLocation("subsystem_cbus") -case object L2 extends TLBusWrapperLocation("subsystem_l2") +case object SBUS extends TLBusWrapperLocation("sbus") +case object PBUS extends TLBusWrapperLocation("pbus") +case object FBUS extends TLBusWrapperLocation("fbus") +case object MBUS extends TLBusWrapperLocation("mbus") +case object CBUS extends TLBusWrapperLocation("cbus") +case object COH extends TLBusWrapperLocation("coh") +case class CSBUS(clusterId: Int) extends TLBusWrapperLocation(s"csbus$clusterId") +case class CMBUS(clusterId: Int) extends TLBusWrapperLocation(s"cmbus$clusterId") +case class CCBUS(clusterId: Int) extends TLBusWrapperLocation(s"ccbus$clusterId") +case class CCOH (clusterId: Int) extends TLBusWrapperLocation(s"ccoh$clusterId") /** Parameterizes the subsystem in terms of optional clock-crossings * that are insertable between some of the five traditional tilelink bus wrappers. @@ -89,20 +95,40 @@ case class HierarchicalBusTopologyParams( /** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */ case class CoherentBusTopologyParams( - sbus: SystemBusParams, // TODO remove this after better width propagation mbus: MemoryBusParams, - l2: BankedL2Params, + coherence: BankedCoherenceParams, sbusToMbusXType: ClockCrossingType = NoCrossing, driveMBusClockFromSBus: Boolean = true ) extends TLBusWrapperTopology( - instantiations = (if (l2.nBanks == 0) Nil else List( + instantiations = (if (coherence.nBanks == 0) Nil else List( (MBUS, mbus), - (L2, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, l2.nBanks, L2.name, sbus.dtsFrequency)(l2.coherenceManager)))), - connections = if (l2.nBanks == 0) Nil else List( - (SBUS, L2, TLBusWrapperConnection(driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), - (L2, MBUS, TLBusWrapperConnection.crossTo( + (COH, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, coherence.nBanks, COH.name)(coherence.coherenceManager)))), + connections = if (coherence.nBanks == 0) Nil else List( + (SBUS, COH, TLBusWrapperConnection(driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), + (COH, MBUS, TLBusWrapperConnection.crossTo( xType = sbusToMbusXType, driveClockFromMaster = if (driveMBusClockFromSBus) Some(true) else None, nodeBinding = BIND_QUERY)) ) ) + +case class ClusterBusTopologyParams( + clusterId: Int, + csbus: SystemBusParams, + ccbus: PeripheryBusParams, + coherence: BankedCoherenceParams +) extends TLBusWrapperTopology( + instantiations = List( + (CSBUS(clusterId), csbus), + (CCBUS(clusterId), ccbus)) ++ (if (coherence.nBanks == 0) Nil else List( + (CMBUS(clusterId), csbus), + (CCOH (clusterId), CoherenceManagerWrapperParams(csbus.blockBytes, csbus.beatBytes, coherence.nBanks, CCOH(clusterId).name)(coherence.coherenceManager)))), + connections = if (coherence.nBanks == 0) Nil else List( + (CSBUS(clusterId), CCOH (clusterId), TLBusWrapperConnection(driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), + (CCOH (clusterId), CMBUS(clusterId), TLBusWrapperConnection.crossTo( + xType = NoCrossing, + driveClockFromMaster = Some(true), + nodeBinding = BIND_QUERY)) + ) +) + diff --git a/src/main/scala/subsystem/Cluster.scala b/src/main/scala/subsystem/Cluster.scala new file mode 100644 index 00000000000..9d82ad616ca --- /dev/null +++ b/src/main/scala/subsystem/Cluster.scala @@ -0,0 +1,236 @@ +package freechips.rocketchip.subsystem + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.{TLDebugModule} +import freechips.rocketchip.diplomacy.{FlipRendering} +import freechips.rocketchip.interrupts.{IntIdentityNode, IntSyncIdentityNode, NullIntSource} +import freechips.rocketchip.prci.{ClockCrossingType, NoCrossing, ClockSinkParameters, ClockGroupIdentityNode, BundleBridgeBlockDuringReset} +import freechips.rocketchip.tile.{RocketTile, NMI, TraceBundle} +import freechips.rocketchip.tilelink.TLWidthWidget +import freechips.rocketchip.util.TraceCoreInterface + +import scala.collection.immutable.SortedMap + +case class ClustersLocated(loc: HierarchicalLocation) extends Field[Seq[CanAttachCluster]](Nil) + +case class ClusterParams( + val clusterId: Int, + val clockSinkParams: ClockSinkParameters = ClockSinkParameters() +) extends HierarchicalElementParams { + val baseName = "cluster" + val uniqueName = s"${baseName}_$clusterId" + def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByClusterIdImpl)(implicit p: Parameters): Cluster = { + new Cluster(this, crossing.crossingType, lookup) + } +} + +class Cluster( + val thisClusterParams: ClusterParams, + crossing: ClockCrossingType, + lookup: LookupByClusterIdImpl)(implicit p: Parameters) extends BaseHierarchicalElement(crossing)(p) + with Attachable + with HasConfigurableTLNetworkTopology + with InstantiatesHierarchicalElements + with HasHierarchicalElements +{ + val busContextName = thisClusterParams.baseName + lazy val clusterId = thisClusterParams.clusterId + lazy val location = InCluster(clusterId) + + lazy val allClockGroupsNode = ClockGroupIdentityNode() + + val csbus = tlBusWrapperLocationMap(CSBUS(clusterId)) // like the sbus in the base subsystem + val ccbus = tlBusWrapperLocationMap(CCBUS(clusterId)) // like the cbus in the base subsystem + val cmbus = tlBusWrapperLocationMap.lift(CMBUS(clusterId)).getOrElse(csbus) + + csbus.clockGroupNode := allClockGroupsNode + ccbus.clockGroupNode := allClockGroupsNode + + val slaveNode = ccbus.inwardNode + val masterNode = cmbus.outwardNode + + + + lazy val ibus = LazyModule(new InterruptBusWrapper) + ibus.clockNode := csbus.fixedClockNode + + def msipDomain = this + def meipDomain = this + def seipDomain = this + def toPlicDomain = this + lazy val msipNodes = totalTileIdList.map { i => (i, IntIdentityNode()) }.to(SortedMap) + lazy val meipNodes = totalTileIdList.map { i => (i, IntIdentityNode()) }.to(SortedMap) + lazy val seipNodes = totalTileIdList.map { i => (i, IntIdentityNode()) }.to(SortedMap) + lazy val tileToPlicNodes = totalTileIdList.map { i => (i, IntIdentityNode()) }.to(SortedMap) + lazy val debugNodes = totalTileIdList.map { i => (i, IntSyncIdentityNode()) }.to(SortedMap) + lazy val nmiNodes = totalTiles.filter { case (i,t) => t.tileParams.core.useNMI } + .mapValues(_ => BundleBridgeIdentityNode[NMI]()).to(SortedMap) + lazy val tileHartIdNodes = totalTileIdList.map { i => (i, BundleBridgeIdentityNode[UInt]()) }.to(SortedMap) + lazy val tileResetVectorNodes = totalTileIdList.map { i => (i, BundleBridgeIdentityNode[UInt]()) }.to(SortedMap) + lazy val traceCoreNodes = totalTileIdList.map { i => (i, BundleBridgeIdentityNode[TraceCoreInterface]()) }.to(SortedMap) + lazy val traceNodes = totalTileIdList.map { i => (i, BundleBridgeIdentityNode[TraceBundle]()) }.to(SortedMap) + + // TODO fix: shouldn't need to connect dummy notifications + tileHaltXbarNode := NullIntSource() + tileWFIXbarNode := NullIntSource() + tileCeaseXbarNode := NullIntSource() + + override lazy val module = new ClusterModuleImp(this) +} + +class ClusterModuleImp(outer: Cluster) extends BaseHierarchicalElementModuleImp[Cluster](outer) + +case class InCluster(id: Int) extends HierarchicalLocation(s"Cluster$id") + +class ClusterPRCIDomain( + clockSinkParams: ClockSinkParameters, + crossingParams: HierarchicalElementCrossingParamsLike, + clusterParams: ClusterParams, + lookup: LookupByClusterIdImpl) + (implicit p: Parameters) extends HierarchicalElementPRCIDomain[Cluster](clockSinkParams, crossingParams) +{ + val element = element_reset_domain { + LazyModule(clusterParams.instantiate(crossingParams, lookup)) + } + // Nothing should depend on the clocks coming from clockNode anyways + clockNode := element.csbus.fixedClockNode +} + + +trait CanAttachCluster { + type ClusterContextType <: DefaultHierarchicalElementContextType + + def clusterParams: ClusterParams + def crossingParams: HierarchicalElementCrossingParamsLike + + def instantiate(allClusterParams: Seq[ClusterParams], instantiatedClusters: SortedMap[Int, ClusterPRCIDomain])(implicit p: Parameters): ClusterPRCIDomain = { + val clockSinkParams = clusterParams.clockSinkParams.copy(name = Some(clusterParams.uniqueName)) + val cluster_prci_domain = LazyModule(new ClusterPRCIDomain( + clockSinkParams, crossingParams, clusterParams, PriorityMuxClusterIdFromSeq(allClusterParams))) + cluster_prci_domain + } + + def connect(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + connectMasterPorts(domain, context) + connectSlavePorts(domain, context) + connectInterrupts(domain, context) + connectPRC(domain, context) + connectOutputNotifications(domain, context) + connectInputConstants(domain, context) + connectTrace(domain, context) + } + + def connectMasterPorts(domain: ClusterPRCIDomain, context: Attachable): Unit = { + implicit val p = context.p + val dataBus = context.locateTLBusWrapper(crossingParams.master.where) + dataBus.coupleFrom(clusterParams.baseName) { bus => + bus :=* crossingParams.master.injectNode(context) :=* domain.crossMasterPort(crossingParams.crossingType) + } + } + def connectSlavePorts(domain: ClusterPRCIDomain, context: Attachable): Unit = { + implicit val p = context.p + val controlBus = context.locateTLBusWrapper(crossingParams.slave.where) + controlBus.coupleTo(clusterParams.baseName) { bus => + domain.crossSlavePort(crossingParams.crossingType) :*= crossingParams.slave.injectNode(context) :*= TLWidthWidget(controlBus.beatBytes) :*= bus + } + } + def connectInterrupts(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + implicit val p = context.p + + domain.element.debugNodes.foreach { case (hartid, node) => + node := context.debugNodes(hartid) + } + + domain.element.msipNodes.foreach { case (hartid, node) => context.msipDomain { + domain.crossIntIn(crossingParams.crossingType, node) := context.msipNodes(hartid) + }} + + domain.element.meipNodes.foreach { case (hartid, node) => context.meipDomain { + domain.crossIntIn(crossingParams.crossingType, node) := context.meipNodes(hartid) + }} + + domain.element.seipNodes.foreach { case (hartid, node) => context.seipDomain { + domain.crossIntIn(crossingParams.crossingType, node) := context.seipNodes(hartid) + }} + + domain.element.tileToPlicNodes.foreach { case (hartid, node) => + FlipRendering { implicit p => + context.tileToPlicNodes(hartid) :=* domain.crossIntOut(crossingParams.crossingType, node) } + } + context.ibus.fromSync :=* domain.crossIntOut(crossingParams.crossingType, domain.element.ibus.toPLIC) + + domain.element.nmiNodes.foreach { case (hartid, node) => + node := context.nmiNodes(hartid) + } + } + + def connectPRC(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + implicit val p = context.p + domain.element.allClockGroupsNode :*= context.allClockGroupsNode + domain { + domain.element_reset_domain.clockNode := crossingParams.resetCrossingType.injectClockNode := domain.clockNode + } + } + + def connectOutputNotifications(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + implicit val p = context.p + context.tileHaltXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.tileHaltXbarNode) + context.tileWFIXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.tileWFIXbarNode) + context.tileCeaseXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.tileCeaseXbarNode) + + } + + def connectInputConstants(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + implicit val p = context.p + val tlBusToGetPrefixFrom = context.locateTLBusWrapper(crossingParams.mmioBaseAddressPrefixWhere) + domain.element.tileHartIdNodes.foreach { case (hartid, node) => + node := context.tileHartIdNodes(hartid) + } + domain.element.tileResetVectorNodes.foreach { case (hartid, node) => + node := context.tileResetVectorNodes(hartid) + } + } + + def connectTrace(domain: ClusterPRCIDomain, context: ClusterContextType): Unit = { + implicit val p = context.p + domain.element.traceNodes.foreach { case (hartid, node) => + val traceNexusNode = BundleBridgeBlockDuringReset[TraceBundle]( + resetCrossingType = crossingParams.resetCrossingType) + context.traceNodes(hartid) := traceNexusNode := node + } + domain.element.traceCoreNodes.foreach { case (hartid, node) => + val traceCoreNexusNode = BundleBridgeBlockDuringReset[TraceCoreInterface]( + resetCrossingType = crossingParams.resetCrossingType) + context.traceCoreNodes(hartid) :*= traceCoreNexusNode := node + } + } +} + +case class ClusterAttachParams( + clusterParams: ClusterParams, + crossingParams: HierarchicalElementCrossingParamsLike +) extends CanAttachCluster + +case class CloneClusterAttachParams( + sourceClusterId: Int, + cloneParams: CanAttachCluster +) extends CanAttachCluster { + def clusterParams = cloneParams.clusterParams + def crossingParams = cloneParams.crossingParams + + override def instantiate(allClusterParams: Seq[ClusterParams], instantiatedClusters: SortedMap[Int, ClusterPRCIDomain])(implicit p: Parameters): ClusterPRCIDomain = { + require(instantiatedClusters.contains(sourceClusterId)) + val clockSinkParams = clusterParams.clockSinkParams.copy(name = Some(clusterParams.uniqueName)) + val cluster_prci_domain = CloneLazyModule( + new ClusterPRCIDomain(clockSinkParams, crossingParams, clusterParams, PriorityMuxClusterIdFromSeq(allClusterParams)), + instantiatedClusters(sourceClusterId) + ) + cluster_prci_domain + } +} diff --git a/src/main/scala/subsystem/Configs.scala b/src/main/scala/subsystem/Configs.scala index a9dbf4307bb..37001b39fd3 100644 --- a/src/main/scala/subsystem/Configs.scala +++ b/src/main/scala/subsystem/Configs.scala @@ -4,45 +4,63 @@ package freechips.rocketchip.subsystem import chisel3.util._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.rocket._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.{DebugModuleKey, DefaultDebugModuleParams, ExportDebug, JTAG, APB} +import freechips.rocketchip.devices.tilelink.{ + BuiltInErrorDeviceParams, BootROMLocated, BootROMParams, CLINTKey, DevNullDevice, CLINTParams, PLICKey, PLICParams, DevNullParams +} +import freechips.rocketchip.prci.{SynchronousCrossing, AsynchronousCrossing, RationalCrossing, ClockCrossingType} +import freechips.rocketchip.diplomacy.{ + AddressSet, MonitorsEnabled, +} +import freechips.rocketchip.resources.{ + DTSModel, DTSCompat, DTSTimebase, BigIntHexContext +} +import freechips.rocketchip.tile.{ + MaxHartIdBits, RocketTileParams, BuildRoCC, AccumulatorExample, OpcodeSet, TranslatorExample, CharacterCountExample, BlackBoxExample +} +import freechips.rocketchip.util.ClockGateModelFile +import scala.reflect.ClassTag + +case object MaxXLen extends Field[Int] class BaseSubsystemConfig extends Config ((site, here, up) => { // Tile parameters - case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */ - case XLen => 64 // Applies to all cores - case MaxHartIdBits => log2Up((site(TilesLocated(InSubsystem)).map(_.tileParams.hartId) :+ 0).max+1) + case MaxXLen => (site(PossibleTileLocations).flatMap(loc => site(TilesLocated(loc))) + .map(_.tileParams.core.xLen) :+ 32).max + case MaxHartIdBits => log2Up((site(PossibleTileLocations).flatMap(loc => site(TilesLocated(loc))) + .map(_.tileParams.tileId) :+ 0).max+1) // Interconnect parameters case SystemBusKey => SystemBusParams( - beatBytes = site(XLen)/8, + beatBytes = 8, blockBytes = site(CacheBlockBytes)) case ControlBusKey => PeripheryBusParams( - beatBytes = site(XLen)/8, + beatBytes = 8, blockBytes = site(CacheBlockBytes), + dtsFrequency = Some(100000000), // Default to 100 MHz cbus clock errorDevice = Some(BuiltInErrorDeviceParams( - errorParams = DevNullParams(List(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=4096)))) + errorParams = DevNullParams(List(AddressSet(0x3000, 0xfff)), maxAtomic=8, maxTransfer=4096)))) case PeripheryBusKey => PeripheryBusParams( - beatBytes = site(XLen)/8, + beatBytes = 8, blockBytes = site(CacheBlockBytes), dtsFrequency = Some(100000000)) // Default to 100 MHz pbus clock case MemoryBusKey => MemoryBusParams( - beatBytes = site(XLen)/8, + beatBytes = 8, blockBytes = site(CacheBlockBytes)) case FrontBusKey => FrontBusParams( - beatBytes = site(XLen)/8, + beatBytes = 8, blockBytes = site(CacheBlockBytes)) // Additional device Parameters case BootROMLocated(InSubsystem) => Some(BootROMParams(contentFileName = "./bootrom/bootrom.img")) - case SubsystemExternalResetVectorKey => false - case DebugModuleKey => Some(DefaultDebugModuleParams(site(XLen))) + case HasTilesExternalResetVectorKey => false + case DebugModuleKey => Some(DefaultDebugModuleParams(64)) case CLINTKey => Some(CLINTParams()) case PLICKey => Some(PLICParams()) case TilesLocated(InSubsystem) => Nil + case PossibleTileLocations => Seq(InSubsystem) }) /* Composable partial function Configs to set individual parameters */ @@ -80,193 +98,43 @@ class WithCoherentBusTopology extends Config((site, here, up) => { fbusToSbusXType = site(FbusToSbusXTypeKey)), driveClocksFromSBus = site(DriveClocksFromSBus)), CoherentBusTopologyParams( - sbus = site(SystemBusKey), mbus = site(MemoryBusKey), - l2 = site(BankedL2Key), + coherence = site(SubsystemBankedCoherenceKey), sbusToMbusXType = site(SbusToMbusXTypeKey), driveMBusClockFromSBus = site(DriveClocksFromSBus))) }) -class WithNBigCores( - n: Int, - overrideIdOffset: Option[Int] = None, - crossing: RocketCrossingParams = RocketCrossingParams() -) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => { - val prev = up(TilesLocated(InSubsystem), site) - val idOffset = overrideIdOffset.getOrElse(prev.size) - val big = RocketTileParams( - core = RocketCoreParams(mulDiv = Some(MulDivParams( - mulUnroll = 8, - mulEarlyOut = true, - divEarlyOut = true))), - dcache = Some(DCacheParams( - rowBits = site(SystemBusKey).beatBits, - nMSHRs = 0, - blockBytes = site(CacheBlockBytes))), - icache = Some(ICacheParams( - rowBits = site(SystemBusKey).beatBits, - blockBytes = site(CacheBlockBytes)))) - List.tabulate(n)(i => RocketTileAttachParams( - big.copy(hartId = i + idOffset), - crossing - )) ++ prev - } -}) - -class WithNMedCores( - n: Int, - overrideIdOffset: Option[Int] = None, - crossing: RocketCrossingParams = RocketCrossingParams() +class WithCluster( + clusterId: Int, + location: HierarchicalLocation = InSubsystem, + crossing: RocketCrossingParams = RocketCrossingParams() // TODO make this not rocket ) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => { - val prev = up(TilesLocated(InSubsystem), site) - val idOffset = overrideIdOffset.getOrElse(prev.size) - val med = RocketTileParams( - core = RocketCoreParams(fpu = None), - btb = None, - dcache = Some(DCacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 64, - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - nMSHRs = 0, - blockBytes = site(CacheBlockBytes))), - icache = Some(ICacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 64, - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - blockBytes = site(CacheBlockBytes)))) - List.tabulate(n)(i => RocketTileAttachParams( - med.copy(hartId = i + idOffset), - crossing - )) ++ prev - } -}) - -class WithNSmallCores( - n: Int, - overrideIdOffset: Option[Int] = None, - crossing: RocketCrossingParams = RocketCrossingParams() -) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => { - val prev = up(TilesLocated(InSubsystem), site) - val idOffset = overrideIdOffset.getOrElse(prev.size) - val small = RocketTileParams( - core = RocketCoreParams(useVM = false, fpu = None), - btb = None, - dcache = Some(DCacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 64, - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - nMSHRs = 0, - blockBytes = site(CacheBlockBytes))), - icache = Some(ICacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 64, - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - blockBytes = site(CacheBlockBytes)))) - List.tabulate(n)(i => RocketTileAttachParams( - small.copy(hartId = i + idOffset), - crossing - )) ++ prev - } + case ClustersLocated(`location`) => up(ClustersLocated(location)) :+ ClusterAttachParams( + ClusterParams(clusterId = clusterId), + crossing) + case TLNetworkTopologyLocated(InCluster(`clusterId`)) => List( + ClusterBusTopologyParams( + clusterId = clusterId, + csbus = site(SystemBusKey), + ccbus = site(ControlBusKey).copy(errorDevice = None), + coherence = site(ClusterBankedCoherenceKey(clusterId)) + ) + ) + case PossibleTileLocations => up(PossibleTileLocations) :+ InCluster(clusterId) }) -class With1TinyCore extends Config((site, here, up) => { - case XLen => 32 - case TilesLocated(InSubsystem) => { - val tiny = RocketTileParams( - core = RocketCoreParams( - useVM = false, - fpu = None, - mulDiv = Some(MulDivParams(mulUnroll = 8))), - btb = None, - dcache = Some(DCacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 256, // 16Kb scratchpad - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - nMSHRs = 0, - blockBytes = site(CacheBlockBytes), - scratch = Some(0x80000000L))), - icache = Some(ICacheParams( - rowBits = site(SystemBusKey).beatBits, - nSets = 64, - nWays = 1, - nTLBSets = 1, - nTLBWays = 4, - blockBytes = site(CacheBlockBytes))) - ) - List(RocketTileAttachParams( - tiny, - RocketCrossingParams( - crossingType = SynchronousCrossing(), - master = TileMasterPortParams()) - )) - } +class WithClusterBanks(clusterId: Int, nBanks: Int = 1) extends Config((site, here, up) => { + case ClusterBankedCoherenceKey(`clusterId`) => up(ClusterBankedCoherenceKey(clusterId)).copy(nBanks=nBanks) }) class WithNBanks(n: Int) extends Config((site, here, up) => { - case BankedL2Key => up(BankedL2Key, site).copy(nBanks = n) + case SubsystemBankedCoherenceKey => up(SubsystemBankedCoherenceKey, site).copy(nBanks = n) }) class WithNTrackersPerBank(n: Int) extends Config((site, here, up) => { case BroadcastKey => up(BroadcastKey, site).copy(nTrackers = n) }) -// This is the number of icache sets for all Rocket tiles -class WithL1ICacheSets(sets: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - icache = tp.tileParams.icache.map(_.copy(nSets = sets)))) - case t => t - } -}) - -// This is the number of icache sets for all Rocket tiles -class WithL1DCacheSets(sets: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - dcache = tp.tileParams.dcache.map(_.copy(nSets = sets)))) - case t => t - } -}) - -class WithL1ICacheWays(ways: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - icache = tp.tileParams.icache.map(_.copy(nWays = ways)))) - case t => t - } -}) - -class WithL1DCacheWays(ways: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - dcache = tp.tileParams.dcache.map(_.copy(nWays = ways)))) - case t => t - } -}) - - -class WithRocketCacheRowBits(n: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - dcache = tp.tileParams.dcache.map(_.copy(rowBits = n)), - icache = tp.tileParams.icache.map(_.copy(rowBits = n)))) - case t => t - } -}) - class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => { case CacheBlockBytes => linesize }) @@ -275,77 +143,22 @@ class WithBufferlessBroadcastHub extends Config((site, here, up) => { case BroadcastKey => up(BroadcastKey, site).copy(bufferless = true) }) -/** - * WARNING!!! IGNORE AT YOUR OWN PERIL!!! - * - * There is a very restrictive set of conditions under which the stateless - * bridge will function properly. There can only be a single tile. This tile - * MUST use the blocking data cache (L1D_MSHRS == 0) and MUST NOT have an - * uncached channel capable of writes (i.e. a RoCC accelerator). - * - * This is because the stateless bridge CANNOT generate probes, so if your - * system depends on coherence between channels in any way, - * DO NOT use this configuration. - */ -class WithIncoherentTiles extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy( - master = tp.crossingParams.master match { - case x: TileMasterPortParams => x.copy(cork = Some(true)) - case _ => throw new Exception("Unrecognized type for RocketCrossingParams.master") - })) - case t => t - } - case BankedL2Key => up(BankedL2Key, site).copy( - coherenceManager = CoherenceManagerWrapper.incoherentManager - ) -}) - -class WithRV32 extends Config((site, here, up) => { - case XLen => 32 - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy( - fpu = tp.tileParams.core.fpu.map(_.copy(fLen = 32)), - mulDiv = Some(MulDivParams(mulUnroll = 8))))) - case t => t - } -}) - -class WithFP16 extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy( - fpu = tp.tileParams.core.fpu.map(_.copy(minFLen = 16)) - ) - )) - case t => t - } -}) - -class WithNonblockingL1(nMSHRs: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - dcache = tp.tileParams.dcache.map(_.copy(nMSHRs = nMSHRs)))) - case t => t - } -}) - -class WithNBreakpoints(hwbp: Int) extends Config ((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nBreakpoints = hwbp))) - case t => t - } -}) - -class WithHypervisor(hext: Boolean = true) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(useHypervisor = hext))) - case t => t - } -}) +class TileAttachConfig[T <: CanAttachTile](f: T => T, locationOpt: Option[HierarchicalLocation], tileIdOpt: Seq[Int])(implicit tag: ClassTag[T]) + extends Config((site, here, up) => { + val partialFn: PartialFunction[CanAttachTile, CanAttachTile] = { case tp: T => if (tileIdOpt.contains(tp.tileParams.tileId) || tileIdOpt.isEmpty) f(tp) else tp } + val alterFn: CanAttachTile => CanAttachTile = x => partialFn.applyOrElse(x, identity[CanAttachTile]) + locationOpt match { + case Some(loc) => { case TilesLocated(`loc`) => up(TilesLocated(loc)) map { alterFn(_) } } + case None => { case TilesLocated(loc) => up(TilesLocated(loc)) map { alterFn(_) } } + } + }) { + // The default constructor applies the modification to all locations + def this(f: T => T)(implicit tag: ClassTag[T]) = this(f, None, Nil) + // The atLocation method applies the modification to only the provided location + def atLocation(loc: HierarchicalLocation) = new TileAttachConfig(f, Some(loc), tileIdOpt) + // The atTileIds method applies the modification only to specified tileIds + def atTileIds(ids: Int*) = new TileAttachConfig(f, locationOpt, tileIdOpt ++ ids) +} class WithRoccExample extends Config((site, here, up) => { case BuildRoCC => List( @@ -367,69 +180,30 @@ class WithRoccExample extends Config((site, here, up) => { }) }) -class WithDefaultBtb extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - btb = Some(BTBParams()))) - case t => t - } -}) - -class WithFastMulDiv extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(mulDiv = Some( - MulDivParams(mulUnroll = 8, mulEarlyOut = (site(XLen) > 32), divEarlyOut = true))))) - case t => t - } -}) - -class WithoutMulDiv extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(mulDiv = None))) - case t => t - } -}) - -class WithoutFPU extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(fpu = None))) - case t => t - } -}) - -class WithFPUWithoutDivSqrt extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(fpu = tp.tileParams.core.fpu.map(_.copy(divSqrt = false))))) - case t => t - } -}) - -class WithRocketDebugROB(enable: Boolean = true) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(debugROB = enable) - )) - } -}) - -class WithRocketCease(enable: Boolean = true) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(haveCease = enable) - )) - } -}) - -class WithNoSimulationTimeout extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(haveSimTimeout = false))) +/** + * WARNING!!! IGNORE AT YOUR OWN PERIL!!! + * + * There is a very restrictive set of conditions under which the stateless + * bridge will function properly. There can only be a single tile. This tile + * MUST use the blocking data cache (L1D_MSHRS == 0) and MUST NOT have an + * uncached channel capable of writes (i.e. a RoCC accelerator). + * + * This is because the stateless bridge CANNOT generate probes, so if your + * system depends on coherence between channels in any way, + * DO NOT use this configuration. + */ +class WithIncoherentTiles extends Config((site, here, up) => { + case TilesLocated(location) => up(TilesLocated(location), site) map { + case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy( + master = tp.crossingParams.master match { + case x: HierarchicalElementMasterPortParams => x.copy(cork = Some(true)) + case _ => throw new Exception("Unrecognized type for RocketCrossingParams.master") + })) case t => t } + case SubsystemBankedCoherenceKey => up(SubsystemBankedCoherenceKey, site).copy( + coherenceManager = CoherenceManagerWrapper.incoherentManager + ) }) class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => { @@ -440,34 +214,9 @@ class WithClockGateModel(file: String = "/vsrc/EICG_wrapper.v") extends Config(( case ClockGateModelFile => Some(file) }) -class WithSynchronousRocketTiles extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy( - crossingType = SynchronousCrossing())) - case t => t - } -}) - -class WithAsynchronousRocketTiles(depth: Int, sync: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy( - crossingType = AsynchronousCrossing())) - case t => t - } -}) - -class WithRationalRocketTiles extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy( - crossingType = RationalCrossing())) - case t => t - } -}) - class WithEdgeDataBits(dataBits: Int) extends Config((site, here, up) => { case MemoryBusKey => up(MemoryBusKey, site).copy(beatBytes = dataBits/8) case ExtIn => up(ExtIn, site).map(_.copy(beatBytes = dataBits/8)) - }) class WithJtagDTM extends Config ((site, here, up) => { @@ -524,6 +273,15 @@ class WithDefaultMemPort extends Config((site, here, up) => { idBits = 4), 1)) }) +class WithCustomMemPort (base_addr: BigInt, base_size: BigInt, data_width: Int, id_bits: Int, maxXferBytes: Int) extends Config((site, here, up) => { + case ExtMem => Some(MemoryPortParams(MasterPortParams( + base = base_addr, + size = base_size, + beatBytes = data_width/8, + idBits = id_bits, + maxXferBytes = maxXferBytes), 1)) +}) + class WithNoMemPort extends Config((site, here, up) => { case ExtMem => None }) @@ -536,6 +294,15 @@ class WithDefaultMMIOPort extends Config((site, here, up) => { idBits = 4)) }) +class WithCustomMMIOPort (base_addr: BigInt, base_size: BigInt, data_width: Int, id_bits: Int, maxXferBytes: Int) extends Config((site, here, up) => { + case ExtBus => Some(MasterPortParams( + base = base_addr, + size = base_size, + beatBytes = data_width/8, + idBits = id_bits, + maxXferBytes = maxXferBytes)) +}) + class WithNoMMIOPort extends Config((site, here, up) => { case ExtBus => None }) @@ -544,31 +311,12 @@ class WithDefaultSlavePort extends Config((site, here, up) => { case ExtIn => Some(SlavePortParams(beatBytes = 8, idBits = 8, sourceBits = 4)) }) -class WithNoSlavePort extends Config((site, here, up) => { - case ExtIn => None +class WithCustomSlavePort (data_width: Int, id_bits: Int) extends Config((site, here, up) => { + case ExtIn => Some(SlavePortParams(beatBytes = data_width/8, idBits = id_bits, sourceBits = 4)) }) -class WithScratchpadsBaseAddress(address: BigInt) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - dcache = tp.tileParams.dcache.map( - _.copy(scratch = Some(address)) - ) - )) - case t => t - } -}) - -class WithScratchpadsOnly extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(useVM = false), - dcache = tp.tileParams.dcache.map(_.copy( - nSets = 256, // 16Kb scratchpad - nWays = 1, - scratch = Some(0x80000000L))))) - case t => t - } +class WithNoSlavePort extends Config((site, here, up) => { + case ExtIn => None }) /** @@ -619,16 +367,21 @@ class WithDontDriveBusClocksFromSBus extends Config((site, here, up) => { case DriveClocksFromSBus => false }) -class WithCloneRocketTiles(n: Int = 1, cloneHart: Int = 0, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => { - val prev = up(TilesLocated(InSubsystem), site) - val idOffset = overrideIdOffset.getOrElse(prev.size) - val tileAttachParams = prev(cloneHart).asInstanceOf[RocketTileAttachParams] - (0 until n).map { i => - CloneTileAttachParams(cloneHart, tileAttachParams.copy( - tileParams = tileAttachParams.tileParams.copy(hartId = i + idOffset) - )) - } ++ prev +class WithCloneCluster( + clusterId: Int, + cloneClusterId: Int = 0, + location: HierarchicalLocation = InSubsystem, + cloneLocation: HierarchicalLocation = InSubsystem +) extends Config((site, here, up) => { + case ClustersLocated(`location`) => { + val prev = up(ClustersLocated(location)) + val clusterAttachParams = up(ClustersLocated(cloneLocation)).find(_.clusterParams.clusterId == cloneClusterId) + .get.asInstanceOf[ClusterAttachParams] + prev :+ CloneClusterAttachParams( + cloneClusterId, + clusterAttachParams.copy(clusterParams = clusterAttachParams.clusterParams.copy(clusterId = clusterId)) + ) } + case TLNetworkTopologyLocated(InCluster(`clusterId`)) => site(TLNetworkTopologyLocated(InCluster(cloneClusterId))) + case PossibleTileLocations => up(PossibleTileLocations) :+ InCluster(clusterId) }) - diff --git a/src/main/scala/subsystem/CrossingWrapper.scala b/src/main/scala/subsystem/CrossingWrapper.scala index 435a90a7b74..c252405fbc4 100644 --- a/src/main/scala/subsystem/CrossingWrapper.scala +++ b/src/main/scala/subsystem/CrossingWrapper.scala @@ -2,13 +2,20 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.amba.axi4._ -import freechips.rocketchip.interrupts._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.axi4.{AXI4InwardNode, AXI4OutwardNode} +import freechips.rocketchip.prci.{ClockCrossingType, HasClockDomainCrossing} +import freechips.rocketchip.tilelink.{TLInwardNode, TLOutwardNode} +import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode} import freechips.rocketchip.prci.{HasResetDomainCrossing, ResetCrossingType} +import freechips.rocketchip.tilelink.TLClockDomainCrossing +import freechips.rocketchip.tilelink.TLResetDomainCrossing +import freechips.rocketchip.interrupts.IntClockDomainCrossing +import freechips.rocketchip.interrupts.IntResetDomainCrossing + @deprecated("Only use this trait if you are confident you island will only ever be crossed to a single clock", "rocket-chip 1.3") trait HasCrossing extends CrossesToOnlyOneClockDomain { this: LazyModule => } diff --git a/src/main/scala/subsystem/FrontBus.scala b/src/main/scala/subsystem/FrontBus.scala index 001af15452e..e968246a130 100644 --- a/src/main/scala/subsystem/FrontBus.scala +++ b/src/main/scala/subsystem/FrontBus.scala @@ -2,10 +2,11 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.tilelink.{BuiltInErrorDeviceParams, BuiltInZeroDeviceParams, BuiltInDevices, HasBuiltInDeviceParams} +import freechips.rocketchip.tilelink.{HasTLBusParams, TLBusWrapper, TLBusWrapperInstantiationLike, HasTLXbarPhy} import freechips.rocketchip.util.{Location} case class FrontBusParams( diff --git a/src/main/scala/subsystem/HasHierarchicalElements.scala b/src/main/scala/subsystem/HasHierarchicalElements.scala new file mode 100644 index 00000000000..d026395a417 --- /dev/null +++ b/src/main/scala/subsystem/HasHierarchicalElements.scala @@ -0,0 +1,249 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.subsystem + +import chisel3._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.{TLDebugModule, HasPeripheryDebug} +import freechips.rocketchip.devices.tilelink.{BasicBusBlocker, BasicBusBlockerParams, CLINT, TLPLIC, CLINTConsts} +import freechips.rocketchip.interrupts.{ + IntNode, IntSyncNode, IntEphemeralNode, NullIntSource, IntNexusNode, IntSourcePortParameters, + IntSourceParameters, IntSinkPortParameters, IntSinkParameters, IntSyncIdentityNode, NullIntSyncSource +} +import freechips.rocketchip.tile.{TileParams, TilePRCIDomain, BaseTile, NMI, TraceBundle} +import freechips.rocketchip.tilelink.{TLNode, TLBuffer, TLCacheCork, TLTempNode, TLFragmenter} +import freechips.rocketchip.prci.{ClockCrossingType, ClockGroup, ResetCrossingType, ClockGroupNode, ClockDomain} +import freechips.rocketchip.rocket.TracedInstruction +import freechips.rocketchip.util.TraceCoreInterface + +import scala.collection.immutable.SortedMap + +/** A default implementation of parameterizing the connectivity of the port where the tile is the master. + * Optional timing buffers and/or an optional CacheCork can be inserted in the interconnect's clock domain. + */ +case class HierarchicalElementMasterPortParams( + buffers: Int = 0, + cork: Option[Boolean] = None, + where: TLBusWrapperLocation = SBUS +) extends HierarchicalElementPortParamsLike { + def injectNode(context: Attachable)(implicit p: Parameters): TLNode = { + (TLBuffer.chainNode(buffers) :=* cork.map { u => TLCacheCork(unsafe = u) } .getOrElse { TLTempNode() }) + } +} + +object HierarchicalElementMasterPortParams { + def locationDefault(loc: HierarchicalLocation) = loc match { + case InSubsystem => HierarchicalElementMasterPortParams() + case InCluster(clusterId) => HierarchicalElementMasterPortParams(where=CSBUS(clusterId)) + } +} + +/** A default implementation of parameterizing the connectivity of the port giving access to slaves inside the tile. + * Optional timing buffers and/or an optional BusBlocker adapter can be inserted in the interconnect's clock domain. + */ +case class HierarchicalElementSlavePortParams( + buffers: Int = 0, + blockerCtrlAddr: Option[BigInt] = None, + blockerCtrlWhere: TLBusWrapperLocation = CBUS, + where: TLBusWrapperLocation = CBUS +) extends HierarchicalElementPortParamsLike { + def injectNode(context: Attachable)(implicit p: Parameters): TLNode = { + val controlBus = context.locateTLBusWrapper(where) + val blockerBus = context.locateTLBusWrapper(blockerCtrlWhere) + blockerCtrlAddr + .map { BasicBusBlockerParams(_, blockerBus.beatBytes, controlBus.beatBytes) } + .map { bbbp => + val blocker = LazyModule(new BasicBusBlocker(bbbp)) + blockerBus.coupleTo("tile_slave_port_bus_blocker") { blocker.controlNode := TLFragmenter(blockerBus) := _ } + blocker.node :*= TLBuffer.chainNode(buffers) + } .getOrElse { TLBuffer.chainNode(buffers) } + } +} + +object HierarchicalElementSlavePortParams { + def locationDefault(loc: HierarchicalLocation) = loc match { + case InSubsystem => HierarchicalElementSlavePortParams() + case InCluster(clusterId) => HierarchicalElementSlavePortParams(where=CCBUS(clusterId), blockerCtrlWhere=CCBUS(clusterId)) + } +} + +/** InstantiatesTiles adds a Config-urable sequence of HierarchicalElements of any type + * to the subsystem class into which it is mixed. + */ +trait InstantiatesHierarchicalElements { this: LazyModule with Attachable => + val location: HierarchicalLocation + + /** Record the order in which to instantiate all tiles, based on statically-assigned ids. + * + * Note that these ids, which are often used as the tiles' default hartid input, + * may or may not be those actually reflected at runtime in e.g. the $mhartid CSR + */ + val tileAttachParams: Seq[CanAttachTile] = p(TilesLocated(location)).sortBy(_.tileParams.tileId) + val tileParams: Seq[TileParams] = tileAttachParams.map(_.tileParams) + val tileCrossingTypes: Seq[ClockCrossingType] = tileAttachParams.map(_.crossingParams.crossingType) + + /** The actual list of instantiated tiles in this block. */ + val tile_prci_domains: SortedMap[Int, TilePRCIDomain[_]] = tileAttachParams.foldLeft(SortedMap[Int, TilePRCIDomain[_]]()) { + case (instantiated, params) => instantiated + (params.tileParams.tileId -> params.instantiate(tileParams, instantiated)(p)) + } + + val clusterAttachParams: Seq[CanAttachCluster] = p(ClustersLocated(location)).sortBy(_.clusterParams.clusterId) + val clusterParams: Seq[ClusterParams] = clusterAttachParams.map(_.clusterParams) + val clusterCrossingTypes: Seq[ClockCrossingType] = clusterAttachParams.map(_.crossingParams.crossingType) + val cluster_prci_domains: SortedMap[Int, ClusterPRCIDomain] = clusterAttachParams.foldLeft(SortedMap[Int, ClusterPRCIDomain]()) { + case (instantiated, params) => instantiated + (params.clusterParams.clusterId -> params.instantiate(clusterParams, instantiated)(p)) + } + + val element_prci_domains: Seq[HierarchicalElementPRCIDomain[_]] = tile_prci_domains.values.toSeq ++ cluster_prci_domains.values.toSeq + + val leafTiles: SortedMap[Int, BaseTile] = SortedMap(tile_prci_domains.mapValues(_.element.asInstanceOf[BaseTile]).toSeq.sortBy(_._1):_*) + val totalTiles: SortedMap[Int, BaseTile] = (leafTiles ++ cluster_prci_domains.values.map(_.element.totalTiles).flatten) + + // Helper functions for accessing certain parameters that are popular to refer to in subsystem code + def nLeafTiles: Int = leafTiles.size + def nTotalTiles: Int = totalTiles.size + def leafTileIdList: Seq[Int] = leafTiles.keys.toSeq.sorted + def totalTileIdList: Seq[Int] = totalTiles.keys.toSeq.sorted + def localIntCounts: SortedMap[Int, Int] = totalTiles.mapValues(_.tileParams.core.nLocalInterrupts).to(SortedMap) + + require(totalTileIdList.distinct.size == totalTiles.size, s"Every tile must be statically assigned a unique id, but got:\n${totalTileIdList}") +} + +/** HasTiles instantiates and also connects a Config-urable sequence of tiles of any type to subsystem interconnect resources. */ +trait HasHierarchicalElements extends DefaultHierarchicalElementContextType +{ this: LazyModule with Attachable with InstantiatesHierarchicalElements => + implicit val p: Parameters + + // connect all the tiles to interconnect attachment points made available in this subsystem context + tileAttachParams.foreach { params => + params.connect(tile_prci_domains(params.tileParams.tileId).asInstanceOf[TilePRCIDomain[params.TileType]], this.asInstanceOf[params.TileContextType]) + } + clusterAttachParams.foreach { params => + params.connect(cluster_prci_domains(params.clusterParams.clusterId).asInstanceOf[ClusterPRCIDomain], this.asInstanceOf[params.ClusterContextType]) + } +} + +/** Provides some Chisel connectivity to certain tile IOs + * This trait is intended for the root subsystem + */ +trait HasHierarchicalElementsRootContextModuleImp extends LazyRawModuleImp { + val outer: InstantiatesHierarchicalElements with HasHierarchicalElements with HasHierarchicalElementsRootContext with HasTileInputConstants + + val reset_vector = outer.tileResetVectorIONodes.zipWithIndex.map { case (n, i) => n.makeIO(s"reset_vector_$i") } + val tile_hartids = outer.tileHartIdIONodes.zipWithIndex.map { case (n, i) => n.makeIO(s"tile_hartids_$i") } + + val meip = if (outer.meipIONode.isDefined) Some(IO(Input(Vec(outer.meipIONode.get.out.size, Bool())))) else None + meip.foreach { m => + m.zipWithIndex.foreach{ case (pin, i) => + (outer.meipIONode.get.out(i)._1)(0) := pin + } + } + val seip = if (outer.seipIONode.isDefined) Some(IO(Input(Vec(outer.seipIONode.get.out.size, Bool())))) else None + seip.foreach { s => + s.zipWithIndex.foreach{ case (pin, i) => + (outer.seipIONode.get.out(i)._1)(0) := pin + } + } + val nmi = outer.nmiIONodes.map { case (i, node) => + node.makeIO(s"nmi_$i") + } +} + +/** Most tile types require only these traits in order for their standardized connect functions to apply. + * + * BaseTiles subtypes with different needs can extend this trait to provide themselves with + * additional external connection points. + */ +trait DefaultHierarchicalElementContextType + extends Attachable + with HasTileNotificationSinks +{ this: LazyModule with Attachable => + def msipDomain: LazyScope + val msipNodes: SortedMap[Int, IntNode] + def meipDomain: LazyScope + val meipNodes: SortedMap[Int, IntNode] + def seipDomain: LazyScope + val seipNodes: SortedMap[Int, IntNode] + def toPlicDomain: LazyScope + val tileToPlicNodes: SortedMap[Int, IntNode] + val debugNodes: SortedMap[Int, IntSyncNode] + val nmiNodes: SortedMap[Int, BundleBridgeNode[NMI]] + val tileHartIdNodes: SortedMap[Int, BundleBridgeNode[UInt]] + val tileResetVectorNodes: SortedMap[Int, BundleBridgeNode[UInt]] + val traceCoreNodes: SortedMap[Int, BundleBridgeNode[TraceCoreInterface]] + val traceNodes: SortedMap[Int, BundleBridgeNode[TraceBundle]] +} + +/** This trait provides the tile attachment context for the root (outermost) subsystem */ +trait HasHierarchicalElementsRootContext +{ this: HasHierarchicalElements + with HasTileNotificationSinks + with InstantiatesHierarchicalElements => + + val clintOpt: Option[CLINT] + val clintDomainOpt: Option[ClockDomain] + val plicOpt: Option[TLPLIC] + val plicDomainOpt: Option[ClockDomain] + val debugOpt: Option[TLDebugModule] + + def msipDomain = clintDomainOpt.getOrElse(this) + def meipDomain = plicDomainOpt.getOrElse(this) + def seipDomain = plicDomainOpt.getOrElse(this) + def toPlicDomain = plicDomainOpt.getOrElse(this) + + val msipNodes: SortedMap[Int, IntNode] = (0 until nTotalTiles).map { i => + (i, IntEphemeralNode()) + }.to(SortedMap) + msipNodes.foreach { + _._2 := clintOpt.map(_.intnode).getOrElse(NullIntSource(sources = CLINTConsts.ints)) + } + + val meipIONode = Option.when(plicOpt.isEmpty)(IntNexusNode( + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, + outputRequiresInput = false, + inputRequiresOutput = false)) + val meipNodes: SortedMap[Int, IntNode] = (0 until nTotalTiles).map { i => + (i, IntEphemeralNode()) + }.to(SortedMap) + + val seipIONode = Option.when(plicOpt.isEmpty)(IntNexusNode( + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, + outputRequiresInput = false, + inputRequiresOutput = false)) + val seipNodes: SortedMap[Int, IntNode] = totalTiles.filter { case (_, t) => t.tileParams.core.hasSupervisorMode } + .mapValues( _ => IntEphemeralNode()).to(SortedMap) + + // meip/seip nodes must be connected in MSMSMS order + // TODO: This is ultra fragile... the plic should just expose two intnodes + for (i <- 0 until nTotalTiles) { + meipNodes.get(i).foreach { _ := plicOpt.map(_.intnode).getOrElse(meipIONode.get) } + seipNodes.get(i).foreach { _ := plicOpt.map(_.intnode).getOrElse(seipIONode.get) } + } + + val tileToPlicNodes: SortedMap[Int, IntNode] = (0 until nTotalTiles).map { i => + plicOpt.map(o => (i, o.intnode :=* IntEphemeralNode())) + }.flatten.to(SortedMap) + + val debugNodes: SortedMap[Int, IntSyncNode] = (0 until nTotalTiles).map { i => + (i, IntSyncIdentityNode()) + }.to(SortedMap) + + debugNodes.foreach { case (hartid, node) => + node := debugOpt.map(_.intnode).getOrElse(NullIntSyncSource()) + } + + val nmiHarts = totalTiles.filter { case (_, t) => t.tileParams.core.useNMI }.keys + val nmiIONodes = nmiHarts.map { i => (i, BundleBridgeSource[NMI]()) }.to(SortedMap) + val nmiNodes: SortedMap[Int, BundleBridgeNode[NMI]] = nmiIONodes.map { case (i, n) => + (i, BundleBridgeEphemeralNode[NMI]() := n) + }.to(SortedMap) + + val traceCoreNodes: SortedMap[Int, BundleBridgeSink[TraceCoreInterface]] = (0 until nTotalTiles).map { i => (i, BundleBridgeSink[TraceCoreInterface]()) }.to(SortedMap) + val traceNodes: SortedMap[Int, BundleBridgeSink[TraceBundle]] = (0 until nTotalTiles).map { i => (i, BundleBridgeSink[TraceBundle]()) }.to(SortedMap) +} diff --git a/src/main/scala/subsystem/HasTiles.scala b/src/main/scala/subsystem/HasTiles.scala index 5c65ed4cd81..ea1f34f7e7b 100644 --- a/src/main/scala/subsystem/HasTiles.scala +++ b/src/main/scala/subsystem/HasTiles.scala @@ -3,19 +3,31 @@ package freechips.rocketchip.subsystem import chisel3._ -import chisel3.dontTouch -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.devices.tilelink.{BasicBusBlocker, BasicBusBlockerParams, CLINTConsts, PLICKey, CanHavePeripheryPLIC, CanHavePeripheryCLINT} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.prci.{ClockGroup, ResetCrossingType, ClockGroupNode} -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.TLDebugModule +import freechips.rocketchip.diplomacy.{DisableMonitors, FlipRendering} +import freechips.rocketchip.interrupts.{IntXbar, IntSinkNode, IntSinkPortSimple, IntSyncAsyncCrossingSink} +import freechips.rocketchip.tile.{MaxHartIdBits, BaseTile, InstantiableTileParams, TileParams, TilePRCIDomain, TraceBundle, PriorityMuxHartIdFromSeq} +import freechips.rocketchip.tilelink.TLWidthWidget +import freechips.rocketchip.prci.{ClockGroup, BundleBridgeBlockDuringReset, NoCrossing, SynchronousCrossing, CreditedCrossing, RationalCrossing, AsynchronousCrossing} +import freechips.rocketchip.rocket.TracedInstruction +import freechips.rocketchip.util.TraceCoreInterface + +import scala.collection.immutable.SortedMap /** Entry point for Config-uring the presence of Tiles */ case class TilesLocated(loc: HierarchicalLocation) extends Field[Seq[CanAttachTile]](Nil) +/** List of HierarchicalLocations which might contain a Tile */ +case object PossibleTileLocations extends Field[Seq[HierarchicalLocation]](Nil) + +/** For determining static tile id */ +case object NumTiles extends Field[Int](0) + /** Whether to add timing-closure registers along the path of the hart id * as it propagates through the subsystem and into the tile. * @@ -24,112 +36,17 @@ case class TilesLocated(loc: HierarchicalLocation) extends Field[Seq[CanAttachTi */ case object InsertTimingClosureRegistersOnHartIds extends Field[Boolean](false) -/** Whether per-tile hart ids are going to be driven as inputs into the subsystem, +/** Whether per-tile hart ids are going to be driven as inputs into a HasTiles block, * and if so, what their width should be. */ -case object SubsystemExternalHartIdWidthKey extends Field[Option[Int]](None) +case object HasTilesExternalHartIdWidthKey extends Field[Option[Int]](None) -/** Whether per-tile reset vectors are going to be driven as inputs into the subsystem. +/** Whether per-tile reset vectors are going to be driven as inputs into a HasTiles block. * * Unlike the hart ids, the reset vector width is determined by the sinks within the tiles, * based on the size of the address map visible to the tiles. */ -case object SubsystemExternalResetVectorKey extends Field[Boolean](true) - -/** An interface for describing the parameteization of how Tiles are connected to interconnects */ -trait TileCrossingParamsLike { - /** The type of clock crossing that should be inserted at the tile boundary. */ - def crossingType: ClockCrossingType - /** Parameters describing the contents and behavior of the point where the tile is attached as an interconnect master. */ - def master: TilePortParamsLike - /** Parameters describing the contents and behavior of the point where the tile is attached as an interconnect slave. */ - def slave: TilePortParamsLike - /** The subnetwork location of the device selecting the apparent base address of MMIO devices inside the tile */ - def mmioBaseAddressPrefixWhere: TLBusWrapperLocation - /** Inject a reset management subgraph that effects the tile child reset only */ - def resetCrossingType: ResetCrossingType - /** Keep the tile clock separate from the interconnect clock (e.g. even if they are synchronous to one another) */ - def forceSeparateClockReset: Boolean -} - -/** An interface for describing the parameterization of how a particular tile port is connected to an interconnect */ -trait TilePortParamsLike { - /** The subnetwork location of the interconnect to which this tile port should be connected. */ - def where: TLBusWrapperLocation - /** Allows port-specific adapters to be injected into the interconnect side of the attachment point. */ - def injectNode(context: Attachable)(implicit p: Parameters): TLNode -} - -/** A default implementation of parameterizing the connectivity of the port where the tile is the master. - * Optional timing buffers and/or an optional CacheCork can be inserted in the interconnect's clock domain. - */ -case class TileMasterPortParams( - buffers: Int = 0, - cork: Option[Boolean] = None, - where: TLBusWrapperLocation = SBUS -) extends TilePortParamsLike { - def injectNode(context: Attachable)(implicit p: Parameters): TLNode = { - (TLBuffer.chainNode(buffers) :=* cork.map { u => TLCacheCork(unsafe = u) } .getOrElse { TLTempNode() }) - } -} - -/** A default implementation of parameterizing the connectivity of the port giving access to slaves inside the tile. - * Optional timing buffers and/or an optional BusBlocker adapter can be inserted in the interconnect's clock domain. - */ -case class TileSlavePortParams( - buffers: Int = 0, - blockerCtrlAddr: Option[BigInt] = None, - blockerCtrlWhere: TLBusWrapperLocation = CBUS, - where: TLBusWrapperLocation = CBUS -) extends TilePortParamsLike { - def injectNode(context: Attachable)(implicit p: Parameters): TLNode = { - val controlBus = context.locateTLBusWrapper(where) - val blockerBus = context.locateTLBusWrapper(blockerCtrlWhere) - blockerCtrlAddr - .map { BasicBusBlockerParams(_, blockerBus.beatBytes, controlBus.beatBytes) } - .map { bbbp => - val blocker = LazyModule(new BasicBusBlocker(bbbp)) - blockerBus.coupleTo("tile_slave_port_bus_blocker") { blocker.controlNode := TLFragmenter(blockerBus) := _ } - blocker.node :*= TLBuffer.chainNode(buffers) - } .getOrElse { TLBuffer.chainNode(buffers) } - } -} - -/** These are sources of interrupts that are driven into the tile. - * They need to be instantiated before tiles are attached to the subsystem containing them. - */ -trait HasTileInterruptSources - extends CanHavePeripheryPLIC - with CanHavePeripheryCLINT - with InstantiatesTiles -{ this: BaseSubsystem => // TODO ideally this bound would be softened to LazyModule - /** meipNode is used to create a single bit subsystem input in Configs without a PLIC */ - val meipNode = p(PLICKey) match { - case Some(_) => None - case None => Some(IntNexusNode( - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1))) }, - sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, - outputRequiresInput = false, - inputRequiresOutput = false)) - } - val seipNode = p(PLICKey) match { - case Some(_) => None - case None => Some(IntNexusNode( - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1))) }, - sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, - outputRequiresInput = false, - inputRequiresOutput = false)) - } - /** Source of Non-maskable Interrupt (NMI) input bundle to each tile. */ - val tileNMINode = BundleBridgeEphemeralNode[NMI]() - val tileNMIIONodes: Seq[BundleBridgeSource[NMI]] = { - Seq.fill(tiles.size) { - val nmiSource = BundleBridgeSource[NMI]() - tileNMINode := nmiSource - nmiSource - } - } -} +case object HasTilesExternalResetVectorKey extends Field[Boolean](true) /** These are sources of "constants" that are driven into the tile. * @@ -137,9 +54,11 @@ trait HasTileInterruptSources * they may be either tied to a contant value or programmed during boot or reset. * They need to be instantiated before tiles are attached within the subsystem containing them. */ -trait HasTileInputConstants extends InstantiatesTiles { this: BaseSubsystem => +trait HasTileInputConstants { this: LazyModule with Attachable with InstantiatesHierarchicalElements => /** tileHartIdNode is used to collect publishers and subscribers of hartids. */ - val tileHartIdNode = BundleBridgeEphemeralNode[UInt]() + val tileHartIdNodes: SortedMap[Int, BundleBridgeEphemeralNode[UInt]] = (0 until nTotalTiles).map { i => + (i, BundleBridgeEphemeralNode[UInt]()) + }.to(SortedMap) /** tileHartIdNexusNode is a BundleBridgeNexus that collects dynamic hart prefixes. * @@ -156,7 +75,7 @@ trait HasTileInputConstants extends InstantiatesTiles { this: BaseSubsystem => val tileHartIdNexusNode = LazyModule(new BundleBridgeNexus[UInt]( inputFn = BundleBridgeNexus.orReduction[UInt](registered = p(InsertTimingClosureRegistersOnHartIds)) _, outputFn = (prefix: UInt, n: Int) => Seq.tabulate(n) { i => - val y = dontTouch(prefix | hartIdList(i).U(p(MaxHartIdBits).W)) // dontTouch to keep constant prop from breaking tile dedup + val y = dontTouch(prefix | totalTileIdList(i).U(p(MaxHartIdBits).W)) // dontTouch to keep constant prop from breaking tile dedup if (p(InsertTimingClosureRegistersOnHartIds)) BundleBridgeNexus.safeRegNext(y) else y }, default = Some(() => 0.U(p(MaxHartIdBits).W)), @@ -166,7 +85,9 @@ trait HasTileInputConstants extends InstantiatesTiles { this: BaseSubsystem => // TODO: Replace the DebugModuleHartSelFuncs config key with logic to consume the dynamic hart IDs /** tileResetVectorNode is used to collect publishers and subscribers of tile reset vector addresses. */ - val tileResetVectorNode = BundleBridgeEphemeralNode[UInt]() + val tileResetVectorNodes: SortedMap[Int, BundleBridgeEphemeralNode[UInt]] = (0 until nTotalTiles).map { i => + (i, BundleBridgeEphemeralNode[UInt]()) + }.to(SortedMap) /** tileResetVectorNexusNode is a BundleBridgeNexus that accepts a single reset vector source, and broadcasts it to all tiles. */ val tileResetVectorNexusNode = BundleBroadcast[UInt]( @@ -177,26 +98,32 @@ trait HasTileInputConstants extends InstantiatesTiles { this: BaseSubsystem => * * Or, if such IOs are not configured to exist, tileHartIdNexusNode is used to supply an id to each tile. */ - val tileHartIdIONodes: Seq[BundleBridgeSource[UInt]] = p(SubsystemExternalHartIdWidthKey) match { - case Some(w) => Seq.fill(tiles.size) { + val tileHartIdIONodes: Seq[BundleBridgeSource[UInt]] = p(HasTilesExternalHartIdWidthKey) match { + case Some(w) => (0 until nTotalTiles).map { i => val hartIdSource = BundleBridgeSource(() => UInt(w.W)) - tileHartIdNode := hartIdSource + tileHartIdNodes(i) := hartIdSource hartIdSource } - case None => { tileHartIdNode :*= tileHartIdNexusNode; Nil } + case None => { + (0 until nTotalTiles).map { i => tileHartIdNodes(i) :*= tileHartIdNexusNode } + Nil + } } /** tileResetVectorIONodes may generate subsystem IOs, one per tile, allowing the parent to assign unique reset vectors. * * Or, if such IOs are not configured to exist, tileResetVectorNexusNode is used to supply a single reset vector to every tile. */ - val tileResetVectorIONodes: Seq[BundleBridgeSource[UInt]] = p(SubsystemExternalResetVectorKey) match { - case true => Seq.fill(tiles.size) { + val tileResetVectorIONodes: Seq[BundleBridgeSource[UInt]] = p(HasTilesExternalResetVectorKey) match { + case true => (0 until nTotalTiles).map { i => val resetVectorSource = BundleBridgeSource[UInt]() - tileResetVectorNode := resetVectorSource + tileResetVectorNodes(i) := resetVectorSource resetVectorSource } - case false => { tileResetVectorNode :*= tileResetVectorNexusNode; Nil } + case false => { + (0 until nTotalTiles).map { i => tileResetVectorNodes(i) :*= tileResetVectorNexusNode } + Nil + } } } @@ -218,20 +145,6 @@ trait HasTileNotificationSinks { this: LazyModule => tileCeaseSinkNode := tileCeaseXbarNode } -/** Most tile types require only these traits in order for their standardized connect functions to apply. - * - * BaseTiles subtypes with different needs can extend this trait to provide themselves with - * additional external connection points. - */ -trait DefaultTileContextType - extends Attachable - with HasTileInterruptSources - with HasTileNotificationSinks - with HasTileInputConstants -{ this: BaseSubsystem => - val debugNode: IntSyncOutwardNode -} // TODO: ideally this bound would be softened to LazyModule - /** Standardized interface by which parameterized tiles can be attached to contexts containing interconnect resources. * * Sub-classes of this trait can optionally override the individual connect functions in order to specialize @@ -240,15 +153,15 @@ trait DefaultTileContextType */ trait CanAttachTile { type TileType <: BaseTile - type TileContextType <: DefaultTileContextType + type TileContextType <: DefaultHierarchicalElementContextType def tileParams: InstantiableTileParams[TileType] - def crossingParams: TileCrossingParamsLike + def crossingParams: HierarchicalElementCrossingParamsLike /** Narrow waist through which all tiles are intended to pass while being instantiated. */ - def instantiate(allTileParams: Seq[TileParams], instantiatedTiles: Seq[TilePRCIDomain[_]])(implicit p: Parameters): TilePRCIDomain[TileType] = { - val clockSinkParams = tileParams.clockSinkParams.copy(name = Some(s"${tileParams.name.getOrElse("core")}_${tileParams.hartId}")) + def instantiate(allTileParams: Seq[TileParams], instantiatedTiles: SortedMap[Int, TilePRCIDomain[_]])(implicit p: Parameters): TilePRCIDomain[TileType] = { + val clockSinkParams = tileParams.clockSinkParams.copy(name = Some(tileParams.uniqueName)) val tile_prci_domain = LazyModule(new TilePRCIDomain[TileType](clockSinkParams, crossingParams) { self => - val tile = self.tile_reset_domain { LazyModule(tileParams.instantiate(crossingParams, PriorityMuxHartIdFromSeq(allTileParams))) } + val element = self.element_reset_domain { LazyModule(tileParams.instantiate(crossingParams, PriorityMuxHartIdFromSeq(allTileParams))) } }) tile_prci_domain } @@ -261,13 +174,14 @@ trait CanAttachTile { connectPRC(domain, context) connectOutputNotifications(domain, context) connectInputConstants(domain, context) + connectTrace(domain, context) } /** Connect the port where the tile is the master to a TileLink interconnect. */ def connectMasterPorts(domain: TilePRCIDomain[TileType], context: Attachable): Unit = { implicit val p = context.p val dataBus = context.locateTLBusWrapper(crossingParams.master.where) - dataBus.coupleFrom(tileParams.name.getOrElse("tile")) { bus => + dataBus.coupleFrom(tileParams.baseName) { bus => bus :=* crossingParams.master.injectNode(context) :=* domain.crossMasterPort(crossingParams.crossingType) } } @@ -277,7 +191,7 @@ trait CanAttachTile { implicit val p = context.p DisableMonitors { implicit p => val controlBus = context.locateTLBusWrapper(crossingParams.slave.where) - controlBus.coupleTo(tileParams.name.getOrElse("tile")) { bus => + controlBus.coupleTo(tileParams.baseName) { bus => domain.crossSlavePort(crossingParams.crossingType) :*= crossingParams.slave.injectNode(context) :*= TLWidthWidget(controlBus.beatBytes) :*= bus } } @@ -291,61 +205,66 @@ trait CanAttachTile { // we stub out missing interrupts with constant sources here. // 1. Debug interrupt is definitely asynchronous in all cases. - domain.tile.intInwardNode := domain { IntSyncAsyncCrossingSink(3) } := context.debugNode + domain.element.intInwardNode := domain { IntSyncAsyncCrossingSink(3) } := + context.debugNodes(domain.element.tileId) - // 2. The CLINT and PLIC output interrupts are synchronous to the TileLink bus clock, + // 2. The CLINT and PLIC output interrupts are synchronous to the CLINT/PLIC respectively, // so might need to be synchronized depending on the Tile's crossing type. // From CLINT: "msip" and "mtip" - domain.crossIntIn(crossingParams.crossingType) := - context.clintOpt.map { _.intnode } - .getOrElse { NullIntSource(sources = CLINTConsts.ints) } + context.msipDomain { + domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode) := + context.msipNodes(domain.element.tileId) + } // From PLIC: "meip" - domain.crossIntIn(crossingParams.crossingType) := - context.plicOpt .map { _.intnode } - .getOrElse { context.meipNode.get } + context.meipDomain { + domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode) := + context.meipNodes(domain.element.tileId) + } // From PLIC: "seip" (only if supervisor mode is enabled) - if (domain.tile.tileParams.core.hasSupervisorMode) { - domain.crossIntIn(crossingParams.crossingType) := - context.plicOpt .map { _.intnode } - .getOrElse { context.seipNode.get } + if (domain.element.tileParams.core.hasSupervisorMode) { + context.seipDomain { + domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode) := + context.seipNodes(domain.element.tileId) + } } // 3. Local Interrupts ("lip") are required to already be synchronous to the Tile's clock. - // (they are connected to domain.tile.intInwardNode in a seperate trait) + // (they are connected to domain.element.intInwardNode in a seperate trait) // 4. Interrupts coming out of the tile are sent to the PLIC, // so might need to be synchronized depending on the Tile's crossing type. - context.plicOpt.foreach { plic => - FlipRendering { implicit p => - plic.intnode :=* domain.crossIntOut(crossingParams.crossingType, domain.tile.intOutwardNode) - } + context.tileToPlicNodes.get(domain.element.tileId).foreach { node => + FlipRendering { implicit p => domain.element.intOutwardNode.foreach { out => + context.toPlicDomain { node := domain.crossIntOut(crossingParams.crossingType, out) } + }} } // 5. Connect NMI inputs to the tile. These inputs are synchronous to the respective core_clock. - domain.tile.nmiNode := context.tileNMINode + domain.element.nmiNode.foreach(_ := context.nmiNodes(domain.element.tileId)) } /** Notifications of tile status are connected to be broadcast without needing to be clock-crossed. */ def connectOutputNotifications(domain: TilePRCIDomain[TileType], context: TileContextType): Unit = { implicit val p = context.p - context.tileHaltXbarNode :=* domain.crossIntOut(NoCrossing, domain.tile.haltNode) - context.tileWFIXbarNode :=* domain.crossIntOut(NoCrossing, domain.tile.wfiNode) - context.tileCeaseXbarNode :=* domain.crossIntOut(NoCrossing, domain.tile.ceaseNode) + domain { + context.tileHaltXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.haltNode) + context.tileWFIXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.wfiNode) + context.tileCeaseXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.ceaseNode) + } // TODO should context be forced to have a trace sink connected here? // for now this just ensures domain.trace[Core]Node has been crossed without connecting it externally - domain.crossTracesOut() } /** Connect inputs to the tile that are assumed to be constant during normal operation, and so are not clock-crossed. */ def connectInputConstants(domain: TilePRCIDomain[TileType], context: TileContextType): Unit = { implicit val p = context.p val tlBusToGetPrefixFrom = context.locateTLBusWrapper(crossingParams.mmioBaseAddressPrefixWhere) - domain.tile.hartIdNode := context.tileHartIdNode - domain.tile.resetVectorNode := context.tileResetVectorNode - tlBusToGetPrefixFrom.prefixNode.foreach { domain.tile.mmioAddressPrefixNode := _ } + domain.element.hartIdNode := context.tileHartIdNodes(domain.element.tileId) + domain.element.resetVectorNode := context.tileResetVectorNodes(domain.element.tileId) + tlBusToGetPrefixFrom.prefixNode.foreach { domain.element.mmioAddressPrefixNode := _ } } /** Connect power/reset/clock resources. */ @@ -362,19 +281,30 @@ trait CanAttachTile { case _: RationalCrossing => domain.clockNode := tlBusToGetClockDriverFrom.clockNode case _: AsynchronousCrossing => { val tileClockGroup = ClockGroup() - tileClockGroup := context.asyncClockGroupsNode + tileClockGroup := context.allClockGroupsNode domain.clockNode := tileClockGroup } }) domain { - domain.tile_reset_domain.clockNode := crossingParams.resetCrossingType.injectClockNode := domain.clockNode + domain.element_reset_domain.clockNode := crossingParams.resetCrossingType.injectClockNode := domain.clockNode } } + + /** Function to handle all trace crossings when tile is instantiated inside domains */ + def connectTrace(domain: TilePRCIDomain[TileType], context: TileContextType): Unit = { + implicit val p = context.p + val traceCrossingNode = BundleBridgeBlockDuringReset[TraceBundle]( + resetCrossingType = crossingParams.resetCrossingType) + context.traceNodes(domain.element.tileId) := traceCrossingNode := domain.element.traceNode + val traceCoreCrossingNode = BundleBridgeBlockDuringReset[TraceCoreInterface]( + resetCrossingType = crossingParams.resetCrossingType) + context.traceCoreNodes(domain.element.tileId) :*= traceCoreCrossingNode := domain.element.traceCoreNode + } } case class CloneTileAttachParams( - sourceHart: Int, + sourceTileId: Int, cloneParams: CanAttachTile ) extends CanAttachTile { type TileType = cloneParams.TileType @@ -382,78 +312,18 @@ case class CloneTileAttachParams( def tileParams = cloneParams.tileParams def crossingParams = cloneParams.crossingParams - require(sourceHart < tileParams.hartId) - override def instantiate(allTileParams: Seq[TileParams], instantiatedTiles: Seq[TilePRCIDomain[_]])(implicit p: Parameters): TilePRCIDomain[TileType] = { - val clockSinkParams = tileParams.clockSinkParams.copy(name = Some(s"${tileParams.name.getOrElse("core")}_${tileParams.hartId}")) + override def instantiate(allTileParams: Seq[TileParams], instantiatedTiles: SortedMap[Int, TilePRCIDomain[_]])(implicit p: Parameters): TilePRCIDomain[TileType] = { + require(instantiatedTiles.contains(sourceTileId)) + val clockSinkParams = tileParams.clockSinkParams.copy(name = Some(tileParams.uniqueName)) val tile_prci_domain = CloneLazyModule( new TilePRCIDomain[TileType](clockSinkParams, crossingParams) { self => - val tile = self.tile_reset_domain { LazyModule(tileParams.instantiate(crossingParams, PriorityMuxHartIdFromSeq(allTileParams))) } + val element = self.element_reset_domain { LazyModule(tileParams.instantiate(crossingParams, PriorityMuxHartIdFromSeq(allTileParams))) } }, - instantiatedTiles(sourceHart).asInstanceOf[TilePRCIDomain[TileType]] + instantiatedTiles(sourceTileId).asInstanceOf[TilePRCIDomain[TileType]] ) - tile_prci_domain - } -} - - -/** InstantiatesTiles adds a Config-urable sequence of tiles of any type - * to the subsystem class into which it is mixed. - */ -trait InstantiatesTiles { this: BaseSubsystem => - /** Record the order in which to instantiate all tiles, based on statically-assigned ids. - * - * Note that these ids, which are often used as the tiles' default hartid input, - * may or may not be those actually reflected at runtime in e.g. the $mhartid CSR - */ - val tileAttachParams: Seq[CanAttachTile] = p(TilesLocated(location)).sortBy(_.tileParams.hartId) - val tileParams: Seq[TileParams] = tileAttachParams.map(_.tileParams) - val tileCrossingTypes: Seq[ClockCrossingType] = tileAttachParams.map(_.crossingParams.crossingType) - - /** The actual list of instantiated tiles in this subsystem. */ - val tile_prci_domains: Seq[TilePRCIDomain[_]] = tileAttachParams.foldLeft(Seq[TilePRCIDomain[_]]()) { - case (instantiated, params) => instantiated :+ params.instantiate(tileParams, instantiated)(p) - } - - val tiles: Seq[BaseTile] = tile_prci_domains.map(_.tile.asInstanceOf[BaseTile]) - - // Helper functions for accessing certain parameters that are popular to refer to in subsystem code - def nTiles: Int = tileAttachParams.size - def hartIdList: Seq[Int] = tileParams.map(_.hartId) - def localIntCounts: Seq[Int] = tileParams.map(_.core.nLocalInterrupts) - - require(hartIdList.distinct.size == tiles.size, s"Every tile must be statically assigned a unique id, but got:\n${hartIdList}") -} - -/** HasTiles instantiates and also connects a Config-urable sequence of tiles of any type to subsystem interconnect resources. */ -trait HasTiles extends InstantiatesTiles with HasCoreMonitorBundles with DefaultTileContextType -{ this: BaseSubsystem => // TODO: ideally this bound would be softened to Attachable - implicit val p: Parameters - - // connect all the tiles to interconnect attachment points made available in this subsystem context - tileAttachParams.zip(tile_prci_domains).foreach { case (params, td) => - params.connect(td.asInstanceOf[TilePRCIDomain[params.TileType]], this.asInstanceOf[params.TileContextType]) + tile_prci_domain } } -/** Provides some Chisel connectivity to certain tile IOs */ -trait HasTilesModuleImp extends LazyModuleImp { - val outer: HasTiles with HasTileInterruptSources with HasTileInputConstants - - val reset_vector = outer.tileResetVectorIONodes.zipWithIndex.map { case (n, i) => n.makeIO(s"reset_vector_$i") } - val tile_hartids = outer.tileHartIdIONodes.zipWithIndex.map { case (n, i) => n.makeIO(s"tile_hartids_$i") } - val meip = if(outer.meipNode.isDefined) Some(IO(Input(Vec(outer.meipNode.get.out.size, Bool())))) else None - meip.foreach { m => - m.zipWithIndex.foreach{ case (pin, i) => - (outer.meipNode.get.out(i)._1)(0) := pin - } - } - val seip = if(outer.seipNode.isDefined) Some(IO(Input(Vec(outer.seipNode.get.out.size, Bool())))) else None - seip.foreach { s => - s.zipWithIndex.foreach{ case (pin, i) => - (outer.seipNode.get.out(i)._1)(0) := pin - } - } - val nmi = outer.tiles.zip(outer.tileNMIIONodes).zipWithIndex.map { case ((tile, n), i) => tile.tileParams.core.useNMI.option(n.makeIO(s"nmi_$i")) } -} diff --git a/src/main/scala/subsystem/HierarchicalElement.scala b/src/main/scala/subsystem/HierarchicalElement.scala new file mode 100644 index 00000000000..861a77970e1 --- /dev/null +++ b/src/main/scala/subsystem/HierarchicalElement.scala @@ -0,0 +1,82 @@ +package freechips.rocketchip.subsystem + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.TLDebugModule +import freechips.rocketchip.diplomacy.{BufferParams} +import freechips.rocketchip.interrupts.IntXbar +import freechips.rocketchip.prci.{ClockSinkParameters, ResetCrossingType, ClockCrossingType} +import freechips.rocketchip.tile.{LookupByHartIdImpl, TraceBundle} +import freechips.rocketchip.tilelink.{TLNode, TLIdentityNode, TLXbar, TLBuffer, TLInwardNode, TLOutwardNode} + +trait HierarchicalElementParams { + val baseName: String // duplicated instances shouuld share a base name + val uniqueName: String + val clockSinkParams: ClockSinkParameters +} + +abstract class InstantiableHierarchicalElementParams[ElementType <: BaseHierarchicalElement] extends HierarchicalElementParams + +/** An interface for describing the parameteization of how HierarchicalElements are connected to interconnects */ +trait HierarchicalElementCrossingParamsLike { + /** The type of clock crossing that should be inserted at the element boundary. */ + def crossingType: ClockCrossingType + /** Parameters describing the contents and behavior of the point where the element is attached as an interconnect master. */ + def master: HierarchicalElementPortParamsLike + /** Parameters describing the contents and behavior of the point where the element is attached as an interconnect slave. */ + def slave: HierarchicalElementPortParamsLike + /** The subnetwork location of the device selecting the apparent base address of MMIO devices inside the element */ + def mmioBaseAddressPrefixWhere: TLBusWrapperLocation + /** Inject a reset management subgraph that effects the element child reset only */ + def resetCrossingType: ResetCrossingType + /** Keep the element clock separate from the interconnect clock (e.g. even if they are synchronous to one another) */ + def forceSeparateClockReset: Boolean +} + +/** An interface for describing the parameterization of how a particular element port is connected to an interconnect */ +trait HierarchicalElementPortParamsLike { + /** The subnetwork location of the interconnect to which this element port should be connected. */ + def where: TLBusWrapperLocation + /** Allows port-specific adapters to be injected into the interconnect side of the attachment point. */ + def injectNode(context: Attachable)(implicit p: Parameters): TLNode +} + +abstract class BaseHierarchicalElement (val crossing: ClockCrossingType)(implicit p: Parameters) + extends LazyModule()(p) + with CrossesToOnlyOneClockDomain +{ + def module: BaseHierarchicalElementModuleImp[BaseHierarchicalElement] + + protected val tlOtherMastersNode = TLIdentityNode() + protected val tlMasterXbar = LazyModule(new TLXbar(nameSuffix = Some(s"MasterXbar_$desiredName"))) + protected val tlSlaveXbar = LazyModule(new TLXbar(nameSuffix = Some(s"SlaveXbar_$desiredName"))) + protected val intXbar = LazyModule(new IntXbar) + + def masterNode: TLOutwardNode + def slaveNode: TLInwardNode + + /** Helper function to insert additional buffers on master ports at the boundary of the tile. + * + * The boundary buffering needed to cut feed-through paths is + * microarchitecture specific, so this may need to be overridden + * in subclasses of this class. + */ + def makeMasterBoundaryBuffers(crossing: ClockCrossingType)(implicit p: Parameters) = TLBuffer(BufferParams.none) + + /** Helper function to insert additional buffers on slave ports at the boundary of the tile. + * + * The boundary buffering needed to cut feed-through paths is + * microarchitecture specific, so this may need to be overridden + * in subclasses of this class. + */ + def makeSlaveBoundaryBuffers(crossing: ClockCrossingType)(implicit p: Parameters) = TLBuffer(BufferParams.none) + + +} + +abstract class BaseHierarchicalElementModuleImp[+L <: BaseHierarchicalElement](val outer: L) extends LazyModuleImp(outer) + diff --git a/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala b/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala new file mode 100644 index 00000000000..b38f208701e --- /dev/null +++ b/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala @@ -0,0 +1,100 @@ +package freechips.rocketchip.subsystem + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.debug.TLDebugModule +import freechips.rocketchip.diplomacy.{DisableMonitors, FlipRendering} +import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode} +import freechips.rocketchip.prci.{ClockCrossingType, ResetCrossingType, ResetDomain, ClockSinkNode, ClockSinkParameters, ClockIdentityNode, FixedClockBroadcast, ClockDomain} +import freechips.rocketchip.tile.{RocketTile, TraceBundle} +import freechips.rocketchip.tilelink.{TLInwardNode, TLOutwardNode} +import freechips.rocketchip.util.TraceCoreInterface + +import freechips.rocketchip.tilelink.TLClockDomainCrossing +import freechips.rocketchip.tilelink.TLResetDomainCrossing +import freechips.rocketchip.interrupts.IntClockDomainCrossing +import freechips.rocketchip.interrupts.IntResetDomainCrossing + +/** A wrapper containing all logic within a managed reset domain for a element. + * + * This does not add a layer of the module hierarchy. + */ +class HierarchicalElementResetDomain(clockSinkParams: ClockSinkParameters, resetCrossingType: ResetCrossingType) + (implicit p: Parameters) + extends ResetDomain + with CrossesToOnlyOneResetDomain +{ + def crossing = resetCrossingType + val clockNode = ClockSinkNode(Seq(clockSinkParams)) + def clockBundle = clockNode.in.head._1 + override def shouldBeInlined = true +} + +/** A wrapper containing all logic necessary to safely place a tile + * inside of a particular Power/Reset/Clock/Interrupt domain. + * + * This adds a layer to the module hierarchy which is a parent of the tile + * and should contain all logic related to clock crossings, isolation cells, + * hierarchical P&R boundary buffers, core-local interrupt handling, + * and any other IOs related to PRCI control. + */ +abstract class HierarchicalElementPRCIDomain[T <: BaseHierarchicalElement]( + clockSinkParams: ClockSinkParameters, + crossingParams: HierarchicalElementCrossingParamsLike) + (implicit p: Parameters) + extends ClockDomain +{ + val element: T + val element_reset_domain = LazyModule(new HierarchicalElementResetDomain(clockSinkParams, crossingParams.resetCrossingType)) + val tapClockNode = ClockIdentityNode() + val clockNode = FixedClockBroadcast() :=* tapClockNode + lazy val clockBundle = tapClockNode.in.head._1 + + /** External code looking to connect and clock-cross the interrupts driven into this tile can call this. */ + def crossIntIn(crossingType: ClockCrossingType, tileNode: IntInwardNode): IntInwardNode = { + // Unlike the other crossing helpers, here nothing is is blocked during reset because we know these are inputs and assume that tile reset is longer than uncore reset + val intInClockXing = this.crossIn(tileNode) + intInClockXing(crossingType) + } + + /** External code looking to connect and clock/reset-cross + * - interrupts raised by devices inside this tile + * - notifications raise by the cores and caches + * can call this function to instantiate the required crossing hardware. + * Takes crossingType as an argument because some interrupts are supposed to be synchronous + * Takes tileNode as an argument because tiles might have multiple outbound interrupt nodes + */ + def crossIntOut(crossingType: ClockCrossingType, tileNode: IntOutwardNode): IntOutwardNode = { + val intOutResetXing = this { element_reset_domain.crossIntOut(tileNode) } + val intOutClockXing = this.crossOut(intOutResetXing) + intOutClockXing(crossingType) + } + + /** External code looking to connect the ports where this tile is slaved to an interconnect + * (while also crossing clock domains) can call this. + */ + def crossSlavePort(crossingType: ClockCrossingType): TLInwardNode = { DisableMonitors { implicit p => FlipRendering { implicit p => + val tlSlaveResetXing = this { + element_reset_domain.crossTLIn(element.slaveNode) :*= + element { element.makeSlaveBoundaryBuffers(crossingType) } + } + val tlSlaveClockXing = this.crossIn(tlSlaveResetXing) + tlSlaveClockXing(crossingType) + } } } + + /** External code looking to connect the ports where this tile masters an interconnect + * (while also crossing clock domains) can call this. + */ + def crossMasterPort(crossingType: ClockCrossingType): TLOutwardNode = { + val tlMasterResetXing = this { DisableMonitors { implicit p => + element { element.makeMasterBoundaryBuffers(crossingType) } :=* + element_reset_domain.crossTLOut(element.masterNode) + } } + val tlMasterClockXing = this.crossOut(tlMasterResetXing) + tlMasterClockXing(crossingType) + } +} diff --git a/src/main/scala/subsystem/InterruptBus.scala b/src/main/scala/subsystem/InterruptBus.scala index e50f82a9ad5..24717df3e76 100644 --- a/src/main/scala/subsystem/InterruptBus.scala +++ b/src/main/scala/subsystem/InterruptBus.scala @@ -3,10 +3,15 @@ package freechips.rocketchip.subsystem import chisel3._ -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.prci.{ClockSinkDomain} + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.resources.{Device, DeviceInterrupts, Description, ResourceBindings} +import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode, IntXbar, IntNameNode, IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.prci.{ClockCrossingType, AsynchronousCrossing, RationalCrossing, ClockSinkDomain} + +import freechips.rocketchip.interrupts.IntClockDomainCrossing /** Collects interrupts from internal and external devices and feeds them into the PLIC */ class InterruptBusWrapper(implicit p: Parameters) extends ClockSinkDomain { @@ -45,7 +50,7 @@ abstract trait HasExtInterrupts { this: BaseSubsystem => */ trait HasAsyncExtInterrupts extends HasExtInterrupts { this: BaseSubsystem => if (nExtInterrupts > 0) { - ibus.fromAsync := extInterrupts + ibus { ibus.fromAsync := extInterrupts } } } @@ -54,7 +59,7 @@ trait HasAsyncExtInterrupts extends HasExtInterrupts { this: BaseSubsystem => */ trait HasSyncExtInterrupts extends HasExtInterrupts { this: BaseSubsystem => if (nExtInterrupts > 0) { - ibus.fromSync := extInterrupts + ibus { ibus.fromSync := extInterrupts } } } @@ -70,7 +75,7 @@ trait HasExtInterruptsBundle { /** This trait performs the translation from a UInt IO into Diplomatic Interrupts. * The wiring must be done in the concrete LazyModuleImp. */ -trait HasExtInterruptsModuleImp extends LazyModuleImp with HasExtInterruptsBundle { +trait HasExtInterruptsModuleImp extends LazyRawModuleImp with HasExtInterruptsBundle { val outer: HasExtInterrupts val interrupts = IO(Input(UInt(outer.nExtInterrupts.W))) diff --git a/src/main/scala/subsystem/LookupByClusterId.scala b/src/main/scala/subsystem/LookupByClusterId.scala new file mode 100644 index 00000000000..d0c5c21a5ab --- /dev/null +++ b/src/main/scala/subsystem/LookupByClusterId.scala @@ -0,0 +1,19 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.subsystem + +import chisel3._ +import chisel3.util._ + +abstract class LookupByClusterIdImpl { + def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T +} + +case class ClustersWontDeduplicate(t: ClusterParams) extends LookupByClusterIdImpl { + def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T = f(t).get +} + +case class PriorityMuxClusterIdFromSeq(seq: Seq[ClusterParams]) extends LookupByClusterIdImpl { + def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T = + PriorityMux(seq.collect { case t if f(t).isDefined => (t.clusterId.U === clusterId) -> f(t).get }) +} diff --git a/src/main/scala/subsystem/MemoryBus.scala b/src/main/scala/subsystem/MemoryBus.scala index 03b8bb22d4b..a58d6b28215 100644 --- a/src/main/scala/subsystem/MemoryBus.scala +++ b/src/main/scala/subsystem/MemoryBus.scala @@ -3,10 +3,15 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.tilelink.{BuiltInDevices, HasBuiltInDeviceParams, BuiltInErrorDeviceParams, BuiltInZeroDeviceParams} +import freechips.rocketchip.tilelink.{ + ReplicatedRegion, HasTLBusParams, HasRegionReplicatorParams, TLBusWrapper, + TLBusWrapperInstantiationLike, RegionReplicator, TLXbar, TLInwardNode, + TLOutwardNode, ProbePicker, TLEdge, TLFIFOFixer +} +import freechips.rocketchip.util.Location /** Parameterization of the memory-side bus created for each memory channel */ case class MemoryBusParams( @@ -39,7 +44,7 @@ class MemoryBus(params: MemoryBusParams, name: String = "memory_bus")(implicit p addressPrefixNexusNode } - private val xbar = LazyModule(new TLXbar).suggestName(busName + "_xbar") + private val xbar = LazyModule(new TLXbar(nameSuffix = Some(name))).suggestName(busName + "_xbar") val inwardNode: TLInwardNode = replicator.map(xbar.node :*=* TLFIFOFixer(TLFIFOFixer.all) :*=* _.node) .getOrElse(xbar.node :*=* TLFIFOFixer(TLFIFOFixer.all)) diff --git a/src/main/scala/subsystem/PeripheryBus.scala b/src/main/scala/subsystem/PeripheryBus.scala index 830e4480925..ee8ccec015e 100644 --- a/src/main/scala/subsystem/PeripheryBus.scala +++ b/src/main/scala/subsystem/PeripheryBus.scala @@ -2,11 +2,17 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.tilelink.{BuiltInZeroDeviceParams, BuiltInErrorDeviceParams, HasBuiltInDeviceParams, BuiltInDevices} +import freechips.rocketchip.diplomacy.BufferParams +import freechips.rocketchip.tilelink.{ + RegionReplicator, ReplicatedRegion, HasTLBusParams, HasRegionReplicatorParams, TLBusWrapper, + TLBusWrapperInstantiationLike, TLFIFOFixer, TLNode, TLXbar, TLInwardNode, TLOutwardNode, + TLBuffer, TLWidthWidget, TLAtomicAutomata, TLEdge +} +import freechips.rocketchip.util.Location case class BusAtomics( arithmetic: Boolean = true, @@ -38,6 +44,7 @@ case class PeripheryBusParams( class PeripheryBus(params: PeripheryBusParams, name: String)(implicit p: Parameters) extends TLBusWrapper(params, name) { + override lazy val desiredName = s"PeripheryBus_$name" private val replicator = params.replication.map(r => LazyModule(new RegionReplicator(r))) val prefixNode = replicator.map { r => r.prefix := addressPrefixNexusNode @@ -46,15 +53,15 @@ class PeripheryBus(params: PeripheryBusParams, name: String)(implicit p: Paramet private val fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all)) private val node: TLNode = params.atomics.map { pa => - val in_xbar = LazyModule(new TLXbar) - val out_xbar = LazyModule(new TLXbar) + val in_xbar = LazyModule(new TLXbar(nameSuffix = Some(s"${name}_in"))) + val out_xbar = LazyModule(new TLXbar(nameSuffix = Some(s"${name}_out"))) val fixer_node = replicator.map(fixer.node :*= _.node).getOrElse(fixer.node) (out_xbar.node :*= fixer_node :*= TLBuffer(pa.buffer) :*= (pa.widenBytes.filter(_ > beatBytes).map { w => - TLWidthWidget(w) :*= TLAtomicAutomata(arithmetic = pa.arithmetic) - } .getOrElse { TLAtomicAutomata(arithmetic = pa.arithmetic) }) + TLWidthWidget(w) :*= TLAtomicAutomata(arithmetic = pa.arithmetic, nameSuffix = Some(name)) + } .getOrElse { TLAtomicAutomata(arithmetic = pa.arithmetic, nameSuffix = Some(name)) }) :*= in_xbar.node) } .getOrElse { TLXbar() :*= fixer.node } diff --git a/src/main/scala/subsystem/Ports.scala b/src/main/scala/subsystem/Ports.scala index 89fc25376fd..d3ed70c5e98 100644 --- a/src/main/scala/subsystem/Ports.scala +++ b/src/main/scala/subsystem/Ports.scala @@ -4,11 +4,31 @@ package freechips.rocketchip.subsystem import chisel3._ -import org.chipsalliance.cde.config.Field -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.amba.axi4._ -import freechips.rocketchip.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.axi4.{ + AXI4SlaveNode, AXI4SlavePortParameters, AXI4SlaveParameters, AXI4UserYanker, AXI4Buffer, + AXI4Deinterleaver, AXI4IdIndexer, AXI4MasterNode, AXI4MasterPortParameters, AXI4ToTL, + AXI4Fragmenter, AXI4MasterParameters +} +import freechips.rocketchip.diplomacy.{ + AddressSet, RegionType, TransferSizes, IdRange, BufferParams +} +import freechips.rocketchip.resources.{ + MemoryDevice, SimpleBus +} +import freechips.rocketchip.tilelink.{ + TLXbar, RegionReplicator, ReplicatedRegion, TLWidthWidget, TLFilter, TLToAXI4, TLBuffer, + TLFIFOFixer, TLSlavePortParameters, TLManagerNode, TLSlaveParameters, TLClientNode, + TLSourceShrinker, TLMasterParameters, TLMasterPortParameters +} +import freechips.rocketchip.util.StringToAugmentedString + +import freechips.rocketchip.tilelink.TLClockDomainCrossing +import freechips.rocketchip.tilelink.TLResetDomainCrossing /** Specifies the size and width of external memory ports */ case class MasterPortParams( @@ -36,6 +56,7 @@ trait CanHaveMasterAXI4MemPort { this: BaseSubsystem => private val portName = "axi4" private val device = new MemoryDevice private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1) + private val mbus = tlBusWrapperLocationMap.get(MBUS).getOrElse(viewpointBus) val memAXI4Node = AXI4SlaveNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels, _) => Seq.tabulate(nMemoryChannels) { channel => @@ -63,7 +84,7 @@ trait CanHaveMasterAXI4MemPort { this: BaseSubsystem => memPortParams.incohBase.foreach(incohBase => { val cohRegion = AddressSet(0, incohBase-1) val incohRegion = AddressSet(incohBase, incohBase-1) - val replicator = sbus { + val replicator = tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location))) { val replicator = LazyModule(new RegionReplicator(ReplicatedRegion(cohRegion, cohRegion.widen(incohBase)))) val prefixSource = BundleBridgeSource[UInt](() => UInt(1.W)) replicator.prefix := prefixSource @@ -71,9 +92,9 @@ trait CanHaveMasterAXI4MemPort { this: BaseSubsystem => InModuleBody { prefixSource.bundle := 0.U(1.W) } replicator } - sbus.coupleTo(s"memory_controller_bypass_port_named_$portName") { + viewpointBus.coupleTo(s"memory_controller_bypass_port_named_$portName") { (mbus.crossIn(mem_bypass_xbar)(ValName("bus_xing"))(p(SbusToMbusXTypeKey)) - := TLWidthWidget(sbus.beatBytes) + := TLWidthWidget(viewpointBus.beatBytes) := replicator.node := TLFilter(TLFilter.mSubtract(cohRegion)) := TLFilter(TLFilter.mResourceRemover) @@ -116,14 +137,14 @@ trait CanHaveMasterAXI4MMIOPort { this: BaseSubsystem => beatBytes = params.beatBytes)).toSeq) mmioPortParamsOpt.map { params => - sbus.coupleTo(s"port_named_$portName") { + viewpointBus.coupleTo(s"port_named_$portName") { (mmioAXI4Node := AXI4Buffer() := AXI4UserYanker() - := AXI4Deinterleaver(sbus.blockBytes) + := AXI4Deinterleaver(viewpointBus.blockBytes) := AXI4IdIndexer(params.idBits) := TLToAXI4() - := TLWidthWidget(sbus.beatBytes) + := TLWidthWidget(viewpointBus.beatBytes) := _) } } @@ -136,6 +157,7 @@ trait CanHaveSlaveAXI4Port { this: BaseSubsystem => private val slavePortParamsOpt = p(ExtIn) private val portName = "slave_port_axi4" private val fifoBits = 1 + private val fbus = tlBusWrapperLocationMap.get(FBUS).getOrElse(viewpointBus) val l2FrontendAXI4Node = AXI4MasterNode( slavePortParamsOpt.map(params => @@ -174,17 +196,17 @@ trait CanHaveMasterTLMMIOPort { this: BaseSubsystem => address = AddressSet.misaligned(params.base, params.size), resources = device.ranges, executable = params.executable, - supportsGet = TransferSizes(1, sbus.blockBytes), - supportsPutFull = TransferSizes(1, sbus.blockBytes), - supportsPutPartial = TransferSizes(1, sbus.blockBytes))), + supportsGet = TransferSizes(1, viewpointBus.blockBytes), + supportsPutFull = TransferSizes(1, viewpointBus.blockBytes), + supportsPutPartial = TransferSizes(1, viewpointBus.blockBytes))), beatBytes = params.beatBytes)).toSeq) mmioPortParamsOpt.map { params => - sbus.coupleTo(s"port_named_$portName") { + viewpointBus.coupleTo(s"port_named_$portName") { (mmioTLNode := TLBuffer() := TLSourceShrinker(1 << params.idBits) - := TLWidthWidget(sbus.beatBytes) + := TLWidthWidget(viewpointBus.beatBytes) := _ ) } } @@ -210,7 +232,7 @@ trait CanHaveSlaveTLPort { this: BaseSubsystem => sourceId = IdRange(0, 1 << params.idBits))))).toSeq) slavePortParamsOpt.map { params => - sbus.coupleFrom(s"port_named_$portName") { + viewpointBus.coupleFrom(s"port_named_$portName") { ( _ := TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes) diff --git a/src/main/scala/subsystem/RTC.scala b/src/main/scala/subsystem/RTC.scala index 499633f679a..c2fd7a5a3f2 100644 --- a/src/main/scala/subsystem/RTC.scala +++ b/src/main/scala/subsystem/RTC.scala @@ -3,27 +3,32 @@ package freechips.rocketchip.subsystem import chisel3._ -import chisel3.util.Counter -import freechips.rocketchip.diplomacy.{LazyModuleImp, DTSTimebase} -import freechips.rocketchip.devices.tilelink.CanHavePeripheryCLINT +import chisel3.util._ -trait HasRTCModuleImp extends LazyModuleImp { - val outer: BaseSubsystem with CanHavePeripheryCLINT - private val pbusFreq = outer.p(PeripheryBusKey).dtsFrequency.get - private val rtcFreq = outer.p(DTSTimebase) - private val internalPeriod: BigInt = pbusFreq / rtcFreq +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.resources.DTSTimebase +import freechips.rocketchip.devices.tilelink.{CLINTAttachKey, CanHavePeripheryCLINT} - val pbus = outer.locateTLBusWrapper(PBUS) - // check whether pbusFreq >= rtcFreq - require(internalPeriod > 0) - // check wehther the integer division is within 5% of the real division - require((pbusFreq - rtcFreq * internalPeriod) * 100 / pbusFreq <= 5) +trait HasRTCModuleImp extends LazyRawModuleImp { + val outer: BaseSubsystem with CanHavePeripheryCLINT // Use the static period to toggle the RTC - chisel3.withClockAndReset(pbus.module.clock, pbus.module.reset) { - val (_, int_rtc_tick) = Counter(true.B, internalPeriod.toInt) - outer.clintOpt.foreach { clint => - clint.module.io.rtcTick := int_rtc_tick + outer.clintDomainOpt.map { domain => { + val bus = outer.locateTLBusWrapper(p(CLINTAttachKey).slaveWhere) + val busFreq = bus.dtsFrequency.get + val rtcFreq = outer.p(DTSTimebase) + val internalPeriod: BigInt = busFreq / rtcFreq + + + // check whether pbusFreq >= rtcFreq + require(internalPeriod > 0) + // check wehther the integer division is within 5% of the real division + require((busFreq - rtcFreq * internalPeriod) * 100 / busFreq <= 5) + + withClockAndReset (domain.module.clock, domain.module.reset) { + val (_, int_rtc_tick) = Counter(true.B, internalPeriod.toInt) + outer.clintTickOpt.foreach { _ := int_rtc_tick } } - } + }} } diff --git a/src/main/scala/subsystem/RocketSubsystem.scala b/src/main/scala/subsystem/RocketSubsystem.scala index e9e1f555515..a10903d050f 100644 --- a/src/main/scala/subsystem/RocketSubsystem.scala +++ b/src/main/scala/subsystem/RocketSubsystem.scala @@ -2,37 +2,54 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing} -import freechips.rocketchip.tile._ -import freechips.rocketchip.devices.debug.{HasPeripheryDebug} +import org.chipsalliance.cde.config._ + +import freechips.rocketchip.devices.debug.HasPeripheryDebug +import freechips.rocketchip.devices.tilelink.{CanHavePeripheryCLINT, CanHavePeripheryPLIC} +import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, SynchronousCrossing, ClockCrossingType} +import freechips.rocketchip.tile.{RocketTile, RocketTileParams} +import freechips.rocketchip.util.HasCoreMonitorBundles case class RocketCrossingParams( crossingType: ClockCrossingType = SynchronousCrossing(), - master: TilePortParamsLike = TileMasterPortParams(), - slave: TileSlavePortParams = TileSlavePortParams(), + master: HierarchicalElementPortParamsLike = HierarchicalElementMasterPortParams(), + slave: HierarchicalElementSlavePortParams = HierarchicalElementSlavePortParams(), mmioBaseAddressPrefixWhere: TLBusWrapperLocation = CBUS, resetCrossingType: ResetCrossingType = NoResetCrossing(), forceSeparateClockReset: Boolean = false -) extends TileCrossingParamsLike +) extends HierarchicalElementCrossingParamsLike case class RocketTileAttachParams( tileParams: RocketTileParams, crossingParams: RocketCrossingParams ) extends CanAttachTile { type TileType = RocketTile } -trait HasRocketTiles extends HasTiles { this: BaseSubsystem => - val rocketTiles = tiles.collect { case r: RocketTile => r } +trait HasRocketTiles { + this: BaseSubsystem with InstantiatesHierarchicalElements => + val rocketTiles = totalTiles.values.collect { case r: RocketTile => r } def coreMonitorBundles = (rocketTiles map { t => t.module.core.rocketImpl.coreMonitorBundle }).toList } -class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem with HasRocketTiles with HasPeripheryDebug { +class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem + with InstantiatesHierarchicalElements + with HasTileNotificationSinks + with HasTileInputConstants + with CanHavePeripheryCLINT + with CanHavePeripheryPLIC + with HasPeripheryDebug + with HasHierarchicalElementsRootContext + with HasHierarchicalElements + with HasCoreMonitorBundles + with HasRocketTiles +{ override lazy val module = new RocketSubsystemModuleImp(this) } class RocketSubsystemModuleImp[+L <: RocketSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) - with HasTilesModuleImp + with HasHierarchicalElementsRootContextModuleImp { + override lazy val outer = _outer +} + diff --git a/src/main/scala/subsystem/SystemBus.scala b/src/main/scala/subsystem/SystemBus.scala index 3d8f98203fb..3596feb01e0 100644 --- a/src/main/scala/subsystem/SystemBus.scala +++ b/src/main/scala/subsystem/SystemBus.scala @@ -2,11 +2,18 @@ package freechips.rocketchip.subsystem -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.tilelink.{ + BuiltInDevices, BuiltInZeroDeviceParams, BuiltInErrorDeviceParams, HasBuiltInDeviceParams +} +import freechips.rocketchip.tilelink.{ + TLArbiter, RegionReplicator, ReplicatedRegion, HasTLBusParams, TLBusWrapper, + TLBusWrapperInstantiationLike, TLXbar, TLEdge, TLInwardNode, TLOutwardNode, + TLFIFOFixer, TLTempNode +} +import freechips.rocketchip.util.Location case class SystemBusParams( beatBytes: Int, @@ -37,7 +44,7 @@ class SystemBus(params: SystemBusParams, name: String = "system_bus")(implicit p addressPrefixNexusNode } - private val system_bus_xbar = LazyModule(new TLXbar(policy = params.policy)) + private val system_bus_xbar = LazyModule(new TLXbar(policy = params.policy, nameSuffix = Some(name))) val inwardNode: TLInwardNode = system_bus_xbar.node :=* TLFIFOFixer(TLFIFOFixer.allVolatile) :=* replicator.map(_.node).getOrElse(TLTempNode()) val outwardNode: TLOutwardNode = system_bus_xbar.node def busView: TLEdge = system_bus_xbar.node.edges.in.head diff --git a/src/main/scala/system/Configs.scala b/src/main/scala/system/Configs.scala index 9fb7debde82..19e3c174b23 100644 --- a/src/main/scala/system/Configs.scala +++ b/src/main/scala/system/Configs.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.system import org.chipsalliance.cde.config.Config import freechips.rocketchip.subsystem._ +import freechips.rocketchip.rocket.{WithNBigCores, WithNMedCores, WithNSmallCores, WithRV32, WithFP16, WithHypervisor, With1TinyCore, WithScratchpadsOnly, WithCloneRocketTiles, WithB} class WithJtagDTMSystem extends freechips.rocketchip.subsystem.WithJtagDTM class WithDebugSBASystem extends freechips.rocketchip.subsystem.WithDebugSBA @@ -26,6 +27,8 @@ class DefaultBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ n class DefaultSmallConfig extends Config(new WithNSmallCores(1) ++ new WithCoherentBusTopology ++ new BaseConfig) class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig) class DefaultFP16Config extends Config(new WithFP16 ++ new DefaultConfig) +class DefaultBConfig extends Config(new WithB ++ new DefaultConfig) +class DefaultRV32BConfig extends Config(new WithB ++ new DefaultRV32Config) class HypervisorConfig extends Config(new WithHypervisor ++ new DefaultConfig) @@ -34,6 +37,17 @@ class DualCoreConfig extends Config(new WithNBigCores(2) ++ new WithCoherentBusT class DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new DefaultConfig) class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new DefaultConfig) +class ClusterConfig extends Config( + new WithNBigCores(2, InCluster(3)) ++ + new WithNBigCores(2, InCluster(1)) ++ + new WithNBigCores(2, InCluster(0)) ++ + new WithCluster(3, location=InCluster(2)) ++ + new WithCluster(2) ++ + new WithCluster(1) ++ + new WithCluster(0) ++ + new DefaultConfig +) + class DualChannelDualBankConfig extends Config( new WithNMemoryChannels(2) ++ new WithNBanks(4) ++ new DefaultConfig diff --git a/src/main/scala/system/RocketTestSuite.scala b/src/main/scala/system/RocketTestSuite.scala index d26c5fcfc75..f188d3cd7b3 100644 --- a/src/main/scala/system/RocketTestSuite.scala +++ b/src/main/scala/system/RocketTestSuite.scala @@ -159,6 +159,23 @@ object DefaultTestSuites { val rv64uzfhNames = rv64ufNames val rv64uzfh = new AssemblyTestSuite("rv64uzfh", rv64uzfhNames)(_) + val rv32uzbaNames = LinkedHashSet("sh1add", "sh2add", "sh3add") + val rv32uzba = new AssemblyTestSuite("rv32uzba", rv32uzbaNames)(_) + + val rv64uzbaNames = rv32uzbaNames ++ rv32uzbaNames.map(_ + "_uw") + "add_uw" + "slli_uw" + val rv64uzba = new AssemblyTestSuite("rv64uzba", rv64uzbaNames)(_) + + val rv32uzbbNames = LinkedHashSet("andn", "clz", "cpop", "ctz", "max", "maxu", "min", "minu", "orc_b", "orn", "rev8", "rol", "ror", "rori", "sext_b", "sext_h", "xnor", "zext_h") + val rv32uzbb = new AssemblyTestSuite("rv32uzbb", rv32uzbbNames)(_) + + val rv64uzbbNames = rv32uzbbNames + "clzw" + "cpopw" + "ctzw" + "rolw" + "roriw" + val rv64uzbb = new AssemblyTestSuite("rv64uzbb", rv64uzbbNames)(_) + + val rv32uzbsNames = LinkedHashSet("bclr", "bclri", "bext", "bexti", "binv", "binvi", "bset", "bseti") + val rv32uzbs = new AssemblyTestSuite("rv32uzbs", rv32uzbsNames)(_) + + val rv64uzbsNames = rv32uzbsNames + val rv64uzbs = new AssemblyTestSuite("rv64uzbs", rv64uzbsNames)(_) val rv64siNames = rv32siNames + "icache-alias" val rv64si = new AssemblyTestSuite("rv64si", rv64siNames)(_) diff --git a/src/main/scala/system/SimAXIMem.scala b/src/main/scala/system/SimAXIMem.scala index a0238522641..f0a08e6d5b8 100644 --- a/src/main/scala/system/SimAXIMem.scala +++ b/src/main/scala/system/SimAXIMem.scala @@ -3,10 +3,13 @@ package freechips.rocketchip.system // TODO this should really be in a testharness package import chisel3._ -import freechips.rocketchip.amba._ -import freechips.rocketchip.amba.axi4._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.amba.AMBACorrupt +import freechips.rocketchip.amba.axi4.{AXI4RAM, AXI4MasterNode, AXI4EdgeParameters, AXI4Xbar, AXI4Buffer, AXI4Fragmenter} +import freechips.rocketchip.diplomacy.AddressSet import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MMIOPort, CanHaveMasterAXI4MemPort, ExtBus, ExtMem} /** Memory with AXI port for use in elaboratable test harnesses. diff --git a/src/main/scala/system/TestHarness.scala b/src/main/scala/system/TestHarness.scala index a1e37dea169..80c711880aa 100644 --- a/src/main/scala/system/TestHarness.scala +++ b/src/main/scala/system/TestHarness.scala @@ -3,9 +3,11 @@ package freechips.rocketchip.system import chisel3._ -import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.devices.debug.Debug -import freechips.rocketchip.diplomacy.LazyModule import freechips.rocketchip.util.AsyncResetReg class TestHarness()(implicit p: Parameters) extends Module { @@ -16,8 +18,10 @@ class TestHarness()(implicit p: Parameters) extends Module { val ldut = LazyModule(new ExampleRocketSystem) val dut = Module(ldut.module) + ldut.io_clocks.get.elements.values.foreach(_.clock := clock) // Allow the debug ndreset to reset the dut, but not until the initial reset has completed - dut.reset := (reset.asBool | ldut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)).asBool + val dut_reset = (reset.asBool | ldut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)).asBool + ldut.io_clocks.get.elements.values.foreach(_.reset := dut_reset) dut.dontTouchPorts() dut.tieOffInterrupts() diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 448050a0d50..263b73c69a8 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -4,34 +4,43 @@ package freechips.rocketchip.tile import chisel3._ import chisel3.util.{log2Ceil, log2Up} + import org.chipsalliance.cde.config._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ + + +import freechips.rocketchip.resources.{PropertyMap, PropertyOption, ResourceReference, DTSTimebase} +import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode} +import freechips.rocketchip.rocket.{ICacheParams, DCacheParams, BTBParams, ASIdBits, VMIdBits, TraceAux, BPWatch} +import freechips.rocketchip.subsystem.{ + HierarchicalElementParams, InstantiableHierarchicalElementParams, HierarchicalElementCrossingParamsLike, + CacheBlockBytes, SystemBusKey, BaseHierarchicalElement, InsertTimingClosureRegistersOnHartIds, BaseHierarchicalElementModuleImp +} +import freechips.rocketchip.tilelink.{TLEphemeralNode, TLOutwardNode, TLNode, TLFragmenter, EarlyAck, TLWidthWidget, TLManagerParameters, ManagerUnification} +import freechips.rocketchip.prci.{ClockCrossingType, ClockSinkParameters} +import freechips.rocketchip.util.{TraceCoreParams, TraceCoreInterface} -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.rocket._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ -import freechips.rocketchip.prci.{ClockSinkParameters} +import freechips.rocketchip.resources.{BigIntToProperty, IntToProperty, StringToProperty} +import freechips.rocketchip.util.BooleanToAugmentedBoolean case object TileVisibilityNodeKey extends Field[TLEphemeralNode] case object TileKey extends Field[TileParams] case object LookupByHartId extends Field[LookupByHartIdImpl] -trait TileParams { +trait TileParams extends HierarchicalElementParams { val core: CoreParams val icache: Option[ICacheParams] val dcache: Option[DCacheParams] val btb: Option[BTBParams] - val hartId: Int - val beuAddr: Option[BigInt] + val tileId: Int // may not be hartid val blockerCtrlAddr: Option[BigInt] - val name: Option[String] - val clockSinkParams: ClockSinkParameters } -abstract class InstantiableTileParams[TileType <: BaseTile] extends TileParams { - def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl) +abstract class InstantiableTileParams[TileType <: BaseTile] + extends InstantiableHierarchicalElementParams[TileType] + with TileParams { + def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl) (implicit p: Parameters): TileType } @@ -52,12 +61,12 @@ trait HasNonDiplomaticTileParameters { def usingPTW: Boolean = usingVM def usingDataScratchpad: Boolean = tileParams.dcache.flatMap(_.scratch).isDefined - def xLen: Int = p(XLen) + def xLen: Int = tileParams.core.xLen def xBytes: Int = xLen / 8 def iLen: Int = 32 def pgIdxBits: Int = 12 def pgLevelBits: Int = 10 - log2Ceil(xLen / 32) - def pgLevels: Int = p(PgLevels) + def pgLevels: Int = tileParams.core.pgLevels def maxSVAddrBits: Int = pgIdxBits + pgLevels * pgLevelBits def maxHypervisorExtraAddrBits: Int = 2 def hypervisorExtraAddrBits: Int = { @@ -77,15 +86,7 @@ trait HasNonDiplomaticTileParameters { xLen match { case 32 => 34; case 64 => 56 } } - /** Use staticIdForMetadataUseOnly to emit information during the build or identify a component to diplomacy. - * - * Including it in a constructed Chisel circuit by converting it to a UInt will prevent - * Chisel/FIRRTL from being able to deduplicate tiles that are otherwise homogeneous, - * a property which is important for hierarchical place & route flows. - */ - def staticIdForMetadataUseOnly: Int = tileParams.hartId - @deprecated("use hartIdSinkNodeOpt.map(_.bundle) or staticIdForMetadataUseOnly", "rocket-chip 1.3") - def hartId: Int = staticIdForMetadataUseOnly + def tileId: Int = tileParams.tileId def cacheBlockBytes = p(CacheBlockBytes) def lgCacheBlockBytes = log2Up(cacheBlockBytes) @@ -103,20 +104,39 @@ trait HasNonDiplomaticTileParameters { val f = if (tileParams.core.fpu.nonEmpty) "f" else "" val d = if (tileParams.core.fpu.nonEmpty && tileParams.core.fpu.get.fLen > 32) "d" else "" val c = if (tileParams.core.useCompressed) "c" else "" - val v = if (tileParams.core.useVector) "v" else "" + val b = if (tileParams.core.useBitmanip) "b" else "" + val v = if (tileParams.core.useVector && tileParams.core.vLen >= 128 && tileParams.core.eLen == 64 && tileParams.core.vfLen == 64) "v" else "" val h = if (usingHypervisor) "h" else "" + + val ext_strs = Seq( + (tileParams.core.useVector) -> s"zvl${tileParams.core.vLen}b", + (tileParams.core.useVector) -> { + val c = tileParams.core.vfLen match { + case 64 => "d" + case 32 => "f" + case 0 => "x" + } + s"zve${tileParams.core.eLen}$c" + }, + (tileParams.core.useVector && tileParams.core.vfh) -> "zvfh", + (tileParams.core.fpu.map(_.fLen >= 16).getOrElse(false) && tileParams.core.minFLen <= 16) -> "zfh", + (tileParams.core.useZba) -> "zba", + (tileParams.core.useZbb) -> "zbb", + (tileParams.core.useZbs) -> "zbs", + (tileParams.core.useConditionalZero) -> "zicond" + ).filter(_._1).map(_._2) + val multiLetterExt = ( // rdcycle[h], rdinstret[h] is implemented // rdtime[h] is not implemented, and could be provided by software emulation // see https://github.com/chipsalliance/rocket-chip/issues/3207 //Some(Seq("zicntr")) ++ - Option.when(tileParams.core.useConditionalZero)(Seq("zicond")) ++ Some(Seq("zicsr", "zifencei", "zihpm")) ++ - Option.when(tileParams.core.fpu.nonEmpty && tileParams.core.fpu.get.fLen >= 16 && tileParams.core.fpu.get.minFLen <= 16)(Seq("zfh")) ++ + Some(ext_strs) ++ Some(tileParams.core.vExts) ++ tileParams.core.customIsaExt.map(Seq(_)) ).flatten val multiLetterString = multiLetterExt.mkString("_") - s"rv${p(XLen)}$ie$m$a$f$d$c$v$h$multiLetterString" + s"rv$xLen$ie$m$a$f$d$c$b$v$h$multiLetterString" } def tileProperties: PropertyMap = { @@ -191,9 +211,8 @@ trait HasTileParameters extends HasNonDiplomaticTileParameters { } /** Base class for all Tiles that use TileLink */ -abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) - extends LazyModule()(q) - with CrossesToOnlyOneClockDomain +abstract class BaseTile private (crossing: ClockCrossingType, q: Parameters) + extends BaseHierarchicalElement(crossing)(q) with HasNonDiplomaticTileParameters { // Public constructor alters Parameters to supply some legacy compatibility keys @@ -205,19 +224,12 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) ))) } + def intInwardNode: IntInwardNode // Interrupts to the core from external devices + def intOutwardNode: Option[IntOutwardNode] // Interrupts from tile-internal devices (e.g. BEU) + def haltNode: IntOutwardNode // Unrecoverable error has occurred; suggest reset + def ceaseNode: IntOutwardNode // Tile has ceased to retire instructions + def wfiNode: IntOutwardNode // Tile is waiting for an interrupt def module: BaseTileModuleImp[BaseTile] - def masterNode: TLOutwardNode - def slaveNode: TLInwardNode - def intInwardNode: IntInwardNode // Interrupts to the core from external devices - def intOutwardNode: IntOutwardNode // Interrupts from tile-internal devices (e.g. BEU) - def haltNode: IntOutwardNode // Unrecoverable error has occurred; suggest reset - def ceaseNode: IntOutwardNode // Tile has ceased to retire instructions - def wfiNode: IntOutwardNode // Tile is waiting for an interrupt - - protected val tlOtherMastersNode = TLIdentityNode() - protected val tlMasterXbar = LazyModule(new TLXbar) - protected val tlSlaveXbar = LazyModule(new TLXbar) - protected val intXbar = LazyModule(new IntXbar) /** Node for broadcasting a hart id to diplomatic consumers within the tile. */ val hartIdNexusNode: BundleBridgeNode[UInt] = BundleBroadcast[UInt](registered = p(InsertTimingClosureRegistersOnHartIds)) @@ -250,10 +262,10 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) resetVectorSinkNode := resetVectorNexusNode := BundleBridgeNameNode("reset_vector") /** Nodes for connecting NMI interrupt sources and vectors into the tile */ - val nmiNexusNode: BundleBridgeNode[NMI] = BundleBroadcast[NMI]() - val nmiSinkNode = BundleBridgeSink[NMI](Some(() => new NMI(visiblePhysAddrBits))) - val nmiNode: BundleBridgeInwardNode[NMI] = - nmiSinkNode := nmiNexusNode := BundleBridgeNameNode("nmi") + val nmiSinkNode = Option.when(tileParams.core.useNMI) { + BundleBridgeSink[NMI](Some(() => new NMI(visiblePhysAddrBits))) + } + val nmiNode: Option[BundleBridgeInwardNode[NMI]] = nmiSinkNode.map(_ := BundleBridgeNameNode("nmi")) /** Node for broadcasting an address prefix to diplomatic consumers within the tile. * @@ -279,15 +291,14 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) protected def traceRetireWidth = tileParams.core.retireWidth /** Node for the core to drive legacy "raw" instruction trace. */ val traceSourceNode = BundleBridgeSource(() => new TraceBundle) - private val traceNexus = BundleBroadcast[TraceBundle]() // backwards compatiblity; not blocked during stretched reset /** Node for external consumers to source a legacy instruction trace from the core. */ - val traceNode: BundleBridgeOutwardNode[TraceBundle] = traceNexus := traceSourceNode + val traceNode = traceSourceNode - protected def traceCoreParams = new TraceCoreParams() + def traceCoreParams = new TraceCoreParams() /** Node for core to drive instruction trace conforming to RISC-V Processor Trace spec V1.0 */ val traceCoreSourceNode = BundleBridgeSource(() => new TraceCoreInterface(traceCoreParams)) /** Node for external consumers to source a V1.0 instruction trace from the core. */ - val traceCoreNode: BundleBridgeOutwardNode[TraceCoreInterface] = traceCoreSourceNode + val traceCoreNode = traceCoreSourceNode /** Node to broadcast collected trace sideband signals into the tile. */ val traceAuxNexusNode = BundleBridgeNexus[TraceAux](default = Some(() => { @@ -347,22 +358,6 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) "hardware-exec-breakpoint-count" -> tileParams.core.nBreakpoints.asProperty ) - /** Helper function to insert additional buffers on master ports at the boundary of the tile. - * - * The boundary buffering needed to cut feed-through paths is - * microarchitecture specific, so this may need to be overridden - * in subclasses of this class. - */ - def makeMasterBoundaryBuffers(crossing: ClockCrossingType)(implicit p: Parameters) = TLBuffer(BufferParams.none) - - /** Helper function to insert additional buffers on slave ports at the boundary of the tile. - * - * The boundary buffering needed to cut feed-through paths is - * microarchitecture specific, so this may need to be overridden - * in subclasses of this class. - */ - def makeSlaveBoundaryBuffers(crossing: ClockCrossingType)(implicit p: Parameters) = TLBuffer(BufferParams.none) - /** Can be used to access derived params calculated by HasCoreParameters * * However, callers must ensure they do not access a diplomatically-determined parameter @@ -373,7 +368,7 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) new C } - this.suggestName(tileParams.name) + this.suggestName(tileParams.baseName) } -abstract class BaseTileModuleImp[+L <: BaseTile](val outer: L) extends LazyModuleImp(outer) with HasTileParameters +abstract class BaseTileModuleImp[+L <: BaseTile](outer: L) extends BaseHierarchicalElementModuleImp[L](outer) diff --git a/src/main/scala/tile/BusErrorUnit.scala b/src/main/scala/tile/BusErrorUnit.scala index 65c91b38e21..850550afb80 100644 --- a/src/main/scala/tile/BusErrorUnit.scala +++ b/src/main/scala/tile/BusErrorUnit.scala @@ -3,17 +3,17 @@ package freechips.rocketchip.tile import chisel3._ -import chisel3.util.log2Ceil -// TODO: remove this import -import chisel3.util.ImplicitConversions._ -import chisel3.util.Valid -import chisel3.DontCare +import chisel3.util._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.rocket._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.interrupts._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.rocket.{DCacheErrors, ICacheErrors} +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.regmapper.{DescribedReg, RegField, RegFieldDesc, RegFieldGroup} +import freechips.rocketchip.tilelink.TLRegisterNode +import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} import freechips.rocketchip.util.property trait BusErrors extends Bundle { @@ -36,14 +36,14 @@ class L1BusErrors(implicit p: Parameters) extends CoreBundle()(p) with BusErrors case class BusErrorUnitParams(addr: BigInt, size: Int = 4096) -class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit p: Parameters) extends LazyModule { +class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams, beatBytes: Int)(implicit p: Parameters) extends LazyModule { val regWidth = 64 val device = new SimpleDevice("bus-error-unit", Seq("sifive,buserror0")) val intNode = IntSourceNode(IntSourcePortSimple(resources = device.int)) val node = TLRegisterNode( address = Seq(AddressSet(params.addr, params.size-1)), device = device, - beatBytes = p(XLen)/8) + beatBytes = beatBytes) lazy val module = new Impl class Impl extends LazyModuleImp(this) { @@ -95,17 +95,17 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit new_value := DontCare for ((((s, en), acc), i) <- (sources zip enable zip accrued).zipWithIndex; if s.nonEmpty) { when (s.get.valid) { - acc := true + acc := true.B when (en) { - cause_wen := true - new_cause := i + cause_wen := true.B + new_cause := i.asUInt new_value := s.get.bits } property.cover(en, s"BusErrorCause_$i", s"Core;;BusErrorCause $i covered") } } - when (cause === 0 && cause_wen) { + when (cause === 0.asUInt && cause_wen) { cause := new_cause value := new_value } @@ -129,10 +129,10 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit // hardwire mask bits for unsupported sources to 0 for ((s, i) <- sources.zipWithIndex; if s.isEmpty) { - enable(i) := false - global_interrupt(i) := false - accrued(i) := false - local_interrupt(i) := false + enable(i) := false.B + global_interrupt(i) := false.B + accrued(i) := false.B + local_interrupt(i) := false.B } } } diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 8c9018da50a..1160247e73a 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -8,7 +8,6 @@ import org.chipsalliance.cde.config._ import freechips.rocketchip.rocket._ import freechips.rocketchip.util._ -case object XLen extends Field[Int] case object MaxHartIdBits extends Field[Int] // These parameters can be varied per-core @@ -26,6 +25,9 @@ trait CoreParams { val vectorUseDCache: Boolean = false val useRVE: Boolean val useConditionalZero: Boolean + val useZba: Boolean + val useZbb: Boolean + val useZbs: Boolean val mulDiv: Option[MulDivParams] val fpu: Option[FPUParams] val fetchWidth: Int @@ -51,6 +53,8 @@ trait CoreParams { val mtvecInit: Option[BigInt] val mtvecWritable: Boolean val traceHasWdata: Boolean + val xLen: Int + val pgLevels: Int def traceCustom: Option[Data] = None def customIsaExt: Option[String] = None def customCSRs(implicit p: Parameters): CustomCSRs = new CustomCSRs @@ -63,10 +67,16 @@ trait CoreParams { def dcacheReqTagBits: Int = 6 def minFLen: Int = 32 + def vLen: Int = 0 - def sLen: Int = 0 - def eLen(xLen: Int, fLen: Int): Int = xLen max fLen + def eLen: Int = 0 + def vfLen: Int = 0 + def vfh: Boolean = false + def vExts: Seq[String] = Nil + def hasV: Boolean = vLen >= 128 && eLen >= 64 && vfLen >= 64 def vMemDataBits: Int = 0 + + def useBitmanip = useZba && useZbb && useZbs } trait HasCoreParameters extends HasTileParameters { @@ -106,14 +116,25 @@ trait HasCoreParameters extends HasTileParameters { val traceHasWdata = coreParams.traceHasWdata def vLen = coreParams.vLen - def sLen = coreParams.sLen - def eLen = coreParams.eLen(xLen, fLen) + def eLen = coreParams.eLen + def vfLen = coreParams.vfLen def vMemDataBits = if (usingVector) coreParams.vMemDataBits else 0 def maxVLMax = vLen if (usingVector) { require(isPow2(vLen), s"vLen ($vLen) must be a power of 2") require(eLen >= 32 && vLen % eLen == 0, s"eLen must divide vLen ($vLen) and be no less than 32") + require(eLen == 32 || eLen == 64) + require(vfLen <= eLen) + require(!coreParams.vfh || (vfLen >= 32 && coreParams.minFLen <= 16)) + } + + if (coreParams.useVM) { + if (coreParams.xLen == 32) { + require(coreParams.pgLevels == 2) + } else { + require(coreParams.pgLevels >= 3) + } } lazy val hartIdLen: Int = p(MaxHartIdBits) @@ -136,33 +157,9 @@ abstract class CoreModule(implicit val p: Parameters) extends Module abstract class CoreBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) with HasCoreParameters -class CoreInterrupts(implicit p: Parameters) extends TileInterrupts()(p) { - val buserror = tileParams.beuAddr.map(a => Bool()) -} - // This is a raw commit trace from the core, not the TraceCoreInterface class TraceBundle(implicit val p: Parameters) extends Bundle with HasCoreParameters { val insns = Vec(coreParams.retireWidth, new TracedInstruction) val time = UInt(64.W) val custom = coreParams.traceCustom } - -trait HasCoreIO extends HasTileParameters { - implicit val p: Parameters - def nTotalRoCCCSRs: Int - val io = IO(new CoreBundle()(p) { - val hartid = Input(UInt(hartIdLen.W)) - val reset_vector = Input(UInt(resetVectorLen.W)) - val interrupts = Input(new CoreInterrupts()) - val imem = new FrontendIO - val dmem = new HellaCacheIO - val ptw = Flipped(new DatapathPTWIO()) - val fpu = Flipped(new FPUCoreIO()) - val rocc = Flipped(new RoCCCoreIO(nTotalRoCCCSRs)) - val trace = Output(new TraceBundle) - val bpwatch = Output(Vec(coreParams.nBreakpoints, new BPWatch(coreParams.retireWidth))) - val cease = Output(Bool()) - val wfi = Output(Bool()) - val traceStall = Input(Bool()) - }) -} diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index 174cd38c7de..1affeb48769 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -19,7 +19,9 @@ case class FPUParams( fLen: Int = 64, divSqrt: Boolean = true, sfmaLatency: Int = 3, - dfmaLatency: Int = 4 + dfmaLatency: Int = 4, + fpmuLatency: Int = 2, + ifpuLatency: Int = 2 ) object FPConstants @@ -45,6 +47,7 @@ trait HasFPUCtrlSigs { val div = Bool() val sqrt = Bool() val wflags = Bool() + val vec = Bool() } class FPUCtrlSigs extends Bundle with HasFPUCtrlSigs @@ -57,121 +60,122 @@ class FPUDecoder(implicit p: Parameters) extends FPUModule()(p) { private val X2 = BitPat.dontCare(2) - val default = List(X,X,X,X,X,X,X,X2,X2,X,X,X,X,X,X,X) + val default = List(X,X,X,X,X,X,X,X2,X2,X,X,X,X,X,X,X,N) val h: Array[(BitPat, List[BitPat])] = - Array(FLH -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N), - FSH -> List(Y,N,N,Y,N,Y,X, I, H,N,Y,N,N,N,N,N), - FMV_H_X -> List(N,Y,N,N,N,X,X, H, I,Y,N,N,N,N,N,N), - FCVT_H_W -> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y), - FCVT_H_WU-> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y), - FCVT_H_L -> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y), - FCVT_H_LU-> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y), - FMV_X_H -> List(N,N,Y,N,N,N,X, I, H,N,Y,N,N,N,N,N), - FCLASS_H -> List(N,N,Y,N,N,N,X, H, H,N,Y,N,N,N,N,N), - FCVT_W_H -> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y), - FCVT_WU_H-> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y), - FCVT_L_H -> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y), - FCVT_LU_H-> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y), - FCVT_S_H -> List(N,Y,Y,N,N,N,X, H, S,N,N,Y,N,N,N,Y), - FCVT_H_S -> List(N,Y,Y,N,N,N,X, S, H,N,N,Y,N,N,N,Y), - FEQ_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y), - FLT_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y), - FLE_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y), - FSGNJ_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N), - FSGNJN_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N), - FSGNJX_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N), - FMIN_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,Y), - FMAX_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,Y), - FADD_H -> List(N,Y,Y,Y,N,N,Y, H, H,N,N,N,Y,N,N,Y), - FSUB_H -> List(N,Y,Y,Y,N,N,Y, H, H,N,N,N,Y,N,N,Y), - FMUL_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,N,Y,N,N,Y), - FMADD_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y), - FMSUB_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y), - FNMADD_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y), - FNMSUB_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y), - FDIV_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,N,N,Y,N,Y), - FSQRT_H -> List(N,Y,Y,N,N,N,X, H, H,N,N,N,N,N,Y,Y)) + Array(FLH -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N,N), + FSH -> List(Y,N,N,Y,N,Y,X, I, H,N,Y,N,N,N,N,N,N), + FMV_H_X -> List(N,Y,N,N,N,X,X, H, I,Y,N,N,N,N,N,N,N), + FCVT_H_W -> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y,N), + FCVT_H_WU-> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y,N), + FCVT_H_L -> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y,N), + FCVT_H_LU-> List(N,Y,N,N,N,X,X, H, H,Y,N,N,N,N,N,Y,N), + FMV_X_H -> List(N,N,Y,N,N,N,X, I, H,N,Y,N,N,N,N,N,N), + FCLASS_H -> List(N,N,Y,N,N,N,X, H, H,N,Y,N,N,N,N,N,N), + FCVT_W_H -> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y,N), + FCVT_WU_H-> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y,N), + FCVT_L_H -> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y,N), + FCVT_LU_H-> List(N,N,Y,N,N,N,X, H,X2,N,Y,N,N,N,N,Y,N), + FCVT_S_H -> List(N,Y,Y,N,N,N,X, H, S,N,N,Y,N,N,N,Y,N), + FCVT_H_S -> List(N,Y,Y,N,N,N,X, S, H,N,N,Y,N,N,N,Y,N), + FEQ_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y,N), + FLT_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y,N), + FLE_H -> List(N,N,Y,Y,N,N,N, H, H,N,Y,N,N,N,N,Y,N), + FSGNJ_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N,N), + FSGNJN_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N,N), + FSGNJX_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,N,N), + FMIN_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,Y,N), + FMAX_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,Y,N,N,N,Y,N), + FADD_H -> List(N,Y,Y,Y,N,N,Y, H, H,N,N,N,Y,N,N,Y,N), + FSUB_H -> List(N,Y,Y,Y,N,N,Y, H, H,N,N,N,Y,N,N,Y,N), + FMUL_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,N,Y,N,N,Y,N), + FMADD_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y,N), + FMSUB_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y,N), + FNMADD_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y,N), + FNMSUB_H -> List(N,Y,Y,Y,Y,N,N, H, H,N,N,N,Y,N,N,Y,N), + FDIV_H -> List(N,Y,Y,Y,N,N,N, H, H,N,N,N,N,Y,N,Y,N), + FSQRT_H -> List(N,Y,Y,N,N,N,X, H, H,N,N,N,N,N,Y,Y,N)) val f: Array[(BitPat, List[BitPat])] = - Array(FLW -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N), - FSW -> List(Y,N,N,Y,N,Y,X, I, S,N,Y,N,N,N,N,N), - FMV_W_X -> List(N,Y,N,N,N,X,X, S, I,Y,N,N,N,N,N,N), - FCVT_S_W -> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y), - FCVT_S_WU-> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y), - FCVT_S_L -> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y), - FCVT_S_LU-> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y), - FMV_X_W -> List(N,N,Y,N,N,N,X, I, S,N,Y,N,N,N,N,N), - FCLASS_S -> List(N,N,Y,N,N,N,X, S, S,N,Y,N,N,N,N,N), - FCVT_W_S -> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y), - FCVT_WU_S-> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y), - FCVT_L_S -> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y), - FCVT_LU_S-> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y), - FEQ_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y), - FLT_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y), - FLE_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y), - FSGNJ_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N), - FSGNJN_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N), - FSGNJX_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N), - FMIN_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,Y), - FMAX_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,Y), - FADD_S -> List(N,Y,Y,Y,N,N,Y, S, S,N,N,N,Y,N,N,Y), - FSUB_S -> List(N,Y,Y,Y,N,N,Y, S, S,N,N,N,Y,N,N,Y), - FMUL_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,N,Y,N,N,Y), - FMADD_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y), - FMSUB_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y), - FNMADD_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y), - FNMSUB_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y), - FDIV_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,N,N,Y,N,Y), - FSQRT_S -> List(N,Y,Y,N,N,N,X, S, S,N,N,N,N,N,Y,Y)) + Array(FLW -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N,N), + FSW -> List(Y,N,N,Y,N,Y,X, I, S,N,Y,N,N,N,N,N,N), + FMV_W_X -> List(N,Y,N,N,N,X,X, S, I,Y,N,N,N,N,N,N,N), + FCVT_S_W -> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y,N), + FCVT_S_WU-> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y,N), + FCVT_S_L -> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y,N), + FCVT_S_LU-> List(N,Y,N,N,N,X,X, S, S,Y,N,N,N,N,N,Y,N), + FMV_X_W -> List(N,N,Y,N,N,N,X, I, S,N,Y,N,N,N,N,N,N), + FCLASS_S -> List(N,N,Y,N,N,N,X, S, S,N,Y,N,N,N,N,N,N), + FCVT_W_S -> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y,N), + FCVT_WU_S-> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y,N), + FCVT_L_S -> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y,N), + FCVT_LU_S-> List(N,N,Y,N,N,N,X, S,X2,N,Y,N,N,N,N,Y,N), + FEQ_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y,N), + FLT_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y,N), + FLE_S -> List(N,N,Y,Y,N,N,N, S, S,N,Y,N,N,N,N,Y,N), + FSGNJ_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N,N), + FSGNJN_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N,N), + FSGNJX_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,N,N), + FMIN_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,Y,N), + FMAX_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,Y,N,N,N,Y,N), + FADD_S -> List(N,Y,Y,Y,N,N,Y, S, S,N,N,N,Y,N,N,Y,N), + FSUB_S -> List(N,Y,Y,Y,N,N,Y, S, S,N,N,N,Y,N,N,Y,N), + FMUL_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,N,Y,N,N,Y,N), + FMADD_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y,N), + FMSUB_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y,N), + FNMADD_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y,N), + FNMSUB_S -> List(N,Y,Y,Y,Y,N,N, S, S,N,N,N,Y,N,N,Y,N), + FDIV_S -> List(N,Y,Y,Y,N,N,N, S, S,N,N,N,N,Y,N,Y,N), + FSQRT_S -> List(N,Y,Y,N,N,N,X, S, S,N,N,N,N,N,Y,Y,N)) val d: Array[(BitPat, List[BitPat])] = - Array(FLD -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N), - FSD -> List(Y,N,N,Y,N,Y,X, I, D,N,Y,N,N,N,N,N), - FMV_D_X -> List(N,Y,N,N,N,X,X, D, I,Y,N,N,N,N,N,N), - FCVT_D_W -> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y), - FCVT_D_WU-> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y), - FCVT_D_L -> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y), - FCVT_D_LU-> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y), - FMV_X_D -> List(N,N,Y,N,N,N,X, I, D,N,Y,N,N,N,N,N), - FCLASS_D -> List(N,N,Y,N,N,N,X, D, D,N,Y,N,N,N,N,N), - FCVT_W_D -> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y), - FCVT_WU_D-> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y), - FCVT_L_D -> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y), - FCVT_LU_D-> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y), - FCVT_S_D -> List(N,Y,Y,N,N,N,X, D, S,N,N,Y,N,N,N,Y), - FCVT_D_S -> List(N,Y,Y,N,N,N,X, S, D,N,N,Y,N,N,N,Y), - FEQ_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y), - FLT_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y), - FLE_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y), - FSGNJ_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N), - FSGNJN_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N), - FSGNJX_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N), - FMIN_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,Y), - FMAX_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,Y), - FADD_D -> List(N,Y,Y,Y,N,N,Y, D, D,N,N,N,Y,N,N,Y), - FSUB_D -> List(N,Y,Y,Y,N,N,Y, D, D,N,N,N,Y,N,N,Y), - FMUL_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,N,Y,N,N,Y), - FMADD_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y), - FMSUB_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y), - FNMADD_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y), - FNMSUB_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y), - FDIV_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,N,N,Y,N,Y), - FSQRT_D -> List(N,Y,Y,N,N,N,X, D, D,N,N,N,N,N,Y,Y)) + Array(FLD -> List(Y,Y,N,N,N,X,X,X2,X2,N,N,N,N,N,N,N,N), + FSD -> List(Y,N,N,Y,N,Y,X, I, D,N,Y,N,N,N,N,N,N), + FMV_D_X -> List(N,Y,N,N,N,X,X, D, I,Y,N,N,N,N,N,N,N), + FCVT_D_W -> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y,N), + FCVT_D_WU-> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y,N), + FCVT_D_L -> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y,N), + FCVT_D_LU-> List(N,Y,N,N,N,X,X, D, D,Y,N,N,N,N,N,Y,N), + FMV_X_D -> List(N,N,Y,N,N,N,X, I, D,N,Y,N,N,N,N,N,N), + FCLASS_D -> List(N,N,Y,N,N,N,X, D, D,N,Y,N,N,N,N,N,N), + FCVT_W_D -> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y,N), + FCVT_WU_D-> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y,N), + FCVT_L_D -> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y,N), + FCVT_LU_D-> List(N,N,Y,N,N,N,X, D,X2,N,Y,N,N,N,N,Y,N), + FCVT_S_D -> List(N,Y,Y,N,N,N,X, D, S,N,N,Y,N,N,N,Y,N), + FCVT_D_S -> List(N,Y,Y,N,N,N,X, S, D,N,N,Y,N,N,N,Y,N), + FEQ_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y,N), + FLT_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y,N), + FLE_D -> List(N,N,Y,Y,N,N,N, D, D,N,Y,N,N,N,N,Y,N), + FSGNJ_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N,N), + FSGNJN_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N,N), + FSGNJX_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,N,N), + FMIN_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,Y,N), + FMAX_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,Y,N,N,N,Y,N), + FADD_D -> List(N,Y,Y,Y,N,N,Y, D, D,N,N,N,Y,N,N,Y,N), + FSUB_D -> List(N,Y,Y,Y,N,N,Y, D, D,N,N,N,Y,N,N,Y,N), + FMUL_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,N,Y,N,N,Y,N), + FMADD_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y,N), + FMSUB_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y,N), + FNMADD_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y,N), + FNMSUB_D -> List(N,Y,Y,Y,Y,N,N, D, D,N,N,N,Y,N,N,Y,N), + FDIV_D -> List(N,Y,Y,Y,N,N,N, D, D,N,N,N,N,Y,N,Y,N), + FSQRT_D -> List(N,Y,Y,N,N,N,X, D, D,N,N,N,N,N,Y,Y,N)) val fcvt_hd: Array[(BitPat, List[BitPat])] = - Array(FCVT_H_D -> List(N,Y,Y,N,N,N,X, D, H,N,N,Y,N,N,N,Y), - FCVT_D_H -> List(N,Y,Y,N,N,N,X, H, D,N,N,Y,N,N,N,Y)) + Array(FCVT_H_D -> List(N,Y,Y,N,N,N,X, D, H,N,N,Y,N,N,N,Y,N), + FCVT_D_H -> List(N,Y,Y,N,N,N,X, H, D,N,N,Y,N,N,N,Y,N)) + val vfmv_f_s: Array[(BitPat, List[BitPat])] = + Array(VFMV_F_S -> List(N,Y,N,N,N,N,X,X2,X2,N,N,N,N,N,N,N,Y)) - val insns = (minFLen, fLen) match { + val insns = ((minFLen, fLen) match { case (32, 32) => f case (16, 32) => h ++ f case (32, 64) => f ++ d case (16, 64) => h ++ f ++ d ++ fcvt_hd - case other => throw new Exception(s"minFLen = ${minFLen} & fLen = ${fLen} is an unsupported configuration") - } + }) ++ (if (usingVector) vfmv_f_s else Array[(BitPat, List[BitPat])]()) val decoder = DecodeLogic(io.inst, default, insns) val s = io.sigs val sigs = Seq(s.ldst, s.wen, s.ren1, s.ren2, s.ren3, s.swap12, s.swap23, s.typeTagIn, s.typeTagOut, s.fromint, s.toint, - s.fastpipe, s.fma, s.div, s.sqrt, s.wflags) + s.fastpipe, s.fma, s.div, s.sqrt, s.wflags, s.vec) sigs zip decoder map {case(s,d) => s := d} } @@ -185,13 +189,15 @@ class FPUCoreIO(implicit p: Parameters) extends CoreBundle()(p) { val fcsr_rm = Input(Bits(FPConstants.RM_SZ.W)) val fcsr_flags = Valid(Bits(FPConstants.FLAGS_SZ.W)) + val v_sew = Input(UInt(3.W)) + val store_data = Output(Bits(fLen.W)) val toint_data = Output(Bits(xLen.W)) - val dmem_resp_val = Input(Bool()) - val dmem_resp_type = Input(Bits(3.W)) - val dmem_resp_tag = Input(UInt(5.W)) - val dmem_resp_data = Input(Bits(fLen.W)) + val ll_resp_val = Input(Bool()) + val ll_resp_type = Input(Bits(3.W)) + val ll_resp_tag = Input(UInt(5.W)) + val ll_resp_data = Input(Bits(fLen.W)) val valid = Input(Bool()) val fcsr_rdy = Output(Bool()) @@ -466,22 +472,23 @@ class FPToInt(implicit p: Parameters) extends FPUModule()(p) with ShouldBeRetime dcmp.io.signaling := !in.rm(1) val tag = in.typeTagOut - val store = (floatTypes.map(t => if (t == FType.H) Fill(maxType.ieeeWidth / minXLen, ieee(in.in1)(15, 0).sextTo(minXLen)) - else Fill(maxType.ieeeWidth / t.ieeeWidth, ieee(in.in1)(t.ieeeWidth - 1, 0))): Seq[UInt])(tag) - val toint = WireDefault(store) + val toint_ieee = (floatTypes.map(t => if (t == FType.H) Fill(maxType.ieeeWidth / minXLen, ieee(in.in1)(15, 0).sextTo(minXLen)) + else Fill(maxType.ieeeWidth / t.ieeeWidth, ieee(in.in1)(t.ieeeWidth - 1, 0))): Seq[UInt])(tag) + + val toint = WireDefault(toint_ieee) val intType = WireDefault(in.fmt(0)) - io.out.bits.store := store + io.out.bits.store := (floatTypes.map(t => Fill(fLen / t.ieeeWidth, ieee(in.in1)(t.ieeeWidth - 1, 0))): Seq[UInt])(tag) io.out.bits.toint := ((0 until nIntTypes).map(i => toint((minXLen << i) - 1, 0).sextTo(xLen)): Seq[UInt])(intType) io.out.bits.exc := 0.U when (in.rm(0)) { val classify_out = (floatTypes.map(t => t.classify(maxType.unsafeConvert(in.in1, t))): Seq[UInt])(tag) - toint := classify_out | (store >> minXLen << minXLen) + toint := classify_out | (toint_ieee >> minXLen << minXLen) intType := false.B } when (in.wflags) { // feq/flt/fle, fcvt - toint := (~in.rm & Cat(dcmp.io.lt, dcmp.io.eq)).orR | (store >> minXLen << minXLen) + toint := (~in.rm & Cat(dcmp.io.lt, dcmp.io.eq)).orR | (toint_ieee >> minXLen << minXLen) io.out.bits.exc := dcmp.io.exceptionFlags intType := false.B @@ -625,6 +632,7 @@ class FPToFP(val latency: Int)(implicit p: Parameters) extends FPUModule()(p) wi class MulAddRecFNPipe(latency: Int, expWidth: Int, sigWidth: Int) extends Module { + override def desiredName = s"MulAddRecFNPipe_l${latency}_e${expWidth}_s${sigWidth}" require(latency<=2) val io = IO(new Bundle { @@ -688,6 +696,7 @@ class MulAddRecFNPipe(latency: Int, expWidth: Int, sigWidth: Int) extends Module class FPUFMAPipe(val latency: Int, val t: FType) (implicit p: Parameters) extends FPUModule()(p) with ShouldBeRetimed { + override def desiredName = s"FPUFMAPipe_l${latency}_f${t.ieeeWidth}" require(latency>0) val io = IO(new Bundle { @@ -727,7 +736,9 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { val io = IO(new FPUIO) val (useClockGating, useDebugROB) = coreParams match { - case r: RocketCoreParams => (r.clockGate, r.debugROB) + case r: RocketCoreParams => + val sz = if (r.debugROB.isDefined) r.debugROB.get.size else 1 + (r.clockGate, sz < 1) case _ => (false, false) } val clock_en_reg = Reg(Bool()) @@ -738,18 +749,31 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { val fp_decoder = Module(new FPUDecoder) fp_decoder.io.inst := io.inst - val id_ctrl = fp_decoder.io.sigs + val id_ctrl = WireInit(fp_decoder.io.sigs) + coreParams match { case r: RocketCoreParams => r.vector.map(v => { + val v_decode = v.decoder(p) // Only need to get ren1 + v_decode.io.inst := io.inst + v_decode.io.vconfig := DontCare // core deals with this + when (v_decode.io.legal && v_decode.io.read_frs1) { + id_ctrl.ren1 := true.B + id_ctrl.swap12 := false.B + id_ctrl.toint := true.B + id_ctrl.typeTagIn := I + id_ctrl.typeTagOut := Mux(io.v_sew === 3.U, D, S) + } + when (v_decode.io.write_frd) { id_ctrl.wen := true.B } + })} val ex_reg_valid = RegNext(io.valid, false.B) val ex_reg_inst = RegEnable(io.inst, io.valid) val ex_reg_ctrl = RegEnable(id_ctrl, io.valid) val ex_ra = List.fill(3)(Reg(UInt())) - // load response - val load_wb = RegNext(io.dmem_resp_val) - val load_wb_typeTag = RegEnable(io.dmem_resp_type(1,0) - typeTagWbOffset, io.dmem_resp_val) - val load_wb_data = RegEnable(io.dmem_resp_data, io.dmem_resp_val) - val load_wb_tag = RegEnable(io.dmem_resp_tag, io.dmem_resp_val) + // load/vector response + val load_wb = RegNext(io.ll_resp_val) + val load_wb_typeTag = RegEnable(io.ll_resp_type(1,0) - typeTagWbOffset, io.ll_resp_val) + val load_wb_data = RegEnable(io.ll_resp_data, io.ll_resp_val) + val load_wb_tag = RegEnable(io.ll_resp_tag, io.ll_resp_val) class FPUImpl { // entering gated-clock domain @@ -833,6 +857,10 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { req.fmaCmd := ex_reg_inst(3,2) | (!ex_ctrl.ren3 && ex_reg_inst(27)) when (ex_cp_valid) { req := io.cp_req.bits + when (io.cp_req.bits.swap12) { + req.in1 := io.cp_req.bits.in2 + req.in2 := io.cp_req.bits.in1 + } when (io.cp_req.bits.swap23) { req.in2 := io.cp_req.bits.in3 req.in3 := io.cp_req.bits.in2 @@ -855,12 +883,12 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { io.cp_resp.valid := true.B } - val ifpu = Module(new IntToFP(2)) + val ifpu = Module(new IntToFP(cfg.ifpuLatency)) ifpu.io.in.valid := req_valid && ex_ctrl.fromint ifpu.io.in.bits := fpiu.io.in.bits ifpu.io.in.bits.in1 := Mux(ex_cp_valid, io.cp_req.bits.in1, io.fromint_data) - val fpmu = Module(new FPToFP(2)) + val fpmu = Module(new FPToFP(cfg.fpmuLatency)) fpmu.io.in.valid := req_valid && ex_ctrl.fastpipe fpmu.io.in.bits := fpiu.io.in.bits fpmu.io.lt := fpiu.io.out.bits.lt @@ -868,6 +896,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { val divSqrt_wen = WireDefault(false.B) val divSqrt_inFlight = WireDefault(false.B) val divSqrt_waddr = Reg(UInt(5.W)) + val divSqrt_cp = Reg(Bool()) val divSqrt_typeTag = Wire(UInt(log2Up(floatTypes.size).W)) val divSqrt_wdata = Wire(UInt((fLen+1).W)) val divSqrt_flags = Wire(UInt(FPConstants.FLAGS_SZ.W)) @@ -932,6 +961,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { } val waddr = Mux(divSqrt_wen, divSqrt_waddr, wbInfo(0).rd) + val wb_cp = Mux(divSqrt_wen, divSqrt_cp, wbInfo(0).cp) val wtypeTag = Mux(divSqrt_wen, divSqrt_typeTag, wbInfo(0).typeTag) val wdata = box(Mux(divSqrt_wen, divSqrt_wdata, (pipes.map(_.res.data): Seq[UInt])(wbInfo(0).pipeid)), wtypeTag) val wexc = (pipes.map(_.res.exc): Seq[UInt])(wbInfo(0).pipeid) @@ -949,11 +979,16 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { DebugROB.pushWb(clock, reset, io.hartid, (!wbInfo(0).cp && wen(0)) || divSqrt_wen, waddr + 32.U, ieee(wdata)) } - when (wbInfo(0).cp && wen(0)) { + when (wb_cp && (wen(0) || divSqrt_wen)) { io.cp_resp.bits.data := wdata io.cp_resp.valid := true.B } - io.cp_req.ready := !ex_reg_valid + + assert(!io.cp_req.valid || pipes.forall(_.lat == pipes.head.lat).B, + s"FPU only supports coprocessor if FMA pipes have uniform latency ${pipes.map(_.lat)}") + // Avoid structural hazards and nacking of external requests + // toint responds in the MEM stage, so an incoming toint can induce a structural hazard against inflight FMAs + io.cp_req.ready := !ex_reg_valid && !(cp_ctrl.toint && wen =/= 0.U) && !divSqrt_inFlight val wb_toint_valid = wb_reg_valid && wb_ctrl.toint val wb_toint_exc = RegEnable(fpiu.io.out.bits.exc, mem_ctrl.toint) @@ -965,10 +1000,10 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { val divSqrt_write_port_busy = (mem_ctrl.div || mem_ctrl.sqrt) && wen.orR io.fcsr_rdy := !(ex_reg_valid && ex_ctrl.wflags || mem_reg_valid && mem_ctrl.wflags || wb_reg_valid && wb_ctrl.toint || wen.orR || divSqrt_inFlight) - io.nack_mem := write_port_busy || divSqrt_write_port_busy || divSqrt_inFlight - io.dec <> fp_decoder.io.sigs + io.nack_mem := (write_port_busy || divSqrt_write_port_busy || divSqrt_inFlight) && !mem_cp_valid + io.dec <> id_ctrl def useScoreboard(f: ((Pipe, Int)) => Bool) = pipes.zipWithIndex.filter(_._1.lat > 3).map(x => f(x)).fold(false.B)(_||_) - io.sboard_set := wb_reg_valid && !wb_cp_valid && RegNext(useScoreboard(_._1.cond(mem_ctrl)) || mem_ctrl.div || mem_ctrl.sqrt) + io.sboard_set := wb_reg_valid && !wb_cp_valid && RegNext(useScoreboard(_._1.cond(mem_ctrl)) || mem_ctrl.div || mem_ctrl.sqrt || mem_ctrl.vec) io.sboard_clr := !wb_cp_valid && (divSqrt_wen || (wen(0) && useScoreboard(x => wbInfo(0).pipeid === x._2.U))) io.sboard_clra := waddr ccover(io.sboard_clr && load_wb, "DUAL_WRITEBACK", "load and FMA writeback on same cycle") @@ -980,6 +1015,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { val divSqrt_killed = RegNext(divSqrt_inValid && killm, true.B) when (divSqrt_inValid) { divSqrt_waddr := mem_reg_inst(11,7) + divSqrt_cp := mem_cp_valid } ccover(divSqrt_inFlight && divSqrt_killed, "DIV_KILLED", "divide killed after issued to divider") @@ -1019,7 +1055,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { mem_reg_valid || mem_cp_valid || // MEM stage wb_reg_valid || wb_cp_valid || // WB stage wen.orR || divSqrt_inFlight || // post-WB stage - io.dmem_resp_val // load writeback + io.ll_resp_val // load writeback } // leaving gated-clock domain val fpuImpl = withClock (gated_clock) { new FPUImpl } diff --git a/src/main/scala/tile/Interrupts.scala b/src/main/scala/tile/Interrupts.scala index 1efdde5983c..6ae4da3d5d2 100644 --- a/src/main/scala/tile/Interrupts.scala +++ b/src/main/scala/tile/Interrupts.scala @@ -3,11 +3,16 @@ package freechips.rocketchip.tile import chisel3._ -import chisel3.util.{RegEnable, log2Ceil} -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.util._ +import chisel3.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ + +import freechips.rocketchip.resources.{Device, DeviceSnippet, Description, ResourceBinding, ResourceInt} +import freechips.rocketchip.interrupts.{IntIdentityNode, IntSinkNode, IntSinkPortSimple, IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.util.CanHaveErrors + +import freechips.rocketchip.resources.{IntToProperty, StringToProperty} +import freechips.rocketchip.util.BooleanToAugmentedBoolean class NMI(val w: Int) extends Bundle { val rnmi = Bool() diff --git a/src/main/scala/tile/LazyRoCC.scala b/src/main/scala/tile/LazyRoCC.scala index c0218d00312..3b869b9aca4 100644 --- a/src/main/scala/tile/LazyRoCC.scala +++ b/src/main/scala/tile/LazyRoCC.scala @@ -5,12 +5,18 @@ package freechips.rocketchip.tile import chisel3._ import chisel3.util._ -import chisel3.util.HasBlackBoxResource import chisel3.experimental.IntParam + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.rocket._ -import freechips.rocketchip.tilelink._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.rocket.{ + MStatus, HellaCacheIO, TLBPTWIO, CanHavePTW, CanHavePTWModule, + SimpleHellaCacheIF, M_XRD, PTE, PRV, M_SZ +} +import freechips.rocketchip.tilelink.{ + TLNode, TLIdentityNode, TLClientNode, TLMasterParameters, TLMasterPortParameters +} import freechips.rocketchip.util.InOrderArbiter case object BuildRoCC extends Field[Seq[Parameters => LazyRoCC]](Nil) @@ -65,6 +71,7 @@ abstract class LazyRoCC( require(roccCSRs.map(_.id).toSet.size == roccCSRs.size) val atlNode: TLNode = TLIdentityNode() val tlNode: TLNode = TLIdentityNode() + val stlNode: TLNode = TLIdentityNode() } class LazyRoCCModuleImp(outer: LazyRoCC) extends LazyModuleImp(outer) { @@ -81,13 +88,14 @@ trait HasLazyRoCC extends CanHavePTW { this: BaseTile => "LazyRoCC instantiations require overlapping CSRs") roccs.map(_.atlNode).foreach { atl => tlMasterXbar.node :=* atl } roccs.map(_.tlNode).foreach { tl => tlOtherMastersNode :=* tl } + roccs.map(_.stlNode).foreach { stl => stl :*= tlSlaveXbar.node } nPTWPorts += roccs.map(_.nPTWPorts).sum nDCachePorts += roccs.size } trait HasLazyRoCCModule extends CanHavePTWModule - with HasCoreParameters { this: RocketTileModuleImp with HasFpuOpt => + with HasCoreParameters { this: RocketTileModuleImp => val (respArb, cmdRouter) = if(outer.roccs.nonEmpty) { val respArb = Module(new RRArbiter(new RoCCResponse()(outer.p), outer.roccs.size)) @@ -100,23 +108,6 @@ trait HasLazyRoCCModule extends CanHavePTWModule dcachePorts += dcIF.io.cache respArb.io.in(i) <> Queue(rocc.module.io.resp) } - - fpuOpt foreach { fpu => - val nFPUPorts = outer.roccs.count(_.usesFPU) - if (usingFPU && nFPUPorts > 0) { - val fpArb = Module(new InOrderArbiter(new FPInput()(outer.p), new FPResult()(outer.p), nFPUPorts)) - val fp_rocc_ios = outer.roccs.filter(_.usesFPU).map(_.module.io) - fpArb.io.in_req <> fp_rocc_ios.map(_.fpu_req) - fp_rocc_ios.zip(fpArb.io.in_resp).foreach { - case (rocc, arb) => rocc.fpu_resp <> arb - } - fpu.io.cp_req <> fpArb.io.out_req - fpArb.io.out_resp <> fpu.io.cp_resp - } else { - fpu.io.cp_req.valid := false.B - fpu.io.cp_resp.ready := false.B - } - } (Some(respArb), Some(cmdRouter)) } else { (None, None) @@ -193,6 +184,7 @@ class AccumulatorExampleModuleImp(outer: AccumulatorExample)(implicit p: Paramet io.mem.req.bits.phys := false.B io.mem.req.bits.dprv := cmd.bits.status.dprv io.mem.req.bits.dv := cmd.bits.status.dv + io.mem.req.bits.no_resp := false.B } class TranslatorExample(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opcodes, nPTWPorts = 1) { diff --git a/src/main/scala/tile/LookupByHartId.scala b/src/main/scala/tile/LookupByHartId.scala index 263dd43c66f..631bb8f651e 100644 --- a/src/main/scala/tile/LookupByHartId.scala +++ b/src/main/scala/tile/LookupByHartId.scala @@ -10,10 +10,10 @@ abstract class LookupByHartIdImpl { } case class HartsWontDeduplicate(t: TileParams) extends LookupByHartIdImpl { - def apply[T <: Data](f: TileParams => Option[T], hartId: UInt): T = f(t).get + def apply[T <: Data](f: TileParams => Option[T], tileId: UInt): T = f(t).get } case class PriorityMuxHartIdFromSeq(seq: Seq[TileParams]) extends LookupByHartIdImpl { - def apply[T <: Data](f: TileParams => Option[T], hartId: UInt): T = - PriorityMux(seq.collect { case t if f(t).isDefined => (t.hartId.U === hartId) -> f(t).get }) + def apply[T <: Data](f: TileParams => Option[T], tileId: UInt): T = + PriorityMux(seq.collect { case t if f(t).isDefined => (t.tileId.U === tileId) -> f(t).get }) } diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 930d803e392..619e7d836ca 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -4,15 +4,29 @@ package freechips.rocketchip.tile import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.rocket._ -import freechips.rocketchip.subsystem.TileCrossingParamsLike -import freechips.rocketchip.util._ -import freechips.rocketchip.prci.{ClockSinkParameters} +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.devices.tilelink.{BasicBusBlockerParams, BasicBusBlocker} +import freechips.rocketchip.diplomacy.{ + AddressSet, DisableMonitors, BufferParams +} +import freechips.rocketchip.resources.{ + SimpleDevice, Description, + ResourceAnchors, ResourceBindings, ResourceBinding, Resource, ResourceAddress, +} +import freechips.rocketchip.interrupts.IntIdentityNode +import freechips.rocketchip.tilelink.{TLIdentityNode, TLBuffer} +import freechips.rocketchip.rocket.{ + RocketCoreParams, ICacheParams, DCacheParams, BTBParams, HasHellaCache, + HasICacheFrontend, ScratchpadSlavePort, HasICacheFrontendModule, Rocket +} +import freechips.rocketchip.subsystem.HierarchicalElementCrossingParamsLike +import freechips.rocketchip.prci.{ClockSinkParameters, RationalCrossing, ClockCrossingType} +import freechips.rocketchip.util.{Annotated, InOrderArbiter} + +import freechips.rocketchip.util.BooleanToAugmentedBoolean case class RocketTileBoundaryBufferParams(force: Boolean = false) @@ -22,16 +36,17 @@ case class RocketTileParams( dcache: Option[DCacheParams] = Some(DCacheParams()), btb: Option[BTBParams] = Some(BTBParams()), dataScratchpadBytes: Int = 0, - name: Option[String] = Some("tile"), - hartId: Int = 0, + tileId: Int = 0, beuAddr: Option[BigInt] = None, blockerCtrlAddr: Option[BigInt] = None, clockSinkParams: ClockSinkParameters = ClockSinkParameters(), boundaryBuffers: Option[RocketTileBoundaryBufferParams] = None - ) extends InstantiableTileParams[RocketTile] { + ) extends InstantiableTileParams[RocketTile] { require(icache.isDefined) require(dcache.isDefined) - def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): RocketTile = { + val baseName = "rockettile" + val uniqueName = s"${baseName}_$tileId" + def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): RocketTile = { new RocketTile(this, crossing, lookup) } } @@ -49,10 +64,10 @@ class RocketTile private( with HasICacheFrontend { // Private constructor ensures altered LazyModule.p is used implicitly - def this(params: RocketTileParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) = + def this(params: RocketTileParams, crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) = this(params, crossing.crossingType, lookup, p) - val intOutwardNode = IntIdentityNode() + val intOutwardNode = rocketParams.beuAddr map { _ => IntIdentityNode() } val slaveNode = TLIdentityNode() val masterNode = visibilityNode @@ -62,8 +77,8 @@ class RocketTile private( dtim_adapter.foreach(lm => connectTLSlave(lm.node, lm.node.portParams.head.beatBytes)) val bus_error_unit = rocketParams.beuAddr map { a => - val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a))) - intOutwardNode := beu.intNode + val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a), xLen/8)) + intOutwardNode.get := beu.intNode connectTLSlave(beu.node, xBytes) beu } @@ -80,7 +95,7 @@ class RocketTile private( masterNode :=* tlOtherMastersNode DisableMonitors { implicit p => tlSlaveXbar.node :*= slaveNode } - nDCachePorts += 1 /*core */ + (dtim_adapter.isDefined).toInt + nDCachePorts += 1 /*core */ + (dtim_adapter.isDefined).toInt + rocketParams.core.vector.map(_.useDCache.toInt).getOrElse(0) val dtimProperty = dtim_adapter.map(d => Map( "sifive,dtim" -> d.device.asProperty)).getOrElse(Nil) @@ -99,8 +114,13 @@ class RocketTile private( } } + val vector_unit = rocketParams.core.vector.map(v => LazyModule(v.build(p))) + vector_unit.foreach(vu => tlMasterXbar.node :=* vu.atlNode) + vector_unit.foreach(vu => tlOtherMastersNode :=* vu.tlNode) + + ResourceBinding { - Resource(cpuDevice, "reg").bind(ResourceAddress(staticIdForMetadataUseOnly)) + Resource(cpuDevice, "reg").bind(ResourceAddress(tileId)) } override lazy val module = new RocketTileModuleImp(this) @@ -125,6 +145,10 @@ class RocketTileModuleImp(outer: RocketTile) extends BaseTileModuleImp(outer) Annotated.params(this, outer.rocketParams) val core = Module(new Rocket(outer)(outer.p)) + outer.vector_unit.foreach { v => + core.io.vector.get <> v.module.io.core + v.module.io.tlb <> outer.dcache.module.io.tlb_port + } // reset vector is connected in the Frontend to s2_pc core.io.reset_vector := DontCare @@ -149,7 +173,7 @@ class RocketTileModuleImp(outer: RocketTile) extends BaseTileModuleImp(outer) beu.module.io.errors.icache := outer.frontend.module.io.errors } - core.io.interrupts.nmi.foreach { nmi => nmi := outer.nmiSinkNode.bundle } + core.io.interrupts.nmi.foreach { nmi => nmi := outer.nmiSinkNode.get.bundle } // Pass through various external constants and reports that were bundle-bridged into the tile outer.traceSourceNode.bundle <> core.io.trace @@ -164,12 +188,15 @@ class RocketTileModuleImp(outer: RocketTile) extends BaseTileModuleImp(outer) dcachePorts += core.io.dmem // TODO outer.dcachePorts += () => module.core.io.dmem ?? fpuOpt foreach { fpu => core.io.fpu :<>= fpu.io.waiveAs[FPUCoreIO](_.cp_req, _.cp_resp) - fpu.io.cp_req := DontCare - fpu.io.cp_resp := DontCare } if (fpuOpt.isEmpty) { core.io.fpu := DontCare } + outer.vector_unit foreach { v => if (outer.rocketParams.core.vector.get.useDCache) { + dcachePorts += v.module.io.dmem + } else { + v.module.io.dmem := DontCare + } } core.io.ptw <> ptw.io.dpath // Connect the coprocessor interfaces @@ -213,4 +240,27 @@ class RocketTileModuleImp(outer: RocketTile) extends BaseTileModuleImp(outer) trait HasFpuOpt { this: RocketTileModuleImp => val fpuOpt = outer.tileParams.core.fpu.map(params => Module(new FPU(params)(outer.p))) + fpuOpt.foreach { fpu => + val nRoCCFPUPorts = outer.roccs.count(_.usesFPU) + val nFPUPorts = nRoCCFPUPorts + outer.rocketParams.core.useVector.toInt + if (nFPUPorts > 0) { + val fpArb = Module(new InOrderArbiter(new FPInput()(outer.p), new FPResult()(outer.p), nFPUPorts)) + fpu.io.cp_req <> fpArb.io.out_req + fpArb.io.out_resp <> fpu.io.cp_resp + + val fp_rocc_ios = outer.roccs.filter(_.usesFPU).map(_.module.io) + for (i <- 0 until nRoCCFPUPorts) { + fpArb.io.in_req(i) <> fp_rocc_ios(i).fpu_req + fp_rocc_ios(i).fpu_resp <> fpArb.io.in_resp(i) + } + outer.vector_unit.foreach(vu => { + fpArb.io.in_req(nRoCCFPUPorts) <> vu.module.io.fp_req + vu.module.io.fp_resp <> fpArb.io.in_resp(nRoCCFPUPorts) + }) + } else { + fpu.io.cp_req.valid := false.B + fpu.io.cp_req.bits := DontCare + fpu.io.cp_resp.ready := false.B + } + } } diff --git a/src/main/scala/tile/TilePRCIDomain.scala b/src/main/scala/tile/TilePRCIDomain.scala index 73972bec4de..80c31f5a4d7 100644 --- a/src/main/scala/tile/TilePRCIDomain.scala +++ b/src/main/scala/tile/TilePRCIDomain.scala @@ -2,30 +2,15 @@ package freechips.rocketchip.tile -import chisel3.Vec -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.prci._ -import freechips.rocketchip.rocket.{TracedInstruction} -import freechips.rocketchip.subsystem.{TileCrossingParamsLike, CrossesToOnlyOneResetDomain} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util.{TraceCoreInterface} +import chisel3._ + +import org.chipsalliance.cde.config._ + +import freechips.rocketchip.prci.ClockSinkParameters +import freechips.rocketchip.rocket.TracedInstruction +import freechips.rocketchip.subsystem.{HierarchicalElementCrossingParamsLike, HierarchicalElementPRCIDomain} +import freechips.rocketchip.util.TraceCoreInterface -/** A wrapper containing all logic within a managed reset domain for a tile. - * - * This does not add a layer of the module hierarchy. - */ -class TileResetDomain(clockSinkParams: ClockSinkParameters, resetCrossingType: ResetCrossingType) - (implicit p: Parameters) - extends ResetDomain - with CrossesToOnlyOneResetDomain -{ - def crossing = resetCrossingType - val clockNode = ClockSinkNode(Seq(clockSinkParams)) - def clockBundle = clockNode.in.head._1 - override def shouldBeInlined = true -} /** A wrapper containing all logic necessary to safely place a tile * inside of a particular Power/Reset/Clock/Interrupt domain. @@ -37,77 +22,9 @@ class TileResetDomain(clockSinkParams: ClockSinkParameters, resetCrossingType: R */ abstract class TilePRCIDomain[T <: BaseTile]( clockSinkParams: ClockSinkParameters, - crossingParams: TileCrossingParamsLike) + crossingParams: HierarchicalElementCrossingParamsLike) (implicit p: Parameters) - extends ClockDomain + extends HierarchicalElementPRCIDomain[T](clockSinkParams, crossingParams) { - val tile: T - val tile_reset_domain = LazyModule(new TileResetDomain(clockSinkParams, crossingParams.resetCrossingType)) - val tapClockNode = ClockIdentityNode() - val clockNode = FixedClockBroadcast(None) :=* tapClockNode - lazy val clockBundle = tapClockNode.in.head._1 - - private val traceSignalName = "trace" - private val traceCoreSignalName = "tracecore" - /** Node to broadcast legacy "raw" instruction trace while surpressing it during (async) reset. */ - val traceNode: BundleBridgeIdentityNode[TraceBundle] = BundleBridgeNameNode(traceSignalName) - /** Node to broadcast standardized instruction trace while surpressing it during (async) reset. */ - val traceCoreNode: BundleBridgeIdentityNode[TraceCoreInterface] = BundleBridgeNameNode(traceCoreSignalName) - - /** Function to handle all trace crossings when tile is instantiated inside domains */ - def crossTracesOut(): Unit = this { - val traceNexusNode = BundleBridgeBlockDuringReset[TraceBundle]( - resetCrossingType = crossingParams.resetCrossingType, - name = Some(traceSignalName)) - traceNode :*= traceNexusNode := tile.traceNode - - val traceCoreNexusNode = BundleBridgeBlockDuringReset[TraceCoreInterface]( - resetCrossingType = crossingParams.resetCrossingType, - name = Some(traceCoreSignalName)) - traceCoreNode :*= traceCoreNexusNode := tile.traceCoreNode - } - - /** External code looking to connect and clock-cross the interrupts driven into this tile can call this. */ - def crossIntIn(crossingType: ClockCrossingType): IntInwardNode = { - // Unlike the other crossing helpers, here nothing is is blocked during reset because we know these are inputs and assume that tile reset is longer than uncore reset - val intInClockXing = this.crossIn(tile.intInwardNode) - intInClockXing(crossingType) - } - - /** External code looking to connect and clock/reset-cross - * - interrupts raised by devices inside this tile - * - notifications raise by the cores and caches - * can call this function to instantiate the required crossing hardware. - * Takes crossingType as an argument because some interrupts are supposed to be synchronous - * Takes tileNode as an argument because tiles might have multiple outbound interrupt nodes - */ - def crossIntOut(crossingType: ClockCrossingType, tileNode: IntOutwardNode): IntOutwardNode = { - val intOutResetXing = this { tile_reset_domain.crossIntOut(tileNode) } - val intOutClockXing = this.crossOut(intOutResetXing) - intOutClockXing(crossingType) - } - - /** External code looking to connect the ports where this tile is slaved to an interconnect - * (while also crossing clock domains) can call this. - */ - def crossSlavePort(crossingType: ClockCrossingType): TLInwardNode = { DisableMonitors { implicit p => FlipRendering { implicit p => - val tlSlaveResetXing = this { - tile_reset_domain.crossTLIn(tile.slaveNode) :*= - tile { tile.makeSlaveBoundaryBuffers(crossingType) } - } - val tlSlaveClockXing = this.crossIn(tlSlaveResetXing) - tlSlaveClockXing(crossingType) - } } } - - /** External code looking to connect the ports where this tile masters an interconnect - * (while also crossing clock domains) can call this. - */ - def crossMasterPort(crossingType: ClockCrossingType): TLOutwardNode = { - val tlMasterResetXing = this { DisableMonitors { implicit p => - tile { tile.makeMasterBoundaryBuffers(crossingType) } :=* - tile_reset_domain.crossTLOut(tile.masterNode) - } } - val tlMasterClockXing = this.crossOut(tlMasterResetXing) - tlMasterClockXing(crossingType) - } + def tile_reset_domain = element_reset_domain } diff --git a/src/main/scala/tilelink/AddressAdjuster.scala b/src/main/scala/tilelink/AddressAdjuster.scala index d4a1fc7bbf1..c9de5710ed2 100644 --- a/src/main/scala/tilelink/AddressAdjuster.scala +++ b/src/main/scala/tilelink/AddressAdjuster.scala @@ -4,8 +4,12 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet class AddressAdjuster( val params: ReplicatedRegion, // only devices in this region get adjusted diff --git a/src/main/scala/tilelink/AsyncCrossing.scala b/src/main/scala/tilelink/AsyncCrossing.scala index f974cf3e270..3eb96dd3c74 100644 --- a/src/main/scala/tilelink/AsyncCrossing.scala +++ b/src/main/scala/tilelink/AsyncCrossing.scala @@ -3,11 +3,14 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, NodeHandle} +import freechips.rocketchip.prci.{AsynchronousCrossing} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property +import freechips.rocketchip.util.{AsyncQueueParams, ToAsyncBundle, FromAsyncBundle, Pow2ClockDivider, property} class TLAsyncCrossingSource(sync: Option[Int])(implicit p: Parameters) extends LazyModule { @@ -18,6 +21,7 @@ class TLAsyncCrossingSource(sync: Option[Int])(implicit p: Parameters) extends L lazy val module = new Impl class Impl extends LazyModuleImp(this) { + override def desiredName = (Seq("TLAsyncCrossingSource") ++ node.in.headOption.map(_._2.bundle.shortName)).mkString("_") (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe val psync = sync.getOrElse(edgeOut.manager.async.sync) @@ -53,6 +57,7 @@ class TLAsyncCrossingSink(params: AsyncQueueParams = AsyncQueueParams())(implici lazy val module = new Impl class Impl extends LazyModuleImp(this) { + override def desiredName = (Seq("TLAsyncCrossingSink") ++ node.out.headOption.map(_._2.bundle.shortName)).mkString("_") (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe diff --git a/src/main/scala/tilelink/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala index 3bf633db0fb..5f0fc655fdc 100644 --- a/src/main/scala/tilelink/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -3,11 +3,15 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} +import freechips.rocketchip.util.leftOR + import scala.math.{min,max} -import chisel3.util.{PriorityMux, Cat, FillInterleaved, Mux1H, MuxLookup, log2Up} // Ensures that all downstream RW managers support Atomic operations. // If !passthrough, intercept all Atomics. Otherwise, only intercept those unsupported downstream. @@ -178,7 +182,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc when (en) { r.fifoId := a_fifoId r.bits := in.a.bits - r.lut := MuxLookup(in.a.bits.param(1, 0), 0.U(4.W), Array( + r.lut := MuxLookup(in.a.bits.param(1, 0), 0.U(4.W))(Array( TLAtomics.AND -> 0x8.U, TLAtomics.OR -> 0xe.U, TLAtomics.XOR -> 0x6.U, @@ -280,9 +284,11 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc object TLAtomicAutomata { - def apply(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true)(implicit p: Parameters): TLNode = + def apply(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true, nameSuffix: Option[String] = None)(implicit p: Parameters): TLNode = { - val atomics = LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough)) + val atomics = LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough) { + override lazy val desiredName = (Seq("TLAtomicAutomata") ++ nameSuffix).mkString("_") + }) atomics.node } diff --git a/src/main/scala/tilelink/BankBinder.scala b/src/main/scala/tilelink/BankBinder.scala index 8859123754d..21b32729a3d 100644 --- a/src/main/scala/tilelink/BankBinder.scala +++ b/src/main/scala/tilelink/BankBinder.scala @@ -2,8 +2,11 @@ package freechips.rocketchip.tilelink -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} case class BankBinderNode(mask: BigInt)(implicit valName: ValName) extends TLCustomNode { diff --git a/src/main/scala/tilelink/BlockDuringReset.scala b/src/main/scala/tilelink/BlockDuringReset.scala index ec676b6fff4..4dc6b2c29ce 100644 --- a/src/main/scala/tilelink/BlockDuringReset.scala +++ b/src/main/scala/tilelink/BlockDuringReset.scala @@ -3,8 +3,10 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.util.BlockDuringReset /** BlockDuringReset ensures that no channel admits to be ready or valid while reset is raised. */ diff --git a/src/main/scala/tilelink/Broadcast.scala b/src/main/scala/tilelink/Broadcast.scala index 0e69bd5d60f..f73cdb97cd0 100644 --- a/src/main/scala/tilelink/Broadcast.scala +++ b/src/main/scala/tilelink/Broadcast.scala @@ -4,12 +4,19 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.interrupts._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.amba.AMBAProt +import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, IdRange, RegionType, TransferSizes} +import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.regmapper.RegField +import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.util.leftOR + +import freechips.rocketchip.util.DataToAugmentedData + import scala.math.{min,max} case class TLBroadcastControlParams( diff --git a/src/main/scala/tilelink/Buffer.scala b/src/main/scala/tilelink/Buffer.scala index 8f43017028c..63fd8ed917f 100644 --- a/src/main/scala/tilelink/Buffer.scala +++ b/src/main/scala/tilelink/Buffer.scala @@ -3,8 +3,12 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.BufferParams class TLBufferNode ( a: BufferParams, @@ -34,6 +38,8 @@ class TLBuffer( lazy val module = new Impl class Impl extends LazyModuleImp(this) { + def headBundle = node.out.head._2.bundle + override def desiredName = (Seq("TLBuffer") ++ node.out.headOption.map(_._2.bundle.shortName)).mkString("_") (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => out.a <> a(in .a) in .d <> d(out.d) diff --git a/src/main/scala/tilelink/Bundles.scala b/src/main/scala/tilelink/Bundles.scala index 5bb53dfe429..735e0839af8 100644 --- a/src/main/scala/tilelink/Bundles.scala +++ b/src/main/scala/tilelink/Bundles.scala @@ -173,6 +173,7 @@ sealed trait TLAddrChannel extends TLDataChannel final class TLBundleA(params: TLBundleParameters) extends TLBundleBase(params) with TLAddrChannel { + override def typeName = s"TLBundleA_${params.shortName}" val channelName = "'A' channel" // fixed fields during multibeat: val opcode = UInt(3.W) @@ -190,6 +191,7 @@ final class TLBundleA(params: TLBundleParameters) final class TLBundleB(params: TLBundleParameters) extends TLBundleBase(params) with TLAddrChannel { + override def typeName = s"TLBundleB_${params.shortName}" val channelName = "'B' channel" // fixed fields during multibeat: val opcode = UInt(3.W) @@ -206,6 +208,7 @@ final class TLBundleB(params: TLBundleParameters) final class TLBundleC(params: TLBundleParameters) extends TLBundleBase(params) with TLAddrChannel { + override def typeName = s"TLBundleC_${params.shortName}" val channelName = "'C' channel" // fixed fields during multibeat: val opcode = UInt(3.W) @@ -223,6 +226,7 @@ final class TLBundleC(params: TLBundleParameters) final class TLBundleD(params: TLBundleParameters) extends TLBundleBase(params) with TLDataChannel { + override def typeName = s"TLBundleD_${params.shortName}" val channelName = "'D' channel" // fixed fields during multibeat: val opcode = UInt(3.W) @@ -241,6 +245,7 @@ final class TLBundleD(params: TLBundleParameters) final class TLBundleE(params: TLBundleParameters) extends TLBundleBase(params) with TLChannel { + override def typeName = s"TLBundleE_${params.shortName}" val channelName = "'E' channel" val sink = UInt(params.sinkBits.W) // to } diff --git a/src/main/scala/tilelink/BusWrapper.scala b/src/main/scala/tilelink/BusWrapper.scala index 657bba873f6..c95a572de1e 100644 --- a/src/main/scala/tilelink/BusWrapper.scala +++ b/src/main/scala/tilelink/BusWrapper.scala @@ -4,15 +4,28 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.diplomacy.{AddressSet, NoHandle, NodeHandle, NodeBinding} // TODO This class should be moved to package subsystem to resolve // the dependency awkwardness of the following imports -import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.prci._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.util._ +import freechips.rocketchip.devices.tilelink.{BuiltInDevices, CanHaveBuiltInDevices} +import freechips.rocketchip.prci.{ + ClockParameters, ClockDomain, ClockGroup, ClockGroupAggregator, ClockSinkNode, + FixedClockBroadcast, ClockGroupEdgeParameters, ClockSinkParameters, ClockSinkDomain, + ClockGroupEphemeralNode, asyncMux, ClockCrossingType, NoCrossing +} +import freechips.rocketchip.subsystem.{ + HasTileLinkLocations, CanConnectWithinContextThatHasTileLinkLocations, + CanInstantiateWithinContextThatHasTileLinkLocations +} +import freechips.rocketchip.util.Location /** Specifies widths of various attachement points in the SoC */ trait HasTLBusParams { @@ -72,15 +85,21 @@ abstract class TLBusWrapper(params: HasTLBusParams, val busName: String)(implici def unifyManagers: List[TLManagerParameters] = ManagerUnification(busView.manager.managers) def crossOutHelper = this.crossOut(outwardNode)(ValName("bus_xing")) def crossInHelper = this.crossIn(inwardNode)(ValName("bus_xing")) + def generateSynchronousDomain(domainName: String): ClockSinkDomain = { + val domain = LazyModule(new ClockSinkDomain(take = fixedClockOpt, name = Some(domainName))) + domain.clockNode := fixedClockNode + domain + } + def generateSynchronousDomain: ClockSinkDomain = generateSynchronousDomain("") protected val addressPrefixNexusNode = BundleBroadcast[UInt](registered = false, default = Some(() => 0.U(1.W))) def to[T](name: String)(body: => T): T = { - this { LazyScope(s"coupler_to_${name}", "TLInterconnectCoupler") { body } } + this { LazyScope(s"coupler_to_${name}", s"TLInterconnectCoupler_${busName}_to_${name}") { body } } } def from[T](name: String)(body: => T): T = { - this { LazyScope(s"coupler_from_${name}", "TLInterconnectCoupler") { body } } + this { LazyScope(s"coupler_from_${name}", s"TLInterconnectCoupler_${busName}_from_${name}") { body } } } def coupleTo[T](name: String)(gen: TLOutwardNode => T): T = @@ -89,15 +108,15 @@ abstract class TLBusWrapper(params: HasTLBusParams, val busName: String)(implici def coupleFrom[T](name: String)(gen: TLInwardNode => T): T = from(name) { gen(inwardNode :*=* TLNameNode("tl")) } - def crossToBus(bus: TLBusWrapper, xType: ClockCrossingType)(implicit asyncClockGroupNode: ClockGroupEphemeralNode): NoHandle = { - bus.clockGroupNode := asyncMux(xType, asyncClockGroupNode, this.clockGroupNode) + def crossToBus(bus: TLBusWrapper, xType: ClockCrossingType, allClockGroupNode: ClockGroupEphemeralNode): NoHandle = { + bus.clockGroupNode := asyncMux(xType, allClockGroupNode, this.clockGroupNode) coupleTo(s"bus_named_${bus.busName}") { bus.crossInHelper(xType) :*= TLWidthWidget(beatBytes) :*= _ } } - def crossFromBus(bus: TLBusWrapper, xType: ClockCrossingType)(implicit asyncClockGroupNode: ClockGroupEphemeralNode): NoHandle = { - bus.clockGroupNode := asyncMux(xType, asyncClockGroupNode, this.clockGroupNode) + def crossFromBus(bus: TLBusWrapper, xType: ClockCrossingType, allClockGroupNode: ClockGroupEphemeralNode): NoHandle = { + bus.clockGroupNode := asyncMux(xType, allClockGroupNode, this.clockGroupNode) coupleFrom(s"bus_named_${bus.busName}") { _ :=* TLWidthWidget(bus.beatBytes) :=* bus.crossOutHelper(xType) } @@ -178,8 +197,8 @@ class TLBusWrapperConnection val masterTLBus = context.locateTLBusWrapper(master) val slaveTLBus = context.locateTLBusWrapper(slave) def bindClocks(implicit p: Parameters) = driveClockFromMaster match { - case Some(true) => slaveTLBus.clockGroupNode := asyncMux(xType, context.asyncClockGroupsNode, masterTLBus.clockGroupNode) - case Some(false) => masterTLBus.clockGroupNode := asyncMux(xType, context.asyncClockGroupsNode, slaveTLBus.clockGroupNode) + case Some(true) => slaveTLBus.clockGroupNode := asyncMux(xType, context.allClockGroupsNode, masterTLBus.clockGroupNode) + case Some(false) => masterTLBus.clockGroupNode := asyncMux(xType, context.allClockGroupsNode, slaveTLBus.clockGroupNode) case None => } def bindTLNodes(implicit p: Parameters) = nodeBinding match { @@ -218,7 +237,7 @@ class TLBusWrapperTopology( } trait HasTLXbarPhy { this: TLBusWrapper => - private val xbar = LazyModule(new TLXbar).suggestName(busName + "_xbar") + private val xbar = LazyModule(new TLXbar(nameSuffix = Some(busName))).suggestName(busName + "_xbar") override def shouldBeInlined = xbar.node.circuitIdentity def inwardNode: TLInwardNode = xbar.node @@ -240,8 +259,8 @@ case class AddressAdjusterWrapperParams( { val dtsFrequency = None def instantiate(context: HasTileLinkLocations, loc: Location[TLBusWrapper])(implicit p: Parameters): AddressAdjusterWrapper = { - val aaWrapper = LazyModule(new AddressAdjusterWrapper(this, loc.name)) - aaWrapper.suggestName(loc.name + "_wrapper") + val aaWrapper = LazyModule(new AddressAdjusterWrapper(this, context.busContextName + "_" + loc.name)) + aaWrapper.suggestName(context.busContextName + "_" + loc.name + "_wrapper") context.tlBusWrapperLocationMap += (loc -> aaWrapper) aaWrapper } @@ -270,8 +289,8 @@ case class TLJBarWrapperParams( { val dtsFrequency = None def instantiate(context: HasTileLinkLocations, loc: Location[TLBusWrapper])(implicit p: Parameters): TLJBarWrapper = { - val jbarWrapper = LazyModule(new TLJBarWrapper(this, loc.name)) - jbarWrapper.suggestName(loc.name + "_wrapper") + val jbarWrapper = LazyModule(new TLJBarWrapper(this, context.busContextName + "_" + loc.name)) + jbarWrapper.suggestName(context.busContextName + "_" + loc.name + "_wrapper") context.tlBusWrapperLocationMap += (loc -> jbarWrapper) jbarWrapper } diff --git a/src/main/scala/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index 8ba1e4b9d7f..a8518d97dee 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -4,10 +4,18 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import TLMessages._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{IdRange, RegionType, TransferSizes} +import freechips.rocketchip.tilelink.TLMessages.{ + AcquireBlock, AcquirePerm, Get, PutFullData, PutPartialData, Release, + ReleaseData, Grant, GrantData, AccessAck, AccessAckData, ReleaseAck +} +import freechips.rocketchip.util.IDPool + +import freechips.rocketchip.util.DataToAugmentedData case class TLCacheCorkParams( unsafe: Boolean = false, diff --git a/src/main/scala/tilelink/Credited.scala b/src/main/scala/tilelink/Credited.scala index 30c73486012..e8a1085f273 100644 --- a/src/main/scala/tilelink/Credited.scala +++ b/src/main/scala/tilelink/Credited.scala @@ -3,11 +3,15 @@ package freechips.rocketchip.tilelink import chisel3._ -import chisel3.util.Decoupled -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet} +import freechips.rocketchip.prci.{CreditedCrossing} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util._ +import freechips.rocketchip.util.{CreditedDelay, CreditedIO} class TLCreditedBuffer(delay: TLCreditedDelay)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/CrossingHelper.scala b/src/main/scala/tilelink/CrossingHelper.scala index 52d96d6f432..fd4bd2e74ce 100644 --- a/src/main/scala/tilelink/CrossingHelper.scala +++ b/src/main/scala/tilelink/CrossingHelper.scala @@ -2,9 +2,13 @@ package freechips.rocketchip.tilelink -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.prci._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.prci.{ + AsynchronousCrossing, CrossingType, ClockCrossingType, NoCrossing, + RationalCrossing, CreditedCrossing, SynchronousCrossing, + ResetCrossingType, NoResetCrossing, StretchedResetCrossing} trait TLOutwardCrossingHelper { type HelperCrossingType <: CrossingType diff --git a/src/main/scala/tilelink/Delayer.scala b/src/main/scala/tilelink/Delayer.scala index eb70bc5e4d5..bb984787938 100644 --- a/src/main/scala/tilelink/Delayer.scala +++ b/src/main/scala/tilelink/Delayer.scala @@ -4,8 +4,9 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ // q is the probability to delay a request class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule @@ -30,6 +31,8 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule anoise.size := LFSRNoiseMaker(anoise.params.sizeBits) anoise.source := LFSRNoiseMaker(anoise.params.sourceBits) anoise.address := LFSRNoiseMaker(anoise.params.addressBits) + anoise.user := DontCare + anoise.echo := DontCare anoise.mask := LFSRNoiseMaker(anoise.params.dataBits/8) anoise.data := LFSRNoiseMaker(anoise.params.dataBits) anoise.corrupt := LFSRNoiseMaker(1) @@ -50,6 +53,8 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule cnoise.size := LFSRNoiseMaker(cnoise.params.sizeBits) cnoise.source := LFSRNoiseMaker(cnoise.params.sourceBits) cnoise.address := LFSRNoiseMaker(cnoise.params.addressBits) + cnoise.user := DontCare + cnoise.echo := DontCare cnoise.data := LFSRNoiseMaker(cnoise.params.dataBits) cnoise.corrupt := LFSRNoiseMaker(1)(0) @@ -60,6 +65,8 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule dnoise.source := LFSRNoiseMaker(dnoise.params.sourceBits) dnoise.sink := LFSRNoiseMaker(dnoise.params.sinkBits) dnoise.denied := LFSRNoiseMaker(1)(0) + dnoise.user := DontCare + dnoise.echo := DontCare dnoise.data := LFSRNoiseMaker(dnoise.params.dataBits) dnoise.corrupt := LFSRNoiseMaker(1)(0) diff --git a/src/main/scala/tilelink/Edges.scala b/src/main/scala/tilelink/Edges.scala index 2c555c03ac2..ef56eb733c6 100644 --- a/src/main/scala/tilelink/Edges.scala +++ b/src/main/scala/tilelink/Edges.scala @@ -4,7 +4,6 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import chisel3.internal.sourceinfo.SourceInfo import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.util._ @@ -274,17 +273,17 @@ class TLEdge( // Does the request need T permissions to be executed? def needT(a: TLBundleA): Bool = { - val acq_needT = MuxLookup(a.param, WireDefault(Bool(), DontCare), Array( + val acq_needT = MuxLookup(a.param, WireDefault(Bool(), DontCare))(Array( TLPermissions.NtoB -> false.B, TLPermissions.NtoT -> true.B, TLPermissions.BtoT -> true.B)) - MuxLookup(a.opcode, WireDefault(Bool(), DontCare), Array( + MuxLookup(a.opcode, WireDefault(Bool(), DontCare))(Array( TLMessages.PutFullData -> true.B, TLMessages.PutPartialData -> true.B, TLMessages.ArithmeticData -> true.B, TLMessages.LogicalData -> true.B, TLMessages.Get -> false.B, - TLMessages.Hint -> MuxLookup(a.param, WireDefault(Bool(), DontCare), Array( + TLMessages.Hint -> MuxLookup(a.param, WireDefault(Bool(), DontCare))(Array( TLHints.PREFETCH_READ -> false.B, TLHints.PREFETCH_WRITE -> true.B)), TLMessages.AcquireBlock -> acq_needT, @@ -345,14 +344,15 @@ class TLEdgeOut( require (manager.anySupportAcquireB, s"TileLink: No managers visible from this edge support Acquires, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsAcquireBFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.AcquireBlock a.param := growPermissions a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) - a.data := 0.U + a.data := DontCare a.corrupt := false.B (legal, a) } @@ -366,8 +366,10 @@ class TLEdgeOut( a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) - a.data := 0.U + a.data := DontCare a.corrupt := false.B (legal, a) } @@ -376,13 +378,14 @@ class TLEdgeOut( require (manager.anySupportAcquireB, s"TileLink: No managers visible from this edge support Acquires, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsAcquireBFast(toAddress, lgSize) val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.Release c.param := shrinkPermissions c.size := lgSize c.source := fromSource c.address := toAddress - c.data := 0.U + c.user := DontCare + c.echo := DontCare + c.data := DontCare c.corrupt := false.B (legal, c) } @@ -391,12 +394,13 @@ class TLEdgeOut( require (manager.anySupportAcquireB, s"TileLink: No managers visible from this edge support Acquires, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsAcquireBFast(toAddress, lgSize) val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.ReleaseData c.param := shrinkPermissions c.size := lgSize c.source := fromSource c.address := toAddress + c.user := DontCare + c.echo := DontCare c.data := data c.corrupt := corrupt (legal, c) @@ -410,13 +414,14 @@ class TLEdgeOut( def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt): TLBundleC = { val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.ProbeAck c.param := reportPermissions c.size := lgSize c.source := fromSource c.address := toAddress - c.data := 0.U + c.user := DontCare + c.echo := DontCare + c.data := DontCare c.corrupt := false.B c } @@ -426,12 +431,13 @@ class TLEdgeOut( def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt, data: UInt, corrupt: Bool): TLBundleC = { val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.ProbeAckData c.param := reportPermissions c.size := lgSize c.source := fromSource c.address := toAddress + c.user := DontCare + c.echo := DontCare c.data := data c.corrupt := corrupt c @@ -452,14 +458,15 @@ class TLEdgeOut( require (manager.anySupportGet, s"TileLink: No managers visible from this edge support Gets, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsGetFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.Get a.param := 0.U a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) - a.data := 0.U + a.data := DontCare a.corrupt := false.B (legal, a) } @@ -471,12 +478,13 @@ class TLEdgeOut( require (manager.anySupportPutFull, s"TileLink: No managers visible from this edge support Puts, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsPutFullFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.PutFullData a.param := 0.U a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) a.data := data a.corrupt := corrupt @@ -490,12 +498,13 @@ class TLEdgeOut( require (manager.anySupportPutPartial, s"TileLink: No managers visible from this edge support masked Puts, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsPutPartialFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.PutPartialData a.param := 0.U a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask a.data := data a.corrupt := corrupt @@ -506,12 +515,13 @@ class TLEdgeOut( require (manager.anySupportArithmetic, s"TileLink: No managers visible from this edge support arithmetic AMOs, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsArithmeticFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.ArithmeticData a.param := atomic a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) a.data := data a.corrupt := corrupt @@ -522,12 +532,13 @@ class TLEdgeOut( require (manager.anySupportLogical, s"TileLink: No managers visible from this edge support logical AMOs, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsLogicalFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.LogicalData a.param := atomic a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) a.data := data a.corrupt := corrupt @@ -538,14 +549,15 @@ class TLEdgeOut( require (manager.anySupportHint, s"TileLink: No managers visible from this edge support Hints, but one of these clients would try to request one: ${client.clients}") val legal = manager.supportsHintFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a :#= DontCare a.opcode := TLMessages.Hint a.param := param a.size := lgSize a.source := fromSource a.address := toAddress + a.user := DontCare + a.echo := DontCare a.mask := mask(toAddress, lgSize) - a.data := 0.U + a.data := DontCare a.corrupt := false.B (legal, a) } @@ -553,13 +565,14 @@ class TLEdgeOut( def AccessAck(b: TLBundleB): TLBundleC = AccessAck(b.source, address(b), b.size) def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt) = { val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.AccessAck c.param := 0.U c.size := lgSize c.source := fromSource c.address := toAddress - c.data := 0.U + c.user := DontCare + c.echo := DontCare + c.data := DontCare c.corrupt := false.B c } @@ -569,12 +582,13 @@ class TLEdgeOut( def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt): TLBundleC = AccessAck(fromSource, toAddress, lgSize, data, false.B) def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, corrupt: Bool) = { val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.AccessAckData c.param := 0.U c.size := lgSize c.source := fromSource c.address := toAddress + c.user := DontCare + c.echo := DontCare c.data := data c.corrupt := corrupt c @@ -583,13 +597,14 @@ class TLEdgeOut( def HintAck(b: TLBundleB): TLBundleC = HintAck(b.source, address(b), b.size) def HintAck(fromSource: UInt, toAddress: UInt, lgSize: UInt) = { val c = Wire(new TLBundleC(bundle)) - c :#= DontCare c.opcode := TLMessages.HintAck c.param := 0.U c.size := lgSize c.source := fromSource c.address := toAddress - c.data := 0.U + c.user := DontCare + c.echo := DontCare + c.data := DontCare c.corrupt := false.B c } @@ -620,7 +635,7 @@ class TLEdgeIn( b.source := toSource b.address := fromAddress b.mask := mask(fromAddress, lgSize) - b.data := 0.U + b.data := DontCare b.corrupt := false.B (legal, b) } @@ -634,7 +649,9 @@ class TLEdgeIn( d.source := toSource d.sink := fromSink d.denied := denied - d.data := 0.U + d.user := DontCare + d.echo := DontCare + d.data := DontCare d.corrupt := false.B d } @@ -648,6 +665,8 @@ class TLEdgeIn( d.source := toSource d.sink := fromSink d.denied := denied + d.user := DontCare + d.echo := DontCare d.data := data d.corrupt := corrupt d @@ -662,7 +681,9 @@ class TLEdgeIn( d.source := toSource d.sink := 0.U d.denied := denied - d.data := 0.U + d.user := DontCare + d.echo := DontCare + d.data := DontCare d.corrupt := false.B d } @@ -678,7 +699,7 @@ class TLEdgeIn( b.source := toSource b.address := fromAddress b.mask := mask(fromAddress, lgSize) - b.data := 0.U + b.data := DontCare b.corrupt := false.B (legal, b) } @@ -759,7 +780,7 @@ class TLEdgeIn( b.source := toSource b.address := fromAddress b.mask := mask(fromAddress, lgSize) - b.data := 0.U + b.data := DontCare b.corrupt := false.B (legal, b) } @@ -775,7 +796,9 @@ class TLEdgeIn( d.source := toSource d.sink := 0.U d.denied := denied - d.data := 0.U + d.user := DontCare + d.echo := DontCare + d.data := DontCare d.corrupt := false.B d } @@ -791,6 +814,8 @@ class TLEdgeIn( d.source := toSource d.sink := 0.U d.denied := denied + d.user := DontCare + d.echo := DontCare d.data := data d.corrupt := corrupt d @@ -807,7 +832,9 @@ class TLEdgeIn( d.source := toSource d.sink := 0.U d.denied := denied - d.data := 0.U + d.user := DontCare + d.echo := DontCare + d.data := DontCare d.corrupt := false.B d } diff --git a/src/main/scala/tilelink/ErrorEvaluator.scala b/src/main/scala/tilelink/ErrorEvaluator.scala index 533cae0475f..e8931e9c650 100644 --- a/src/main/scala/tilelink/ErrorEvaluator.scala +++ b/src/main/scala/tilelink/ErrorEvaluator.scala @@ -3,9 +3,14 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.util.UIntToOH1 + +import freechips.rocketchip.util.DataToAugmentedData // Check if a request satisfies some interesting property class RequestPattern(test: TLBundleA => Bool) diff --git a/src/main/scala/tilelink/FIFOFixer.scala b/src/main/scala/tilelink/FIFOFixer.scala index 6aaff7ad641..efa0e966b46 100644 --- a/src/main/scala/tilelink/FIFOFixer.scala +++ b/src/main/scala/tilelink/FIFOFixer.scala @@ -4,8 +4,12 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.diplomacy.RegionType import freechips.rocketchip.util.property class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Parameters) extends LazyModule @@ -33,12 +37,14 @@ class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Para (fixMap, splatMap) } - val node = TLAdapterNode( - clientFn = { cp => cp }, - managerFn = { mp => + val node = new AdapterNode(TLImp)( + { cp => cp }, + { mp => val (fixMap, _) = fifoMap(mp.managers) mp.v1copy(managers = (fixMap zip mp.managers) map { case (id, m) => m.v1copy(fifoId = id) }) - }) + }) with TLFormatNode { + override def circuitIdentity = edges.in.map(_.client.clients.filter(c => c.requestFifo && c.sourceId.size > 1).size).sum == 0 + } lazy val module = new Impl class Impl extends LazyModuleImp(this) { diff --git a/src/main/scala/tilelink/Filter.scala b/src/main/scala/tilelink/Filter.scala index fcc59dc5eb5..cd6ab212d2a 100644 --- a/src/main/scala/tilelink/Filter.scala +++ b/src/main/scala/tilelink/Filter.scala @@ -3,8 +3,11 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} class TLFilter( mfilter: TLFilter.ManagerFilter = TLFilter.mIdentity, diff --git a/src/main/scala/tilelink/Fragmenter.scala b/src/main/scala/tilelink/Fragmenter.scala index 0aace162b46..68eae711aa2 100644 --- a/src/main/scala/tilelink/Fragmenter.scala +++ b/src/main/scala/tilelink/Fragmenter.scala @@ -4,11 +4,18 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, BufferParams, IdRange, TransferSizes} +import freechips.rocketchip.util.{Repeater, OH1ToUInt, UIntToOH1} + import scala.math.min +import freechips.rocketchip.util.DataToAugmentedData + object EarlyAck { sealed trait T case object AllPuts extends T @@ -21,10 +28,11 @@ object EarlyAck { // alwaysMin: fragment all requests down to minSize (else fragment to maximum supported by manager) // earlyAck: should a multibeat Put should be acknowledged on the first beat or last beat // holdFirstDeny: allow the Fragmenter to unsafely combine multibeat Gets by taking the first denied for the whole burst +// nameSuffix: appends a suffix to the module name // Fragmenter modifies: PutFull, PutPartial, LogicalData, Get, Hint // Fragmenter passes: ArithmeticData (truncated to minSize if alwaysMin) // Fragmenter cannot modify acquire (could livelock); thus it is unsafe to put caches on both sides -class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = false, val earlyAck: EarlyAck.T = EarlyAck.None, val holdFirstDeny: Boolean = false)(implicit p: Parameters) extends LazyModule +class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = false, val earlyAck: EarlyAck.T = EarlyAck.None, val holdFirstDeny: Boolean = false, val nameSuffix: Option[String] = None)(implicit p: Parameters) extends LazyModule { require(isPow2 (maxSize), s"TLFragmenter expects pow2(maxSize), but got $maxSize") require(isPow2 (minSize), s"TLFragmenter expects pow2(minSize), but got $minSize") @@ -82,6 +90,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = lazy val module = new Impl class Impl extends LazyModuleImp(this) { + override def desiredName = (Seq("TLFragmenter") ++ nameSuffix).mkString("_") (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => if (noChangeRequired) { out <> in @@ -92,8 +101,9 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = val beatBytes = manager.beatBytes val fifoId = managers(0).fifoId require (fifoId.isDefined && managers.map(_.fifoId == fifoId).reduce(_ && _)) - require (!manager.anySupportAcquireB) - + require (!manager.anySupportAcquireB || !edgeOut.client.anySupportProbe, + s"TLFragmenter (with parent $parent) can't fragment a caching client's requests into a cacheable region") + require (minSize >= beatBytes, s"TLFragmenter (with parent $parent) can't support fragmenting ($minSize) to sub-beat ($beatBytes) accesses") // We can't support devices which are cached on both sides of us require (!edgeOut.manager.anySupportAcquireB || !edgeIn.client.anySupportProbe) @@ -275,7 +285,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = val maxLgHint = Mux1H(find, maxLgHints) val limit = if (alwaysMin) lgMinSize else - MuxLookup(in_a.bits.opcode, lgMinSize, Array( + MuxLookup(in_a.bits.opcode, lgMinSize)(Array( TLMessages.PutFullData -> maxLgPutFull, TLMessages.PutPartialData -> maxLgPutPartial, TLMessages.ArithmeticData -> maxLgArithmetic, @@ -329,15 +339,17 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = object TLFragmenter { - def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: EarlyAck.T = EarlyAck.None, holdFirstDeny: Boolean = false)(implicit p: Parameters): TLNode = + def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: EarlyAck.T = EarlyAck.None, holdFirstDeny: Boolean = false, nameSuffix: Option[String] = None)(implicit p: Parameters): TLNode = { if (minSize <= maxSize) { - val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck, holdFirstDeny)) + val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck, holdFirstDeny, nameSuffix)) fragmenter.node } else { TLEphemeralNode()(ValName("no_fragmenter")) } } - def apply(wrapper: TLBusWrapper)(implicit p: Parameters): TLNode = apply(wrapper.beatBytes, wrapper.blockBytes) + def apply(wrapper: TLBusWrapper, nameSuffix: Option[String])(implicit p: Parameters): TLNode = apply(wrapper.beatBytes, wrapper.blockBytes, nameSuffix = nameSuffix) + + def apply(wrapper: TLBusWrapper)(implicit p: Parameters): TLNode = apply(wrapper, None) } // Synthesizable unit tests diff --git a/src/main/scala/tilelink/Fuzzer.scala b/src/main/scala/tilelink/Fuzzer.scala index 1b3ed7fee7e..0dbf21fc831 100644 --- a/src/main/scala/tilelink/Fuzzer.scala +++ b/src/main/scala/tilelink/Fuzzer.scala @@ -4,9 +4,14 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, IdRange} +import freechips.rocketchip.util.{leftOR, UIntToOH1} + +import freechips.rocketchip.util.DataToAugmentedData class IDMapGenerator(numIds: Int) extends Module { require (numIds > 0) @@ -180,7 +185,7 @@ class TLFuzzer( // Pick a specific message to try to send val a_type_sel = noiseMaker(3, inc, 0) - val legal = legal_dest && MuxLookup(a_type_sel, glegal, Seq( + val legal = legal_dest && MuxLookup(a_type_sel, glegal)(Seq( "b000".U -> glegal, "b001".U -> (pflegal && !noModify.B), "b010".U -> (pplegal && !noModify.B), @@ -188,7 +193,7 @@ class TLFuzzer( "b100".U -> (llegal && !noModify.B), "b101".U -> hlegal)) - val bits = MuxLookup(a_type_sel, gbits, Seq( + val bits = MuxLookup(a_type_sel, gbits)(Seq( "b000".U -> gbits, "b001".U -> pfbits, "b010".U -> ppbits, diff --git a/src/main/scala/tilelink/HintHandler.scala b/src/main/scala/tilelink/HintHandler.scala index 3b581a84621..982a1461d81 100644 --- a/src/main/scala/tilelink/HintHandler.scala +++ b/src/main/scala/tilelink/HintHandler.scala @@ -3,9 +3,12 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, IdRange, TransferSizes} +import freechips.rocketchip.util.Repeater import freechips.rocketchip.devices.tilelink.TLROM // Acks Hints for managers that don't support them or Acks all Hints if !passthrough diff --git a/src/main/scala/tilelink/Isolation.scala b/src/main/scala/tilelink/Isolation.scala index 44154313c4c..90ebe4dd07a 100644 --- a/src/main/scala/tilelink/Isolation.scala +++ b/src/main/scala/tilelink/Isolation.scala @@ -3,8 +3,10 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.util.AsyncBundle // READ the comments in the TLIsolation object before you instantiate this module diff --git a/src/main/scala/tilelink/Jbar.scala b/src/main/scala/tilelink/Jbar.scala index c4ce2396fdc..084af313489 100644 --- a/src/main/scala/tilelink/Jbar.scala +++ b/src/main/scala/tilelink/Jbar.scala @@ -3,8 +3,11 @@ package freechips.rocketchip.tilelink import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet class TLJbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/Map.scala b/src/main/scala/tilelink/Map.scala index a37bb04f5bc..b3578c05a0f 100644 --- a/src/main/scala/tilelink/Map.scala +++ b/src/main/scala/tilelink/Map.scala @@ -3,8 +3,11 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet // Moves the AddressSets of slave devices around // Combine with TLFilter to remove slaves or reduce their size diff --git a/src/main/scala/tilelink/Metadata.scala b/src/main/scala/tilelink/Metadata.scala index cbd0d8c509d..7f4f2854c7e 100644 --- a/src/main/scala/tilelink/Metadata.scala +++ b/src/main/scala/tilelink/Metadata.scala @@ -81,7 +81,7 @@ class ClientMetadata extends Bundle { import ClientStates._ val c = categorize(cmd) //assert(c === rd || param === toT, "Client was expecting trunk permissions.") - MuxLookup(Cat(c, param), Nothing, Seq( + MuxLookup(Cat(c, param), Nothing)(Seq( //(effect param) -> (next) Cat(rd, toB) -> Branch, Cat(rd, toT) -> Trunk, @@ -137,7 +137,7 @@ class ClientMetadata extends Bundle { private def cmdToPermCap(cmd: UInt): UInt = { import MemoryOpCategories._ import TLPermissions._ - MuxLookup(cmd, toN, Seq( + MuxLookup(cmd, toN)(Seq( M_FLUSH -> toN, M_PRODUCE -> toB, M_CLEAN -> toT)) diff --git a/src/main/scala/tilelink/Monitor.scala b/src/main/scala/tilelink/Monitor.scala index f34e388e54c..0c5586cd583 100644 --- a/src/main/scala/tilelink/Monitor.scala +++ b/src/main/scala/tilelink/Monitor.scala @@ -5,10 +5,13 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ import chisel3.experimental.SourceLine -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ + +import freechips.rocketchip.diplomacy.EnableMonitors +import freechips.rocketchip.formal.{MonitorDirection, IfThen, Property, PropertyClass, TestplanTestType, TLMonitorStrictMode} import freechips.rocketchip.util.PlusArg -import freechips.rocketchip.formal._ case class TLMonitorArgs(edge: TLEdge) @@ -587,7 +590,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec } if (edge.manager.minLatency > 0) { - assume(a_set =/= d_clr || !a_set.orR, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra) + assume(a_set =/= d_clr || !a_set.orR, s"'A' and 'D' concurrent, despite minlatency > 0" + extra) } inflight := (inflight | a_set) & ~d_clr @@ -608,7 +611,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec val log_a_size_bus_size = log2Ceil(a_size_bus_size) def size_to_numfullbits(x: UInt): UInt = (1.U << x) - 1.U //convert a number to that many full bits - val inflight = RegInit(0.U(edge.client.endSourceId.W)) + val inflight = RegInit(0.U((2 max edge.client.endSourceId).W)) // size up to avoid width error inflight.suggestName("inflight") val inflight_opcodes = RegInit(0.U((edge.client.endSourceId << log_a_opcode_bus_size).W)) inflight_opcodes.suggestName("inflight_opcodes") @@ -629,7 +632,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec val a_sizes_set = WireInit(0.U((edge.client.endSourceId << log_a_size_bus_size).W)) a_sizes_set.suggestName("a_sizes_set") - val a_opcode_lookup = WireInit(0.U((1 << log_a_opcode_bus_size).W)) + val a_opcode_lookup = WireInit(0.U((a_opcode_bus_size - 1).W)) a_opcode_lookup.suggestName("a_opcode_lookup") a_opcode_lookup := ((inflight_opcodes) >> (bundle.d.bits.source << log_a_opcode_bus_size.U) & size_to_numfullbits(1.U << log_a_opcode_bus_size.U)) >> 1.U @@ -696,7 +699,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec } if (edge.manager.minLatency > 0) { - assume(a_set_wo_ready =/= d_clr_wo_ready || !a_set_wo_ready.orR, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra) + assume(a_set_wo_ready =/= d_clr_wo_ready || !a_set_wo_ready.orR, s"'A' and 'D' concurrent, despite minlatency > 0" + extra) } inflight := (inflight | a_set) & ~d_clr @@ -720,7 +723,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec val log_c_size_bus_size = log2Ceil(c_size_bus_size) def size_to_numfullbits(x: UInt): UInt = (1.U << x) - 1.U //convert a number to that many full bits - val inflight = RegInit(0.U(edge.client.endSourceId.W)) + val inflight = RegInit(0.U((2 max edge.client.endSourceId).W)) val inflight_opcodes = RegInit(0.U((edge.client.endSourceId << log_c_opcode_bus_size).W)) val inflight_sizes = RegInit(0.U((edge.client.endSourceId << log_c_size_bus_size).W)) inflight.suggestName("inflight") @@ -804,7 +807,7 @@ class TLMonitor(args: TLMonitorArgs, monitorDir: MonitorDirection = MonitorDirec if (edge.manager.minLatency > 0) { when (c_set_wo_ready.orR) { - assume(c_set_wo_ready =/= d_clr_wo_ready, s"'C' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra) + assume(c_set_wo_ready =/= d_clr_wo_ready, s"'C' and 'D' concurrent, despite minlatency > 0" + extra) } } diff --git a/src/main/scala/tilelink/Nodes.scala b/src/main/scala/tilelink/Nodes.scala index ddf4cfb0440..6b193f8ec0b 100644 --- a/src/main/scala/tilelink/Nodes.scala +++ b/src/main/scala/tilelink/Nodes.scala @@ -4,8 +4,11 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ + import freechips.rocketchip.util.{AsyncQueueParams,RationalDirection} case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args)) diff --git a/src/main/scala/tilelink/Parameters.scala b/src/main/scala/tilelink/Parameters.scala index eb32ea8638a..66748a1bd68 100644 --- a/src/main/scala/tilelink/Parameters.scala +++ b/src/main/scala/tilelink/Parameters.scala @@ -5,9 +5,20 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ import chisel3.experimental.SourceInfo -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.diplomacy.{ + AddressDecoder, AddressSet, BufferParams, DirectedBuffers, IdMap, IdMapEntry, + IdRange, RegionType, TransferSizes +} +import freechips.rocketchip.resources.{Resource, ResourceAddress, ResourcePermissions} +import freechips.rocketchip.util.{ + AsyncQueueParams, BundleField, BundleFieldBase, BundleKeyBase, + CreditedDelay, groupByIntoSeq, RationalDirection, SimpleProduct +} + import scala.math.max //These transfer sizes describe requests issued from masters on the A channel that will be responded by slaves on the D channel @@ -177,6 +188,7 @@ class TLSlaveParameters private( // ReleaseAck may NEVER be denied extends SimpleProduct { + def sortedAddress = address.sorted override def canEqual(that: Any): Boolean = that.isInstanceOf[TLSlaveParameters] override def productPrefix = "TLSlaveParameters" // We intentionally omit nodePath for equality testing / formatting @@ -516,6 +528,7 @@ class TLSlavePortParameters private( val responseFields: Seq[BundleFieldBase], val requestKeys: Seq[BundleKeyBase]) extends SimpleProduct { + def sortedSlaves = slaves.sortBy(_.sortedAddress.head) override def canEqual(that: Any): Boolean = that.isInstanceOf[TLSlavePortParameters] override def productPrefix = "TLSlavePortParameters" def productArity: Int = 6 @@ -596,16 +609,16 @@ class TLSlavePortParameters private( def find(address: BigInt) = slaves.find(_.address.exists(_.contains(address))) // The safe version will check the entire address - def findSafe(address: UInt) = VecInit(slaves.map(_.address.map(_.contains(address)).reduce(_ || _))) + def findSafe(address: UInt) = VecInit(sortedSlaves.map(_.address.map(_.contains(address)).reduce(_ || _))) // The fast version assumes the address is valid (you probably want fastProperty instead of this function) def findFast(address: UInt) = { val routingMask = AddressDecoder(slaves.map(_.address)) - VecInit(slaves.map(_.address.map(_.widen(~routingMask)).distinct.map(_.contains(address)).reduce(_ || _))) + VecInit(sortedSlaves.map(_.address.map(_.widen(~routingMask)).distinct.map(_.contains(address)).reduce(_ || _))) } // Compute the simplest AddressSets that decide a key def fastPropertyGroup[K](p: TLSlaveParameters => K): Seq[(K, Seq[AddressSet])] = { - val groups = groupByIntoSeq(slaves.map(m => (p(m), m.address)))( _._1).map { case (k, vs) => + val groups = groupByIntoSeq(sortedSlaves.map(m => (p(m), m.address)))( _._1).map { case (k, vs) => k -> vs.flatMap(_._2) } val reductionMask = AddressDecoder(groups.map(_._2)) @@ -1299,6 +1312,9 @@ case class TLBundleParameters( val addrLoBits = log2Up(dataBits/8) + // Used to uniquify bus IP names + def shortName = s"a${addressBits}d${dataBits}s${sourceBits}k${sinkBits}z${sizeBits}" + (if (hasBCE) "c" else "u") + def union(x: TLBundleParameters) = TLBundleParameters( max(addressBits, x.addressBits), diff --git a/src/main/scala/tilelink/PatternPusher.scala b/src/main/scala/tilelink/PatternPusher.scala index 7276d6ea48b..08e9eaba740 100644 --- a/src/main/scala/tilelink/PatternPusher.scala +++ b/src/main/scala/tilelink/PatternPusher.scala @@ -4,9 +4,11 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.util.DataToAugmentedData trait Pattern { def address: BigInt @@ -73,7 +75,7 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter } val (plegal, pbits) = pattern.map(_.bits(edgeOut)).unzip - assert (end || VecInit(plegal)(step), s"Pattern pusher ${name} tried to push an illegal request") + assert (end || VecInit(plegal)(step), s"Pattern pusher ${this.name} tried to push an illegal request") a.valid := io.run && ready && !end && !flight a.bits := VecInit(pbits)(step) diff --git a/src/main/scala/tilelink/ProbePicker.scala b/src/main/scala/tilelink/ProbePicker.scala index 7b902b771c2..abb4e70f583 100644 --- a/src/main/scala/tilelink/ProbePicker.scala +++ b/src/main/scala/tilelink/ProbePicker.scala @@ -4,8 +4,11 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, IdRange} /* A ProbePicker is used to unify multiple cache banks into one logical cache */ class ProbePicker(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/tilelink/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala index 46c02cdd804..4a785242906 100644 --- a/src/main/scala/tilelink/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -4,9 +4,13 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.util.{CRC, UIntToOH1} + +import freechips.rocketchip.util.DataToAugmentedData // We detect concurrent puts that put memory into an undefined state. // put0, put0Ack, put1, put1Ack => ok: defined diff --git a/src/main/scala/tilelink/RationalCrossing.scala b/src/main/scala/tilelink/RationalCrossing.scala index e39860e3797..3dd7ad289b9 100644 --- a/src/main/scala/tilelink/RationalCrossing.scala +++ b/src/main/scala/tilelink/RationalCrossing.scala @@ -10,9 +10,15 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, NodeHandle} +import freechips.rocketchip.util.{ + FromRational, ToRational, RationalDirection, Symmetric, FastToSlow, SlowToFast, Pow2ClockDivider, ClockDivider3 +} + class TLRationalCrossingSource(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/RegionReplication.scala b/src/main/scala/tilelink/RegionReplication.scala index 567b120ae71..396f5052562 100644 --- a/src/main/scala/tilelink/RegionReplication.scala +++ b/src/main/scala/tilelink/RegionReplication.scala @@ -3,8 +3,12 @@ package freechips.rocketchip.tilelink import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet /* Address inside the 'local' space are replicated to fill the 'remote' space. */ diff --git a/src/main/scala/tilelink/RegisterRouter.scala b/src/main/scala/tilelink/RegisterRouter.scala index 5a76cce107e..f66a018bf23 100644 --- a/src/main/scala/tilelink/RegisterRouter.scala +++ b/src/main/scala/tilelink/RegisterRouter.scala @@ -4,11 +4,16 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import chisel3.RawModule -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} +import freechips.rocketchip.resources.{Device, Resource, ResourceBindings} +import freechips.rocketchip.prci.{NoCrossing} +import freechips.rocketchip.regmapper.{RegField, RegMapper, RegMapperParams, RegMapperInput, RegisterRouter} +import freechips.rocketchip.util.{BundleField, ControlKey, ElaborationArtefacts, GenRegDescsAnno} import scala.math.min @@ -128,66 +133,6 @@ case class TLRegisterNode( } } -@deprecated("Use HasTLControlRegMap+HasInterruptSources traits in place of TLRegisterRouter+TLRegBundle+TLRegModule", "rocket-chip 1.3") -abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule -{ - // Allow devices to extend the DTS mapping - def extraResources(resources: ResourceBindings) = Map[String, Seq[ResourceValue]]() - val device = new SimpleDevice(devname, devcompat) { - override def describe(resources: ResourceBindings): Description = { - val Description(name, mapping) = super.describe(resources) - Description(name, mapping ++ extraResources(resources)) - } - } - - val node = TLRegisterNode(Seq(address), device, "reg/control", concurrency, beatBytes, undefZero, executable) - import freechips.rocketchip.interrupts._ - val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int")))) -} - -@deprecated("TLRegBundleArg is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -case class TLRegBundleArg()(implicit val p: Parameters) - -@deprecated("TLRegBundleBase is no longer necessary, use IO(...) to make any additional IOs", "rocket-chip 1.3") -class TLRegBundleBase(arg: TLRegBundleArg) extends Bundle -{ - implicit val p = arg.p -} - -@deprecated("Use HasTLControlRegMap+HasInterruptSources traits in place of TLRegisterRouter+TLRegBundle+TLRegModule", "rocket-chip 1.3") -class TLRegBundle[P](val params: P, val arg: TLRegBundleArg) extends TLRegBundleBase(arg) - -@deprecated("Use HasTLControlRegMap+HasInterruptSources traits in place of TLRegisterRouter+TLRegBundle+TLRegModule", "rocket-chip 1.3") -class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, router: TLRegisterRouterBase) - extends LazyModuleImp(router) with HasRegMap -{ - val io = IO(bundleBuilder) - val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 - val address = router.address - def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) -} - -@deprecated("Use HasTLControlRegMap+HasInterruptSources traits in place of TLRegisterRouter+TLRegBundle+TLRegModule", "rocket-chip 1.3") -class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp]( - val base: BigInt, - val devname: String, - val devcompat: Seq[String], - val interrupts: Int = 0, - val size: BigInt = 4096, - val concurrency: Int = 0, - val beatBytes: Int = 4, - val undefZero: Boolean = true, - val executable: Boolean = false) - (bundleBuilder: TLRegBundleArg => B) - (moduleBuilder: (=> B, TLRegisterRouterBase) => M)(implicit p: Parameters) - extends TLRegisterRouterBase(devname, devcompat, AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) -{ - require (isPow2(size)) - // require (size >= 4096) ... not absolutely required, but highly recommended - - lazy val module = moduleBuilder(bundleBuilder(TLRegBundleArg()), this) -} - /** Mix HasTLControlRegMap into any subclass of RegisterRouter to gain helper functions for attaching a device control register map to TileLink. * - The intended use case is that controlNode will diplomatically publish a SW-visible device's memory-mapped control registers. * - Use the clock crossing helper controlXing to externally connect controlNode to a TileLink interconnect. diff --git a/src/main/scala/tilelink/RegisterRouterTest.scala b/src/main/scala/tilelink/RegisterRouterTest.scala index 238c8d7a730..d3a64055f69 100644 --- a/src/main/scala/tilelink/RegisterRouterTest.scala +++ b/src/main/scala/tilelink/RegisterRouterTest.scala @@ -3,10 +3,12 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + import freechips.rocketchip.regmapper.{RRTest0, RRTest1} -import freechips.rocketchip.unittest._ +import freechips.rocketchip.unittest.{UnitTest, UnitTestModule} class TLRRTest0(address: BigInt)(implicit p: Parameters) extends RRTest0(address) diff --git a/src/main/scala/tilelink/SRAM.scala b/src/main/scala/tilelink/SRAM.scala index f92e142ccaf..6703bac3c37 100644 --- a/src/main/scala/tilelink/SRAM.scala +++ b/src/main/scala/tilelink/SRAM.scala @@ -4,10 +4,17 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.bundlebridge._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} +import freechips.rocketchip.resources.{Device, DeviceRegName, DiplomaticSRAM, HasJustOneSeqMem} +import freechips.rocketchip.util.{CanHaveErrors, ECCParams, property, SECDEDCode} + +import freechips.rocketchip.util.DataToAugmentedData +import freechips.rocketchip.util.BooleanToAugmentedBoolean class TLRAMErrors(val params: ECCParams, val addrBits: Int) extends Bundle with CanHaveErrors { val correctable = (params.code.canCorrect && params.notifyErrors).option(Valid(UInt(addrBits.W))) @@ -44,7 +51,7 @@ class TLRAM( supportsPutFull = TransferSizes(1, beatBytes), supportsArithmetic = if (atomics) TransferSizes(1, beatBytes) else TransferSizes.none, supportsLogical = if (atomics) TransferSizes(1, beatBytes) else TransferSizes.none, - fifoId = Some(0))), // requests are handled in order + fifoId = Some(0)).v2copy(name=devName)), // requests are handled in order beatBytes = beatBytes, minLatency = 1))) // no bypass needed for this device @@ -229,14 +236,15 @@ class TLRAM( val r_ready = !d_wb && !r_replay && (!d_full || d_ready) && (!r_respond || (!d_win && in.d.ready)) in.a.ready := !(d_full && d_wb) && (!r_full || r_ready) && (!r_full || !(r_atomic || r_sublane)) - // ignore sublane if mask is all set + // ignore sublane if it is a read or mask is all set + val a_read = in.a.bits.opcode === TLMessages.Get val a_sublane = if (eccBytes == 1) false.B else - ((in.a.bits.opcode === TLMessages.PutPartialData) && (~in.a.bits.mask.andR)) || - in.a.bits.size < log2Ceil(eccBytes).U + ~a_read && + (((in.a.bits.opcode === TLMessages.PutPartialData) && (~in.a.bits.mask.andR)) || + in.a.bits.size < log2Ceil(eccBytes).U) val a_atomic = if (!atomics) false.B else in.a.bits.opcode === TLMessages.ArithmeticData || in.a.bits.opcode === TLMessages.LogicalData - val a_read = in.a.bits.opcode === TLMessages.Get // Forward pipeline stage from R to D when (d_ready) { d_full := false.B } diff --git a/src/main/scala/tilelink/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala index 16fac848d60..c72d42f3e85 100644 --- a/src/main/scala/tilelink/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -4,9 +4,14 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.IdRange +import freechips.rocketchip.util.leftOR + +import freechips.rocketchip.util.DataToAugmentedData class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/ToAHB.scala b/src/main/scala/tilelink/ToAHB.scala index 5f960aa944c..a5267704295 100644 --- a/src/main/scala/tilelink/ToAHB.scala +++ b/src/main/scala/tilelink/ToAHB.scala @@ -4,13 +4,17 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import freechips.rocketchip.amba._ -import freechips.rocketchip.amba.ahb._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import AHBParameters._ -import chisel3.util.{RegEnable, Queue, Cat, log2Ceil} + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} +import freechips.rocketchip.amba.ahb.{AHBImpMaster, AHBParameters, AHBMasterParameters, AHBMasterPortParameters} +import freechips.rocketchip.amba.ahb.AHBParameters.{BURST_INCR, BURST_SINGLE, TRANS_NONSEQ, TRANS_SEQ, TRANS_IDLE, TRANS_BUSY, PROT_DEFAULT} +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.util.{BundleMap, UIntToOH1} case class TLToAHBNode(supportHints: Boolean)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AHBImpMaster)( dFn = { cp => diff --git a/src/main/scala/tilelink/ToAPB.scala b/src/main/scala/tilelink/ToAPB.scala index 91c172d658a..8b045144fd3 100644 --- a/src/main/scala/tilelink/ToAPB.scala +++ b/src/main/scala/tilelink/ToAPB.scala @@ -3,13 +3,18 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.amba.apb._ -import freechips.rocketchip.amba._ -import APBParameters._ import chisel3.util._ +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.diplomacy.TransferSizes +import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} +import freechips.rocketchip.amba.apb.{APBImp, APBMasterParameters, APBMasterPortParameters} +import freechips.rocketchip.amba.apb.APBParameters.PROT_DEFAULT + case class TLToAPBNode()(implicit valName: ValName) extends MixedAdapterNode(TLImp, APBImp)( dFn = { cp => APBMasterPortParameters( diff --git a/src/main/scala/tilelink/ToAXI4.scala b/src/main/scala/tilelink/ToAXI4.scala index 2c8ab84bb31..a01ad75cf7a 100644 --- a/src/main/scala/tilelink/ToAXI4.scala +++ b/src/main/scala/tilelink/ToAXI4.scala @@ -3,12 +3,19 @@ package freechips.rocketchip.tilelink import chisel3._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ -import freechips.rocketchip.amba.axi4._ -import freechips.rocketchip.amba._ -import chisel3.util.{log2Ceil, UIntToOH, Queue, Decoupled, Cat} +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.amba.{AMBACorrupt, AMBACorruptField, AMBAProt, AMBAProtField} +import freechips.rocketchip.amba.axi4.{AXI4BundleARW, AXI4MasterParameters, AXI4MasterPortParameters, AXI4Parameters, AXI4Imp} +import freechips.rocketchip.diplomacy.{IdMap, IdMapEntry, IdRange} +import freechips.rocketchip.util.{BundleField, ControlKey, ElaborationArtefacts, UIntToOH1} + +import freechips.rocketchip.util.DataToAugmentedData class AXI4TLStateBundle(val sourceBits: Int) extends Bundle { val size = UInt(4.W) @@ -145,8 +152,8 @@ class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String val depth = if (combinational) 1 else 2 val out_arw = Wire(Decoupled(new AXI4BundleARW(out.params))) val out_w = Wire(chiselTypeOf(out.w)) - out.w :<>= Queue.irrevocable(out_w, entries=depth, combinational) - val queue_arw = Queue.irrevocable(out_arw, entries=depth, combinational) + out.w :<>= Queue.irrevocable(out_w, entries=depth, flow=combinational) + val queue_arw = Queue.irrevocable(out_arw, entries=depth, flow=combinational) // Fan out the ARW channel to AR and AW out.ar.bits := queue_arw.bits diff --git a/src/main/scala/tilelink/WidthWidget.scala b/src/main/scala/tilelink/WidthWidget.scala index 514f0c5a9ef..e8b21026f0c 100644 --- a/src/main/scala/tilelink/WidthWidget.scala +++ b/src/main/scala/tilelink/WidthWidget.scala @@ -3,10 +3,13 @@ package freechips.rocketchip.tilelink import chisel3._ -import chisel3.util.{DecoupledIO, log2Ceil, Cat, RegEnable} -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.util.{Repeater, UIntToOH1} // innBeatBytes => the new client-facing bus width class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyModule @@ -18,6 +21,8 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod override def circuitIdentity = edges.out.map(_.manager).forall(noChangeRequired) } + override lazy val desiredName = s"TLWidthWidget$innerBeatBytes" + lazy val module = new Impl class Impl extends LazyModuleImp(this) { def merge[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = { @@ -174,14 +179,19 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod // The assumption is that this sort of situation happens only where // you connect a narrow master to the system bus, so there are few sources. - def sourceMap(source: UInt) = { + def sourceMap(source_bits: UInt) = { + val source = if (edgeIn.client.endSourceId == 1) 0.U(0.W) else source_bits require (edgeOut.manager.beatBytes > edgeIn.manager.beatBytes) val keepBits = log2Ceil(edgeOut.manager.beatBytes) val dropBits = log2Ceil(edgeIn.manager.beatBytes) val sources = Reg(Vec(edgeIn.client.endSourceId, UInt((keepBits-dropBits).W))) val a_sel = in.a.bits.address(keepBits-1, dropBits) when (in.a.fire) { - sources(in.a.bits.source) := a_sel + if (edgeIn.client.endSourceId == 1) { // avoid extraction-index-width warning + sources(0) := a_sel + } else { + sources(in.a.bits.source) := a_sel + } } // depopulate unused source registers: diff --git a/src/main/scala/tilelink/Xbar.scala b/src/main/scala/tilelink/Xbar.scala index 1d6a82bbdc6..4d6c9ef7b63 100644 --- a/src/main/scala/tilelink/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -4,9 +4,12 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ -import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.util._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.lazymodule._ + +import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, RegionType, IdRange, TriStateValue} +import freechips.rocketchip.util.BundleField // Trades off slave port proximity against routing resource cost object ForceFanout @@ -30,7 +33,7 @@ object ForceFanout private case class ForceFanoutParams(a: Boolean, b: Boolean, c: Boolean, d: Boolean, e: Boolean) private case object ForceFanoutKey extends Field(ForceFanoutParams(false, false, false, false, false)) -class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule +class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin, nameSuffix: Option[String] = None)(implicit p: Parameters) extends LazyModule { val node = new TLNexusNode( clientFn = { seq => @@ -74,7 +77,8 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame println (s" Your TLXbar ($name with parent $parent) is very large, with ${node.in.size} Masters and ${node.out.size} Slaves.") println (s"!!! WARNING !!!") } - + val wide_bundle = TLBundleParameters.union((node.in ++ node.out).map(_._2.bundle)) + override def desiredName = (Seq("TLXbar") ++ nameSuffix ++ Seq(s"i${node.in.size}_o${node.out.size}_${wide_bundle.shortName}")).mkString("_") TLXbar.circuit(policy, node.in, node.out) } } @@ -157,8 +161,8 @@ object TLXbar val r = inputIdRanges(i) if (connectAIO(i).exists(x=>x)) { - in(i).a.squeezeAll.waiveAll :<>= io_in(i).a.squeezeAll.waiveAll in(i).a.bits.user := DontCare + in(i).a.squeezeAll.waiveAll :<>= io_in(i).a.squeezeAll.waiveAll in(i).a.bits.source := io_in(i).a.bits.source | r.start.U } else { in(i).a := DontCare @@ -178,8 +182,8 @@ object TLXbar } if (connectCIO(i).exists(x=>x)) { - in(i).c.squeezeAll.waiveAll :<>= io_in(i).c.squeezeAll.waiveAll in(i).c.bits.user := DontCare + in(i).c.squeezeAll.waiveAll :<>= io_in(i).c.squeezeAll.waiveAll in(i).c.bits.source := io_in(i).c.bits.source | r.start.U } else { in(i).c := DontCare @@ -214,8 +218,8 @@ object TLXbar val r = outputIdRanges(o) if (connectAOI(o).exists(x=>x)) { - io_out(o).a.squeezeAll.waiveAll :<>= out(o).a.squeezeAll.waiveAll out(o).a.bits.user := DontCare + io_out(o).a.squeezeAll.waiveAll :<>= out(o).a.squeezeAll.waiveAll } else { out(o).a := DontCare io_out(o).a := DontCare @@ -233,8 +237,8 @@ object TLXbar } if (connectCOI(o).exists(x=>x)) { - io_out(o).c.squeezeAll.waiveAll :<>= out(o).c.squeezeAll.waiveAll out(o).c.bits.user := DontCare + io_out(o).c.squeezeAll.waiveAll :<>= out(o).c.squeezeAll.waiveAll } else { out(o).c := DontCare io_out(o).c := DontCare @@ -337,9 +341,9 @@ object TLXbar } } - def apply(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters): TLNode = + def apply(policy: TLArbiter.Policy = TLArbiter.roundRobin, nameSuffix: Option[String] = None)(implicit p: Parameters): TLNode = { - val xbar = LazyModule(new TLXbar(policy)) + val xbar = LazyModule(new TLXbar(policy, nameSuffix)) xbar.node } diff --git a/src/main/scala/tilelink/package.scala b/src/main/scala/tilelink/package.scala index 6afc522d813..317d4052b08 100644 --- a/src/main/scala/tilelink/package.scala +++ b/src/main/scala/tilelink/package.scala @@ -2,8 +2,10 @@ package freechips.rocketchip -import freechips.rocketchip.diplomacy.{HasClockDomainCrossing, _} -import freechips.rocketchip.prci.{HasResetDomainCrossing} +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.nodes._ + +import freechips.rocketchip.prci.{HasResetDomainCrossing, HasClockDomainCrossing} package object tilelink { diff --git a/src/main/scala/unittest/TestGenerator.scala b/src/main/scala/unittest/TestGenerator.scala index 9440ebad0d6..d38fe9fc30c 100644 --- a/src/main/scala/unittest/TestGenerator.scala +++ b/src/main/scala/unittest/TestGenerator.scala @@ -3,8 +3,9 @@ package freechips.rocketchip.unittest import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy._ +import org.chipsalliance.diplomacy.lazymodule._ abstract class LazyUnitTest(implicit p: Parameters) extends LazyModule { self => diff --git a/src/main/scala/util/Annotations.scala b/src/main/scala/util/Annotations.scala index 6cb8a4be85d..851571ba46e 100644 --- a/src/main/scala/util/Annotations.scala +++ b/src/main/scala/util/Annotations.scala @@ -4,11 +4,14 @@ package freechips.rocketchip.util import chisel3._ import chisel3.experimental.{annotate, ChiselAnnotation} -import chisel3.RawModule + import firrtl.annotations._ -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper._ +import org.chipsalliance.diplomacy + +import freechips.rocketchip.diplomacy.{AddressRange, AddressSet} +import freechips.rocketchip.resources.{AddressMapEntry, ResourcePermissions} +import freechips.rocketchip.regmapper.{RegField, RegFieldDescSer, RegistersSer} import org.json4s.JsonDSL._ import org.json4s.jackson.JsonMethods.{pretty, render} diff --git a/src/main/scala/util/AsyncQueue.scala b/src/main/scala/util/AsyncQueue.scala index a7332358c56..713393ce9e3 100644 --- a/src/main/scala/util/AsyncQueue.scala +++ b/src/main/scala/util/AsyncQueue.scala @@ -68,6 +68,8 @@ class AsyncValidSync(sync: Int, desc: String) extends RawModule { } class AsyncQueueSource[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { + override def desiredName = s"AsyncQueueSource_${gen.typeName}" + val io = IO(new Bundle { // These come from the source domain val enq = Flipped(Decoupled(gen)) @@ -132,6 +134,8 @@ class AsyncQueueSource[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueP } class AsyncQueueSink[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { + override def desiredName = s"AsyncQueueSink_${gen.typeName}" + val io = IO(new Bundle { // These come from the sink domain val deq = Decoupled(gen) diff --git a/src/main/scala/util/DelayQueue.scala b/src/main/scala/util/DelayQueue.scala index cdfa2f50743..47a9ace983a 100644 --- a/src/main/scala/util/DelayQueue.scala +++ b/src/main/scala/util/DelayQueue.scala @@ -15,23 +15,23 @@ import chisel3.util._ * @param timer cycle count timer * @param entries cycle delay */ -class DelayQueue[T <: Data](gen: T, entries: Int) extends Module { +class DelayQueue[T <: Data](gen: T, entries: Int, width: Int) extends Module { val io = IO(new Bundle { val enq = Flipped(DecoupledIO(gen)) val deq = DecoupledIO(gen) - val timer = Input(UInt()) - val delay = Input(UInt()) + val timer = Input(UInt(width.W)) + val delay = Input(UInt(width.W)) }) val q = Module(new Queue(new Bundle { - val data = gen - val time = UInt(io.timer.getWidth.W) + val data = gen.cloneType + val time = UInt(width.W) }, entries, flow=true)) - val delay_r = RegInit(0.U(io.delay.getWidth.W)) + val delay_r = RegInit(0.U(width.W)) when (delay_r =/= io.delay) { delay_r := io.delay - assert(q.io.count == 0, "Undefined behavior when delay is changed while queue has elements.") + //assert(q.io.count == 0, "Undefined behavior when delay is changed while queue has elements.") } q.io.enq.bits.data := io.enq.bits @@ -53,7 +53,7 @@ object DelayQueue { * @param depth queue size */ def apply[T <: Data](source: DecoupledIO[T], timer: UInt, delay: UInt, depth: Int): DecoupledIO[T] = { - val delayQueue = Module(new DelayQueue(chiselTypeOf(source.bits), depth)) + val delayQueue = Module(new DelayQueue(chiselTypeOf(source.bits), depth, timer.getWidth)) delayQueue.io.enq <> source delayQueue.io.timer := timer delayQueue.io.delay := delay diff --git a/src/main/scala/util/HeterogeneousBag.scala b/src/main/scala/util/HeterogeneousBag.scala deleted file mode 100644 index f9a591b4b42..00000000000 --- a/src/main/scala/util/HeterogeneousBag.scala +++ /dev/null @@ -1,24 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.util - -import chisel3._ -import chisel3.Record -import chisel3.reflect.DataMirror.internal.chiselTypeClone -import scala.collection.immutable.ListMap - -final case class HeterogeneousBag[T <: Data](elts: Seq[T]) extends Record with collection.IndexedSeq[T] { - def apply(x: Int) = elements(x.toString).asInstanceOf[T] - def length = elts.length - - override def className: String = super.className - val elements = ListMap(elts.zipWithIndex.map { case (n,i) => (i.toString, chiselTypeClone(n)) }:_*) - // IndexedSeq has its own hashCode/equals that we must not use - override def hashCode: Int = super[Record].hashCode - override def equals(that: Any): Boolean = super[Record].equals(that) -} - -object HeterogeneousBag -{ - def fromNode[D <: Data, E](elts: Seq[(D, E)]) = new HeterogeneousBag(elts.map(_._1.cloneType)) -} diff --git a/src/main/scala/util/PSDTestMode.scala b/src/main/scala/util/PSDTestMode.scala index 1ca26d79596..30c97a9078c 100644 --- a/src/main/scala/util/PSDTestMode.scala +++ b/src/main/scala/util/PSDTestMode.scala @@ -3,8 +3,10 @@ package freechips.rocketchip.util import chisel3._ + import org.chipsalliance.cde.config._ -import freechips.rocketchip.diplomacy.{BundleBridgeEphemeralNode, ValName} +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ case object IncludePSDTest extends Field[Boolean](false) case object PSDTestModeBroadcastKey extends Field( diff --git a/src/main/scala/util/RecordMap.scala b/src/main/scala/util/RecordMap.scala index 4dd6bc11ae9..fb2b227164c 100644 --- a/src/main/scala/util/RecordMap.scala +++ b/src/main/scala/util/RecordMap.scala @@ -4,8 +4,8 @@ package freechips.rocketchip.util import chisel3._ import scala.collection.immutable.ListMap -import chisel3.internal.requireIsChiselType -import chisel3.experimental.DataMirror.internal.chiselTypeClone +import chisel3.experimental.requireIsChiselType +import chisel3.reflect.DataMirror.internal.chiselTypeClone final class RecordMap[T <: Data] (eltMap: ListMap[String, T]) extends Record { diff --git a/src/main/scala/util/Repeater.scala b/src/main/scala/util/Repeater.scala index a0b0c5b297d..f97593d9ffd 100644 --- a/src/main/scala/util/Repeater.scala +++ b/src/main/scala/util/Repeater.scala @@ -9,6 +9,7 @@ import chisel3.util.{Decoupled, DecoupledIO} // When repeat is asserted, the Repeater copies the input and repeats it next cycle. class Repeater[T <: Data](gen: T) extends Module { + override def desiredName = s"Repeater_${gen.typeName}" val io = IO( new Bundle { val repeat = Input(Bool()) val full = Output(Bool()) diff --git a/src/main/scala/util/TraceCoreInterface.scala b/src/main/scala/util/TraceCoreInterface.scala index 6f948e09d32..fad9263a47d 100644 --- a/src/main/scala/util/TraceCoreInterface.scala +++ b/src/main/scala/util/TraceCoreInterface.scala @@ -4,7 +4,6 @@ package freechips.rocketchip.util import chisel3._ -import chisel3.experimental.ChiselEnum // Definitions for Trace core Interface defined in RISC-V Processor Trace Specification V1.0 object TraceItype extends ChiselEnum { diff --git a/src/main/scala/util/package.scala b/src/main/scala/util/package.scala index 6fb8895fb5c..6ca4961d580 100644 --- a/src/main/scala/util/package.scala +++ b/src/main/scala/util/package.scala @@ -270,7 +270,7 @@ package object util { val y = Output(chiselTypeOf(in)) }) io.y := io.x - override def desiredName = "OptimizationBarrier" + override def desiredName = s"OptimizationBarrier_${in.typeName}" }) barrier.io.x := in barrier.io.y @@ -294,4 +294,10 @@ package object util { case x if x == n => in case _ => throw new Exception(s"must provide exactly 1 or $n of some field, but got:\n$in") } + + // HeterogeneousBag moved to standalond diplomacy + @deprecated("HeterogeneousBag has been absorbed into standalone diplomacy library", "rocketchip 2.0.0") + def HeterogeneousBag[T <: Data](elts: Seq[T]) = _root_.org.chipsalliance.diplomacy.nodes.HeterogeneousBag[T](elts) + @deprecated("HeterogeneousBag has been absorbed into standalone diplomacy library", "rocketchip 2.0.0") + val HeterogeneousBag = _root_.org.chipsalliance.diplomacy.nodes.HeterogeneousBag } diff --git a/torture b/torture deleted file mode 160000 index 99d8b2b441e..00000000000 --- a/torture +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 99d8b2b441ecaa18b852505bb7718ee04e2753f5