提交 28913228 编写于 作者: A Allen

Merge branch 'soc-diplomacy' of github.com:RISCVERS/XiangShan into dev-lsu

[submodule "rocket-chip"]
path = rocket-chip
url = https://github.com/chipsalliance/rocket-chip.git
branch = 2bdb03dbca3f77ad4c378cc1b95ab4961bc1448a
...@@ -17,11 +17,11 @@ REMOTE_PRJ_HOME = $(REMOTE_PREFIX)/$(abspath .)/ ...@@ -17,11 +17,11 @@ REMOTE_PRJ_HOME = $(REMOTE_PREFIX)/$(abspath .)/
.DEFAULT_GOAL = verilog .DEFAULT_GOAL = verilog
help: help:
mill chiselModule.test.runMain top.$(TOP) --help mill XiangShan.test.runMain top.$(TOP) --help
$(TOP_V): $(SCALA_FILE) $(TOP_V): $(SCALA_FILE)
mkdir -p $(@D) mkdir -p $(@D)
mill chiselModule.runMain top.$(TOP) -X verilog -td $(@D) --output-file $(@F) --infer-rw $(FPGATOP) --repl-seq-mem -c:$(FPGATOP):-o:$(@D)/$(@F).conf mill XiangShan.runMain top.$(TOP) -X verilog -td $(@D) --output-file $(@F) --infer-rw $(FPGATOP) --repl-seq-mem -c:$(FPGATOP):-o:$(@D)/$(@F).conf
$(MEM_GEN) $(@D)/$(@F).conf >> $@ $(MEM_GEN) $(@D)/$(@F).conf >> $@
sed -i -e 's/_\(aw\|ar\|w\|r\|b\)_\(\|bits_\)/_\1/g' $@ sed -i -e 's/_\(aw\|ar\|w\|r\|b\)_\(\|bits_\)/_\1/g' $@
@git log -n 1 >> .__head__ @git log -n 1 >> .__head__
...@@ -48,9 +48,9 @@ SIM_ARGS = ...@@ -48,9 +48,9 @@ SIM_ARGS =
$(SIM_TOP_V): $(SCALA_FILE) $(TEST_FILE) $(SIM_TOP_V): $(SCALA_FILE) $(TEST_FILE)
mkdir -p $(@D) mkdir -p $(@D)
ifeq ($(REMOTE),localhost) ifeq ($(REMOTE),localhost)
mill chiselModule.test.runMain $(SIMTOP) -X verilog -td $(@D) --full-stacktrace --output-file $(@F) $(SIM_ARGS) mill XiangShan.test.runMain $(SIMTOP) -X verilog -td $(@D) --full-stacktrace --output-file $(@F) $(SIM_ARGS)
else else
ssh -tt $(REMOTE) "cd $(REMOTE_PRJ_HOME) && mill chiselModule.test.runMain $(SIMTOP) -X verilog -td $(@D) --full-stacktrace --output-file $(@F) $(SIM_ARGS)" ssh -tt $(REMOTE) "cd $(REMOTE_PRJ_HOME) && mill XiangShan.test.runMain $(SIMTOP) -X verilog -td $(@D) --full-stacktrace --output-file $(@F) $(SIM_ARGS)"
endif endif
......
// See README.md for license details.
def scalacOptionsVersion(scalaVersion: String): Seq[String] = {
Seq() ++ {
// If we're building with Scala > 2.11, enable the compile option
// switch to support our anonymous Bundle definitions:
// https://github.com/scala/bug/issues/10047
CrossVersion.partialVersion(scalaVersion) match {
case Some((2, scalaMajor: Long)) if scalaMajor < 12 => Seq()
case _ => Seq("-Xsource:2.11")
}
}
}
def javacOptionsVersion(scalaVersion: String): Seq[String] = {
Seq() ++ {
// Scala 2.12 requires Java 8. We continue to generate
// Java 7 compatible code for Scala 2.11
// for compatibility with old clients.
CrossVersion.partialVersion(scalaVersion) match {
case Some((2, scalaMajor: Long)) if scalaMajor < 12 =>
Seq("-source", "1.7", "-target", "1.7")
case _ =>
Seq("-source", "1.8", "-target", "1.8")
}
}
}
name := "xiangshan"
version := "3.1.1"
scalaVersion := "2.11.12"
crossScalaVersions := Seq("2.11.12", "2.12.4")
resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
Resolver.sonatypeRepo("releases")
)
// Provide a managed dependency on X if -DXVersion="" is supplied on the command line.
val defaultVersions = Map(
"chisel3" -> "3.3.2",
"chisel-iotesters" -> "[1.2.5,1.3-SNAPSHOT["
)
libraryDependencies ++= Seq("chisel3","chisel-iotesters").map {
dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }
libraryDependencies += "net.java.dev.jna" % "jna" % "4.0.0"
scalacOptions ++= scalacOptionsVersion(scalaVersion.value)
javacOptions ++= javacOptionsVersion(scalaVersion.value)
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.2.1"
import mill._, scalalib._ import os.Path
import mill._
import mill.modules.Util
import scalalib._
import coursier.maven.MavenRepository import coursier.maven.MavenRepository
object CustomZincWorkerModule extends ZincWorkerModule { object CustomZincWorkerModule extends ZincWorkerModule {
def repositories() = super.repositories ++ Seq( def repositories() = Seq(
MavenRepository("https://oss.sonatype.org/content/repositories/releases"), MavenRepository("https://maven.aliyun.com/repository/public"),
MavenRepository("https://oss.sonatype.org/content/repositories/snapshots") MavenRepository("https://maven.aliyun.com/repository/apache-snapshots")
) )
} }
/** trait CommonModule extends ScalaModule {
* Scala 2.12 module that is source-compatible with 2.11. override def scalaVersion = "2.12.10"
* This is due to Chisel's use of structural types. See
* https://github.com/freechipsproject/chisel3/issues/606 override def scalacOptions = Seq("-Xsource:2.11")
*/
trait HasXsource211 extends ScalaModule { override def zincWorker = CustomZincWorkerModule
override def scalacOptions = T {
super.scalacOptions() ++ Seq( private val macroParadise = ivy"org.scalamacros:::paradise:2.1.0"
"-deprecation",
"-unchecked", override def compileIvyDeps = Agg(macroParadise)
"-Xsource:2.11"
) override def scalacPluginIvyDeps = Agg(macroParadise)
}
object `rocket-chip` extends SbtModule with CommonModule {
val rocketChisel = Agg(
ivy"edu.berkeley.cs::chisel3:3.3.1"
)
override def ivyDeps = super.ivyDeps() ++ Agg(
ivy"${scalaOrganization()}:scala-reflect:${scalaVersion()}",
ivy"org.json4s::json4s-jackson:3.6.1"
) ++ rocketChisel
object `api-config-chipsalliance` extends CommonModule {
override def millSourcePath = super.millSourcePath / 'design / 'craft
} }
object macros extends SbtModule with CommonModule
object hardfloat extends SbtModule with CommonModule {
override def ivyDeps = super.ivyDeps() ++ rocketChisel
}
override def moduleDeps = super.moduleDeps ++ Seq(
`api-config-chipsalliance`, macros, hardfloat
)
} }
trait HasChisel3 extends ScalaModule { object XiangShan extends CommonModule with SbtModule {
override def ivyDeps = Agg( override def millSourcePath = millOuterCtx.millSourcePath
override def forkArgs = Seq("-Xmx10G")
override def ivyDeps = super.ivyDeps() ++ Agg(
ivy"edu.berkeley.cs::chisel3:3.3.2" ivy"edu.berkeley.cs::chisel3:3.3.2"
) )
}
override def moduleDeps = super.moduleDeps ++ Seq(`rocket-chip`)
trait HasChiselTests extends CrossSbtModule {
object test extends Tests { object test extends Tests {
override def ivyDeps = Agg( override def ivyDeps = super.ivyDeps() ++ Agg(
ivy"org.scalatest::scalatest:3.0.4", ivy"org.scalatest::scalatest:3.0.4",
ivy"edu.berkeley.cs::chisel-iotesters:1.2+", ivy"edu.berkeley.cs::chisel-iotesters:1.2+",
ivy"edu.berkeley.cs::chiseltest:0.2.1" ivy"edu.berkeley.cs::chiseltest:0.2.1"
) )
def testFrameworks = Seq("org.scalatest.tools.Framework")
def testFrameworks = Seq(
"org.scalatest.tools.Framework"
)
def testOnly(args: String*) = T.command { def testOnly(args: String*) = T.command {
super.runMain("org.scalatest.tools.Runner", args: _*) super.runMain("org.scalatest.tools.Runner", args: _*)
} }
} }
}
trait HasMacroParadise extends ScalaModule {
// Enable macro paradise for @chiselName et al
val macroPlugins = Agg(ivy"org.scalamacros:::paradise:2.1.0")
def scalacPluginIvyDeps = macroPlugins
def compileIvyDeps = macroPlugins
}
object chiselModule extends CrossSbtModule with HasChisel3 with HasChiselTests with HasXsource211 with HasMacroParadise {
def zincWorker = CustomZincWorkerModule
def crossScalaVersion = "2.11.12"
def forkArgs = Seq("-Xmx10G")
} }
Subproject commit 2bdb03dbca3f77ad4c378cc1b95ab4961bc1448a
package device package device
import chipsalliance.rocketchip.config.Parameters
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.diplomacy.AddressSet
import bus.axi4._
import utils._ import utils._
trait HasSDConst { trait HasSDConst {
def MemorySize = 4L * 1024 * 1024 * 1024 // 4GB def MemorySize = 4L * 1024 * 1024 * 1024 // 4GB
def READ_BL_LEN = 15 def READ_BL_LEN = 15
def BlockLen = (1 << READ_BL_LEN) def BlockLen = (1 << READ_BL_LEN)
def NrBlock = MemorySize / BlockLen def NrBlock = MemorySize / BlockLen
def C_SIZE_MULT = 7 // only 3 bits def C_SIZE_MULT = 7 // only 3 bits
def MULT = (1 << (C_SIZE_MULT + 2)) def MULT = (1 << (C_SIZE_MULT + 2))
def C_SIZE = NrBlock / MULT - 1 def C_SIZE = NrBlock / MULT - 1
} }
...@@ -27,99 +31,108 @@ class SDHelper extends BlackBox with HasBlackBoxInline { ...@@ -27,99 +31,108 @@ class SDHelper extends BlackBox with HasBlackBoxInline {
setInline("SDHelper.v", setInline("SDHelper.v",
s""" s"""
|import "DPI-C" function void sd_setaddr(input int addr); |import "DPI-C" function void sd_setaddr(input int addr);
|import "DPI-C" function void sd_read(output int data); |import "DPI-C" function void sd_read(output int data);
| |
|module SDHelper ( |module SDHelper (
| input clk, | input clk,
| input setAddr, | input setAddr,
| input [31:0] addr, | input [31:0] addr,
| input ren, | input ren,
| output reg [31:0] data | output reg [31:0] data
|); |);
| |
| always@(*) begin | always@(*) begin
| if (setAddr) sd_setaddr(addr); | if (setAddr) sd_setaddr(addr);
| if (ren) sd_read(data); | if (ren) sd_read(data);
| end | end
| |
|endmodule |endmodule
""".stripMargin) """.stripMargin)
} }
class AXI4DummySD extends AXI4SlaveModule(new AXI4Lite) with HasSDConst { class AXI4DummySD
val range = List.range(0,21) (
val sdcmd :: sdarg :: sdtout :: sdcdiv :: sdrsp0 :: sdrsp1 :: sdrsp2 :: sdrsp3 :: sdhsts :: __pad0 :: __pad1 :: __pad2 :: sdvdd :: sdedm :: sdhcfg :: sdhbct :: sddata :: __pad10 :: __pad11 :: __pad12 :: sdhblc :: Nil = range address: AddressSet
)(implicit p: Parameters)
extends AXI4SlaveModule(address, executable = false) with HasSDConst
{
override lazy val module = new AXI4SlaveModuleImp[Null](this) {
val range = List.range(0, 21)
val sdcmd :: sdarg :: sdtout :: sdcdiv :: sdrsp0 :: sdrsp1 :: sdrsp2 :: sdrsp3 :: sdhsts :: __pad0 :: __pad1 :: __pad2 :: sdvdd :: sdedm :: sdhcfg :: sdhbct :: sddata :: __pad10 :: __pad11 :: __pad12 :: sdhblc :: Nil = range
val regs = List.fill(range.size)(RegInit(0.U(32.W))) val regs = List.fill(range.size)(RegInit(0.U(32.W)))
val edmConst = (8 << 4).U // number of data in fifo val edmConst = (8 << 4).U // number of data in fifo
val MMC_SEND_OP_COND = 1 val MMC_SEND_OP_COND = 1
val MMC_ALL_SEND_CID = 2 val MMC_ALL_SEND_CID = 2
val MMC_SEND_CSD = 9 val MMC_SEND_CSD = 9
val MMC_SEND_STATUS = 13 val MMC_SEND_STATUS = 13
val MMC_READ_MULTIPLE_BLOCK = 18 val MMC_READ_MULTIPLE_BLOCK = 18
val setAddr = WireInit(false.B) val setAddr = WireInit(false.B)
def cmdWfn(wdata: UInt) = { def cmdWfn(wdata: UInt) = {
val cmd = wdata(5,0) val cmd = wdata(5, 0)
switch (cmd) { switch(cmd) {
is (MMC_SEND_OP_COND.U) { is(MMC_SEND_OP_COND.U) {
regs(sdrsp0) := "h80ff8000".U regs(sdrsp0) := "h80ff8000".U
} }
is (MMC_ALL_SEND_CID.U) { is(MMC_ALL_SEND_CID.U) {
regs(sdrsp0) := "h00000001".U regs(sdrsp0) := "h00000001".U
regs(sdrsp1) := "h00000000".U regs(sdrsp1) := "h00000000".U
regs(sdrsp2) := "h00000000".U regs(sdrsp2) := "h00000000".U
regs(sdrsp3) := "h15000000".U regs(sdrsp3) := "h15000000".U
} }
is (MMC_SEND_CSD.U) { is(MMC_SEND_CSD.U) {
regs(sdrsp0) := "h92404001".U regs(sdrsp0) := "h92404001".U
regs(sdrsp1) := "h124b97e3".U | (C_SIZE.U(1,0) << 30) regs(sdrsp1) := "h124b97e3".U | (C_SIZE.U(1, 0) << 30)
regs(sdrsp2) := "h0f508000".U | C_SIZE.U(11,2) | (READ_BL_LEN.U << 16) regs(sdrsp2) := "h0f508000".U | C_SIZE.U(11, 2) | (READ_BL_LEN.U << 16)
regs(sdrsp3) := "h8c26012a".U regs(sdrsp3) := "h8c26012a".U
} }
is (MMC_SEND_STATUS.U) { is(MMC_SEND_STATUS.U) {
regs(sdrsp0) := 0.U regs(sdrsp0) := 0.U
regs(sdrsp1) := 0.U regs(sdrsp1) := 0.U
regs(sdrsp2) := 0.U regs(sdrsp2) := 0.U
regs(sdrsp3) := 0.U regs(sdrsp3) := 0.U
} }
is (MMC_READ_MULTIPLE_BLOCK.U) { is(MMC_READ_MULTIPLE_BLOCK.U) {
setAddr := true.B setAddr := true.B
}
} }
wdata
} }
wdata
}
val sdHelper = Module(new SDHelper) val sdHelper = Module(new SDHelper)
sdHelper.io.clk := clock sdHelper.io.clk := clock
sdHelper.io.ren := (getOffset(raddr) === 0x40.U && io.in.ar.fire()) sdHelper.io.ren := (getOffset(raddr) === 0x40.U && in.ar.fire())
sdHelper.io.setAddr := setAddr sdHelper.io.setAddr := setAddr
sdHelper.io.addr := regs(sdarg) sdHelper.io.addr := regs(sdarg)
def sdRead = sdHelper.io.data
def sdRead = sdHelper.io.data
val mapping = Map(
RegMap(0x00, regs(sdcmd), cmdWfn), val mapping = Map(
RegMap(0x04, regs(sdarg)), RegMap(0x00, regs(sdcmd), cmdWfn),
RegMap(0x10, regs(sdrsp0), RegMap.Unwritable), RegMap(0x04, regs(sdarg)),
RegMap(0x14, regs(sdrsp1), RegMap.Unwritable), RegMap(0x10, regs(sdrsp0), RegMap.Unwritable),
RegMap(0x18, regs(sdrsp2), RegMap.Unwritable), RegMap(0x14, regs(sdrsp1), RegMap.Unwritable),
RegMap(0x1c, regs(sdrsp3), RegMap.Unwritable), RegMap(0x18, regs(sdrsp2), RegMap.Unwritable),
RegMap(0x20, regs(sdhsts)), RegMap(0x1c, regs(sdrsp3), RegMap.Unwritable),
RegMap(0x34, edmConst, RegMap.Unwritable), RegMap(0x20, regs(sdhsts)),
RegMap(0x38, regs(sdhcfg)), RegMap(0x34, edmConst, RegMap.Unwritable),
RegMap(0x38, regs(sdhbct)), RegMap(0x38, regs(sdhcfg)),
RegMap(0x40, sdRead, RegMap.Unwritable), RegMap(0x38, regs(sdhbct)),
RegMap(0x50, regs(sdhblc)) RegMap(0x40, sdRead, RegMap.Unwritable),
) RegMap(0x50, regs(sdhblc))
def getOffset(addr: UInt) = addr(12,0) )
val strb = Mux(waddr(2), in.w.bits.strb(7,4), in.w.bits.strb(3,0)) def getOffset(addr: UInt) = addr(12, 0)
val rdata = Wire(UInt(64.W))
RegMap.generate(mapping, getOffset(raddr), rdata, val strb = Mux(waddr(2), in.w.bits.strb(7, 4), in.w.bits.strb(3, 0))
getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(strb)) val rdata = Wire(UInt(64.W))
RegMap.generate(mapping, getOffset(raddr), rdata,
in.r.bits.data := RegEnable(RegNext(Fill(2, rdata(31,0))), ren) getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(strb))
in.r.bits.data := Fill(2, rdata(31, 0))
}
} }
...@@ -2,25 +2,33 @@ package device ...@@ -2,25 +2,33 @@ package device
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chipsalliance.rocketchip.config.Parameters
import bus.axi4._ import freechips.rocketchip.diplomacy.AddressSet
import utils._ import utils._
class AXI4Flash extends AXI4SlaveModule(new AXI4Lite) { class AXI4Flash
val jmpToDramInstr1 = "h0010029b".U // addiw t0,zero,1 (
val jmpToDramInstr2 = "h01f29293".U // slli t0,t0,0x1f address: AddressSet
val jmpToDramInstr3 = "h00028067".U // jr t0 )(implicit p: Parameters)
extends AXI4SlaveModule(address, executable = false)
{
override lazy val module = new AXI4SlaveModuleImp(this){
val jmpToDramInstr1 = "h0010029b".U // addiw t0,zero,1
val jmpToDramInstr2 = "h01f29293".U // slli t0,t0,0x1f
val jmpToDramInstr3 = "h00028067".U // jr t0
val mapping = Map( val mapping = Map(
RegMap(0x0, jmpToDramInstr1, RegMap.Unwritable), RegMap(0x0, jmpToDramInstr1, RegMap.Unwritable),
RegMap(0x4, jmpToDramInstr2, RegMap.Unwritable), RegMap(0x4, jmpToDramInstr2, RegMap.Unwritable),
RegMap(0x8, jmpToDramInstr3, RegMap.Unwritable) RegMap(0x8, jmpToDramInstr3, RegMap.Unwritable)
) )
def getOffset(addr: UInt) = addr(12,0) def getOffset(addr: UInt) = addr(12,0)
val rdata = Wire(UInt(64.W)) val rdata = Wire(UInt(64.W))
RegMap.generate(mapping, getOffset(raddr), rdata, RegMap.generate(mapping, getOffset(raddr), rdata,
getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb)) getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb))
in.r.bits.data := RegEnable(RegNext(Fill(2, rdata(31,0))), ren) in.r.bits.data := Fill(2, rdata(31,0))
}
} }
...@@ -2,8 +2,8 @@ package device ...@@ -2,8 +2,8 @@ package device
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chipsalliance.rocketchip.config.Parameters
import bus.axi4._ import freechips.rocketchip.diplomacy.AddressSet
import utils._ import utils._
class KeyboardIO extends Bundle { class KeyboardIO extends Bundle {
...@@ -12,17 +12,25 @@ class KeyboardIO extends Bundle { ...@@ -12,17 +12,25 @@ class KeyboardIO extends Bundle {
} }
// this Module is not tested // this Module is not tested
class AXI4Keyboard extends AXI4SlaveModule(new AXI4Lite, new KeyboardIO) { class AXI4Keyboard
val buf = Reg(UInt(10.W)) (
val ps2ClkLatch = RegNext(io.extra.get.ps2Clk) address: AddressSet
val negedge = RegNext(ps2ClkLatch) && ~ps2ClkLatch )(implicit p: Parameters)
when (negedge) { buf := Cat(io.extra.get.ps2Data, buf(9,1)) } extends AXI4SlaveModule(address, executable = false, _extra = new KeyboardIO)
{
override lazy val module = new AXI4SlaveModuleImp[KeyboardIO](this){
val buf = Reg(UInt(10.W))
val ps2ClkLatch = RegNext(io.extra.get.ps2Clk)
val negedge = RegNext(ps2ClkLatch) && ~ps2ClkLatch
when (negedge) { buf := Cat(io.extra.get.ps2Data, buf(9,1)) }
val cnt = Counter(negedge, 10)
val queue = Module(new Queue(UInt(8.W), 8))
queue.io.enq.valid := cnt._2 && !buf(0) && io.extra.get.ps2Data && buf(9,1).xorR
queue.io.enq.bits := buf(8,1)
queue.io.deq.ready := in.r.ready
val cnt = Counter(negedge, 10) in.r.bits.data := Mux(queue.io.deq.valid, queue.io.deq.bits, 0.U)
val queue = Module(new Queue(UInt(8.W), 8)) }
queue.io.enq.valid := cnt._2 && !buf(0) && io.extra.get.ps2Data && buf(9,1).xorR
queue.io.enq.bits := buf(8,1)
queue.io.deq.ready := in.r.ready
in.r.bits.data := Mux(queue.io.deq.valid, queue.io.deq.bits, 0.U)
} }
package device package device
import chipsalliance.rocketchip.config.Parameters
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chisel3.util.experimental.loadMemoryFromFile import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType}
import xiangshan.HasXSParameter
import noop.HasNOOPParameter class RAMHelper(memByte: BigInt) extends BlackBox with HasXSParameter {
import bus.axi4._
import utils._
class RAMHelper(memByte: Int) extends BlackBox with HasNOOPParameter {
val io = IO(new Bundle { val io = IO(new Bundle {
val clk = Input(Clock()) val clk = Input(Clock())
val rIdx = Input(UInt(DataBits.W)) val rIdx = Input(UInt(DataBits.W))
...@@ -20,35 +18,51 @@ class RAMHelper(memByte: Int) extends BlackBox with HasNOOPParameter { ...@@ -20,35 +18,51 @@ class RAMHelper(memByte: Int) extends BlackBox with HasNOOPParameter {
}) })
} }
class AXI4RAM[T <: AXI4Lite](_type: T = new AXI4, memByte: Int, class AXI4RAM
useBlackBox: Boolean = false) extends AXI4SlaveModule(_type) with HasNOOPParameter { (
address: AddressSet,
val offsetBits = log2Up(memByte) memByte: Long,
val offsetMask = (1 << offsetBits) - 1 useBlackBox: Boolean = false,
def index(addr: UInt) = (addr & offsetMask.U) >> log2Ceil(DataBytes) executable: Boolean = true,
def inRange(idx: UInt) = idx < (memByte / 8).U beatBytes: Int = 8,
burstLen: Int = 16
val wIdx = index(waddr) + writeBeatCnt )(implicit p: Parameters)
val rIdx = index(raddr) + readBeatCnt extends AXI4SlaveModule(address, executable, beatBytes, burstLen)
val wen = in.w.fire() && inRange(wIdx) {
val rdata = if (useBlackBox) { override lazy val module = new AXI4SlaveModuleImp(this){
val mem = Module(new RAMHelper(memByte))
mem.io.clk := clock val offsetBits = log2Up(memByte)
mem.io.rIdx := rIdx val offsetMask = (1 << offsetBits) - 1
mem.io.wIdx := wIdx
mem.io.wdata := in.w.bits.data
mem.io.wmask := fullMask def index(addr: UInt) = ((addr & offsetMask.U) >> log2Ceil(beatBytes)).asUInt()
mem.io.wen := wen
mem.io.rdata
} else {
val mem = Mem(memByte / DataBytes, Vec(DataBytes, UInt(8.W)))
val wdata = VecInit.tabulate(DataBytes) { i => in.w.bits.data(8*(i+1)-1, 8*i) }
when (wen) { mem.write(wIdx, wdata, in.w.bits.strb.asBools) }
Cat(mem.read(rIdx).reverse)
}
in.r.bits.data := RegEnable(rdata, ren) def inRange(idx: UInt) = idx < (memByte / 8).U
val wIdx = index(waddr) + writeBeatCnt
val rIdx = index(raddr) + readBeatCnt
val wen = in.w.fire() && inRange(wIdx)
val rdata = if (useBlackBox) {
val mem = Module(new RAMHelper(memByte))
mem.io.clk := clock
mem.io.rIdx := rIdx
mem.io.wIdx := wIdx
mem.io.wdata := in.w.bits.data
mem.io.wmask := fullMask
mem.io.wen := wen
mem.io.rdata
} else {
val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W)))
val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8 * (i + 1) - 1, 8 * i) }
when(wen) {
mem.write(wIdx, wdata, in.w.bits.strb.asBools())
}
Cat(mem.read(rIdx).reverse)
}
in.r.bits.data := rdata
}
} }
package device
import chisel3._
import chisel3.util._
import noop.HasNOOPParameter
import bus.axi4._
import utils._
abstract class AXI4SlaveModule[T <: AXI4Lite, B <: Data](_type :T = new AXI4, _extra: B = null)
extends Module with HasNOOPParameter {
val io = IO(new Bundle{
val in = Flipped(_type)
val extra = if (_extra != null) Some(Flipped(Flipped(_extra))) else None
})
val in = io.in
val fullMask = MaskExpand(in.w.bits.strb)
def genWdata(originData: UInt) = (originData & ~fullMask) | (in.w.bits.data & fullMask)
val raddr = Wire(UInt())
val ren = Wire(Bool())
val (readBeatCnt, rLast) = in match {
case axi4: AXI4 =>
val c = Counter(256)
val beatCnt = Counter(256)
val len = HoldUnless(axi4.ar.bits.len, axi4.ar.fire())
val burst = HoldUnless(axi4.ar.bits.burst, axi4.ar.fire())
val wrapAddr = axi4.ar.bits.addr & ~(axi4.ar.bits.len.asTypeOf(UInt(PAddrBits.W)) << axi4.ar.bits.size)
raddr := HoldUnless(wrapAddr, axi4.ar.fire())
axi4.r.bits.last := (c.value === len)
when (ren) {
beatCnt.inc()
when (burst === AXI4Parameters.BURST_WRAP && beatCnt.value === len) { beatCnt.value := 0.U }
}
when (axi4.r.fire()) {
c.inc()
when (axi4.r.bits.last) { c.value := 0.U }
}
when (axi4.ar.fire()) {
beatCnt.value := (axi4.ar.bits.addr >> axi4.ar.bits.size) & axi4.ar.bits.len
when (axi4.ar.bits.len =/= 0.U && axi4.ar.bits.burst === AXI4Parameters.BURST_WRAP) {
assert(axi4.ar.bits.len === 1.U || axi4.ar.bits.len === 3.U ||
axi4.ar.bits.len === 7.U || axi4.ar.bits.len === 15.U)
}
}
(beatCnt.value, axi4.r.bits.last)
case axi4lite: AXI4Lite =>
raddr := axi4lite.ar.bits.addr
(0.U, true.B)
}
val r_busy = BoolStopWatch(in.ar.fire(), in.r.fire() && rLast, startHighPriority = true)
in.ar.ready := in.r.ready || !r_busy
in.r.bits.resp := AXI4Parameters.RESP_OKAY
ren := RegNext(in.ar.fire()) || (in.r.fire() && !rLast)
in.r.valid := BoolStopWatch(ren && (in.ar.fire() || r_busy), in.r.fire(), startHighPriority = true)
val waddr = Wire(UInt())
val (writeBeatCnt, wLast) = in match {
case axi4: AXI4 =>
val c = Counter(256)
waddr := HoldUnless(axi4.aw.bits.addr, axi4.aw.fire())
when (axi4.w.fire()) {
c.inc()
when (axi4.w.bits.last) { c.value := 0.U }
}
(c.value, axi4.w.bits.last)
case axi4lite: AXI4Lite =>
waddr := axi4lite.aw.bits.addr
(0.U, true.B)
}
val w_busy = BoolStopWatch(in.aw.fire(), in.b.fire(), startHighPriority = true)
in.aw.ready := !w_busy
in. w.ready := in.aw.valid || (w_busy)
in.b.bits.resp := AXI4Parameters.RESP_OKAY
in.b.valid := BoolStopWatch(in.w.fire() && wLast, in.b.fire(), startHighPriority = true)
in match {
case axi4: AXI4 =>
axi4.b.bits.id := RegEnable(axi4.aw.bits.id, axi4.aw.fire())
axi4.b.bits.user := RegEnable(axi4.aw.bits.user, axi4.aw.fire())
axi4.r.bits.id := RegEnable(axi4.ar.bits.id, axi4.ar.fire())
axi4.r.bits.user := RegEnable(axi4.ar.bits.user, axi4.ar.fire())
case axi4lite: AXI4Lite =>
}
}
package device
import chisel3._
import chisel3.util._
import utils._
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes}
import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters}
import xiangshan.HasXSLog
abstract class AXI4SlaveModule[T <: Data]
(
address: AddressSet,
executable: Boolean = true,
beatBytes: Int = 8,
burstLen: Int = 1,
val _extra: T = null
)(implicit p: Parameters) extends LazyModule {
val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
Seq(AXI4SlaveParameters(
Seq(address),
regionType = RegionType.UNCACHED,
executable = executable,
supportsWrite = TransferSizes(1, beatBytes * burstLen),
supportsRead = TransferSizes(1, beatBytes * burstLen),
interleavedId = Some(0)
)),
beatBytes = beatBytes
)))
lazy val module = new AXI4SlaveModuleImp[T](this)
}
class AXI4SlaveModuleImp[T<:Data](outer: AXI4SlaveModule[T])
extends LazyModuleImp(outer) with HasXSLog
{
val io = IO(new Bundle {
val extra = if(outer._extra == null) None else Some(outer._extra.cloneType)
})
val (in, edge) = outer.node.in.head
// val timer = GTimer()
when(in.ar.fire()){
XSDebug(p"[ar] addr: ${Hexadecimal(in.ar.bits.addr)} " +
p"arlen:${in.ar.bits.len} arsize:${in.ar.bits.size} " +
p"id: ${in.ar.bits.id}\n"
)
}
when(in.aw.fire()){
XSDebug(p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " +
p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " +
p"id: ${in.aw.bits.id}\n"
)
}
when(in.w.fire()){
XSDebug(p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n")
}
when(in.b.fire()){
XSDebug(p"[b] id: ${in.b.bits.id}\n")
}
when(in.r.fire()){
XSDebug(p"[r] id: ${in.r.bits.id} data: ${Hexadecimal(in.r.bits.data)}\n")
}
when(in.aw.fire()){
assert(in.aw.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
}
when(in.ar.fire()){
assert(in.ar.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
}
private val s_idle :: s_rdata :: s_wdata :: s_wresp :: Nil = Enum(4)
private val state = RegInit(s_idle)
switch(state){
is(s_idle){
when(in.ar.fire()){
state := s_rdata
}
when(in.aw.fire()){
state := s_wdata
}
}
is(s_rdata){
when(in.r.fire() && in.r.bits.last){
state := s_idle
}
}
is(s_wdata){
when(in.w.fire() && in.w.bits.last){
state := s_wresp
}
}
is(s_wresp){
when(in.b.fire()){
state := s_idle
}
}
}
val fullMask = MaskExpand(in.w.bits.strb)
def genWdata(originData: UInt) = (originData & (~fullMask).asUInt()) | (in.w.bits.data & fullMask)
val raddr = Wire(UInt())
val (readBeatCnt, rLast) = {
val c = Counter(256)
val len = HoldUnless(in.ar.bits.len, in.ar.fire())
raddr := HoldUnless(in.ar.bits.addr, in.ar.fire())
in.r.bits.last := (c.value === len)
when(in.r.fire()) {
c.inc()
when(in.r.bits.last) {
c.value := 0.U
}
}
when(in.ar.fire()) {
assert(
in.ar.bits.len === 0.U ||
in.ar.bits.len === 1.U ||
in.ar.bits.len === 3.U ||
in.ar.bits.len === 7.U ||
in.ar.bits.len === 15.U
)
}
(c.value, in.r.bits.last)
}
in.ar.ready := state === s_idle
in.r.bits.resp := AXI4Parameters.RESP_OKAY
in.r.valid := state === s_rdata
val waddr = Wire(UInt())
val (writeBeatCnt, wLast) = {
val c = Counter(256)
waddr := HoldUnless(in.aw.bits.addr, in.aw.fire())
when(in.w.fire()) {
c.inc()
when(in.w.bits.last) {
c.value := 0.U
}
}
(c.value, in.w.bits.last)
}
in.aw.ready := state === s_idle
in.w.ready := state === s_wdata
in.b.bits.resp := AXI4Parameters.RESP_OKAY
in.b.valid := state===s_wresp
in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire())
in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire())
in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire())
in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire())
}
package device package device
import chisel3._ import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils import chisel3.util.experimental.BoringUtils
import bus.axi4._ import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.AddressSet
import utils._ import utils._
class TimerIO extends Bundle { class TimerIO extends Bundle {
val mtip = Output(Bool()) val mtip = Output(Bool())
} }
class AXI4Timer(sim: Boolean = false) extends AXI4SlaveModule(new AXI4Lite, new TimerIO) { class AXI4Timer
val mtime = RegInit(0.U(64.W)) // unit: us (
val mtimecmp = RegInit(0.U(64.W)) sim: Boolean = false,
address: AddressSet
val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 10000) )(implicit p: Parameters)
val freq = RegInit(clk.U(16.W)) extends AXI4SlaveModule(address, executable = false, _extra = new TimerIO)
val inc = RegInit(1000.U(16.W)) {
override lazy val module = new AXI4SlaveModuleImp[TimerIO](this){
val cnt = RegInit(0.U(16.W)) val mtime = RegInit(0.U(64.W)) // unit: us
val nextCnt = cnt + 1.U val mtimecmp = RegInit(0.U(64.W))
cnt := Mux(nextCnt < freq, nextCnt, 0.U)
val tick = (nextCnt === freq) val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 10000)
when (tick) { mtime := mtime + inc } val freq = RegInit(clk.U(16.W))
val inc = RegInit(1000.U(16.W))
if (sim) {
val isWFI = WireInit(false.B) val cnt = RegInit(0.U(16.W))
BoringUtils.addSink(isWFI, "isWFI") val nextCnt = cnt + 1.U
when (isWFI) { mtime := mtime + 100000.U } cnt := Mux(nextCnt < freq, nextCnt, 0.U)
val tick = (nextCnt === freq)
when (tick) { mtime := mtime + inc }
if (sim) {
val isWFI = WireInit(false.B)
BoringUtils.addSink(isWFI, "isWFI")
when (isWFI) { mtime := mtime + 100000.U }
}
val mapping = Map(
RegMap(0x4000, mtimecmp),
RegMap(0x8000, freq),
RegMap(0x8008, inc),
RegMap(0xbff8, mtime)
)
def getOffset(addr: UInt) = addr(15,0)
RegMap.generate(mapping, getOffset(raddr), in.r.bits.data,
getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb))
io.extra.get.mtip := RegNext(mtime >= mtimecmp)
} }
val mapping = Map(
RegMap(0x4000, mtimecmp),
RegMap(0x8000, freq),
RegMap(0x8008, inc),
RegMap(0xbff8, mtime)
)
def getOffset(addr: UInt) = addr(15,0)
RegMap.generate(mapping, getOffset(raddr), in.r.bits.data,
getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb))
io.extra.get.mtip := RegNext(mtime >= mtimecmp)
} }
...@@ -2,8 +2,10 @@ package device ...@@ -2,8 +2,10 @@ package device
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import bus.axi4._ import bus.axi4._
import chipsalliance.rocketchip.config.Parameters
import chisel3.util.experimental.BoringUtils
import freechips.rocketchip.diplomacy.AddressSet
import utils._ import utils._
class UARTIO extends Bundle { class UARTIO extends Bundle {
...@@ -17,23 +19,31 @@ class UARTIO extends Bundle { ...@@ -17,23 +19,31 @@ class UARTIO extends Bundle {
} }
} }
class AXI4UART extends AXI4SlaveModule(new AXI4Lite, new UARTIO) { class AXI4UART
val rxfifo = RegInit(0.U(32.W)) (
val txfifo = Reg(UInt(32.W)) address: AddressSet
val stat = RegInit(1.U(32.W)) )(implicit p: Parameters)
val ctrl = RegInit(0.U(32.W)) extends AXI4SlaveModule(address, executable = false, _extra = new UARTIO)
{
override lazy val module = new AXI4SlaveModuleImp[UARTIO](this){
val rxfifo = RegInit(0.U(32.W))
val txfifo = Reg(UInt(32.W))
val stat = RegInit(1.U(32.W))
val ctrl = RegInit(0.U(32.W))
io.extra.get.out.valid := (waddr(3,0) === 4.U && in.w.fire()) io.extra.get.out.valid := (waddr(3,0) === 4.U && in.w.fire())
io.extra.get.out.ch := in.w.bits.data(7,0) io.extra.get.out.ch := in.w.bits.data(7,0)
io.extra.get.in.valid := (raddr(3,0) === 0.U && ren) io.extra.get.in.valid := (raddr(3,0) === 0.U && in.r.fire())
val mapping = Map( val mapping = Map(
RegMap(0x0, io.extra.get.in.ch, RegMap.Unwritable), RegMap(0x0, io.extra.get.in.ch, RegMap.Unwritable),
RegMap(0x4, txfifo), RegMap(0x4, txfifo),
RegMap(0x8, stat), RegMap(0x8, stat),
RegMap(0xc, ctrl) RegMap(0xc, ctrl)
) )
RegMap.generate(mapping, raddr(3,0), in.r.bits.data, RegMap.generate(mapping, raddr(3,0), in.r.bits.data,
waddr(3,0), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(2,0))) waddr(3,0), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(2,0))
)
}
} }
...@@ -2,8 +2,9 @@ package device ...@@ -2,8 +2,9 @@ package device
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chipsalliance.rocketchip.config.Parameters
import bus.axi4._ import freechips.rocketchip.amba.axi4.{AXI4AdapterNode, AXI4IdentityNode, AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters, AXI4Xbar}
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType}
import utils._ import utils._
trait HasVGAConst { trait HasVGAConst {
...@@ -51,19 +52,26 @@ class VGACtrlBundle extends Bundle { ...@@ -51,19 +52,26 @@ class VGACtrlBundle extends Bundle {
val sync = Output(Bool()) val sync = Output(Bool())
} }
class VGACtrl extends AXI4SlaveModule(new AXI4Lite, new VGACtrlBundle) with HasVGAParameter { class VGACtrl
val fbSizeReg = Cat(FBWidth.U(16.W), FBHeight.U(16.W)) (
val sync = in.aw.fire() address: AddressSet
)(implicit p: Parameters)
extends AXI4SlaveModule(address, _extra = new VGACtrlBundle, executable = false) with HasVGAParameter {
override lazy val module = new AXI4SlaveModuleImp[VGACtrlBundle](this) {
val fbSizeReg = Cat(FBWidth.U(16.W), FBHeight.U(16.W))
val sync = in.aw.fire()
val mapping = Map( val mapping = Map(
RegMap(0x0, fbSizeReg, RegMap.Unwritable), RegMap(0x0, fbSizeReg, RegMap.Unwritable),
RegMap(0x4, sync, RegMap.Unwritable) RegMap(0x4, sync, RegMap.Unwritable)
) )
RegMap.generate(mapping, raddr(3,0), in.r.bits.data, RegMap.generate(mapping, raddr(3, 0), in.r.bits.data,
waddr(3,0), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb)) waddr(3, 0), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb))
io.extra.get.sync := sync io.extra.get.sync := sync
}
} }
class FBHelper extends BlackBox with HasBlackBoxInline { class FBHelper extends BlackBox with HasBlackBoxInline {
...@@ -76,84 +84,161 @@ class FBHelper extends BlackBox with HasBlackBoxInline { ...@@ -76,84 +84,161 @@ class FBHelper extends BlackBox with HasBlackBoxInline {
setInline("FBHelper.v", setInline("FBHelper.v",
s""" s"""
|import "DPI-C" function void put_pixel(input int pixel); |import "DPI-C" function void put_pixel(input int pixel);
|import "DPI-C" function void vmem_sync(); |import "DPI-C" function void vmem_sync();
| |
|module FBHelper ( |module FBHelper (
| input clk, | input clk,
| input valid, | input valid,
| input [31:0] pixel, | input [31:0] pixel,
| input sync | input sync
|); |);
| |
| always@(posedge clk) begin | always@(posedge clk) begin
| if (valid) put_pixel(pixel); | if (valid) put_pixel(pixel);
| if (sync) vmem_sync(); | if (sync) vmem_sync();
| end | end
| |
|endmodule |endmodule
""".stripMargin) """.stripMargin)
} }
class AXI4VGA(sim: Boolean = false) extends Module with HasVGAParameter { class AXI4VGA
val AXIidBits = 2 (
val io = IO(new Bundle { sim: Boolean = false,
val in = new Bundle { fbAddress: AddressSet,
val fb = Flipped(new AXI4Lite) ctrlAddress: AddressSet
val ctrl = Flipped(new AXI4Lite) )(implicit p: Parameters)
extends LazyModule with HasVGAParameter {
private val fb = LazyModule(new AXI4RAM(
fbAddress,
memByte= FBPixels * 4,
sim,
executable = false
))
private val ctrl = LazyModule(new VGACtrl(ctrlAddress))
val node = AXI4IdentityNode()
fb.node := node
ctrl.node := node
lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle() {
val vga = new VGABundle
})
val out_fb = node.out.head._1
val out_ctrl = node.out.last._1
val in_fb = node.in.head._1
val in_ctrl = node.in.last._1
in_fb.ar.ready := true.B
in_fb.r.bits.data := 0.U
in_fb.r.bits.resp := AXI4Parameters.RESP_OKAY
in_fb.r.valid := BoolStopWatch(in_fb.ar.fire(), in_fb.r.fire(), startHighPriority = true)
def inRange(x: UInt, start: Int, end: Int) = (x >= start.U) && (x < end.U)
val (hCounter, hFinish) = Counter(true.B, HTotal)
val (vCounter, vFinish) = Counter(hFinish, VTotal)
io.vga.hsync := hCounter >= HFrontPorch.U
io.vga.vsync := vCounter >= VFrontPorch.U
val hInRange = inRange(hCounter, HActive, HBackPorch)
val vInRange = inRange(vCounter, VActive, VBackPorch)
io.vga.valid := hInRange && vInRange
val hCounterIsOdd = hCounter(0)
val hCounterIs2 = hCounter(1, 0) === 2.U
val vCounterIsOdd = vCounter(0)
// there is 2 cycle latency to read block memory,
// so we should issue the read request 2 cycle eariler
val nextPixel = inRange(hCounter, HActive - 1, HBackPorch - 1) && vInRange && hCounterIsOdd
val fbPixelAddrV0 = Counter(nextPixel && !vCounterIsOdd, FBPixels)._1
val fbPixelAddrV1 = Counter(nextPixel && vCounterIsOdd, FBPixels)._1
// each pixel is 4 bytes
out_fb.ar.bits.prot := 0.U
out_fb.ar.bits.addr := Cat(Mux(vCounterIsOdd, fbPixelAddrV1, fbPixelAddrV0), 0.U(2.W))
out_fb.ar.valid := RegNext(nextPixel) && hCounterIs2
out_fb.r.ready := true.B
val data = HoldUnless(out_fb.r.bits.data, out_fb.r.fire())
val color = Mux(hCounter(1), data(63, 32), data(31, 0))
io.vga.rgb := Mux(io.vga.valid, color(23, 0), 0.U)
if (sim) {
val fbHelper = Module(new FBHelper)
fbHelper.io.clk := clock
fbHelper.io.valid := io.vga.valid
fbHelper.io.pixel := color
fbHelper.io.sync := ctrl.module.io.extra.get.sync
} }
val vga = new VGABundle
})
val ctrl = Module(new VGACtrl)
io.in.ctrl <> ctrl.io.in
val fb = Module(new AXI4RAM(new AXI4Lite, memByte = FBPixels * 4))
// writable by axi4lite
// but it only readable by the internel controller
fb.io.in.aw <> io.in.fb.aw
fb.io.in.w <> io.in.fb.w
io.in.fb.b <> fb.io.in.b
io.in.fb.ar.ready := true.B
io.in.fb.r.bits.data := 0.U
io.in.fb.r.bits.resp := AXI4Parameters.RESP_OKAY
io.in.fb.r.valid := BoolStopWatch(io.in.fb.ar.fire(), io.in.fb.r.fire(), startHighPriority = true)
def inRange(x: UInt, start: Int, end: Int) = (x >= start.U) && (x < end.U)
val (hCounter, hFinish) = Counter(true.B, HTotal)
val (vCounter, vFinish) = Counter(hFinish, VTotal)
io.vga.hsync := hCounter >= HFrontPorch.U
io.vga.vsync := vCounter >= VFrontPorch.U
val hInRange = inRange(hCounter, HActive, HBackPorch)
val vInRange = inRange(vCounter, VActive, VBackPorch)
io.vga.valid := hInRange && vInRange
val hCounterIsOdd = hCounter(0)
val hCounterIs2 = hCounter(1,0) === 2.U
val vCounterIsOdd = vCounter(0)
// there is 2 cycle latency to read block memory,
// so we should issue the read request 2 cycle eariler
val nextPixel = inRange(hCounter, HActive - 1, HBackPorch - 1) && vInRange && hCounterIsOdd
val fbPixelAddrV0 = Counter(nextPixel && !vCounterIsOdd, FBPixels)._1
val fbPixelAddrV1 = Counter(nextPixel && vCounterIsOdd, FBPixels)._1
// each pixel is 4 bytes
fb.io.in.ar.bits.prot := 0.U
fb.io.in.ar.bits.addr := Cat(Mux(vCounterIsOdd, fbPixelAddrV1, fbPixelAddrV0), 0.U(2.W))
fb.io.in.ar.valid := RegNext(nextPixel) && hCounterIs2
fb.io.in.r.ready := true.B
val data = HoldUnless(fb.io.in.r.bits.data, fb.io.in.r.fire())
val color = Mux(hCounter(1), data(63, 32), data(31, 0))
io.vga.rgb := Mux(io.vga.valid, color(23, 0), 0.U)
if (sim) {
val fbHelper = Module(new FBHelper)
fbHelper.io.clk := clock
fbHelper.io.valid := io.vga.valid
fbHelper.io.pixel := color
fbHelper.io.sync := ctrl.io.extra.get.sync
} }
// val AXIidBits = 2
// val io = IO(new Bundle {
// val in = new Bundle {
// val fb = Flipped(new AXI4Lite)
// val ctrl = Flipped(new AXI4Lite)
// }
// val vga = new VGABundle
// })
//
// val ctrl = Module(new VGACtrl)
// io.in.ctrl <> ctrl.io.in
// val fb = Module(new AXI4RAM(new AXI4Lite, memByte = FBPixels * 4))
// // writable by axi4lite
// // but it only readable by the internel controller
// fb.io.in.aw <> io.in.fb.aw
// fb.io.in.w <> io.in.fb.w
// io.in.fb.b <> fb.io.in.b
// io.in.fb.ar.ready := true.B
// io.in.fb.r.bits.data := 0.U
// io.in.fb.r.bits.resp := AXI4Parameters.RESP_OKAY
// io.in.fb.r.valid := BoolStopWatch(io.in.fb.ar.fire(), io.in.fb.r.fire(), startHighPriority = true)
//
// def inRange(x: UInt, start: Int, end: Int) = (x >= start.U) && (x < end.U)
//
// val (hCounter, hFinish) = Counter(true.B, HTotal)
// val (vCounter, vFinish) = Counter(hFinish, VTotal)
//
// io.vga.hsync := hCounter >= HFrontPorch.U
// io.vga.vsync := vCounter >= VFrontPorch.U
//
// val hInRange = inRange(hCounter, HActive, HBackPorch)
// val vInRange = inRange(vCounter, VActive, VBackPorch)
// io.vga.valid := hInRange && vInRange
//
// val hCounterIsOdd = hCounter(0)
// val hCounterIs2 = hCounter(1,0) === 2.U
// val vCounterIsOdd = vCounter(0)
// // there is 2 cycle latency to read block memory,
// // so we should issue the read request 2 cycle eariler
// val nextPixel = inRange(hCounter, HActive - 1, HBackPorch - 1) && vInRange && hCounterIsOdd
// val fbPixelAddrV0 = Counter(nextPixel && !vCounterIsOdd, FBPixels)._1
// val fbPixelAddrV1 = Counter(nextPixel && vCounterIsOdd, FBPixels)._1
//
// // each pixel is 4 bytes
// fb.io.in.ar.bits.prot := 0.U
// fb.io.in.ar.bits.addr := Cat(Mux(vCounterIsOdd, fbPixelAddrV1, fbPixelAddrV0), 0.U(2.W))
// fb.io.in.ar.valid := RegNext(nextPixel) && hCounterIs2
//
// fb.io.in.r.ready := true.B
// val data = HoldUnless(fb.io.in.r.bits.data, fb.io.in.r.fire())
// val color = Mux(hCounter(1), data(63, 32), data(31, 0))
// io.vga.rgb := Mux(io.vga.valid, color(23, 0), 0.U)
//
// if (sim) {
// val fbHelper = Module(new FBHelper)
// fbHelper.io.clk := clock
// fbHelper.io.valid := io.vga.valid
// fbHelper.io.pixel := color
// fbHelper.io.sync := ctrl.io.extra.get.sync
// }
} }
package device
import chisel3._
import chisel3.util._
import freechips.rocketchip.tilelink._
import chipsalliance.rocketchip.config._
import chisel3.util.experimental.BoringUtils
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.RegField
import utils.{HasTLDump, XSDebug}
import xiangshan.HasXSLog
class TLTimer(address: Seq[AddressSet], sim: Boolean)(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice("clint", Seq("XiangShan", "clint"))
val node = TLRegisterNode(address, device, beatBytes = 8)
lazy val module = new LazyModuleImp(this) with HasXSLog with HasTLDump{
val mtip = IO(Output(Bool()))
val mtime = RegInit(0.U(64.W)) // unit: us
val mtimecmp = RegInit(0.U(64.W))
val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 100)
val freq = RegInit(clk.U(16.W))
val inc = RegInit(1000.U(16.W))
val cnt = RegInit(0.U(16.W))
val nextCnt = cnt + 1.U
cnt := Mux(nextCnt < freq, nextCnt, 0.U)
val tick = (nextCnt === freq)
when (tick) { mtime := mtime + inc }
if (sim) {
val isWFI = WireInit(false.B)
BoringUtils.addSink(isWFI, "isWFI")
when (isWFI) { mtime := mtime + 100000.U }
}
node.regmap( mapping =
0x4000 -> RegField.bytes(mtimecmp),
0x8000 -> RegField.bytes(freq),
0x8008 -> RegField.bytes(inc),
0xbff8 -> RegField.bytes(mtime)
)
val in = node.in.head._1
when(in.a.valid){
XSDebug("[A] channel valid ready=%d ", in.a.ready)
in.a.bits.dump
}
// val gtime = GTimer()
// printf(p"[$gtime][Timer] mtime=$mtime cnt=$cnt freq=$freq\n")
mtip := RegNext(mtime >= mtimecmp)
}
}
package gpu //package gpu
//
import chisel3._ //import chisel3._
import chisel3.util._ //import chisel3.util._
//
import bus.axi4._ //import bus.axi4._
import device.AXI4SlaveModule //import device.AXI4SlaveModule
import utils._ //import utils._
//
class PixelBundle extends Bundle { //class PixelBundle extends Bundle {
val a = UInt(8.W) // val a = UInt(8.W)
val r = UInt(8.W) // val r = UInt(8.W)
val g = UInt(8.W) // val g = UInt(8.W)
val b = UInt(8.W) // val b = UInt(8.W)
} //}
//
/* struct texture { ///* struct texture {
* uint32_t pixels[TextureW * TextureH]; // * uint32_t pixels[TextureW * TextureH];
* } __attribute__((packed)); // * } __attribute__((packed));
*/ // */
class TextureLineBundle extends Bundle { //class TextureLineBundle extends Bundle {
val pixels = Vec(8, new PixelBundle) // val pixels = Vec(8, new PixelBundle)
} //}
//
/* struct sprite { ///* struct sprite {
* uint16_t texture, x, y; // * uint16_t texture, x, y;
* uint32_t display : 4; // * uint32_t display : 4;
* uint32_t z : 12; // * uint32_t z : 12;
* } __attribute__((packed)); // * } __attribute__((packed));
*/ // */
class SpriteBundle extends Bundle { //class SpriteBundle extends Bundle {
val z = UInt(12.W) // val z = UInt(12.W)
val display = UInt(4.W) // val display = UInt(4.W)
val y = UInt(16.W) // val y = UInt(16.W)
val x = UInt(16.W) // val x = UInt(16.W)
val texture = UInt(16.W) // val texture = UInt(16.W)
} //}
//
trait GPUConst { //trait GPUConst {
val BeatBytes = 4 // val BeatBytes = 4
//
val TextureW = 8 // val TextureW = 8
val TextureH = 8 // val TextureH = 8
val ColorBytes = 4 // val ColorBytes = 4
//
val TextureLineBytes = TextureW * ColorBytes // val TextureLineBytes = TextureW * ColorBytes
val TextureLineBeats = TextureLineBytes / BeatBytes // val TextureLineBeats = TextureLineBytes / BeatBytes
val TextureLineShift = log2Up(TextureLineBytes) // val TextureLineShift = log2Up(TextureLineBytes)
val TextureBytes = TextureLineBytes * TextureH // val TextureBytes = TextureLineBytes * TextureH
val TextureShift = log2Up(TextureBytes) // val TextureShift = log2Up(TextureBytes)
val TextureMaxNum = 65536 // 0 indicate the end // val TextureMaxNum = 65536 // 0 indicate the end
val TextureIdBits = log2Up(TextureMaxNum) // val TextureIdBits = log2Up(TextureMaxNum)
val TextureArrayBytes = TextureMaxNum * TextureBytes // val TextureArrayBytes = TextureMaxNum * TextureBytes
val TextureBase = 0x60000000L - TextureArrayBytes * 2 // val TextureBase = 0x60000000L - TextureArrayBytes * 2
//
def textureLineAddr(idx: UInt, line: UInt): UInt = TextureBase.U | // def textureLineAddr(idx: UInt, line: UInt): UInt = TextureBase.U |
(idx(TextureIdBits - 1, 0) << TextureShift.U) | // (idx(TextureIdBits - 1, 0) << TextureShift.U) |
(line(2, 0) << TextureLineShift.U) // (line(2, 0) << TextureLineShift.U)
//
val SpriteBase = TextureBase + TextureArrayBytes // val SpriteBase = TextureBase + TextureArrayBytes
val SpriteBytes = 8 // val SpriteBytes = 8
val SpriteBeats = SpriteBytes / BeatBytes // val SpriteBeats = SpriteBytes / BeatBytes
val SpriteShift = log2Up(SpriteBytes) // val SpriteShift = log2Up(SpriteBytes)
def spriteAddr(idx: UInt): UInt = SpriteBase.U | (idx << SpriteShift.U) // def spriteAddr(idx: UInt): UInt = SpriteBase.U | (idx << SpriteShift.U)
//
val ScreenW = 400 // val ScreenW = 400
val ScreenH = 300 // val ScreenH = 300
val FrameBufBase = 0x40000000L // val FrameBufBase = 0x40000000L
def fbAddr(x: UInt, y: UInt): UInt = { // def fbAddr(x: UInt, y: UInt): UInt = {
assert(x < ScreenW.U && y < ScreenH.U) // assert(x < ScreenW.U && y < ScreenH.U)
FrameBufBase.U + ((y * ScreenW.U + x) << 2) // FrameBufBase.U + ((y * ScreenW.U + x) << 2)
} // }
} //}
//
class GPUOutBundle extends Bundle { //class GPUOutBundle extends Bundle {
// can use 32 bit after implementing burst // // can use 32 bit after implementing burst
val metaData = new AXI4 // val metaData = new AXI4
val fb = new AXI4 // val fb = new AXI4
} //}
//
class AXI4GPU extends AXI4SlaveModule(new AXI4Lite, new GPUOutBundle) with GPUConst { //class AXI4GPU extends AXI4SlaveModule(new AXI4Lite, new GPUOutBundle) with GPUConst {
val out = io.extra.get // val out = io.extra.get
//
// control registers // // control registers
def index(addr: UInt) = (addr & 0xf.U) >> 2 // def index(addr: UInt) = (addr & 0xf.U) >> 2
val statIdx = 0 // val statIdx = 0
val ctrlIdx = 1 // val ctrlIdx = 1
//
val statReg = Reg(UInt(32.W)) // val statReg = Reg(UInt(32.W))
val ctrlReg = Reg(UInt(32.W)) // val ctrlReg = Reg(UInt(32.W))
//
def readReg(addr: UInt) = LookupTree(index(addr), List( // def readReg(addr: UInt) = LookupTree(index(addr), List(
statIdx.U -> statReg, // statIdx.U -> statReg,
ctrlIdx.U -> ctrlReg // ctrlIdx.U -> ctrlReg
)) // ))
in.r.bits.data := RegEnable(readReg(in.ar.bits.addr), in.ar.fire()) // in.r.bits.data := RegEnable(readReg(in.ar.bits.addr), in.ar.fire())
//
val wIdx = index(in.aw.bits.addr) // val wIdx = index(in.aw.bits.addr)
val wdata = genWdata(readReg(in.aw.bits.addr)) // val wdata = genWdata(readReg(in.aw.bits.addr))
when (in.aw.fire()) { // when (in.aw.fire()) {
when (wIdx === ctrlIdx.U) { ctrlReg := wdata } // when (wIdx === ctrlIdx.U) { ctrlReg := wdata }
} // }
//
val startCmd = ctrlReg(0) && !RegNext(ctrlReg(0)) // val startCmd = ctrlReg(0) && !RegNext(ctrlReg(0))
//
val s_idle :: s_sprite_read :: s_texture_read :: s_render_line :: s_render_bwait :: Nil = Enum(5) // val s_idle :: s_sprite_read :: s_texture_read :: s_render_line :: s_render_bwait :: Nil = Enum(5)
val state = RegInit(s_idle) // val state = RegInit(s_idle)
statReg := (state =/= s_idle) // statReg := (state =/= s_idle)
//
out := DontCare // out := DontCare
out.metaData.ar.bits.prot := AXI4Parameters.PROT_PRIVILEDGED // out.metaData.ar.bits.prot := AXI4Parameters.PROT_PRIVILEDGED
out.metaData.ar.bits.id := 0.U // out.metaData.ar.bits.id := 0.U
out.metaData.ar.bits.size := "b10".U // 32 bit // out.metaData.ar.bits.size := "b10".U // 32 bit
out.metaData.ar.bits.burst := AXI4Parameters.BURST_INCR // out.metaData.ar.bits.burst := AXI4Parameters.BURST_INCR
out.metaData.ar.bits.lock := false.B // out.metaData.ar.bits.lock := false.B
out.metaData.ar.bits.cache := 0.U // out.metaData.ar.bits.cache := 0.U
out.metaData.ar.bits.qos := 0.U // out.metaData.ar.bits.qos := 0.U
out.metaData.ar.bits.user := 0.U // out.metaData.ar.bits.user := 0.U
out.fb.w.bits.last := false.B // out.fb.w.bits.last := false.B
out.fb.aw.bits := out.metaData.ar.bits // out.fb.aw.bits := out.metaData.ar.bits
//
out.metaData.r.ready := false.B // out.metaData.r.ready := false.B
val metaDataRwait = RegInit(false.B) // val metaDataRwait = RegInit(false.B)
//
val spriteIdx = Counter(65536) // val spriteIdx = Counter(65536)
when (state === s_idle && startCmd) { // when (state === s_idle && startCmd) {
printf("GPU start!!!!\n"); // printf("GPU start!!!!\n");
state := s_sprite_read // state := s_sprite_read
spriteIdx.value := 0.U // spriteIdx.value := 0.U
} // }
//
val textureLineCnt = Counter(TextureH) // val textureLineCnt = Counter(TextureH)
//
val spriteBufReg = Reg(Vec(SpriteBeats, UInt(32.W))) // val spriteBufReg = Reg(Vec(SpriteBeats, UInt(32.W)))
val spriteBuf = spriteBufReg.asTypeOf(new SpriteBundle) // val spriteBuf = spriteBufReg.asTypeOf(new SpriteBundle)
val spriteReadCnt = Counter(SpriteBeats) // val spriteReadCnt = Counter(SpriteBeats)
when (state === s_sprite_read) { // when (state === s_sprite_read) {
out.metaData.ar.bits.addr := spriteAddr(spriteIdx.value) // out.metaData.ar.bits.addr := spriteAddr(spriteIdx.value)
out.metaData.ar.bits.len := (SpriteBeats - 1).U // 2 beats // out.metaData.ar.bits.len := (SpriteBeats - 1).U // 2 beats
out.metaData.r.ready := true.B // out.metaData.r.ready := true.B
when (out.metaData.ar.fire()) { metaDataRwait := true.B } // when (out.metaData.ar.fire()) { metaDataRwait := true.B }
//
when (out.metaData.r.fire()) { // when (out.metaData.r.fire()) {
spriteBufReg(spriteReadCnt.value) := out.metaData.r.bits.data // spriteBufReg(spriteReadCnt.value) := out.metaData.r.bits.data
when (spriteReadCnt.inc()) { // when (spriteReadCnt.inc()) {
metaDataRwait := false.B // metaDataRwait := false.B
textureLineCnt.value := 0.U // textureLineCnt.value := 0.U
// since textureId is read at the first beat before, // // since textureId is read at the first beat before,
// we can use a valid textureId here // // we can use a valid textureId here
val isEnd = spriteBuf.texture === 0.U // val isEnd = spriteBuf.texture === 0.U
state := Mux(isEnd, s_idle, s_texture_read) // state := Mux(isEnd, s_idle, s_texture_read)
} // }
} // }
} // }
//
val textureLineBuf = Reg(Vec(TextureLineBeats, UInt(32.W))) // val textureLineBuf = Reg(Vec(TextureLineBeats, UInt(32.W)))
val textureLineReadCnt = Counter(TextureLineBeats) // val textureLineReadCnt = Counter(TextureLineBeats)
when (state === s_texture_read) { // when (state === s_texture_read) {
out.metaData.ar.bits.addr := textureLineAddr(spriteBuf.texture, textureLineCnt.value) // out.metaData.ar.bits.addr := textureLineAddr(spriteBuf.texture, textureLineCnt.value)
out.metaData.ar.bits.len := (TextureLineBeats - 1).U // 8 beats // out.metaData.ar.bits.len := (TextureLineBeats - 1).U // 8 beats
out.metaData.r.ready := true.B // out.metaData.r.ready := true.B
when (out.metaData.ar.fire()) { metaDataRwait := true.B } // when (out.metaData.ar.fire()) { metaDataRwait := true.B }
//
when (out.metaData.r.fire()) { // when (out.metaData.r.fire()) {
textureLineBuf(textureLineReadCnt.value) := out.metaData.r.bits.data // textureLineBuf(textureLineReadCnt.value) := out.metaData.r.bits.data
when (textureLineReadCnt.inc()) { // when (textureLineReadCnt.inc()) {
metaDataRwait := false.B // metaDataRwait := false.B
state := s_render_line // state := s_render_line
} // }
} // }
} // }
//
val textureLineWriteCnt = Counter(TextureLineBeats) // val textureLineWriteCnt = Counter(TextureLineBeats)
val wSend = Wire(Bool()) // val wSend = Wire(Bool())
out.fb.aw.bits.addr := fbAddr(x = spriteBuf.x, y = spriteBuf.y + textureLineCnt.value) // out.fb.aw.bits.addr := fbAddr(x = spriteBuf.x, y = spriteBuf.y + textureLineCnt.value)
out.fb.aw.bits.len := (TextureLineBeats - 1).U // 8 beats // out.fb.aw.bits.len := (TextureLineBeats - 1).U // 8 beats
out.fb.w.bits.data := textureLineBuf(textureLineWriteCnt.value) // out.fb.w.bits.data := textureLineBuf(textureLineWriteCnt.value)
out.fb.w.bits.strb := 0xf.U // out.fb.w.bits.strb := 0xf.U
out.fb.w.bits.last := textureLineWriteCnt.value === (TextureLineBeats - 1).U // out.fb.w.bits.last := textureLineWriteCnt.value === (TextureLineBeats - 1).U
when (state === s_render_line) { // when (state === s_render_line) {
// FIXME: check the result of renderLineMask // // FIXME: check the result of renderLineMask
//val renderLineMask = Cat(textureLineBuf.asTypeOf(new TextureLineBundle).pixels.map( // //val renderLineMask = Cat(textureLineBuf.asTypeOf(new TextureLineBundle).pixels.map(
// c => Mux(c.a === 0.U, 0.U(4.W), 0xf.U(4.W)))) // // c => Mux(c.a === 0.U, 0.U(4.W), 0xf.U(4.W))))
//
when (out.fb.w.fire()) { textureLineWriteCnt.inc() } // when (out.fb.w.fire()) { textureLineWriteCnt.inc() }
when (wSend) { state := s_render_bwait } // when (wSend) { state := s_render_bwait }
} // }
//
when (state === s_render_bwait) { // when (state === s_render_bwait) {
when (out.fb.b.fire()) { // when (out.fb.b.fire()) {
val finishOneTexture = textureLineCnt.inc() // val finishOneTexture = textureLineCnt.inc()
when (finishOneTexture) { spriteIdx.inc() } // when (finishOneTexture) { spriteIdx.inc() }
state := Mux(finishOneTexture, s_sprite_read, s_texture_read) // state := Mux(finishOneTexture, s_sprite_read, s_texture_read)
} // }
} // }
//
out.metaData.ar.valid := BoolStopWatch( // out.metaData.ar.valid := BoolStopWatch(
(state === s_sprite_read || state === s_texture_read) && !metaDataRwait, out.metaData.ar.fire()) // (state === s_sprite_read || state === s_texture_read) && !metaDataRwait, out.metaData.ar.fire())
out.metaData.aw.valid := false.B // out.metaData.aw.valid := false.B
out.metaData.w.valid := false.B // out.metaData.w.valid := false.B
out.metaData.b.ready := true.B // out.metaData.b.ready := true.B
//
val awAck = BoolStopWatch(out.fb.aw.fire(), wSend) // val awAck = BoolStopWatch(out.fb.aw.fire(), wSend)
val wAck = BoolStopWatch(out.fb.w.fire() && out.fb.w.bits.last, wSend) // val wAck = BoolStopWatch(out.fb.w.fire() && out.fb.w.bits.last, wSend)
wSend := (out.fb.aw.fire() && out.fb.w.fire() && out.fb.w.bits.last) || (awAck && wAck) // wSend := (out.fb.aw.fire() && out.fb.w.fire() && out.fb.w.bits.last) || (awAck && wAck)
//
out.fb.aw.valid := (state === s_render_line) && !awAck // out.fb.aw.valid := (state === s_render_line) && !awAck
out.fb.w .valid := (state === s_render_line) && !wAck // out.fb.w .valid := (state === s_render_line) && !wAck
out.fb.b.ready := BoolStopWatch(wSend, out.fb.b.fire()) // out.fb.b.ready := BoolStopWatch(wSend, out.fb.b.fire())
out.fb.ar.valid := false.B // out.fb.ar.valid := false.B
out.fb.r.ready := true.B // out.fb.r.ready := true.B
} //}
package system package system
import noop.{Cache, CacheConfig} import chipsalliance.rocketchip.config.Parameters
import bus.axi4.{AXI4, AXI4Lite, AXI4ToAXI4Lite} import device.{AXI4Timer, TLTimer}
import bus.simplebus._
import bus.tilelink.{NaiveTL1toN, MMIOTLToAXI4, TLCached}
import device.AXI4Timer
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chisel3.util.experimental.BoringUtils import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp}
import top.Parameters import freechips.rocketchip.tilelink.{TLBuffer, TLFuzzer, TLIdentityNode, TLXbar}
import utils.DebugIdentityNode
import xiangshan.{HasXSParameter, XSCore} import xiangshan.{HasXSParameter, XSCore}
...@@ -20,7 +18,7 @@ case class SoCParameters ...@@ -20,7 +18,7 @@ case class SoCParameters
) )
trait HasSoCParameter extends HasXSParameter{ trait HasSoCParameter extends HasXSParameter{
val soc = Parameters.get.socParameters val soc = top.Parameters.get.socParameters
val EnableILA = soc.EnableILA val EnableILA = soc.EnableILA
val HasL2cache = soc.HasL2Cache val HasL2cache = soc.HasL2Cache
val HasPrefetch = soc.HasPrefetch val HasPrefetch = soc.HasPrefetch
...@@ -28,36 +26,86 @@ trait HasSoCParameter extends HasXSParameter{ ...@@ -28,36 +26,86 @@ trait HasSoCParameter extends HasXSParameter{
class ILABundle extends Bundle {} class ILABundle extends Bundle {}
class XSSoc extends Module with HasSoCParameter {
val io = IO(new Bundle{
val mem = new TLCached(l1BusParams)
val mmio = new TLCached(l1BusParams)
val frontend = Flipped(new AXI4) //TODO: do we need it ?
val meip = Input(Bool())
val ila = if (env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
})
val xsCore = Module(new XSCore) class DummyCore()(implicit p: Parameters) extends LazyModule {
val mem = TLFuzzer(nOperations = 10)
val mmio = TLFuzzer(nOperations = 10)
io.frontend <> DontCare lazy val module = new LazyModuleImp(this){
io.mem <> xsCore.io.mem }
}
class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
private val xsCore = LazyModule(new XSCore())
// only mem and extDev visible externally
val mem = xsCore.mem
val extDev = TLIdentityNode()
val addrSpace = List( private val mmioXbar = TLXbar()
(0x40000000L, 0x40000000L), // external devices private val clint = LazyModule(new TLTimer(
(0x38000000L, 0x00010000L) // CLINT Seq(AddressSet(0x38000000L, 0x0000ffffL)),
) sim = !env.FPGAPlatform
val mmioXbar = Module(new NaiveTL1toN(addrSpace, xsCore.io.mem.params)) ))
mmioXbar.io.in <> xsCore.io.mmio
val extDev = mmioXbar.io.out(0) mmioXbar :=
val clint = Module(new AXI4Timer(sim = !env.FPGAPlatform)) TLBuffer() :=
clint.io.in <> AXI4ToAXI4Lite(MMIOTLToAXI4(mmioXbar.io.out(1))) DebugIdentityNode() :=
xsCore.mmio
io.mmio <> extDev clint.node :=
mmioXbar
extDev :=
mmioXbar
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle{
val meip = Input(Bool())
val ila = if(env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
})
val mtipSync = WireInit(0.U(1.W)) //clint.module.mtip
val meipSync = RegNext(RegNext(io.meip))
ExcitingUtils.addSource(mtipSync, "mtip")
ExcitingUtils.addSource(meipSync, "meip")
}
val mtipSync = clint.io.extra.get.mtip
val meipSync = RegNext(RegNext(io.meip))
ExcitingUtils.addSource(mtipSync, "mtip")
ExcitingUtils.addSource(meipSync, "meip")
} }
//class XSSoc extends Module with HasSoCParameter {
// val io = IO(new Bundle{
// val mem = new TLCached(l1BusParams)
// val mmio = new TLCached(l1BusParams)
// val frontend = Flipped(new AXI4) //TODO: do we need it ?
// val meip = Input(Bool())
// val ila = if (env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
// })
//
// val xsCore = Module(new XSCore)
//
// io.frontend <> DontCare
//
// io.mem <> xsCore.io.mem
//
// val addrSpace = List(
// (0x40000000L, 0x40000000L), // external devices
// (0x38000000L, 0x00010000L) // CLINT
// )
// val mmioXbar = Module(new NaiveTL1toN(addrSpace, xsCore.io.mem.params))
// mmioXbar.io.in <> xsCore.io.mmio
//
// val extDev = mmioXbar.io.out(0)
// val clint = Module(new AXI4Timer(sim = !env.FPGAPlatform))
// clint.io.in <> AXI4ToAXI4Lite(MMIOTLToAXI4(mmioXbar.io.out(1)))
//
// io.mmio <> extDev
//
// val mtipSync = clint.io.extra.get.mtip
// val meipSync = RegNext(RegNext(io.meip))
// ExcitingUtils.addSource(mtipSync, "mtip")
// ExcitingUtils.addSource(meipSync, "meip")
//}
package top //package top
//
import system.XSSoc //import system.XSSoc
import device.{AXI4Flash, AXI4Timer, AXI4VGA} //import device.{AXI4Flash, AXI4Timer, AXI4VGA}
import gpu._ //import gpu._
import chisel3._ //import chisel3._
import chisel3.stage.ChiselGeneratorAnnotation //import chisel3.stage.ChiselGeneratorAnnotation
//
class Top extends Module { //class Top extends Module {
val io = IO(new Bundle{}) // val io = IO(new Bundle{})
val xsSoc = Module(new XSSoc()) // val xsSoc = Module(new XSSoc())
val timer = Module(new AXI4Timer) // val timer = Module(new AXI4Timer)
val vga = Module(new AXI4VGA) // val vga = Module(new AXI4VGA)
val flash = Module(new AXI4Flash) // val flash = Module(new AXI4Flash)
// val gpu = Module(new AXI4GPU) //// val gpu = Module(new AXI4GPU)
//
xsSoc.io := DontCare // xsSoc.io := DontCare
timer.io := DontCare // timer.io := DontCare
vga.io := DontCare // vga.io := DontCare
flash.io := DontCare // flash.io := DontCare
// gpu.io := DontCare //// gpu.io := DontCare
dontTouch(xsSoc.io) // dontTouch(xsSoc.io)
dontTouch(timer.io) // dontTouch(timer.io)
dontTouch(vga.io) // dontTouch(vga.io)
dontTouch(flash.io) // dontTouch(flash.io)
// dontTouch(gpu.io) //// dontTouch(gpu.io)
} //}
//
object TopMain extends App { //object TopMain extends App {
(new chisel3.stage.ChiselStage).execute( // (new chisel3.stage.ChiselStage).execute(
args, // args,
Seq(ChiselGeneratorAnnotation(() => new Top)) // Seq(ChiselGeneratorAnnotation(() => new Top))
) // )
} //}
package utils
import chisel3._
import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink.{TLClientNode, TLIdentityNode, TLMasterParameters, TLMasterPortParameters}
import xiangshan.HasXSLog
class DebugIdentityNode()(implicit p: Parameters) extends LazyModule {
val node = TLIdentityNode()
val n = TLClientNode(Seq(TLMasterPortParameters.v1(
Seq(
TLMasterParameters.v1("debug node")
)
)))
lazy val module = new LazyModuleImp(this) with HasXSLog with HasTLDump{
val (out, _) = node.out(0)
val (in, _) = node.in(0)
when(in.a.fire()){
XSDebug(" ")
in.a.bits.dump
}
when(in.d.fire()){
XSDebug(" ")
in.d.bits.dump
}
}
}
object DebugIdentityNode {
def apply()(implicit p: Parameters): TLIdentityNode = {
val identityNode = LazyModule(new DebugIdentityNode())
identityNode.node
}
}
\ No newline at end of file
package utils
import chisel3._
import freechips.rocketchip.tilelink.{TLBundle, TLBundleA, TLBundleB, TLBundleC, TLBundleD, TLBundleE, TLChannel}
import xiangshan.HasXSLog
trait HasTLDump { this: HasXSLog =>
implicit class dumpA(a: TLBundleA) {
def dump =
XSDebug(false, true.B,
a.channelName + " opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.opcode, a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
implicit class dumpB(b: TLBundleB) {
def dump =
XSDebug(false, true.B,
b.channelName + " opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.opcode, b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
implicit class dumpC(c: TLBundleC) {
def dump =
XSDebug(false, true.B,
c.channelName + " opcode: %x param: %x size: %x source: %d address: %x data: %x corrupt: %b\n",
c.opcode, c.param, c.size, c.source, c.address, c.data, c.corrupt
)
}
implicit class dumpD(d: TLBundleD) {
def dump =
XSDebug(false, true.B,
d.channelName + " opcode: %x param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.opcode, d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
implicit class dumpE(e: TLBundleE) {
def dump =
XSDebug(false, true.B, e.channelName + " sink: %d\n", e.sink)
}
}
...@@ -2,7 +2,6 @@ package xiangshan ...@@ -2,7 +2,6 @@ package xiangshan
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import bus.simplebus._
import noop.{Cache, CacheConfig, HasExceptionNO, TLB, TLBConfig} import noop.{Cache, CacheConfig, HasExceptionNO, TLB, TLBConfig}
import top.Parameters import top.Parameters
import xiangshan.backend._ import xiangshan.backend._
...@@ -10,8 +9,10 @@ import xiangshan.backend.dispatch.DispatchParameters ...@@ -10,8 +9,10 @@ import xiangshan.backend.dispatch.DispatchParameters
import xiangshan.backend.exu.ExuParameters import xiangshan.backend.exu.ExuParameters
import xiangshan.frontend._ import xiangshan.frontend._
import xiangshan.mem._ import xiangshan.mem._
import xiangshan.cache.{DCacheParameters, ICacheParameters} import xiangshan.cache.{DCache, DCacheParameters, ICacheParameters, Uncache}
import bus.tilelink.{TLArbiter, TLCached, TLMasterUtilities, TLParameters} import chipsalliance.rocketchip.config
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink.{TLBundleParameters, TLClientNode, TLIdentityNode}
import utils._ import utils._
case class XSCoreParameters case class XSCoreParameters
...@@ -149,12 +150,6 @@ trait HasXSParameter { ...@@ -149,12 +150,6 @@ trait HasXSParameter {
val RefillSize = core.RefillSize val RefillSize = core.RefillSize
val l1BusDataWidth = 64 val l1BusDataWidth = 64
val l1BusParams = TLParameters(
addressBits = PAddrBits,
dataBits = l1BusDataWidth,
sourceBits = 3,
sinkBits = 3
)
val icacheParameters = ICacheParameters( val icacheParameters = ICacheParameters(
) )
...@@ -162,12 +157,11 @@ trait HasXSParameter { ...@@ -162,12 +157,11 @@ trait HasXSParameter {
val LRSCCycles = 16 val LRSCCycles = 16
val dcacheParameters = DCacheParameters( val dcacheParameters = DCacheParameters(
tagECC = Some("secded"), tagECC = Some("secded"),
dataECC = Some("secded"), dataECC = Some("secded")
busParams = l1BusParams
) )
} }
trait HasXSLog { this: Module => trait HasXSLog { this: RawModule =>
implicit val moduleName: String = this.name implicit val moduleName: String = this.name
} }
...@@ -210,47 +204,38 @@ object AddressSpace extends HasXSParameter { ...@@ -210,47 +204,38 @@ object AddressSpace extends HasXSParameter {
} }
class TLReqProducer extends XSModule {
val io = IO(new TLCached(l1BusParams))
io <> DontCare class XSCore()(implicit p: config.Parameters) extends LazyModule {
val addr = RegInit("h80000000".U) val dcache = LazyModule(new DCache())
addr := addr + 4.U val uncache = LazyModule(new Uncache())
val (legal, bundle) = TLMasterUtilities.Get(io.params, 0.U, addr, 3.U)
io.a.bits := bundle
io.a.valid := true.B
assert(legal)
io.d.ready := true.B
when(io.a.fire()){
io.a.bits.dump()
}
when(io.d.fire()){
io.d.bits.dump()
}
}
class XSCore extends XSModule { // TODO: crossbar Icache/Dcache/PTW here
val io = IO(new Bundle { val mem = dcache.clientNode
val mem = new TLCached(l1BusParams) val mmio = uncache.clientNode
val mmio = new TLCached(l1BusParams)
})
// val fakecache = Module(new TLReqProducer) lazy val module = new XSCoreImp(this)
// io.mem <> fakecache.io }
io.mmio <> DontCare class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer) with HasXSParameter {
val front = Module(new Frontend) val front = Module(new Frontend)
val backend = Module(new Backend) val backend = Module(new Backend)
val mem = Module(new Memend) val mem = Module(new Memend)
val dcache = outer.dcache.module
val uncache = outer.uncache.module
// TODO: connect this
dcache.io.lsu.misc <> DontCare
front.io.backend <> backend.io.frontend front.io.backend <> backend.io.frontend
mem.io.backend <> backend.io.mem mem.io.backend <> backend.io.mem
mem.io.mem <> io.mem dcache.io.lsu.load <> mem.io.loadUnitToDcacheVec
mem.io.mmio <> io.mmio dcache.io.lsu.lsroq <> mem.io.miscToDcache
dcache.io.lsu.store <> mem.io.sbufferToDcache
uncache.io.lsroq <> mem.io.uncache
backend.io.memMMU.imem <> DontCare backend.io.memMMU.imem <> DontCare
backend.io.memMMU.dmem <> DontCare backend.io.memMMU.dmem <> DontCare
} }
...@@ -322,7 +322,8 @@ class CSR extends FunctionUnit(csrCfg) with HasCSRConst{ ...@@ -322,7 +322,8 @@ class CSR extends FunctionUnit(csrCfg) with HasCSRConst{
val stval = Reg(UInt(XLEN.W)) val stval = Reg(UInt(XLEN.W))
val sscratch = RegInit(UInt(XLEN.W), 0.U) val sscratch = RegInit(UInt(XLEN.W), 0.U)
val scounteren = RegInit(UInt(XLEN.W), 0.U) val scounteren = RegInit(UInt(XLEN.W), 0.U)
ExcitingUtils.addSource(satp, "CSRSATP") // FIXME
// ExcitingUtils.addSource(satp, "CSRSATP")
// User-Level CSRs // User-Level CSRs
val uepc = Reg(UInt(XLEN.W)) val uepc = Reg(UInt(XLEN.W))
......
...@@ -4,8 +4,7 @@ package xiangshan.cache ...@@ -4,8 +4,7 @@ package xiangshan.cache
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import xiangshan.{HasXSParameter, XSBundle, XSModule}
import xiangshan.{HasXSParameter, XSModule, XSBundle}
// this file contains common building blocks that can be shared by ICache and DCache // this file contains common building blocks that can be shared by ICache and DCache
// this is the common parameter base for L1 ICache and L1 DCache // this is the common parameter base for L1 ICache and L1 DCache
......
...@@ -2,16 +2,17 @@ package xiangshan.cache ...@@ -2,16 +2,17 @@ package xiangshan.cache
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut}
import utils.{Code, RandomReplacement, XSDebug}
import utils.{XSDebug, Code, RandomReplacement}
import bus.tilelink.{TLParameters, ClientMetadata}
import scala.math.max import scala.math.max
// DCache specific parameters // DCache specific parameters
// L1 DCache is 64set, 8way-associative, with 64byte block, a total of 32KB // L1 DCache is 64set, 8way-associative, with 64byte block, a total of 32KB
// It's a virtually indexed, physically tagged cache. // It's a virtually indexed, physically tagged cache.
case class DCacheParameters( case class DCacheParameters
(
nSets: Int = 64, nSets: Int = 64,
nWays: Int = 8, nWays: Int = 8,
rowBits: Int = 64, rowBits: Int = 64,
...@@ -28,8 +29,8 @@ case class DCacheParameters( ...@@ -28,8 +29,8 @@ case class DCacheParameters(
nSDQ: Int = 17, nSDQ: Int = 17,
nRPQ: Int = 16, nRPQ: Int = 16,
nMMIOs: Int = 1, nMMIOs: Int = 1,
blockBytes: Int = 64, blockBytes: Int = 64
busParams: TLParameters) extends L1CacheParameters { ) extends L1CacheParameters {
def tagCode: Code = Code.fromString(tagECC) def tagCode: Code = Code.fromString(tagECC)
def dataCode: Code = Code.fromString(dataECC) def dataCode: Code = Code.fromString(dataECC)
...@@ -55,7 +56,7 @@ trait HasDCacheParameters extends HasL1CacheParameters { ...@@ -55,7 +56,7 @@ trait HasDCacheParameters extends HasL1CacheParameters {
def offsetlsb = wordOffBits def offsetlsb = wordOffBits
def get_beat(addr: UInt) = addr(blockOffBits - 1, beatOffBits) def get_beat(addr: UInt) = addr(blockOffBits - 1, beatOffBits)
def get_tag(addr: UInt) = addr >> untagBits def get_tag(addr: UInt) = (addr >> untagBits).asUInt()
def get_idx(addr: UInt) = addr(untagBits-1, blockOffBits) def get_idx(addr: UInt) = addr(untagBits-1, blockOffBits)
def get_block(addr: UInt) = addr >> blockOffBits def get_block(addr: UInt) = addr >> blockOffBits
def get_block_addr(addr: UInt) = (addr >> blockOffBits) << blockOffBits def get_block_addr(addr: UInt) = (addr >> blockOffBits) << blockOffBits
...@@ -207,9 +208,9 @@ class DuplicatedDataArray extends AbstractDataArray ...@@ -207,9 +208,9 @@ class DuplicatedDataArray extends AbstractDataArray
{ {
// write is always ready // write is always ready
io.write.ready := true.B io.write.ready := true.B
val waddr = io.write.bits.addr >> blockOffBits val waddr = (io.write.bits.addr >> blockOffBits).asUInt()
for (j <- 0 until LoadPipelineWidth) { for (j <- 0 until LoadPipelineWidth) {
val raddr = io.read(j).bits.addr >> blockOffBits val raddr = (io.read(j).bits.addr >> blockOffBits).asUInt()
// raddr === waddr is undefined behavior! // raddr === waddr is undefined behavior!
// block read in this case // block read in this case
io.read(j).ready := !io.write.valid || raddr =/= waddr io.read(j).ready := !io.write.valid || raddr =/= waddr
...@@ -297,7 +298,8 @@ class DuplicatedMetaArray extends DCacheModule { ...@@ -297,7 +298,8 @@ class DuplicatedMetaArray extends DCacheModule {
for (w <- 0 until LoadPipelineWidth) { for (w <- 0 until LoadPipelineWidth) {
meta(w).io.write <> io.write meta(w).io.write <> io.write
meta(w).io.read <> io.read(w) meta(w).io.read <> io.read(w)
meta(w).io.resp <> io.resp(w) io.resp(w) <> meta(w).io.resp
// meta(w).io.resp <> io.resp(w)
} }
def dump() = { def dump() = {
......
package xiangshan.cache package xiangshan.cache
import chipsalliance.rocketchip.config.Parameters
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes}
import utils.XSDebug import freechips.rocketchip.tilelink.{TLClientNode, TLClientParameters, TLMasterParameters, TLMasterPortParameters, TLArbiter}
import bus.tilelink._ import xiangshan.MicroOp
import xiangshan.{MicroOp}
// Meta data for dcache requests // Meta data for dcache requests
// anything that should go with reqs and resps goes here // anything that should go with reqs and resps goes here
...@@ -77,13 +77,33 @@ class DCacheToLsuIO extends DCacheBundle { ...@@ -77,13 +77,33 @@ class DCacheToLsuIO extends DCacheBundle {
class DCacheIO extends DCacheBundle { class DCacheIO extends DCacheBundle {
val lsu = new DCacheToLsuIO val lsu = new DCacheToLsuIO
// TODO: remove ptw port, it directly connect to L2
val ptw = Flipped(new DCacheLoadIO) val ptw = Flipped(new DCacheLoadIO)
val bus = new TLCached(cfg.busParams)
} }
class DCache extends DCacheModule {
class DCache()(implicit p: Parameters) extends LazyModule with HasDCacheParameters {
val clientParameters = TLMasterPortParameters.v1(
Seq(TLMasterParameters.v1(
name = "dcache",
sourceId = IdRange(0, cfg.nMissEntries+1),
supportsProbe = TransferSizes(cfg.blockBytes)
))
)
val clientNode = TLClientNode(Seq(clientParameters))
lazy val module = new DCacheImp(this)
}
class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParameters {
val io = IO(new DCacheIO) val io = IO(new DCacheIO)
val (bus, edge) = outer.clientNode.out.head
//---------------------------------------- //----------------------------------------
// core data structures // core data structures
val dataArray = Module(new DuplicatedDataArray) val dataArray = Module(new DuplicatedDataArray)
...@@ -98,9 +118,9 @@ class DCache extends DCacheModule { ...@@ -98,9 +118,9 @@ class DCache extends DCacheModule {
val loadMissQueue = Module(new LoadMissQueue) val loadMissQueue = Module(new LoadMissQueue)
val storeMissQueue = Module(new StoreMissQueue) val storeMissQueue = Module(new StoreMissQueue)
val miscMissQueue = Module(new MiscMissQueue) val miscMissQueue = Module(new MiscMissQueue)
val missQueue = Module(new MissQueue) val missQueue = Module(new MissQueue(edge))
val wb = Module(new WritebackUnit) val wb = Module(new WritebackUnit(edge))
val prober = Module(new ProbeUnit) val prober = Module(new ProbeUnit(edge))
//---------------------------------------- //----------------------------------------
...@@ -135,15 +155,15 @@ class DCache extends DCacheModule { ...@@ -135,15 +155,15 @@ class DCache extends DCacheModule {
metaArray.io.read(0) <> metaReadArb.io.out metaArray.io.read(0) <> metaReadArb.io.out
metaArray.io.resp(0) <> missQueue.io.meta_resp missQueue.io.meta_resp <> metaArray.io.resp(0)
metaArray.io.resp(0) <> prober.io.meta_resp prober.io.meta_resp <> metaArray.io.resp(0)
metaArray.io.resp(0) <> stu.io.meta_resp stu.io.meta_resp <> metaArray.io.resp(0)
metaArray.io.resp(0) <> ldu(0).io.meta_resp ldu(0).io.meta_resp <> metaArray.io.resp(0)
metaArray.io.resp(0) <> misc.io.meta_resp misc.io.meta_resp <> metaArray.io.resp(0)
for (w <- 1 until LoadPipelineWidth) { for (w <- 1 until LoadPipelineWidth) {
metaArray.io.read(w) <> ldu(w).io.meta_read metaArray.io.read(w) <> ldu(w).io.meta_read
metaArray.io.resp(w) <> ldu(w).io.meta_resp ldu(w).io.meta_resp <> metaArray.io.resp(w)
} }
//---------------------------------------- //----------------------------------------
...@@ -409,36 +429,37 @@ class DCache extends DCacheModule { ...@@ -409,36 +429,37 @@ class DCache extends DCacheModule {
missFinish <> missFinishArb.io.out missFinish <> missFinishArb.io.out
// tilelink stuff // tilelink stuff
io.bus.a <> missQueue.io.mem_acquire bus.a <> missQueue.io.mem_acquire
io.bus.e <> missQueue.io.mem_finish bus.e <> missQueue.io.mem_finish
when (io.bus.d.bits.source === cfg.nMissEntries.U) { when (bus.d.bits.source === cfg.nMissEntries.U) {
// This should be ReleaseAck // This should be ReleaseAck
io.bus.d.ready := true.B bus.d.ready := true.B
missQueue.io.mem_grant.valid := false.B missQueue.io.mem_grant.valid := false.B
missQueue.io.mem_grant.bits := DontCare missQueue.io.mem_grant.bits := DontCare
} .otherwise { } .otherwise {
// This should be GrantData // This should be GrantData
missQueue.io.mem_grant <> io.bus.d missQueue.io.mem_grant <> bus.d
} }
//---------------------------------------- //----------------------------------------
// prober // prober
io.bus.b <> prober.io.req // bus.b <> prober.io.req
prober.io.req := DontCare
//---------------------------------------- //----------------------------------------
// wb // wb
// 0 goes to prober, 1 goes to missQueue evictions // 0 goes to prober, 1 goes to missQueue evictions
val wbArb = Module(new Arbiter(new WritebackReq, 2)) val wbArb = Module(new Arbiter(new WritebackReq(edge.bundle.sourceBits), 2))
wbArb.io.in(0) <> prober.io.wb_req wbArb.io.in(0) <> prober.io.wb_req
wbArb.io.in(1) <> missQueue.io.wb_req wbArb.io.in(1) <> missQueue.io.wb_req
wb.io.req <> wbArb.io.out wb.io.req <> wbArb.io.out
missQueue.io.wb_resp := wb.io.resp missQueue.io.wb_resp := wb.io.resp
prober.io.wb_resp := wb.io.resp prober.io.wb_resp := wb.io.resp
wb.io.mem_grant := io.bus.d.fire() && io.bus.d.bits.source === cfg.nMissEntries.U wb.io.mem_grant := bus.d.fire() && bus.d.bits.source === cfg.nMissEntries.U
TLArbiter.lowestFromSeq(io.bus.c, Seq(prober.io.rep, wb.io.release)) TLArbiter.lowestFromSeq(edge, bus.c, Seq(prober.io.rep, wb.io.release))
// synchronization stuff // synchronization stuff
def block_load(addr: UInt) = { def block_load(addr: UInt) = {
......
...@@ -2,9 +2,8 @@ package xiangshan.cache ...@@ -2,9 +2,8 @@ package xiangshan.cache
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.tilelink._
import utils.XSDebug import utils.{HasTLDump, XSDebug}
import bus.tilelink._
class MissReq extends DCacheBundle class MissReq extends DCacheBundle
{ {
...@@ -27,7 +26,7 @@ class MissFinish extends DCacheBundle ...@@ -27,7 +26,7 @@ class MissFinish extends DCacheBundle
// One miss entry deals with one missed block // One miss entry deals with one missed block
class MissEntry extends DCacheModule class MissEntry(edge: TLEdgeOut) extends DCacheModule
{ {
val io = IO(new Bundle { val io = IO(new Bundle {
// MSHR ID // MSHR ID
...@@ -41,16 +40,16 @@ class MissEntry extends DCacheModule ...@@ -41,16 +40,16 @@ class MissEntry extends DCacheModule
val block_idx = Output(Valid(UInt())) val block_idx = Output(Valid(UInt()))
val block_addr = Output(Valid(UInt())) val block_addr = Output(Valid(UInt()))
val mem_acquire = DecoupledIO(new TLBundleA(cfg.busParams)) val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
val mem_grant = Flipped(DecoupledIO(new TLBundleD(cfg.busParams))) val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
val mem_finish = DecoupledIO(new TLBundleE(cfg.busParams)) val mem_finish = DecoupledIO(new TLBundleE(edge.bundle))
val meta_read = DecoupledIO(new L1MetaReadReq) val meta_read = DecoupledIO(new L1MetaReadReq)
val meta_resp = Input(Vec(nWays, new L1Metadata)) val meta_resp = Input(Vec(nWays, new L1Metadata))
val meta_write = DecoupledIO(new L1MetaWriteReq) val meta_write = DecoupledIO(new L1MetaWriteReq)
val refill = DecoupledIO(new L1DataWriteReq) val refill = DecoupledIO(new L1DataWriteReq)
val wb_req = DecoupledIO(new WritebackReq) val wb_req = DecoupledIO(new WritebackReq(edge.bundle.sourceBits))
val wb_resp = Input(Bool()) val wb_resp = Input(Bool())
}) })
...@@ -84,9 +83,9 @@ class MissEntry extends DCacheModule ...@@ -84,9 +83,9 @@ class MissEntry extends DCacheModule
val grow_param = new_coh.onAccess(req.cmd)._2 val grow_param = new_coh.onAccess(req.cmd)._2
val coh_on_grant = new_coh.onGrant(req.cmd, io.mem_grant.bits.param) val coh_on_grant = new_coh.onGrant(req.cmd, io.mem_grant.bits.param)
val (_, _, refill_done, refill_address_inc) = TLUtilities.addr_inc(io.mem_grant) val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
val grantack = Reg(Valid(new TLBundleE(cfg.busParams))) val grantack = Reg(Valid(new TLBundleE(edge.bundle)))
val refill_ctr = Reg(UInt(log2Up(cacheDataBeats).W)) val refill_ctr = Reg(UInt(log2Up(cacheDataBeats).W))
val should_refill_data = Reg(Bool()) val should_refill_data = Reg(Bool())
...@@ -192,7 +191,7 @@ class MissEntry extends DCacheModule ...@@ -192,7 +191,7 @@ class MissEntry extends DCacheModule
// eg: when several load miss on the same block // eg: when several load miss on the same block
// assert(isWrite(req.cmd)) // assert(isWrite(req.cmd))
new_coh := coh_on_hit new_coh := coh_on_hit
new_state := s_send_resp new_state := s_meta_write_req
} .otherwise { // upgrade permissions } .otherwise { // upgrade permissions
new_coh := old_coh new_coh := old_coh
new_state := s_refill_req new_state := s_refill_req
...@@ -240,10 +239,10 @@ class MissEntry extends DCacheModule ...@@ -240,10 +239,10 @@ class MissEntry extends DCacheModule
when (state === s_refill_req) { when (state === s_refill_req) {
io.mem_acquire.valid := true.B io.mem_acquire.valid := true.B
// TODO: Use AcquirePerm if just doing permissions acquire // TODO: Use AcquirePerm if just doing permissions acquire
io.mem_acquire.bits := TLMasterUtilities.AcquireBlock( // TODO: review this
params = cfg.busParams, io.mem_acquire.bits := edge.AcquireBlock(
fromSource = io.id, fromSource = io.id,
toAddress = Cat(req_tag, req_idx) << blockOffBits, toAddress = (Cat(req_tag, req_idx) << blockOffBits).asUInt(),
lgSize = (log2Up(cfg.blockBytes)).U, lgSize = (log2Up(cfg.blockBytes)).U,
growPermissions = grow_param)._2 growPermissions = grow_param)._2
when (io.mem_acquire.fire()) { when (io.mem_acquire.fire()) {
...@@ -255,7 +254,7 @@ class MissEntry extends DCacheModule ...@@ -255,7 +254,7 @@ class MissEntry extends DCacheModule
when (state === s_refill_resp) { when (state === s_refill_resp) {
io.mem_grant.ready := true.B io.mem_grant.ready := true.B
when (TLUtilities.hasData(io.mem_grant.bits)) { when (edge.hasData(io.mem_grant.bits)) {
when (io.mem_grant.fire()) { when (io.mem_grant.fire()) {
should_refill_data := true.B should_refill_data := true.B
refill_ctr := refill_ctr + 1.U refill_ctr := refill_ctr + 1.U
...@@ -267,8 +266,8 @@ class MissEntry extends DCacheModule ...@@ -267,8 +266,8 @@ class MissEntry extends DCacheModule
} }
when (refill_done) { when (refill_done) {
grantack.valid := TLUtilities.isRequest(io.mem_grant.bits) grantack.valid := edge.isRequest(io.mem_grant.bits)
grantack.bits := TLMasterUtilities.GrantAck(io.mem_grant.bits) grantack.bits := edge.GrantAck(io.mem_grant.bits)
new_coh := coh_on_grant new_coh := coh_on_grant
state := s_mem_finish state := s_mem_finish
...@@ -345,23 +344,23 @@ class MissEntry extends DCacheModule ...@@ -345,23 +344,23 @@ class MissEntry extends DCacheModule
} }
class MissQueue extends DCacheModule class MissQueue(edge: TLEdgeOut) extends DCacheModule with HasTLDump
{ {
val io = IO(new Bundle { val io = IO(new Bundle {
val req = Flipped(DecoupledIO(new MissReq)) val req = Flipped(DecoupledIO(new MissReq))
val resp = ValidIO(new MissResp) val resp = ValidIO(new MissResp)
val finish = Flipped(DecoupledIO(new MissFinish)) val finish = Flipped(DecoupledIO(new MissFinish))
val mem_acquire = Decoupled(new TLBundleA(cfg.busParams)) val mem_acquire = Decoupled(new TLBundleA(edge.bundle))
val mem_grant = Flipped(Decoupled(new TLBundleD(cfg.busParams))) val mem_grant = Flipped(Decoupled(new TLBundleD(edge.bundle)))
val mem_finish = Decoupled(new TLBundleE(cfg.busParams)) val mem_finish = Decoupled(new TLBundleE(edge.bundle))
val meta_read = Decoupled(new L1MetaReadReq) val meta_read = Decoupled(new L1MetaReadReq)
val meta_resp = Input(Vec(nWays, new L1Metadata)) val meta_resp = Input(Vec(nWays, new L1Metadata))
val meta_write = Decoupled(new L1MetaWriteReq) val meta_write = Decoupled(new L1MetaWriteReq)
val refill = Decoupled(new L1DataWriteReq) val refill = Decoupled(new L1DataWriteReq)
val wb_req = Decoupled(new WritebackReq) val wb_req = Decoupled(new WritebackReq(edge.bundle.sourceBits))
val wb_resp = Input(Bool()) val wb_resp = Input(Bool())
val inflight_req_idxes = Output(Vec(cfg.nMissEntries, Valid(UInt()))) val inflight_req_idxes = Output(Vec(cfg.nMissEntries, Valid(UInt())))
...@@ -372,7 +371,7 @@ class MissQueue extends DCacheModule ...@@ -372,7 +371,7 @@ class MissQueue extends DCacheModule
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, cfg.nMissEntries)) val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, cfg.nMissEntries))
val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, cfg.nMissEntries)) val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, cfg.nMissEntries))
val refill_arb = Module(new Arbiter(new L1DataWriteReq, cfg.nMissEntries)) val refill_arb = Module(new Arbiter(new L1DataWriteReq, cfg.nMissEntries))
val wb_req_arb = Module(new Arbiter(new WritebackReq, cfg.nMissEntries)) val wb_req_arb = Module(new Arbiter(new WritebackReq(edge.bundle.sourceBits), cfg.nMissEntries))
// assign default values to output signals // assign default values to output signals
io.finish.ready := false.B io.finish.ready := false.B
...@@ -382,7 +381,7 @@ class MissQueue extends DCacheModule ...@@ -382,7 +381,7 @@ class MissQueue extends DCacheModule
val req_ready = WireInit(false.B) val req_ready = WireInit(false.B)
val entries = (0 until cfg.nMissEntries) map { i => val entries = (0 until cfg.nMissEntries) map { i =>
val entry = Module(new MissEntry) val entry = Module(new MissEntry(edge))
entry.io.id := i.U(log2Up(cfg.nMissEntries).W) entry.io.id := i.U(log2Up(cfg.nMissEntries).W)
...@@ -436,8 +435,8 @@ class MissQueue extends DCacheModule ...@@ -436,8 +435,8 @@ class MissQueue extends DCacheModule
io.refill <> refill_arb.io.out io.refill <> refill_arb.io.out
io.wb_req <> wb_req_arb.io.out io.wb_req <> wb_req_arb.io.out
TLArbiter.lowestFromSeq(io.mem_acquire, entries.map(_.io.mem_acquire)) TLArbiter.lowestFromSeq(edge, io.mem_acquire, entries.map(_.io.mem_acquire))
TLArbiter.lowestFromSeq(io.mem_finish, entries.map(_.io.mem_finish)) TLArbiter.lowestFromSeq(edge, io.mem_finish, entries.map(_.io.mem_finish))
// print all input/output requests for debug purpose // print all input/output requests for debug purpose
......
...@@ -4,16 +4,17 @@ import chisel3._ ...@@ -4,16 +4,17 @@ import chisel3._
import chisel3.util._ import chisel3.util._
import utils.XSDebug import utils.XSDebug
import bus.tilelink._ import freechips.rocketchip.tilelink._
import utils.{HasTLDump, XSDebug}
class ProbeUnit extends DCacheModule { class ProbeUnit(edge: TLEdgeOut) extends DCacheModule {
val io = IO(new Bundle { val io = IO(new Bundle {
val req = Flipped(Decoupled(new TLBundleB(cfg.busParams))) val req = Flipped(Decoupled(new TLBundleB(edge.bundle)))
val rep = Decoupled(new TLBundleC(cfg.busParams)) val rep = Decoupled(new TLBundleC(edge.bundle))
val meta_read = Decoupled(new L1MetaReadReq) val meta_read = Decoupled(new L1MetaReadReq)
val meta_resp = Input(Vec(nWays, new L1Metadata)) val meta_resp = Input(Vec(nWays, new L1Metadata))
val meta_write = Decoupled(new L1MetaWriteReq) val meta_write = Decoupled(new L1MetaWriteReq)
val wb_req = Decoupled(new WritebackReq()) val wb_req = Decoupled(new WritebackReq(edge.bundle.sourceBits))
val wb_resp = Input(Bool()) val wb_resp = Input(Bool())
}) })
...@@ -21,7 +22,7 @@ class ProbeUnit extends DCacheModule { ...@@ -21,7 +22,7 @@ class ProbeUnit extends DCacheModule {
val state = RegInit(s_invalid) val state = RegInit(s_invalid)
val req = Reg(new TLBundleB(cfg.busParams)) val req = Reg(new TLBundleB(edge.bundle))
val req_idx = get_idx(req.address) val req_idx = get_idx(req.address)
val req_tag = get_tag(req.address) val req_tag = get_tag(req.address)
val req_block_addr = get_block_addr(req.address) val req_block_addr = get_block_addr(req.address)
...@@ -87,7 +88,7 @@ class ProbeUnit extends DCacheModule { ...@@ -87,7 +88,7 @@ class ProbeUnit extends DCacheModule {
// no need to write back, just release // no need to write back, just release
when (state === s_release) { when (state === s_release) {
io.rep.valid := true.B io.rep.valid := true.B
io.rep.bits := TLMasterUtilities.ProbeAck(req, report_param) io.rep.bits := edge.ProbeAck(req, report_param)
when (io.rep.fire()) { when (io.rep.fire()) {
state := Mux(tag_matches, s_meta_write_req, s_invalid) state := Mux(tag_matches, s_meta_write_req, s_invalid)
......
...@@ -90,6 +90,9 @@ class StorePipe extends DCacheModule ...@@ -90,6 +90,9 @@ class StorePipe extends DCacheModule
s2_nack := s2_nack_hit || s2_nack_set_busy s2_nack := s2_nack_hit || s2_nack_set_busy
val s2_info = p"tag match: $s2_tag_match hasPerm: $s2_has_permission" +
p" hit state: $s2_hit_state new state: $s2_new_hit_state s2_nack: $s2_nack\n"
val data_resp = io.data_resp val data_resp = io.data_resp
val s2_data = data_resp(s2_hit_way) val s2_data = data_resp(s2_hit_way)
val wdata = Wire(Vec(refillCycles, UInt(rowBits.W))) val wdata = Wire(Vec(refillCycles, UInt(rowBits.W)))
...@@ -160,21 +163,18 @@ class StorePipe extends DCacheModule ...@@ -160,21 +163,18 @@ class StorePipe extends DCacheModule
// ------- // -------
// Debug logging functions // Debug logging functions
def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool, def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool, req: DCacheLineReq ) = {
req: DCacheLineReq ) = {
when (valid) { when (valid) {
XSDebug(s"$pipeline_stage_name cmd: %x addr: %x id: %d replay: %b\n", XSDebug(
req.cmd, req.addr, req.meta.id, req.meta.replay) s"$pipeline_stage_name cmd: %x addr: %x id: %d replay: %b\n",
(0 until refillCycles) map { r => req.cmd, req.addr, req.meta.id, req.meta.replay
XSDebug(s"cycle: $r data: %x wmask: %x\n", )
req.data(r), req.mask(r))
}
} }
} }
def dump_pipeline_valids(pipeline_stage_name: String, signal_name: String, valid: Bool) = { def dump_pipeline_valids(pipeline_stage_name: String, signal_name: String, valid: Bool) = {
when (valid) { when (valid) {
XSDebug(s"$pipeline_stage_name $signal_name\n") XSDebug(p"$pipeline_stage_name $signal_name " + s2_info)
} }
} }
} }
...@@ -2,13 +2,14 @@ package xiangshan.cache ...@@ -2,13 +2,14 @@ package xiangshan.cache
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import utils.{HasTLDump, PriorityMuxWithFlag, XSDebug}
import utils.XSDebug import chipsalliance.rocketchip.config.Parameters
import bus.tilelink._ import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes}
import xiangshan.{MicroOp, Redirect, NeedImpl} import freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters}
import xiangshan.{HasXSLog, MicroOp, NeedImpl, Redirect}
// One miss entry deals with one mmio request // One miss entry deals with one mmio request
class MMIOEntry extends DCacheModule class MMIOEntry(edge: TLEdgeOut) extends DCacheModule
{ {
val io = IO(new Bundle { val io = IO(new Bundle {
// MSHR ID // MSHR ID
...@@ -18,10 +19,11 @@ class MMIOEntry extends DCacheModule ...@@ -18,10 +19,11 @@ class MMIOEntry extends DCacheModule
val req = Flipped(DecoupledIO(new DCacheWordReq )) val req = Flipped(DecoupledIO(new DCacheWordReq ))
val resp = DecoupledIO(new DCacheResp) val resp = DecoupledIO(new DCacheResp)
val mem_acquire = DecoupledIO(new TLBundleA(cfg.busParams)) val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
val mem_grant = Flipped(DecoupledIO(new TLBundleD(cfg.busParams))) val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
}) })
val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4) val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4)
val state = RegInit(s_invalid) val state = RegInit(s_invalid)
...@@ -49,26 +51,36 @@ class MMIOEntry extends DCacheModule ...@@ -49,26 +51,36 @@ class MMIOEntry extends DCacheModule
when (io.req.fire()) { when (io.req.fire()) {
req := io.req.bits req := io.req.bits
req.addr := io.req.bits.addr
state := s_refill_req state := s_refill_req
} }
} }
// -------------------------------------------- // --------------------------------------------
// refill // refill
// access 64bit data, addr are 64bit aligned // TODO: determine 'lgSize' in memend
val load = TLMasterUtilities.Get( val size = PopCount(req.mask)
params = cfg.busParams, val (lgSize, legal) = PriorityMuxWithFlag(Seq(
1.U -> 0.U,
2.U -> 1.U,
4.U -> 2.U,
8.U -> 3.U
).map(m => (size===m._1) -> m._2))
assert(!(io.mem_acquire.valid && !legal))
val load = edge.Get(
fromSource = io.id, fromSource = io.id,
toAddress = req.addr, toAddress = req.addr,
lgSize = (log2Up(DataBytes)).U)._2 lgSize = lgSize
)._2
val store = TLMasterUtilities.Put( val store = edge.Put(
params = cfg.busParams,
fromSource = io.id, fromSource = io.id,
toAddress = req.addr, toAddress = req.addr,
lgSize = (log2Up(DataBytes)).U, lgSize = lgSize,
data = req.data, data = req.data,
mask = req.mask)._2 mask = req.mask
)._2
when (state === s_refill_req) { when (state === s_refill_req) {
io.mem_acquire.valid := true.B io.mem_acquire.valid := true.B
...@@ -79,7 +91,7 @@ class MMIOEntry extends DCacheModule ...@@ -79,7 +91,7 @@ class MMIOEntry extends DCacheModule
} }
} }
val (_, _, refill_done, _) = TLUtilities.addr_inc(io.mem_grant) val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant)
when (state === s_refill_resp) { when (state === s_refill_resp) {
io.mem_grant.ready := true.B io.mem_grant.ready := true.B
...@@ -108,34 +120,55 @@ class MMIOEntry extends DCacheModule ...@@ -108,34 +120,55 @@ class MMIOEntry extends DCacheModule
class UncacheIO extends DCacheBundle { class UncacheIO extends DCacheBundle {
val lsroq = Flipped(new DCacheLoadIO) val lsroq = Flipped(new DCacheLoadIO)
val bus = new TLCached(l1BusParams)
} }
// convert DCacheIO to TileLink // convert DCacheIO to TileLink
// for Now, we only deal with TL-UL // for Now, we only deal with TL-UL
class Uncache extends DCacheModule {
class Uncache()(implicit p: Parameters) extends LazyModule with HasDCacheParameters {
val clientParameters = TLMasterPortParameters.v1(
clients = Seq(TLMasterParameters.v1(
"uncache",
sourceId = IdRange(0, cfg.nMMIOEntries)
))
)
val clientNode = TLClientNode(Seq(clientParameters))
lazy val module = new UncacheImp(this)
}
class UncacheImp(outer: Uncache)
extends LazyModuleImp(outer)
with HasDCacheParameters
with HasXSLog
with HasTLDump
{
val io = IO(new UncacheIO) val io = IO(new UncacheIO)
val (bus, edge) = outer.clientNode.out.head
val resp_arb = Module(new Arbiter(new DCacheResp, cfg.nMMIOEntries)) val resp_arb = Module(new Arbiter(new DCacheResp, cfg.nMMIOEntries))
val req = io.lsroq.req val req = io.lsroq.req
val resp = io.lsroq.resp val resp = io.lsroq.resp
val mem_acquire = io.bus.a val mem_acquire = bus.a
val mem_grant = io.bus.d val mem_grant = bus.d
val entry_alloc_idx = Wire(UInt()) val entry_alloc_idx = Wire(UInt())
val req_ready = WireInit(false.B) val req_ready = WireInit(false.B)
// assign default values to output signals // assign default values to output signals
io.bus.b.ready := false.B bus.b.ready := false.B
io.bus.c.valid := false.B bus.c.valid := false.B
io.bus.c.bits := DontCare bus.c.bits := DontCare
io.bus.d.ready := false.B bus.d.ready := false.B
io.bus.e.valid := false.B bus.e.valid := false.B
io.bus.e.bits := DontCare bus.e.bits := DontCare
val entries = (0 until cfg.nMMIOEntries) map { i => val entries = (0 until cfg.nMMIOEntries) map { i =>
val entry = Module(new MMIOEntry) val entry = Module(new MMIOEntry(edge))
entry.io.id := i.U(log2Up(cfg.nMMIOEntries).W) entry.io.id := i.U(log2Up(cfg.nMMIOEntries).W)
...@@ -161,7 +194,7 @@ class Uncache extends DCacheModule { ...@@ -161,7 +194,7 @@ class Uncache extends DCacheModule {
req.ready := req_ready req.ready := req_ready
resp <> resp_arb.io.out resp <> resp_arb.io.out
TLArbiter.lowestFromSeq(mem_acquire, entries.map(_.io.mem_acquire)) TLArbiter.lowestFromSeq(edge, mem_acquire, entries.map(_.io.mem_acquire))
// print all input/output requests for debug purpose // print all input/output requests for debug purpose
...@@ -172,12 +205,12 @@ class Uncache extends DCacheModule { ...@@ -172,12 +205,12 @@ class Uncache extends DCacheModule {
XSDebug(resp.fire(), "data: %x\n", req.bits.data) XSDebug(resp.fire(), "data: %x\n", req.bits.data)
// print tilelink messages // print tilelink messages
when (mem_acquire.fire()) { when(mem_acquire.valid){
XSDebug("mem_acquire ") XSDebug("mem_acquire valid, ready=%d ", mem_acquire.ready)
mem_acquire.bits.dump mem_acquire.bits.dump
} }
when (mem_grant.fire()) { when (mem_grant.fire()) {
XSDebug("mem_grant ") XSDebug("mem_grant fire ")
mem_grant.bits.dump mem_grant.bits.dump
} }
} }
...@@ -2,38 +2,37 @@ package xiangshan.cache ...@@ -2,38 +2,37 @@ package xiangshan.cache
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chisel3.util.experimental.BoringUtils
import utils.XSDebug import utils.XSDebug
import bus.tilelink._ import freechips.rocketchip.tilelink.{TLBundleC, TLEdgeOut, TLPermissions}
class WritebackReq extends DCacheBundle { class WritebackReq(sourceBits: Int) extends DCacheBundle {
val tag = Bits(tagBits.W) val tag = Bits(tagBits.W)
val idx = Bits(idxBits.W) val idx = Bits(idxBits.W)
// TODO: make it configurable val source = UInt(sourceBits.W)
val source = UInt(cfg.busParams.sourceBits.W)
val param = UInt(TLPermissions.cWidth.W) val param = UInt(TLPermissions.cWidth.W)
val way_en = Bits(nWays.W) val way_en = Bits(nWays.W)
val voluntary = Bool() val voluntary = Bool()
override def cloneType: WritebackReq.this.type = new WritebackReq(sourceBits).asInstanceOf[this.type]
} }
class WritebackUnit extends DCacheModule { class WritebackUnit(edge: TLEdgeOut) extends DCacheModule {
val io = IO(new Bundle { val io = IO(new Bundle {
val req = Flipped(DecoupledIO(new WritebackReq())) val req = Flipped(DecoupledIO(new WritebackReq(edge.bundle.sourceBits)))
val resp = Output(Bool()) val resp = Output(Bool())
val data_req = DecoupledIO(new L1DataReadReq) val data_req = DecoupledIO(new L1DataReadReq)
val data_resp = Input(Vec(nWays, Vec(refillCycles, Bits(encRowBits.W)))) val data_resp = Input(Vec(nWays, Vec(refillCycles, Bits(encRowBits.W))))
val release = DecoupledIO(new TLBundleC(cfg.busParams)) val release = DecoupledIO(new TLBundleC(edge.bundle))
val mem_grant = Input(Bool()) val mem_grant = Input(Bool())
}) })
val req = Reg(new WritebackReq()) val req = Reg(new WritebackReq(edge.bundle.sourceBits))
val s_invalid :: s_data_read_req :: s_data_read_resp :: s_active :: s_grant :: s_resp :: Nil = Enum(6) val s_invalid :: s_data_read_req :: s_data_read_resp :: s_active :: s_grant :: s_resp :: Nil = Enum(6)
val state = RegInit(s_invalid) val state = RegInit(s_invalid)
val data_req_cnt = RegInit(0.U(log2Up(refillCycles+1).W)) val data_req_cnt = RegInit(0.U(log2Up(refillCycles+1).W))
val (_, last_beat, all_beats_done, beat_count) = TLUtilities.count(io.release) val (_, last_beat, all_beats_done, beat_count) = edge.count(io.release)
val wb_buffer = Reg(Vec(refillCycles, UInt(rowBits.W))) val wb_buffer = Reg(Vec(refillCycles, UInt(rowBits.W)))
val acked = RegInit(false.B) val acked = RegInit(false.B)
...@@ -89,23 +88,24 @@ class WritebackUnit extends DCacheModule { ...@@ -89,23 +88,24 @@ class WritebackUnit extends DCacheModule {
} }
// release // release
val r_address = Cat(req.tag, req.idx) << blockOffBits val r_address = (Cat(req.tag, req.idx) << blockOffBits).asUInt()
val id = cfg.nMissEntries val id = cfg.nMissEntries
val probeResponse = TLMasterUtilities.ProbeAck(
params = cfg.busParams, val probeResponse = edge.ProbeAck(
fromSource = id.U, fromSource = id.U,
toAddress = r_address, toAddress = r_address,
lgSize = log2Ceil(cfg.blockBytes).U, lgSize = log2Ceil(cfg.blockBytes).U,
reportPermissions = req.param, reportPermissions = req.param,
data = wb_buffer(data_req_cnt)) data = wb_buffer(data_req_cnt)
)
val voluntaryRelease = TLMasterUtilities.Release(
params = cfg.busParams, val voluntaryRelease = edge.Release(
fromSource = id.U, fromSource = id.U,
toAddress = r_address, toAddress = r_address,
lgSize = log2Ceil(cfg.blockBytes).U, lgSize = log2Ceil(cfg.blockBytes).U,
shrinkPermissions = req.param, shrinkPermissions = req.param,
data = wb_buffer(data_req_cnt))._2 data = wb_buffer(data_req_cnt)
)._2
when (state === s_active) { when (state === s_active) {
io.release.valid := data_req_cnt < refillCycles.U io.release.valid := data_req_cnt < refillCycles.U
......
...@@ -111,10 +111,9 @@ class LoadUnit extends XSModule { ...@@ -111,10 +111,9 @@ class LoadUnit extends XSModule {
val l3_valid = RegNext(l2_out.fire(), false.B) val l3_valid = RegNext(l2_out.fire(), false.B)
val l3_dtlb_miss = RegEnable(next = l2_dtlb_miss, enable = l2_out.fire(), init = false.B) val l3_dtlb_miss = RegEnable(next = l2_dtlb_miss, enable = l2_out.fire(), init = false.B)
val l3_dcache = RegEnable(next = l2_dcache, enable = l2_out.fire(), init = false.B) val l3_dcache = RegEnable(next = l2_dcache, enable = l2_out.fire(), init = false.B)
val l3_mmio = RegEnable(next = l2_mmio, enable = l2_out.fire(), init = false.B)
val l3_tlbFeedback = RegEnable(next = l2_tlbFeedback, enable = l2_out.fire()) val l3_tlbFeedback = RegEnable(next = l2_tlbFeedback, enable = l2_out.fire())
val l3_uop = RegEnable(l2_out.bits.uop, l2_out.fire())
val l3_bundle = RegEnable(next = l2_out.bits, enable = l2_out.fire()) val l3_bundle = RegEnable(next = l2_out.bits, enable = l2_out.fire())
val l3_uop = l3_bundle.uop
// dltb miss reqs ends here // dltb miss reqs ends here
val l3_passdown = l3_valid && !l3_dtlb_miss && !l3_uop.needFlush(io.redirect) val l3_passdown = l3_valid && !l3_dtlb_miss && !l3_uop.needFlush(io.redirect)
...@@ -126,7 +125,7 @@ class LoadUnit extends XSModule { ...@@ -126,7 +125,7 @@ class LoadUnit extends XSModule {
XSDebug(l3_valid, "l3: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x dltb_miss %b dcache %b mmio %b\n", XSDebug(l3_valid, "l3: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x dltb_miss %b dcache %b mmio %b\n",
l3_bundle.uop.cf.pc, l3_bundle.vaddr, l3_bundle.paddr, l3_bundle.uop.cf.pc, l3_bundle.vaddr, l3_bundle.paddr,
l3_bundle.uop.ctrl.fuOpType, l3_bundle.data, l3_bundle.mask, l3_bundle.uop.ctrl.fuOpType, l3_bundle.data, l3_bundle.mask,
l3_dtlb_miss, l3_dcache, l3_mmio) l3_dtlb_miss, l3_dcache, l3_bundle.mmio)
XSDebug(io.tlbFeedback.valid, "tlbFeedback: hit %b roqIdx %d\n", XSDebug(io.tlbFeedback.valid, "tlbFeedback: hit %b roqIdx %d\n",
io.tlbFeedback.bits.hit, io.tlbFeedback.bits.roqIdx) io.tlbFeedback.bits.hit, io.tlbFeedback.bits.roqIdx)
...@@ -142,7 +141,6 @@ class LoadUnit extends XSModule { ...@@ -142,7 +141,6 @@ class LoadUnit extends XSModule {
val l4_valid = RegNext(l3_passdown, false.B) val l4_valid = RegNext(l3_passdown, false.B)
val l4_dcache = RegNext(l3_dcache, false.B) val l4_dcache = RegNext(l3_dcache, false.B)
val l4_mmio = RegNext(l3_mmio, false.B)
val l4_bundle = RegNext(l3_bundle) val l4_bundle = RegNext(l3_bundle)
assert(!(io.dcache.resp.ready && !io.dcache.resp.valid), "DCache response got lost") assert(!(io.dcache.resp.ready && !io.dcache.resp.valid), "DCache response got lost")
...@@ -194,7 +192,7 @@ class LoadUnit extends XSModule { ...@@ -194,7 +192,7 @@ class LoadUnit extends XSModule {
XSDebug(l4_valid, "l4: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x forwardData: 0x%x forwardMask: %x dcache %b mmio %b\n", XSDebug(l4_valid, "l4: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x forwardData: 0x%x forwardMask: %x dcache %b mmio %b\n",
l4_out.bits.uop.cf.pc, l4_out.bits.vaddr, l4_out.bits.paddr, l4_out.bits.uop.cf.pc, l4_out.bits.vaddr, l4_out.bits.paddr,
l4_out.bits.uop.ctrl.fuOpType, l4_out.bits.data, l4_out.bits.mask, l4_out.bits.uop.ctrl.fuOpType, l4_out.bits.data, l4_out.bits.mask,
l4_out.bits.forwardData.asUInt, l4_out.bits.forwardMask.asUInt, l4_dcache, l4_mmio) l4_out.bits.forwardData.asUInt, l4_out.bits.forwardMask.asUInt, l4_dcache, l4_out.bits.mmio)
XSDebug(l5_in.valid, "L5: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x forwardData: 0x%x forwardMask: %x\n", XSDebug(l5_in.valid, "L5: pc 0x%x addr 0x%x -> 0x%x op %b data 0x%x mask %x forwardData: 0x%x forwardMask: %x\n",
l5_in.bits.uop.cf.pc, l5_in.bits.vaddr, l5_in.bits.paddr, l5_in.bits.uop.cf.pc, l5_in.bits.vaddr, l5_in.bits.paddr,
......
...@@ -114,26 +114,38 @@ class MemToBackendIO extends XSBundle { ...@@ -114,26 +114,38 @@ class MemToBackendIO extends XSBundle {
class Memend extends XSModule { class Memend extends XSModule {
val io = IO(new Bundle{ val io = IO(new Bundle{
val backend = new MemToBackendIO val backend = new MemToBackendIO
val mem = new TLCached(l1BusParams) val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheLoadIO)
val mmio = new TLCached(l1BusParams) val miscToDcache = new DCacheLoadIO
val sbufferToDcache = new DCacheStoreIO
val uncache = new DCacheLoadIO
}) })
val loadUnits = (0 until exuParameters.LduCnt).map(_ => Module(new LoadUnit)) val loadUnits = (0 until exuParameters.LduCnt).map(_ => Module(new LoadUnit))
val storeUnits = (0 until exuParameters.StuCnt).map(_ => Module(new StoreUnit)) val storeUnits = (0 until exuParameters.StuCnt).map(_ => Module(new StoreUnit))
val miscUnit = Module(new MiscUnit) val miscUnit = Module(new MiscUnit)
val dcache = Module(new DCache)
val uncache = Module(new Uncache)
// val mshq = Module(new MSHQ) // val mshq = Module(new MSHQ)
val dtlb = Module(new Dtlb) val dtlb = Module(new Dtlb) //TODO: move dtlb out
val lsroq = Module(new Lsroq) val lsroq = Module(new Lsroq)
val sbuffer = Module(new FakeSbuffer) val sbuffer = Module(new FakeSbuffer)
dtlb.io := DontCare dtlb.io := DontCare
dcache.io.bus <> io.mem val loadUnitToDcacheVec = Wire(Vec(exuParameters.LduCnt, new DCacheLoadIO))
uncache.io.bus <> io.mmio
dcache.io.lsu.misc <> DontCare val sbufferToDcache = Wire(new DCacheStoreIO)
dcache.io.ptw <> DontCare
val lsroqToUncache = Wire(new DCacheLoadIO)
// lsroq and miscUnit share one dcache port
val lsroqToDcache = Wire(new DCacheLoadIO)
val miscUnitToDcache = Wire(new DCacheLoadIO)
// misc + miss --> arbiter --> miscToDcache
val miscToDcache = io.miscToDcache
// connect dcache ports
io.loadUnitToDcacheVec <> loadUnitToDcacheVec
io.sbufferToDcache <> sbufferToDcache
io.uncache <> lsroqToUncache
// LoadUnit // LoadUnit
for (i <- 0 until exuParameters.LduCnt) { for (i <- 0 until exuParameters.LduCnt) {
...@@ -141,15 +153,15 @@ class Memend extends XSModule { ...@@ -141,15 +153,15 @@ class Memend extends XSModule {
loadUnits(i).io.ldout <> io.backend.ldout(i) loadUnits(i).io.ldout <> io.backend.ldout(i)
loadUnits(i).io.redirect <> io.backend.redirect loadUnits(i).io.redirect <> io.backend.redirect
loadUnits(i).io.tlbFeedback <> io.backend.tlbFeedback(i) loadUnits(i).io.tlbFeedback <> io.backend.tlbFeedback(i)
loadUnits(i).io.dcache <> dcache.io.lsu.load(i) loadUnits(i).io.dcache <> loadUnitToDcacheVec(i)
loadUnits(i).io.dtlb <> dtlb.io.lsu(i) loadUnits(i).io.dtlb <> dtlb.io.lsu(i)
loadUnits(i).io.sbuffer <> sbuffer.io.forward(i) loadUnits(i).io.sbuffer <> sbuffer.io.forward(i)
lsroq.io.loadIn(i) <> loadUnits(i).io.lsroq.loadIn lsroq.io.loadIn(i) <> loadUnits(i).io.lsroq.loadIn
lsroq.io.ldout(i) <> loadUnits(i).io.lsroq.ldout lsroq.io.ldout(i) <> loadUnits(i).io.lsroq.ldout
lsroq.io.forward(i) <> loadUnits(i).io.lsroq.forward lsroq.io.forward(i) <> loadUnits(i).io.lsroq.forward
} }
// StoreUnit // StoreUnit
for (i <- 0 until exuParameters.StuCnt) { for (i <- 0 until exuParameters.StuCnt) {
storeUnits(i).io.stin <> io.backend.stin(i) storeUnits(i).io.stin <> io.backend.stin(i)
...@@ -159,7 +171,7 @@ class Memend extends XSModule { ...@@ -159,7 +171,7 @@ class Memend extends XSModule {
storeUnits(i).io.lsroq <> lsroq.io.storeIn(i) storeUnits(i).io.lsroq <> lsroq.io.storeIn(i)
} }
sbuffer.io.dcache <> dcache.io.lsu.store sbuffer.io.dcache <> sbufferToDcache
lsroq.io.stout <> io.backend.stout lsroq.io.stout <> io.backend.stout
lsroq.io.commits <> io.backend.commits lsroq.io.commits <> io.backend.commits
...@@ -167,28 +179,40 @@ class Memend extends XSModule { ...@@ -167,28 +179,40 @@ class Memend extends XSModule {
lsroq.io.lsroqIdxs <> io.backend.lsroqIdxs lsroq.io.lsroqIdxs <> io.backend.lsroqIdxs
lsroq.io.brqRedirect := io.backend.redirect lsroq.io.brqRedirect := io.backend.redirect
io.backend.replayAll <> lsroq.io.rollback io.backend.replayAll <> lsroq.io.rollback
lsroq.io.dcache <> dcache.io.lsu.lsroq // TODO: Add AMO lsroq.io.dcache <> lsroqToDcache // TODO: Add AMO
lsroq.io.uncache <> uncache.io.lsroq lsroq.io.uncache <> lsroqToUncache
// LSROQ to store buffer // LSROQ to store buffer
lsroq.io.sbuffer <> sbuffer.io.in lsroq.io.sbuffer <> sbuffer.io.in
// MiscUnit // MiscUnit
// MiscUnit will override other control signials, // MiscUnit will override other control signials,
// as misc insts (LR/SC/AMO) will block the pipeline // as misc insts (LR/SC/AMO) will block the pipeline
miscUnit.io <> DontCare miscUnit.io <> DontCare
miscUnit.io.in.bits := Mux(io.backend.ldin(0).valid, io.backend.ldin(0).bits, io.backend.ldin(1).bits) miscUnit.io.in.bits := Mux(io.backend.ldin(0).valid, io.backend.ldin(0).bits, io.backend.ldin(1).bits)
miscUnit.io.in.valid := io.backend.ldin(0).valid && io.backend.ldin(0).bits.uop.ctrl.fuType === FuType.mou || miscUnit.io.in.valid := io.backend.ldin(0).valid && io.backend.ldin(0).bits.uop.ctrl.fuType === FuType.mou ||
io.backend.ldin(1).valid && io.backend.ldin(1).bits.uop.ctrl.fuType === FuType.mou io.backend.ldin(1).valid && io.backend.ldin(1).bits.uop.ctrl.fuType === FuType.mou
when(miscUnit.io.dtlb.req.valid){ when(miscUnit.io.dtlb.req.valid){
dtlb.io.lsu(0) <> miscUnit.io.dtlb dtlb.io.lsu(0) <> miscUnit.io.dtlb
}
when(miscUnit.io.dcache.req.valid){
dcache.io.lsu.lsroq.req <> miscUnit.io.dcache.req
}
when(dcache.io.lsu.lsroq.resp.valid && dcache.io.lsu.lsroq.resp.bits.meta.id(1, 0) === DCacheMiscType.misc){
dcache.io.lsu.lsroq.resp <> miscUnit.io.dcache.resp
} }
miscUnit.io.dcache <> miscUnitToDcache
assert(!(lsroqToDcache.req.valid && miscUnitToDcache.req.valid))
val memReqArb = Module(new Arbiter(miscToDcache.req.bits.cloneType, 2))
memReqArb.io.in(0) <> lsroqToDcache.req
memReqArb.io.in(1) <> miscUnitToDcache.req
miscToDcache.req <> memReqArb.io.out
miscToDcache.s1_kill := lsroqToDcache.s1_kill
lsroqToDcache.resp <> miscToDcache.resp
miscUnitToDcache.resp <> miscToDcache.resp
// override resp's valid bit
lsroqToDcache.resp.valid := miscToDcache.resp.valid &&
miscToDcache.resp.bits.meta.id(1, 0)===DCacheMiscType.miss
miscUnitToDcache.resp.valid := miscToDcache.resp.valid &&
miscToDcache.resp.bits.meta.id(1, 0)===DCacheMiscType.misc
when(miscUnit.io.out.valid){ when(miscUnit.io.out.valid){
io.backend.ldout(0) <> miscUnit.io.out io.backend.ldout(0) <> miscUnit.io.out
} }
......
#include "emu.h" #include "emu.h"
#include "difftest.h" #include "difftest.h"
#include <getopt.h>
void* get_ram_start(); void* get_ram_start();
long get_ram_size(); long get_ram_size();
uint64_t get_nemu_this_pc(); uint64_t get_nemu_this_pc();
void set_nemu_this_pc(uint64_t pc); void set_nemu_this_pc(uint64_t pc);
Emulator::Emulator(EmuArgs &args):
static inline void print_help(const char *file) {
printf("Usage: %s [OPTION...]\n", file);
printf("\n");
printf(" -s, --seed=NUM use this seed\n");
printf(" -C, --max-cycles=NUM execute at most NUM cycles\n");
printf(" -i, --image=FILE run with this image file\n");
printf(" -b, --log-begin=NUM display log from NUM th cycle\n");
printf(" -e, --log-end=NUM stop display log at NUM th cycle\n");
printf(" --load-snapshot=PATH load snapshot from PATH\n");
printf(" --dump-wave dump waveform when log is enabled\n");
printf(" -h, --help print program help info\n");
printf("\n");
}
inline EmuArgs parse_args(int argc, const char *argv[]) {
EmuArgs args;
int long_index = 0;
const struct option long_options[] = {
{ "load-snapshot", 1, NULL, 0 },
{ "dump-wave", 0, NULL, 0 },
{ "seed", 1, NULL, 's' },
{ "max-cycles", 1, NULL, 'C' },
{ "image", 1, NULL, 'i' },
{ "log-begin", 1, NULL, 'b' },
{ "log-end", 1, NULL, 'e' },
{ "help", 0, NULL, 'h' },
{ 0, 0, NULL, 0 }
};
int o;
while ( (o = getopt_long(argc, const_cast<char *const*>(argv),
"-s:C:hi:m:b:e:", long_options, &long_index)) != -1) {
switch (o) {
case 0:
switch (long_index) {
case 0: args.snapshot_path = optarg; continue;
case 1: args.enable_waveform = true; continue;
}
// fall through
default:
print_help(argv[0]);
exit(0);
case 's':
if(std::string(optarg) != "NO_SEED") {
args.seed = atoll(optarg);
printf("Using seed = %d\n", args.seed);
}
break;
case 'C': args.max_cycles = atoll(optarg); break;
case 'i': args.image = optarg; break;
case 'b': args.log_begin = atoll(optarg); break;
case 'e': args.log_end = atoll(optarg); break;
}
}
Verilated::commandArgs(argc, argv); // Prepare extra args for TLMonitor
return args;
}
Emulator::Emulator(int argc, const char *argv[]):
dut_ptr(new VXSSimTop), dut_ptr(new VXSSimTop),
cycles(0), hascommit(0), trapCode(STATE_RUNNING) cycles(0), hascommit(0), trapCode(STATE_RUNNING)
{ {
args = parse_args(argc, argv);
// srand // srand
srand(args.seed); srand(args.seed);
srand48(args.seed); srand48(args.seed);
......
...@@ -30,6 +30,7 @@ class Emulator { ...@@ -30,6 +30,7 @@ class Emulator {
VerilatedVcdC* tfp; VerilatedVcdC* tfp;
bool enable_waveform; bool enable_waveform;
VerilatedSaveMem snapshot_slot[2]; VerilatedSaveMem snapshot_slot[2];
EmuArgs args;
enum { enum {
STATE_GOODTRAP = 0, STATE_GOODTRAP = 0,
...@@ -55,9 +56,10 @@ class Emulator { ...@@ -55,9 +56,10 @@ class Emulator {
inline char* waveform_filename(time_t t); inline char* waveform_filename(time_t t);
public: public:
Emulator(EmuArgs &args); Emulator(int argc, const char *argv[]);
~Emulator(); ~Emulator();
uint64_t execute(uint64_t n); uint64_t execute(uint64_t n);
uint64_t get_cycles() const { return cycles; } uint64_t get_cycles() const { return cycles; }
EmuArgs get_args() const { return args; }
bool is_good_trap() { return trapCode == STATE_GOODTRAP; }; bool is_good_trap() { return trapCode == STATE_GOODTRAP; };
}; };
#include "emu.h" #include "emu.h"
#include <getopt.h>
#include <functional> #include <functional>
static char mybuf[BUFSIZ]; static char mybuf[BUFSIZ];
...@@ -8,74 +7,16 @@ static char mybuf[BUFSIZ]; ...@@ -8,74 +7,16 @@ static char mybuf[BUFSIZ];
std::function<double()> get_sc_time_stamp = []() -> double { return 0; }; std::function<double()> get_sc_time_stamp = []() -> double { return 0; };
double sc_time_stamp() { return get_sc_time_stamp(); } double sc_time_stamp() { return get_sc_time_stamp(); }
static inline void print_help(const char *file) {
printf("Usage: %s [OPTION...]\n", file);
printf("\n");
printf(" -s, --seed=NUM use this seed\n");
printf(" -C, --max-cycles=NUM execute at most NUM cycles\n");
printf(" -i, --image=FILE run with this image file\n");
printf(" -b, --log-begin=NUM display log from NUM th cycle\n");
printf(" -e, --log-end=NUM stop display log at NUM th cycle\n");
printf(" --load-snapshot=PATH load snapshot from PATH\n");
printf(" --dump-wave dump waveform when log is enabled\n");
printf(" -h, --help print program help info\n");
printf("\n");
}
static inline EmuArgs parse_args(int argc, const char *argv[]) {
EmuArgs args;
int long_index = 0;
const struct option long_options[] = {
{ "load-snapshot", 1, NULL, 0 },
{ "dump-wave", 0, NULL, 0 },
{ "seed", 1, NULL, 's' },
{ "max-cycles", 1, NULL, 'C' },
{ "image", 1, NULL, 'i' },
{ "log-begin", 1, NULL, 'b' },
{ "log-end", 1, NULL, 'e' },
{ "help", 0, NULL, 'h' },
{ 0, 0, NULL, 0 }
};
int o;
while ( (o = getopt_long(argc, const_cast<char *const*>(argv),
"-s:C:hi:m:b:e:", long_options, &long_index)) != -1) {
switch (o) {
case 0:
switch (long_index) {
case 0: args.snapshot_path = optarg; continue;
case 1: args.enable_waveform = true; continue;
}
// fall through
default:
print_help(argv[0]);
exit(0);
case 's':
if(std::string(optarg) != "NO_SEED") {
args.seed = atoll(optarg);
printf("Using seed = %d\n", args.seed);
}
break;
case 'C': args.max_cycles = atoll(optarg); break;
case 'i': args.image = optarg; break;
case 'b': args.log_begin = atoll(optarg); break;
case 'e': args.log_end = atoll(optarg); break;
}
}
return args;
}
int main(int argc, const char** argv) { int main(int argc, const char** argv) {
setbuf(stderr, mybuf); setbuf(stderr, mybuf);
auto args = parse_args(argc, argv); auto emu = new Emulator(argc, argv);
auto emu = new Emulator(args);
get_sc_time_stamp = [&emu]() -> double { get_sc_time_stamp = [&emu]() -> double {
return emu->get_cycles(); return emu->get_cycles();
}; };
auto args = emu->get_args();
uint64_t cycles = emu->execute(args.max_cycles); uint64_t cycles = emu->execute(args.max_cycles);
bool is_good_trap = emu->is_good_trap(); bool is_good_trap = emu->is_good_trap();
delete emu; delete emu;
......
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chisel3.util._
import chiseltest._
import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4MasterNode, AXI4MasterParameters, AXI4MasterPortParameters, AXI4Parameters, AXI4UserYanker}
import freechips.rocketchip.diplomacy._
class AXI4BurstMaster
(
startAddr: Long = 0,
nOp: Int = 1,
beatBytes: Int = 8,
burstLen: Int = 16,
idRange: IdRange = IdRange(0, 1)
)(implicit p: Parameters) extends LazyModule {
val node = AXI4MasterNode(Seq(AXI4MasterPortParameters(
Seq(AXI4MasterParameters("burst master", idRange))
)))
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle{
val finished = Output(Bool())
})
val (out, edge) = node.out.head
val cnt = RegInit(nOp.U)
val addr = RegInit(startAddr.U)
val s_idle :: s_addr :: s_data :: Nil = Enum(3)
val state = RegInit(s_idle)
val ar = out.ar
val r = out.r
switch(state){
is(s_idle){
when(cnt =/= 0.U){
state := s_addr
}
}
is(s_addr){
when(ar.ready){
state := s_data
}
}
is(s_data){
when(r.valid){
addr := addr + beatBytes.U
}
when(r.valid && r.bits.last){
state := s_idle
cnt := cnt - 1.U
}
}
}
io.finished := cnt === 0.U
ar.valid := state === s_addr
ar.bits.addr := addr
ar.bits.size := log2Up(beatBytes).U
ar.bits.len := (burstLen-1).U
ar.bits.burst := AXI4Parameters.BURST_INCR
r.ready := state === s_data
}
}
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chiseltest._
import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4UserYanker}
import org.scalatest.{FlatSpec, Matchers}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
import utils.DebugIdentityNode
class AXI4RamFuzzTest()(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x38000000L, 0x0000ffffL)
val fuzz = LazyModule(new TLFuzzer(
nOperations = 10,
overrideAddress = Some(addressSet),
inFlight = 10
))
val ident = LazyModule(new DebugIdentityNode())
val axiRam = LazyModule(new AXI4RAM(addressSet, memByte = 1024))
axiRam.node :=
AXI4UserYanker() :=
TLToAXI4() :=
TLFragmenter(8, 8) :=
ident.node :=
fuzz.node
lazy val module = new LazyModuleImp(this){
val finished = IO(Output(Bool()))
finished := fuzz.module.io.finished
}
}
class AXI4RamBurstTest()(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x38000000L, 0x0000ffffL)
val burst = LazyModule(new AXI4BurstMaster(startAddr = addressSet.base.toLong, nOp = 3))
val axiRam = LazyModule(new AXI4RAM(addressSet, memByte = 1024))
axiRam.node := burst.node
lazy val module = new LazyModuleImp(this){
val finished = IO(Output(Bool()))
finished := burst.module.io.finished
}
}
class AXI4RamTLBurstTest()(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x38000000L, 0x0000ffffL)
val tlburst = LazyModule(new TLBurstMaster(startAddr = addressSet.base.toLong, nOp = 1, burstLen = 32))
val ident = LazyModule(new DebugIdentityNode())
val axiRam = LazyModule(new AXI4RAM(addressSet, memByte = 1024))
axiRam.node :=
AXI4UserYanker() :=
TLToAXI4() :=
TLFragmenter(8, 32 * 8, holdFirstDeny = true) :=
ident.node :=
tlburst.node
lazy val module = new LazyModuleImp(this){
val finished = IO(Output(Bool()))
finished := tlburst.module.io.finished
}
}
class AXI4RamTest extends FlatSpec with ChiselScalatestTester with Matchers {
it should "run with fuzz" in {
implicit val p = Parameters.empty
test(LazyModule(new AXI4RamFuzzTest()).module){ c =>
while (!c.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
it should "run in burst mode with axi master" in {
implicit val p = Parameters.empty
test(LazyModule(new AXI4RamBurstTest()).module){c =>
while (!c.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
it should "run in burst mode with tilelink master" in {
implicit val p = Parameters.empty
test(LazyModule(new AXI4RamTLBurstTest()).module){c =>
while (!c.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
}
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chiseltest._
import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4UserYanker}
import org.scalatest.{FlatSpec, Matchers}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
import utils.DebugIdentityNode
class AXI4TimerTestTop(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x38000000L, 0x0000ffffL)
val fuzz = LazyModule(new TLFuzzer(nOperations = 10, overrideAddress = Some(addressSet), inFlight = 1))
val ident = LazyModule(new DebugIdentityNode())
val axiTimer = LazyModule(new AXI4Timer(sim = true, addressSet))
axiTimer.node :=
AXI4UserYanker() :=
TLToAXI4() :=
ident.node :=
fuzz.node
lazy val module = new LazyModuleImp(this){
val finished = IO(Output(Bool()))
finished := fuzz.module.io.finished
}
}
class AXI4TimerTest extends FlatSpec with Matchers with ChiselScalatestTester {
it should "run" in {
implicit val p = Parameters.empty
test(LazyModule(new AXI4TimerTestTop()).module){ c =>
while (!c.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
}
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chiseltest._
import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4UserYanker, AXI4Xbar}
import org.scalatest.{FlatSpec, Matchers}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
import top.SimMMIO
import utils.DebugIdentityNode
class SimMMIOTestTop()(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x40600000L, 0xf)
val fuzz = LazyModule(new TLFuzzer(nOperations = 10, inFlight = 1, overrideAddress = Some(addressSet)))
val simMMIO = LazyModule(new SimMMIO())
simMMIO.axiBus :=
AXI4UserYanker() :=
TLToAXI4() :=
DebugIdentityNode() :=
fuzz.node
lazy val module = new LazyModuleImp(this){
val finished = IO(Output(Bool()))
finished := fuzz.module.io.finished
}
}
class SimMMIOTest extends FlatSpec with ChiselScalatestTester with Matchers {
it should "run" in {
implicit val p = Parameters.empty
test(LazyModule(new SimMMIOTestTop()).module){c =>
while (!c.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
}
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chisel3.util._
import chiseltest._
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
class TLBurstMaster
(
startAddr: Long = 0,
nOp: Int = 1,
beatBytes: Int = 8,
burstLen: Int = 16,
idRange: IdRange = IdRange(0, 1)
)(implicit p: Parameters) extends LazyModule {
val node = TLClientNode(Seq(TLMasterPortParameters.v1(
Seq(TLMasterParameters.v1("TLMaster", idRange))
)))
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle() {
val finished = Output(Bool())
})
val (out , edge) = node.out.head
val cnt = RegInit(nOp.U)
val addr = RegInit(startAddr.U)
val s_idle :: s_addr :: s_data :: Nil = Enum(3)
val state = RegInit(s_idle)
switch(state){
is(s_idle){
when(cnt =/= 0.U){
state := s_addr
}
}
is(s_addr){
when(out.a.fire()){
state := s_data
}
}
is(s_data){
when(out.d.fire()){
addr := addr + beatBytes.U
}
when(edge.done(out.d)){
state := s_idle
cnt := cnt - 1.U
}
}
}
io.finished := cnt===0.U
val a = out.a
val d = out.d
a.valid := state === s_addr
val (_, bundleA) = edge.Get(idRange.start.U, addr, log2Up(beatBytes*burstLen).U)
a.bits := bundleA
d.ready := state === s_data
}
}
package device
import chipsalliance.rocketchip.config._
import chisel3._
import chiseltest._
import org.scalatest.{FlatSpec, Matchers}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
import utils.DebugIdentityNode
class TLTimerTestTop()(implicit p: Parameters) extends LazyModule {
val addressSet = AddressSet(0x38000000L, 0x0000ffffL)
val timer = LazyModule(new TLTimer(Seq(addressSet), sim = true))
val ident = LazyModule(new DebugIdentityNode)
val fuzz = LazyModule(new TLFuzzer(
nOperations = 10,
overrideAddress = Some(addressSet)
))
timer.node := ident.node := TLDelayer(0.1) := fuzz.node
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle() {
val finished = Output(Bool())
})
io.finished := fuzz.module.io.finished
}
}
class TLTimerTest extends FlatSpec with ChiselScalatestTester with Matchers {
it should "run" in {
implicit val p = Parameters.empty
test(LazyModule(new TLTimerTestTop()).module){ c =>
while (!c.io.finished.peek().litToBoolean){
c.clock.step(1)
}
}
}
}
package top package top
import bus.axi4.AXI4ToAXI4Lite
import chisel3._ import chisel3._
import chisel3.util._ import chipsalliance.rocketchip.config
import bus.simplebus._
import bus.tilelink.{NaiveTL1toN, MMIOTLToAXI4, TLCached, TLParameters}
import device._ import device._
import freechips.rocketchip.amba.axi4.{AXI4MasterParameters, AXI4MasterPortParameters, AXI4SlaveNode, AXI4SlavePortParameters, AXI4ToTL, AXI4Xbar}
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink.{TLErrorEvaluator, TLMasterParameters, TLXbar}
class SimMMIO()(implicit p: config.Parameters) extends LazyModule {
val uart = LazyModule(new AXI4UART(AddressSet(0x40600000L, 0xf)))
val vga = LazyModule(new AXI4VGA(
sim = false,
fbAddress = AddressSet(0x50000000L, 0x3fffffL),
ctrlAddress = AddressSet(0x40001000L, 0x7L)
))
val flash = LazyModule(new AXI4Flash(AddressSet(0x40000000L, 0xfff)))
val sd = LazyModule(new AXI4DummySD(AddressSet(0x40002000L, 0xfff)))
val axiBus = AXI4Xbar()
uart.node := axiBus
vga.node :*= axiBus
flash.node := axiBus
sd.node := axiBus
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle() {
val uart = new UARTIO
})
io.uart <> uart.module.io.extra.get
}
class SimMMIO(para: TLParameters) extends Module {
val io = IO(new Bundle {
val rw = Flipped(TLCached(para))
val uart = new UARTIO
})
val devAddrSpace = List(
(0x40600000L, 0x10L), // uart
(0x50000000L, 0x400000L), // vmem
(0x40001000L, 0x8L), // vga ctrl
(0x40000000L, 0x1000L), // flash
(0x40002000L, 0x1000L) // dummy sdcard
)
val xbar = Module(new NaiveTL1toN(devAddrSpace, io.rw.params))
xbar.io.in <> io.rw
val axiOut = xbar.io.out.map(tl => AXI4ToAXI4Lite(MMIOTLToAXI4(tl)))
val uart = Module(new AXI4UART)
val vga = Module(new AXI4VGA(sim = true))
val flash = Module(new AXI4Flash)
val sd = Module(new AXI4DummySD)
uart.io.in <> axiOut(0)
vga.io.in.fb <> axiOut(1)
vga.io.in.ctrl <> axiOut(2)
flash.io.in <> axiOut(3)
sd.io.in <> axiOut(4)
vga.io.vga := DontCare
io.uart <> uart.io.extra.get
} }
//class SimMMIO(para: TLParameters) extends Module {
// val io = IO(new Bundle {
// val rw = Flipped(TLCached(para))
// val uart = new UARTIO
// })
//
// val devAddrSpace = List(
// (0x40600000L, 0x10L), // uart
// (0x50000000L, 0x400000L), // vmem
// (0x40001000L, 0x8L), // vga ctrl
// (0x40000000L, 0x1000L), // flash
// (0x40002000L, 0x1000L) // dummy sdcard
// )
//
// val xbar = Module(new NaiveTL1toN(devAddrSpace, io.rw.params))
// xbar.io.in <> io.rw
//
// val axiOut = xbar.io.out.map(tl => AXI4ToAXI4Lite(MMIOTLToAXI4(tl)))
//
// val uart = Module(new AXI4UART)
// val vga = Module(new AXI4VGA(sim = true))
// val flash = Module(new AXI4Flash)
// val sd = Module(new AXI4DummySD)
//
// uart.io.in <> axiOut(0)
// vga.io.in.fb <> axiOut(1)
// vga.io.in.ctrl <> axiOut(2)
// flash.io.in <> axiOut(3)
// sd.io.in <> axiOut(4)
// vga.io.vga := DontCare
// io.uart <> uart.io.extra.get
//}
...@@ -4,10 +4,12 @@ import system._ ...@@ -4,10 +4,12 @@ import system._
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import chisel3.util.experimental.BoringUtils import chisel3.util.experimental.BoringUtils
import bus.axi4._ import chipsalliance.rocketchip.config
import bus.tilelink.FakeTLLLC
import chisel3.stage.ChiselGeneratorAnnotation import chisel3.stage.ChiselGeneratorAnnotation
import device._ import device._
import freechips.rocketchip.amba.axi4.{AXI4Fragmenter, AXI4UserYanker}
import freechips.rocketchip.diplomacy.{AddressSet, BufferParams, LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink.{TLBuffer, TLCacheCork, TLFragmenter, TLFuzzer, TLToAXI4, TLXbar}
import xiangshan._ import xiangshan._
import utils._ import utils._
import firrtl.stage.RunFirrtlTransformAnnotation import firrtl.stage.RunFirrtlTransformAnnotation
...@@ -25,7 +27,7 @@ class DiffTestIO extends XSBundle { ...@@ -25,7 +27,7 @@ class DiffTestIO extends XSBundle {
val wpc = Output(Vec(CommitWidth, UInt(VAddrBits.W))) // set difftest width to 6 val wpc = Output(Vec(CommitWidth, UInt(VAddrBits.W))) // set difftest width to 6
val isRVC = Output(Bool()) val isRVC = Output(Bool())
val intrNO = Output(UInt(64.W)) val intrNO = Output(UInt(64.W))
val priviledgeMode = Output(UInt(2.W)) val priviledgeMode = Output(UInt(2.W))
val mstatus = Output(UInt(64.W)) val mstatus = Output(UInt(64.W))
val sstatus = Output(UInt(64.W)) val sstatus = Output(UInt(64.W))
...@@ -48,71 +50,82 @@ class TrapIO extends XSBundle { ...@@ -48,71 +50,82 @@ class TrapIO extends XSBundle {
val instrCnt = Output(UInt(XLEN.W)) val instrCnt = Output(UInt(XLEN.W))
} }
class XSSimTop extends XSModule {
val io = IO(new Bundle{ class XSSimTop()(implicit p: config.Parameters) extends LazyModule {
val difftest = new DiffTestIO
val logCtrl = new LogCtrlIO val memAddressSet = AddressSet(0x0L, 0xffffffffffL)
val trap = new TrapIO
val uart = new UARTIO val soc = LazyModule(new XSSoc())
}) val axiRam = LazyModule(new AXI4RAM(
memAddressSet,
val soc = Module(new XSSoc()) memByte = 128 * 1024 * 1024,
val mem = Module(new AXI4RAM(memByte = 128 * 1024 * 1024, useBlackBox = true)) useBlackBox = true
// Be careful with the commit checking of emu. ))
// A large delay will make emu incorrectly report getting stuck. val axiMMIO = LazyModule(new SimMMIO())
val memdelay = Module(new AXI4Delayer(0))
val mmio = Module(new SimMMIO(soc.io.mmio.params)) axiRam.node :=
val tlToAXI = Module(new FakeTLLLC(l1BusParams)) AXI4UserYanker() :=
TLToAXI4() :=
soc.io.frontend := DontCare TLBuffer(BufferParams.default) :=
TLFragmenter(8, 64, holdFirstDeny = true) :=
tlToAXI.io.in <> soc.io.mem TLCacheCork(sinkIds = 1) :=
memdelay.io.in <> tlToAXI.io.out DebugIdentityNode() :=
mem.io.in <> memdelay.io.out soc.mem
mmio.io.rw <> soc.io.mmio axiMMIO.axiBus :=
io.uart <> mmio.io.uart AXI4UserYanker() :=
TLToAXI4() :=
// soc.io.meip := Counter(true.B, 9973)._2 // use prime here to not overlapped by mtip TLFragmenter(8, 8) :=
soc.io.meip := false.B // use prime here to not overlapped by mtip soc.extDev
val difftest = WireInit(0.U.asTypeOf(new DiffTestIO)) lazy val module = new LazyModuleImp(this) {
BoringUtils.addSink(difftest.commit, "difftestCommit") val io = IO(new Bundle {
BoringUtils.addSink(difftest.thisPC, "difftestThisPC") val difftest = new DiffTestIO
BoringUtils.addSink(difftest.thisINST, "difftestThisINST") val logCtrl = new LogCtrlIO
BoringUtils.addSink(difftest.skip, "difftestSkip") val trap = new TrapIO
BoringUtils.addSink(difftest.isRVC, "difftestIsRVC") val uart = new UARTIO
BoringUtils.addSink(difftest.wen, "difftestWen") })
BoringUtils.addSink(difftest.wdata, "difftestWdata")
BoringUtils.addSink(difftest.wdst, "difftestWdst") io.uart <> axiMMIO.module.io.uart
BoringUtils.addSink(difftest.wpc, "difftestWpc") soc.module.io.meip := false.B
BoringUtils.addSink(difftest.intrNO, "difftestIntrNO")
BoringUtils.addSink(difftest.r, "difftestRegs") val difftest = WireInit(0.U.asTypeOf(new DiffTestIO))
BoringUtils.addSink(difftest.priviledgeMode, "difftestMode") BoringUtils.addSink(difftest.commit, "difftestCommit")
BoringUtils.addSink(difftest.mstatus, "difftestMstatus") BoringUtils.addSink(difftest.thisPC, "difftestThisPC")
BoringUtils.addSink(difftest.sstatus, "difftestSstatus") BoringUtils.addSink(difftest.thisINST, "difftestThisINST")
BoringUtils.addSink(difftest.mepc, "difftestMepc") BoringUtils.addSink(difftest.skip, "difftestSkip")
BoringUtils.addSink(difftest.sepc, "difftestSepc") BoringUtils.addSink(difftest.isRVC, "difftestIsRVC")
BoringUtils.addSink(difftest.mcause, "difftestMcause") BoringUtils.addSink(difftest.wen, "difftestWen")
BoringUtils.addSink(difftest.scause, "difftestScause") BoringUtils.addSink(difftest.wdata, "difftestWdata")
io.difftest := difftest BoringUtils.addSink(difftest.wdst, "difftestWdst")
BoringUtils.addSink(difftest.wpc, "difftestWpc")
val trap = WireInit(0.U.asTypeOf(new TrapIO)) BoringUtils.addSink(difftest.intrNO, "difftestIntrNO")
ExcitingUtils.addSink(trap.valid, "trapValid") BoringUtils.addSink(difftest.r, "difftestRegs")
ExcitingUtils.addSink(trap.code, "trapCode") BoringUtils.addSink(difftest.priviledgeMode, "difftestMode")
ExcitingUtils.addSink(trap.pc, "trapPC") BoringUtils.addSink(difftest.mstatus, "difftestMstatus")
ExcitingUtils.addSink(trap.cycleCnt, "trapCycleCnt") BoringUtils.addSink(difftest.sstatus, "difftestSstatus")
ExcitingUtils.addSink(trap.instrCnt, "trapInstrCnt") BoringUtils.addSink(difftest.mepc, "difftestMepc")
io.trap := trap BoringUtils.addSink(difftest.sepc, "difftestSepc")
BoringUtils.addSink(difftest.mcause, "difftestMcause")
val timer = GTimer() BoringUtils.addSink(difftest.scause, "difftestScause")
val logEnable = (timer >= io.logCtrl.log_begin) && (timer < io.logCtrl.log_end) io.difftest := difftest
ExcitingUtils.addSource(logEnable, "DISPLAY_LOG_ENABLE")
ExcitingUtils.addSource(timer, "logTimestamp") val trap = WireInit(0.U.asTypeOf(new TrapIO))
ExcitingUtils.addSink(trap.valid, "trapValid")
ExcitingUtils.fixConnections() ExcitingUtils.addSink(trap.code, "trapCode")
// Check and dispaly all source and sink connections ExcitingUtils.addSink(trap.pc, "trapPC")
ExcitingUtils.checkAndDisplay() ExcitingUtils.addSink(trap.cycleCnt, "trapCycleCnt")
ExcitingUtils.addSink(trap.instrCnt, "trapInstrCnt")
io.trap := trap
val timer = GTimer()
val logEnable = (timer >= io.logCtrl.log_begin) && (timer < io.logCtrl.log_end)
ExcitingUtils.addSource(logEnable, "DISPLAY_LOG_ENABLE")
ExcitingUtils.addSource(timer, "logTimestamp")
// Check and dispaly all source and sink connections
ExcitingUtils.checkAndDisplay()
}
} }
object TestMain extends App { object TestMain extends App {
...@@ -121,11 +134,12 @@ object TestMain extends App { ...@@ -121,11 +134,12 @@ object TestMain extends App {
if(args.contains("--disable-log")) Parameters.simParameters // sim only, disable log if(args.contains("--disable-log")) Parameters.simParameters // sim only, disable log
else Parameters.debugParameters // open log else Parameters.debugParameters // open log
) )
implicit val p = config.Parameters.empty
// generate verilog // generate verilog
(new chisel3.stage.ChiselStage).execute( (new chisel3.stage.ChiselStage).execute(
args.filterNot(_ == "--disable-log"), args.filterNot(_ == "--disable-log"),
Seq( Seq(
ChiselGeneratorAnnotation(() => new XSSimTop) ChiselGeneratorAnnotation(() => LazyModule(new XSSimTop).module)
// RunFirrtlTransformAnnotation(new ShowPrintTransform) // RunFirrtlTransformAnnotation(new ShowPrintTransform)
) )
) )
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册