1
0

Refactor package hierarchy and remove legacy bus protocol implementations (#845)

* Refactors package hierarchy.

Additionally:
  - Removes legacy ground tests and configs
  - Removes legacy bus protocol implementations
  - Removes NTiles
  - Adds devices package
  - Adds more functions to util package
This commit is contained in:
Henry Cook 2017-07-07 10:48:16 -07:00 committed by GitHub
parent c28c23150d
commit 4c595d175c
238 changed files with 1347 additions and 10978 deletions

View File

@ -84,7 +84,3 @@ jobs:
script: script:
- travis_wait 80 make emulator-ndebug -C regression SUITE=RocketSuiteA JVM_MEMORY=3G - travis_wait 80 make emulator-ndebug -C regression SUITE=RocketSuiteA JVM_MEMORY=3G
- travis_wait 80 make emulator-regression-tests -C regression SUITE=RocketSuiteA JVM_MEMORY=3G - travis_wait 80 make emulator-regression-tests -C regression SUITE=RocketSuiteA JVM_MEMORY=3G
- <<: *test
script:
- travis_wait 80 make emulator-ndebug -C regression SUITE=GroundtestSuite JVM_MEMORY=3G
- travis_wait 80 make emulator-regression-tests -C regression SUITE=GroundtestSuite JVM_MEMORY=3G

View File

@ -4,7 +4,7 @@ $(error Please set environment variable RISCV. Please take a look at README)
endif endif
MODEL ?= TestHarness MODEL ?= TestHarness
PROJECT ?= rocketchip PROJECT ?= freechips.rocketchip.chip
CFG_PROJECT ?= $(PROJECT) CFG_PROJECT ?= $(PROJECT)
CONFIG ?= DefaultConfig CONFIG ?= DefaultConfig
# TODO: For now must match rocketchip.Generator # TODO: For now must match rocketchip.Generator

View File

@ -154,13 +154,20 @@ Some of these packages provide Scala utilities for generator configuration,
while other contain the actual Chisel RTL generators themselves. while other contain the actual Chisel RTL generators themselves.
Here is a brief description of what can be found in each package: Here is a brief description of what can be found in each package:
* **amba**
This RTL package uses diplomacy to generate bus implementations of AMBA protocols, including AXI4, AHB-lite, and APB.
* **chip**
This top-level utility package invokes Chisel to elaborate a particular configuration of a coreplex,
along with the appropriate testing collateral.
* **config** * **config**
This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped
parameterization library. parameterization library.
* **coreplex** * **coreplex**
This RTL package generates a complete coreplex by gluing together a variety of other components, This RTL package generates a complete coreplex by gluing together a variety of components from other packages,
including tiled Rocket cores, an L1-to-L2 network, L2 coherence agents, and internal devices including: tiled Rocket cores, a system bus network, coherence agents, debug devices, interrupt handlers, externally-facing peripherals,
such as the debug unit and interrupt handlers. clock-crossers and converters from TileLink to external bus protocols (e.g. AXI or AHB).
* **devices**
This RTL package contains implementations for peripheral devices, including the Debug module and various TL slaves.
* **diplomacy** * **diplomacy**
This utility package extends Chisel by allowing for two-phase hardware elaboration, in which certain parameters This utility package extends Chisel by allowing for two-phase hardware elaboration, in which certain parameters
are dynamically negotiated between modules. are dynamically negotiated between modules.
@ -176,16 +183,13 @@ This RTL package generates the Rocket in-order pipelined core,
as well as the L1 instruction and data caches. as well as the L1 instruction and data caches.
This library is intended to be used by a chip generator that instantiates the This library is intended to be used by a chip generator that instantiates the
core within a memory system and connects it to the outside world. core within a memory system and connects it to the outside world.
* **uncore** * **tile**
This RTL package generates a variety of uncore logic and devices, such as This RTL package contains components that can be combined with cores to construct tiles, such as FPUs and accelerators.
such as the L2 coherence hub and Debug modules, as well as defining their interfaces and protocols. * **tilelink**
Contains implementations of both TileLink and AXI4. This RTL package uses diplomacy to generate bus implementations of the TileLink protocol. It also contains a variety
of adapters and protocol converters.
* **unittest** * **unittest**
This utility package contains a framework for generateing synthesizeable hardware testers of individual modules. This utility package contains a framework for generateing synthesizeable hardware testers of individual modules.
* **rocketchip**
This top-level RTL package instantiates a coreplex and drops in any additional
externally-facing peripheral devices. It also includes clock-crossers and converters
from TileLink to external bus protocols (e.g. AXI or AHB).
* **util** * **util**
This utility package provides a variety of common Scala and Chisel constructs that are re-used across This utility package provides a variety of common Scala and Chisel constructs that are re-used across
multiple other packages, multiple other packages,

View File

@ -42,31 +42,23 @@ $(error Set SUITE to the regression suite you want to run)
endif endif
ifeq ($(SUITE),RocketSuiteA) ifeq ($(SUITE),RocketSuiteA)
PROJECT=rocketchip PROJECT=freechips.rocketchip.chip
CONFIGS=DefaultConfig CONFIGS=DefaultConfig
endif endif
ifeq ($(SUITE),RocketSuiteB) ifeq ($(SUITE),RocketSuiteB)
PROJECT=rocketchip PROJECT=freechips.rocketchip.chip
CONFIGS=DefaultBufferlessConfig CONFIGS=DefaultBufferlessConfig
endif endif
ifeq ($(SUITE),RocketSuiteC) ifeq ($(SUITE),RocketSuiteC)
PROJECT=rocketchip PROJECT=freechips.rocketchip.chip
CONFIGS=DefaultL2Config TinyConfig CONFIGS=TinyConfig
endif
ifeq ($(SUITE),GroundtestSuite)
PROJECT=groundtest
CONFIGS=MemtestConfig MemtestBufferlessConfig MemtestStatelessConfig \
BroadcastRegressionTestConfig BufferlessRegressionTestConfig CacheRegressionTestConfig \
ComparatorConfig ComparatorBufferlessConfig ComparatorStatelessConfig
# FancyMemtestConfig takes too long to compile
endif endif
ifeq ($(SUITE),UnittestSuite) ifeq ($(SUITE),UnittestSuite)
PROJECT=unittest PROJECT=freechips.rocketchip.unittest
CONFIGS=UncoreUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig CONFIGS=AMBAUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig
endif endif
ifeq ($(SUITE), JtagDtmSuite) ifeq ($(SUITE), JtagDtmSuite)

View File

@ -1,9 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import util.GenericParameterizedBundle import freechips.rocketchip.util.GenericParameterizedBundle
abstract class AHBBundleBase(params: AHBBundleParameters) extends GenericParameterizedBundle(params) abstract class AHBBundleBase(params: AHBBundleParameters) extends GenericParameterizedBundle(params)

View File

@ -1,11 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.diplomacy._
import diplomacy._
object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBEdgeParameters, AHBBundle] object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBEdgeParameters, AHBBundle]
{ {

View File

@ -1,10 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.diplomacy._
import diplomacy._
import scala.math.max import scala.math.max
case class AHBSlaveParameters( case class AHBSlaveParameters(

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max} import scala.math.{min,max}
class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
@ -57,7 +59,7 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
d_taken := Bool(false) d_taken := Bool(false)
d_read := !ahb.hwrite d_read := !ahb.hwrite
d_index := ahb.haddr >> log2Ceil(beatBytes) d_index := ahb.haddr >> log2Ceil(beatBytes)
d_mask := uncore.tilelink2.maskGen(ahb.haddr, ahb.hsize, beatBytes) d_mask := MaskGen(ahb.haddr, ahb.hsize, beatBytes)
} }
out.ready := Bool(true) out.ready := Bool(true)
@ -77,10 +79,10 @@ object AHBRegisterNode
abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
{ {
val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable) val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
} }
case class AHBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AHBBundle])(implicit val p: Parameters) case class AHBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AHBBundle])(implicit val p: Parameters)
class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle
{ {

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.util._
class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, fuzzHreadyout: Boolean = false)(implicit p: Parameters) extends LazyModule class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, fuzzHreadyout: Boolean = false)(implicit p: Parameters) extends LazyModule
{ {
@ -35,7 +35,7 @@ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4
// The mask and address during the address phase // The mask and address during the address phase
val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ
val a_request = in.hready && in.hsel && a_access val a_request = in.hready && in.hsel && a_access
val a_mask = uncore.tilelink2.maskGen(in.haddr, in.hsize, beatBytes) val a_mask = MaskGen(in.haddr, in.hsize, beatBytes)
val a_address = Cat((mask zip (in.haddr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) val a_address = Cat((mask zip (in.haddr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse)
val a_write = in.hwrite val a_write = in.hwrite

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.devices.tilelink.TLTestRAM
import uncore.tilelink2._ import freechips.rocketchip.diplomacy._
import unittest._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.unittest._
class RRTest0(address: BigInt)(implicit p: Parameters) extends AHBRegisterRouter(address, 0, 32, 0, 4)( class RRTest0(address: BigInt)(implicit p: Parameters) extends AHBRegisterRouter(address, 0, 32, 0, 4)(
new AHBRegBundle((), _) with RRTest0Bundle)( new AHBRegBundle((), _) with RRTest0Bundle)(

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.MaskGen
case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)( case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)(
dFn = { case AHBMasterPortParameters(masters) => dFn = { case AHBMasterPortParameters(masters) =>
@ -108,7 +109,7 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule
out.a.bits.source := UInt(0) out.a.bits.source := UInt(0)
out.a.bits.address := d_addr out.a.bits.address := d_addr
out.a.bits.data := in.hwdata out.a.bits.data := in.hwdata
out.a.bits.mask := maskGen(d_addr, d_size, beatBytes) out.a.bits.mask := MaskGen(d_addr, d_size, beatBytes)
out.d.ready := d_recv // backpressure AccessAckData arriving faster than AHB beats out.d.ready := d_recv // backpressure AccessAckData arriving faster than AHB beats
in.hrdata := out.d.bits.data in.hrdata := out.d.bits.data

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.ahb package freechips.rocketchip.amba.ahb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import scala.math.{min,max} import scala.math.{min,max}
class AHBFanout()(implicit p: Parameters) extends LazyModule { class AHBFanout()(implicit p: Parameters) extends LazyModule {

View File

@ -1,9 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore package freechips.rocketchip.amba
import Chisel._ import Chisel._
import diplomacy._ import freechips.rocketchip.diplomacy.OutwardNodeHandle
package object ahb package object ahb
{ {

View File

@ -1,9 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import util.GenericParameterizedBundle import freechips.rocketchip.util.GenericParameterizedBundle
abstract class APBBundleBase(params: APBBundleParameters) extends GenericParameterizedBundle(params) abstract class APBBundleBase(params: APBBundleParameters) extends GenericParameterizedBundle(params)

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBEdgeParameters, APBBundle] object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBEdgeParameters, APBBundle]
{ {

View File

@ -1,10 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import scala.math.max import scala.math.max
case class APBSlaveParameters( case class APBSlaveParameters(

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.HeterogeneousBag
import scala.math.{min,max} import scala.math.{min,max}
class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
@ -61,10 +63,10 @@ object APBRegisterNode
abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
{ {
val node = APBRegisterNode(address, concurrency, beatBytes, undefZero, executable) val node = APBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
} }
case class APBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[APBBundle])(implicit val p: Parameters) case class APBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[APBBundle])(implicit val p: Parameters)
class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle
{ {

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.util._
class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,12 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import unittest._ import freechips.rocketchip.unittest._
class RRTest0(address: BigInt)(implicit p: Parameters) extends APBRegisterRouter(address, 0, 32, 0, 4)( class RRTest0(address: BigInt)(implicit p: Parameters) extends APBRegisterRouter(address, 0, 32, 0, 4)(
new APBRegBundle((), _) with RRTest0Bundle)( new APBRegBundle((), _) with RRTest0Bundle)(

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.apb package freechips.rocketchip.amba.apb
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import scala.math.{min,max} import scala.math.{min,max}
class APBFanout()(implicit p: Parameters) extends LazyModule { class APBFanout()(implicit p: Parameters) extends LazyModule {

View File

@ -1,9 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore package freechips.rocketchip.amba
import Chisel._ import Chisel._
import diplomacy._ import freechips.rocketchip.diplomacy.OutwardNodeHandle
package object apb package object apb
{ {

View File

@ -1,12 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import chisel3.util.IrrevocableIO import chisel3.util.IrrevocableIO
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import scala.math.{min,max} import scala.math.{min,max}
// pipe is only used if a queue has depth = 1 // pipe is only used if a queue has depth = 1

View File

@ -1,10 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.util.Irrevocable import chisel3.util.Irrevocable
import util.GenericParameterizedBundle import freechips.rocketchip.util.GenericParameterizedBundle
abstract class AXI4BundleBase(params: AXI4BundleParameters) extends GenericParameterizedBundle(params) abstract class AXI4BundleBase(params: AXI4BundleParameters) extends GenericParameterizedBundle(params)

View File

@ -1,14 +1,14 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import chisel3.util.IrrevocableIO import chisel3.util.IrrevocableIO
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.{leftOR, rightOR, UIntToOH1, OH1ToOH}
import scala.math.{min,max} import scala.math.{min,max}
import uncore.tilelink2.{leftOR, rightOR, UIntToOH1, OH1ToOH}
class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyModule class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,14 +1,14 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import chisel3.util.IrrevocableIO import chisel3.util.IrrevocableIO
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.{leftOR, rightOR, UIntToOH1, OH1ToOH}
import scala.math.{min,max} import scala.math.{min,max}
import uncore.tilelink2.{leftOR, rightOR, UIntToOH1, OH1ToOH}
class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import scala.math.{min,max} import scala.math.{min,max}
class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle] object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle]
{ {

View File

@ -1,10 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import scala.math.max import scala.math.max
case class AXI4SlaveParameters( case class AXI4SlaveParameters(

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.util.{Irrevocable, IrrevocableIO} import chisel3.util.{Irrevocable, IrrevocableIO}

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max} import scala.math.{min,max}
class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
@ -43,7 +45,7 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
val aw_extra = Cat(Seq(aw.bits.id) ++ aw.bits.user.toList) val aw_extra = Cat(Seq(aw.bits.id) ++ aw.bits.user.toList)
val in_extra = Mux(ar.valid, ar_extra, aw_extra) val in_extra = Mux(ar.valid, ar_extra, aw_extra)
val addr = Mux(ar.valid, ar.bits.addr, aw.bits.addr) val addr = Mux(ar.valid, ar.bits.addr, aw.bits.addr)
val mask = uncore.tilelink2.maskGen(ar.bits.addr, ar.bits.size, beatBytes) val mask = MaskGen(ar.bits.addr, ar.bits.size, beatBytes)
in.bits.read := ar.valid in.bits.read := ar.valid
in.bits.index := addr >> log2Ceil(beatBytes) in.bits.index := addr >> log2Ceil(beatBytes)
@ -87,10 +89,10 @@ object AXI4RegisterNode
abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
{ {
val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable) val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable)
val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
} }
case class AXI4RegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters) case class AXI4RegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters)
class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle
{ {

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.util._
class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.devices.tilelink.TLError
import uncore.tilelink2._ import freechips.rocketchip.diplomacy._
import unittest._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.unittest._
class RRTest0(address: BigInt)(implicit p: Parameters) extends AXI4RegisterRouter(address, 0, 32, 0, 4)( class RRTest0(address: BigInt)(implicit p: Parameters) extends AXI4RegisterRouter(address, 0, 32, 0, 4)(
new AXI4RegBundle((), _) with RRTest0Bundle)( new AXI4RegBundle((), _) with RRTest0Bundle)(

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)( case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)(
dFn = { case AXI4MasterPortParameters(masters, userBits) => dFn = { case AXI4MasterPortParameters(masters, userBits) =>

View File

@ -1,12 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.axi4 package freechips.rocketchip.amba.axi4
import Chisel._ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import uncore.tilelink2.UIntToOH1 import freechips.rocketchip.util.UIntToOH1
class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) extends LazyModule class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,9 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore package freechips.rocketchip.amba
import Chisel._ import Chisel._
import diplomacy._ import freechips.rocketchip.diplomacy.OutwardNodeHandle
package object axi4 package object axi4
{ {

View File

@ -1,24 +1,24 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import junctions._
import rocket._ import freechips.rocketchip.config._
import diplomacy._ import freechips.rocketchip.coreplex._
import uncore.agents._ import freechips.rocketchip.devices._
import uncore.tilelink2._ import freechips.rocketchip.diplomacy._
import uncore.devices._ import freechips.rocketchip.rocket._
import uncore.converters._ import freechips.rocketchip.tile.XLen
import util._ import freechips.rocketchip.tilelink._
import coreplex._ import freechips.rocketchip.util._
import scala.math.max import scala.math.max
import scala.collection.mutable.{LinkedHashSet, ListBuffer} import scala.collection.mutable.{LinkedHashSet, ListBuffer}
import scala.collection.immutable.HashMap import scala.collection.immutable.HashMap
import DefaultTestSuites._ import DefaultTestSuites._
import config._
import tile.XLen
class BasePlatformConfig extends Config((site, here, up) => { class BasePlatformConfig extends Config((site, here, up) => {
// DTS descriptive parameters // DTS descriptive parameters
@ -49,33 +49,23 @@ class BasePlatformConfig extends Config((site, here, up) => {
class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig) class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig)
class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig) class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig)
class DefaultL2Config extends Config(new WithL2Cache ++ new WithNBigCores(1) ++ new BaseConfig)
class DefaultBufferlessConfig extends Config( class DefaultBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new WithNBigCores(1) ++ new BaseConfig) new WithBufferlessBroadcastHub ++ new WithNBigCores(1) ++ new BaseConfig)
class FPGAConfig extends Config(Parameters.empty) class FPGAConfig extends Config(Parameters.empty)
class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig) class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig)
class DefaultL2FPGAConfig extends Config(
new WithL2Capacity(64) ++ new WithL2Cache ++ new DefaultFPGAConfig)
class DefaultSmallConfig extends Config(new WithNSmallCores(1) ++ new BaseConfig) class DefaultSmallConfig extends Config(new WithNSmallCores(1) ++ new BaseConfig)
class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig) class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig)
class DualBankConfig extends Config( class DualBankConfig extends Config(
new WithNBanksPerMemChannel(2) ++ new BaseConfig) new WithNBanksPerMemChannel(2) ++ new BaseConfig)
class DualBankL2Config extends Config(
new WithNBanksPerMemChannel(2) ++ new WithL2Cache ++ new BaseConfig)
class DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig) class DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig)
class DualChannelL2Config extends Config(
new WithNMemoryChannels(2) ++ new WithL2Cache ++ new BaseConfig)
class DualChannelDualBankConfig extends Config( class DualChannelDualBankConfig extends Config(
new WithNMemoryChannels(2) ++ new WithNMemoryChannels(2) ++
new WithNBanksPerMemChannel(2) ++ new BaseConfig) new WithNBanksPerMemChannel(2) ++ new BaseConfig)
class DualChannelDualBankL2Config extends Config(
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++
new WithL2Cache ++ new BaseConfig)
class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig) class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig)
@ -84,11 +74,7 @@ class Edge128BitConfig extends Config(
class Edge32BitConfig extends Config( class Edge32BitConfig extends Config(
new WithEdgeDataBits(32) ++ new BaseConfig) new WithEdgeDataBits(32) ++ new BaseConfig)
class SmallL2Config extends Config( class SingleChannelBenchmarkConfig extends Config(new DefaultConfig)
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
new WithL2Capacity(256) ++ new DefaultL2Config)
class SingleChannelBenchmarkConfig extends Config(new WithL2Capacity(256) ++ new DefaultL2Config)
class DualChannelBenchmarkConfig extends Config(new WithNMemoryChannels(2) ++ new SingleChannelBenchmarkConfig) class DualChannelBenchmarkConfig extends Config(new WithNMemoryChannels(2) ++ new SingleChannelBenchmarkConfig)
class QuadChannelBenchmarkConfig extends Config(new WithNMemoryChannels(4) ++ new SingleChannelBenchmarkConfig) class QuadChannelBenchmarkConfig extends Config(new WithNMemoryChannels(4) ++ new SingleChannelBenchmarkConfig)
class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ new SingleChannelBenchmarkConfig) class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ new SingleChannelBenchmarkConfig)
@ -96,9 +82,9 @@ class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ ne
class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig) class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig)
class DualCoreConfig extends Config( class DualCoreConfig extends Config(
new WithNBigCores(2) ++ new WithL2Cache ++ new BaseConfig) new WithNBigCores(2) ++ new BaseConfig)
class HeterogeneousDualCoreConfig extends Config( class HeterogeneousDualCoreConfig extends Config(
new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new WithL2Cache ++ new BaseConfig) new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new BaseConfig)
class TinyConfig extends Config( class TinyConfig extends Config(
new WithNMemoryChannels(0) ++ new WithNMemoryChannels(0) ++

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import util._
import config._ import freechips.rocketchip.config._
import jtag._ import freechips.rocketchip.devices.debug.{DMIConsts, DMIIO, DMIReq, DMIResp}
import uncore.devices.{DMIConsts, DMIIO, DMIReq, DMIResp} import freechips.rocketchip.jtag._
import freechips.rocketchip.util._
case object IncludeJtagDTM extends Field[Boolean] case object IncludeJtagDTM extends Field[Boolean]

View File

@ -1,11 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import config._
import junctions._ import freechips.rocketchip.config.Parameters
import rocketchip._
/** Example system with periphery devices (w/o coreplex) */ /** Example system with periphery devices (w/o coreplex) */
abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem

View File

@ -1,14 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import tile.XLen import freechips.rocketchip.coreplex.RocketTilesKey
import coreplex.RocketTilesKey import freechips.rocketchip.tile.XLen
import freechips.rocketchip.util.GeneratorApp
import scala.collection.mutable.LinkedHashSet import scala.collection.mutable.LinkedHashSet
/** A Generator for platforms containing Rocket Coreplexes */ /** A Generator for platforms containing Rocket Coreplexes */
object Generator extends util.GeneratorApp { object Generator extends GeneratorApp {
val rv64RegrTestNames = LinkedHashSet( val rv64RegrTestNames = LinkedHashSet(
"rv64ud-v-fcvt", "rv64ud-v-fcvt",

View File

@ -1,14 +1,17 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import config._
import coreplex._ import freechips.rocketchip.config._
import diplomacy._ import freechips.rocketchip.coreplex._
import uncore.tilelink2._ import freechips.rocketchip.devices.tilelink._
import uncore.axi4._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.util._
import scala.math.{min,max} import scala.math.{min,max}
/** Specifies the size of external memory */ /** Specifies the size of external memory */
@ -42,7 +45,7 @@ trait HasPeripheryParameters {
def socBusBytes = socBusConfig.beatBytes def socBusBytes = socBusConfig.beatBytes
def cacheBlockBytes = p(CacheBlockBytes) def cacheBlockBytes = p(CacheBlockBytes)
def peripheryBusArithmetic = p(PeripheryBusArithmetic) def peripheryBusArithmetic = p(PeripheryBusArithmetic)
def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels def nMemoryChannels = p(BankedL2Config).nMemoryChannels
def nExtInterrupts = p(NExtTopInterrupts) def nExtInterrupts = p(NExtTopInterrupts)
} }

View File

@ -1,15 +1,17 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import config._
import coreplex._ import freechips.rocketchip.config._
import diplomacy._ import freechips.rocketchip.devices.debug._
import jtag.JTAGIO import freechips.rocketchip.devices.tilelink._
import uncore.tilelink2._ import freechips.rocketchip.coreplex._
import uncore.devices._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.jtag.JTAGIO
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
/** All the traits defined in this file assume that they are being mixed in /** All the traits defined in this file assume that they are being mixed in
* to a system that has a standard RISCV-based coreplex platform. * to a system that has a standard RISCV-based coreplex platform.
@ -89,7 +91,7 @@ trait HasPeripheryRTCCounter extends HasSystemNetworks with HasCoreplexRISCVPlat
trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp { trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp {
val outer: HasPeripheryRTCCounter val outer: HasPeripheryRTCCounter
val period = p(rocketchip.RTCPeriod) val period = p(RTCPeriod)
val rtcCounter = RegInit(UInt(0, width = log2Up(period))) val rtcCounter = RegInit(UInt(0, width = log2Up(period)))
val rtcWrap = rtcCounter === UInt(period-1) val rtcWrap = rtcCounter === UInt(period-1)

View File

@ -1,10 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import coreplex.RocketPlex
import diplomacy.{LazyModule, LazyMultiIOModuleImp} import freechips.rocketchip.coreplex.RocketPlex
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
/** Add a RocketPlex to the system */ /** Add a RocketPlex to the system */
trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform { trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform {

View File

@ -1,9 +1,8 @@
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._
import scala.collection.mutable.LinkedHashSet import scala.collection.mutable.LinkedHashSet
abstract class RocketTestSuite { abstract class RocketTestSuite {

View File

@ -1,11 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import config.Parameters
import diplomacy._ import freechips.rocketchip.config.Parameters
import util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
import freechips.rocketchip.util.ElaborationArtefacts
/** BareSystem is the root class for creating a top-level RTL module */ /** BareSystem is the root class for creating a top-level RTL module */
abstract class BareSystem(implicit p: Parameters) extends LazyModule { abstract class BareSystem(implicit p: Parameters) extends LazyModule {

View File

@ -1,14 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import Chisel._ import Chisel._
import config._
import junctions._ import freechips.rocketchip.amba.axi4._
import diplomacy._ import freechips.rocketchip.config.Parameters
import coreplex._ import freechips.rocketchip.coreplex._
import uncore.axi4._ import freechips.rocketchip.devices.debug._
import jtag.JTAGIO import freechips.rocketchip.diplomacy._
import freechips.rocketchip.jtag.JTAGIO
class TestHarness()(implicit p: Parameters) extends Module { class TestHarness()(implicit p: Parameters) extends Module {
val io = new Bundle { val io = new Bundle {
@ -52,11 +53,11 @@ class SimDTM(implicit p: Parameters) extends BlackBox {
val io = new Bundle { val io = new Bundle {
val clk = Clock(INPUT) val clk = Clock(INPUT)
val reset = Bool(INPUT) val reset = Bool(INPUT)
val debug = new uncore.devices.DMIIO val debug = new DMIIO
val exit = UInt(OUTPUT, 32) val exit = UInt(OUTPUT, 32)
} }
def connect(tbclk: Clock, tbreset: Bool, dutio: uncore.devices.ClockedDMIIO, tbsuccess: Bool) = { def connect(tbclk: Clock, tbreset: Bool, dutio: ClockedDMIIO, tbsuccess: Bool) = {
io.clk := tbclk io.clk := tbclk
io.reset := tbreset io.reset := tbreset
dutio.dmi <> io.debug dutio.dmi <> io.debug

View File

@ -1,18 +1,13 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocketchip package freechips.rocketchip.chip
import config._
import junctions._
import diplomacy._
import uncore.devices._
import tile.XLen
import coreplex._
import uncore.tilelink2._
import util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.DTB
import freechips.rocketchip.coreplex.BootROMFile
import java.nio.file.{Files, Paths} import java.nio.file.{Files, Paths}
import java.nio.{ByteBuffer, ByteOrder} import java.nio.{ByteBuffer, ByteOrder}
import scala.collection.mutable.ArrayBuffer
class RangeManager { class RangeManager {
private var finalized = false private var finalized = false
@ -39,7 +34,7 @@ class RangeManager {
class ResourceManager[T] { class ResourceManager[T] {
private var finalized = false private var finalized = false
private val l = collection.mutable.ArrayBuffer[T]() private val l = ArrayBuffer[T]()
def add(element: T) = { require(!finalized); l += element } def add(element: T) = { require(!finalized); l += element }
def add(list: Seq[T]) = { require(!finalized); l ++= list } def add(list: Seq[T]) = { require(!finalized); l ++= list }
def get: Seq[T] = { finalized = true; l } def get: Seq[T] = { finalized = true; l }

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package config package freechips.rocketchip.config
class Field[T] class Field[T]

View File

@ -1,14 +1,14 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config._
import diplomacy._ import freechips.rocketchip.config._
import tile.XLen import freechips.rocketchip.diplomacy._
import tile.TileInterrupts import freechips.rocketchip.tile.{ XLen, TileInterrupts}
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import util._ import freechips.rocketchip.util._
/** Widths of various points in the SoC */ /** Widths of various points in the SoC */
case class TLBusConfig(beatBytes: Int) case class TLBusConfig(beatBytes: Int)

View File

@ -1,18 +1,18 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config._
import diplomacy._ import freechips.rocketchip.config._
import rocket._ import freechips.rocketchip.devices.debug._
import tile._ import freechips.rocketchip.devices.tilelink._
import uncore.converters._ import freechips.rocketchip.diplomacy._
import uncore.devices._ import freechips.rocketchip.rocket._
import uncore.tilelink2._ import freechips.rocketchip.tile._
import uncore.util._ import freechips.rocketchip.tilelink._
import util._ import freechips.rocketchip.util._
class BaseCoreplexConfig extends Config ((site, here, up) => { class BaseCoreplexConfig extends Config ((site, here, up) => {
case PAddrBits => 32 case PAddrBits => 32
@ -20,14 +20,13 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
case ASIdBits => 0 case ASIdBits => 0
case XLen => 64 // Applies to all cores case XLen => 64 // Applies to all cores
case ResetVectorBits => site(PAddrBits) case ResetVectorBits => site(PAddrBits)
case MaxHartIdBits => log2Up(site(NTiles)) case MaxHartIdBits => log2Up(site(RocketTilesKey).size)
case BuildCore => (p: Parameters) => new Rocket()(p) case BuildCore => (p: Parameters) => new Rocket()(p)
case RocketCrossing => SynchronousCrossing() case RocketCrossing => SynchronousCrossing()
case RocketTilesKey => Nil case RocketTilesKey => Nil
case DMKey => DefaultDebugModuleConfig(site(XLen)) case DMKey => DefaultDebugModuleConfig(site(XLen))
case PLICKey => PLICParams() case PLICKey => PLICParams()
case ClintKey => ClintParams() case ClintKey => ClintParams()
case NTiles => site(RocketTilesKey).size
case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8) case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8)
case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth
case BootROMFile => "./bootrom/bootrom.img" case BootROMFile => "./bootrom/bootrom.img"
@ -112,10 +111,6 @@ class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => {
case CacheBlockBytes => linesize case CacheBlockBytes => linesize
}) })
class WithL2Cache extends Config(Parameters.empty) // TODO: re-add L2
class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty) // TODO: re-add L2
class WithNL2Ways(n: Int) extends Config(Parameters.empty) // TODO: re-add L2
class WithBufferlessBroadcastHub extends Config((site, here, up) => { class WithBufferlessBroadcastHub extends Config((site, here, up) => {
case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true) case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true)
}) })

View File

@ -1,13 +1,14 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config._
import diplomacy._ import freechips.rocketchip.config._
import uncore.tilelink2._ import freechips.rocketchip.diplomacy._
import uncore.util._ import freechips.rocketchip.rocket.PAddrBits
import util._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
trait CoreplexNetwork extends HasCoreplexParameters { trait CoreplexNetwork extends HasCoreplexParameters {
val module: CoreplexNetworkModule val module: CoreplexNetworkModule
@ -112,7 +113,7 @@ trait CoreplexNetworkModule extends HasCoreplexParameters {
val io: CoreplexNetworkBundle val io: CoreplexNetworkBundle
println("Generated Address Map") println("Generated Address Map")
private val aw = (outer.p(rocket.PAddrBits)-1)/4 + 1 private val aw = (outer.p(PAddrBits)-1)/4 + 1
private val fmt = s"\t%${aw}x - %${aw}x %c%c%c%c %s" private val fmt = s"\t%${aw}x - %${aw}x %c%c%c%c %s"
private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = { private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = {

View File

@ -1,14 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.diplomacy.LazyModule
import diplomacy._ import freechips.rocketchip.tilelink._
import rocket._
import tile._
import uncore.tilelink2._
import util._
trait HasISPPort extends CoreplexNetwork { trait HasISPPort extends CoreplexNetwork {
val module: HasISPPortModule val module: HasISPPortModule

View File

@ -1,17 +1,17 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config.Field
import diplomacy._
import tile._
import uncore.tilelink2._
import uncore.devices._
import util._
/** Number of tiles */ import freechips.rocketchip.config.Field
case object NTiles extends Field[Int] import freechips.rocketchip.devices.debug._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tile._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
case object PLICKey extends Field[PLICParams] case object PLICKey extends Field[PLICParams]
case object ClintKey extends Field[ClintParams] case object ClintKey extends Field[ClintParams]

View File

@ -1,9 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config.Parameters
import freechips.rocketchip.config.Parameters
class RocketPlex(implicit p: Parameters) extends BaseCoreplex class RocketPlex(implicit p: Parameters) extends BaseCoreplex
with CoreplexRISCVPlatform with CoreplexRISCVPlatform

View File

@ -1,22 +1,22 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package coreplex package freechips.rocketchip.coreplex
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Field
import diplomacy._ import freechips.rocketchip.diplomacy._
import rocket._ import freechips.rocketchip.rocket._
import tile._ import freechips.rocketchip.tile._
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import util._ import freechips.rocketchip.util._
sealed trait ClockCrossing sealed trait CoreplexClockCrossing
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossing case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends CoreplexClockCrossing
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends ClockCrossing case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing
case class AsynchronousCrossing(depth: Int, sync: Int = 2) extends ClockCrossing case class AsynchronousCrossing(depth: Int, sync: Int = 2) extends CoreplexClockCrossing
case object RocketTilesKey extends Field[Seq[RocketTileParams]] case object RocketTilesKey extends Field[Seq[RocketTileParams]]
case object RocketCrossing extends Field[ClockCrossing] case object RocketCrossing extends Field[CoreplexClockCrossing]
trait HasRocketTiles extends CoreplexRISCVPlatform { trait HasRocketTiles extends CoreplexRISCVPlatform {
val module: HasRocketTilesModule val module: HasRocketTilesModule

View File

@ -1,16 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.devices package freechips.rocketchip.devices.debug
import Chisel._ import Chisel._
import junctions._ import freechips.rocketchip.config._
import util._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import tile.XLen import freechips.rocketchip.rocket.Instructions
import uncore.tilelink2._ import freechips.rocketchip.tile.XLen
import config._ import freechips.rocketchip.tilelink._
import diplomacy._ import freechips.rocketchip.util._
/** Constant values used by both Debug Bus Response & Request /** Constant values used by both Debug Bus Response & Request
*/ */
@ -756,7 +755,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
val goReg = Reg(Bool()) val goReg = Reg(Bool())
val goAbstract = Wire(init = false.B) val goAbstract = Wire(init = false.B)
val jalAbstract = Wire(init = (new GeneratedUJ()).fromBits(rocket.Instructions.JAL.value.U)) val jalAbstract = Wire(init = (new GeneratedUJ()).fromBits(Instructions.JAL.value.U))
jalAbstract.setImm(ABSTRACT(cfg) - WHERETO) jalAbstract.setImm(ABSTRACT(cfg) - WHERETO)
when (~io.dmactive){ when (~io.dmactive){
@ -838,20 +837,20 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
val abstractGeneratedS = Wire(new GeneratedS()) val abstractGeneratedS = Wire(new GeneratedS())
val nop = Wire(new GeneratedI()) val nop = Wire(new GeneratedI())
abstractGeneratedI.opcode := ((new GeneratedI()).fromBits(rocket.Instructions.LW.value.U)).opcode abstractGeneratedI.opcode := ((new GeneratedI()).fromBits(Instructions.LW.value.U)).opcode
abstractGeneratedI.rd := (accessRegisterCommandReg.regno & 0x1F.U) abstractGeneratedI.rd := (accessRegisterCommandReg.regno & 0x1F.U)
abstractGeneratedI.funct3 := accessRegisterCommandReg.size abstractGeneratedI.funct3 := accessRegisterCommandReg.size
abstractGeneratedI.rs1 := 0.U abstractGeneratedI.rs1 := 0.U
abstractGeneratedI.imm := DATA.U abstractGeneratedI.imm := DATA.U
abstractGeneratedS.opcode := ((new GeneratedS()).fromBits(rocket.Instructions.SW.value.U)).opcode abstractGeneratedS.opcode := ((new GeneratedS()).fromBits(Instructions.SW.value.U)).opcode
abstractGeneratedS.immlo := (DATA & 0x1F).U abstractGeneratedS.immlo := (DATA & 0x1F).U
abstractGeneratedS.funct3 := accessRegisterCommandReg.size abstractGeneratedS.funct3 := accessRegisterCommandReg.size
abstractGeneratedS.rs1 := 0.U abstractGeneratedS.rs1 := 0.U
abstractGeneratedS.rs2 := (accessRegisterCommandReg.regno & 0x1F.U) abstractGeneratedS.rs2 := (accessRegisterCommandReg.regno & 0x1F.U)
abstractGeneratedS.immhi := (DATA >> 5).U abstractGeneratedS.immhi := (DATA >> 5).U
nop := ((new GeneratedI()).fromBits(rocket.Instructions.ADDI.value.U)) nop := ((new GeneratedI()).fromBits(Instructions.ADDI.value.U))
nop.rd := 0.U nop.rd := 0.U
nop.rs1 := 0.U nop.rs1 := 0.U
nop.imm := 0.U nop.imm := 0.U
@ -867,7 +866,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
) )
abstractGeneratedMem(1) := Mux(accessRegisterCommandReg.postexec, abstractGeneratedMem(1) := Mux(accessRegisterCommandReg.postexec,
nop.asUInt(), nop.asUInt(),
rocket.Instructions.EBREAK.value.U) Instructions.EBREAK.value.U)
} }
//-------------------------------------------------------------- //--------------------------------------------------------------

View File

@ -1,6 +1,6 @@
// This file was auto-generated by 'make publish' in debug/ directory. // This file was auto-generated by 'make publish' in debug/ directory.
package uncore.devices package freechips.rocketchip.devices.debug
object DebugRomContents { object DebugRomContents {

View File

@ -1,4 +1,4 @@
package uncore.devices package freechips.rocketchip.devices.debug
import Chisel._ import Chisel._

View File

@ -1,4 +1,4 @@
package uncore.devices package freechips.rocketchip.devices.debug
import Chisel._ import Chisel._

View File

@ -1,18 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.devices package freechips.rocketchip.devices.tilelink
import Chisel._ import Chisel._
import junctions._ import freechips.rocketchip.config.Parameters
import junctions.NastiConstants._ import freechips.rocketchip.diplomacy._
import regmapper._ import freechips.rocketchip.regmapper._
import diplomacy._ import freechips.rocketchip.tile.XLen
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import uncore.util._ import freechips.rocketchip.util._
import util._
import scala.math.{min,max} import scala.math.{min,max}
import config._
import tile.XLen
object ClintConsts object ClintConsts
{ {

View File

@ -1,11 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.tilelink2 package freechips.rocketchip.devices.tilelink
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,18 +1,16 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.devices package freechips.rocketchip.devices.tilelink
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import freechips.rocketchip.config.Parameters
import junctions._ import freechips.rocketchip.diplomacy._
import diplomacy._ import freechips.rocketchip.regmapper._
import regmapper._ import freechips.rocketchip.tile.XLen
import uncore.tilelink2._ import freechips.rocketchip.tilelink._
import config._ import freechips.rocketchip.util._
import scala.math.min import scala.math.min
import tile.XLen
import util._
class GatewayPLICIO extends Bundle { class GatewayPLICIO extends Bundle {
val valid = Bool(OUTPUT) val valid = Bool(OUTPUT)

View File

@ -0,0 +1,52 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package freechips.rocketchip.devices.tilelink
import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4,
resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule
{
val node = TLManagerNode(beatBytes, TLManagerParameters (
address = List(AddressSet(base, size-1)),
resources = resources,
regionType = RegionType.UNCACHED,
executable = executable,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val contents = contentsDelayed
val wrapSize = 1 << log2Ceil(contents.size)
require (wrapSize <= size)
val in = io.in(0)
val edge = node.edgesIn(0)
val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq
val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8})
val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes)))
in.d.valid := in.a.valid
in.a.ready := in.d.ready
val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes))
val high = if (wrapSize == size) UInt(0) else in.a.bits.address(log2Ceil(size)-1, log2Ceil(wrapSize))
in.d.bits := edge.AccessAck(in.a.bits, UInt(0), Mux(high.orR, UInt(0), rom(index)))
// Tie off unused channels
in.b.valid := Bool(false)
in.c.ready := Bool(true)
in.e.ready := Bool(true)
}
}

View File

@ -1,11 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.tilelink2 package freechips.rocketchip.devices.tilelink
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import util._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
// Do not use this for synthesis! Only for simulation. // Do not use this for synthesis! Only for simulation.
class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
@ -63,7 +64,7 @@ class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int
} }
/** Synthesizeable unit testing */ /** Synthesizeable unit testing */
import unittest._ import freechips.rocketchip.unittest._
class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule { class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule {
val fuzz = LazyModule(new TLFuzzer(txns)) val fuzz = LazyModule(new TLFuzzer(txns))

View File

@ -1,10 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package uncore.tilelink2 package freechips.rocketchip.devices.tilelink
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config.Parameters
import diplomacy._ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
{ {

View File

@ -1,8 +1,8 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import Chisel.log2Ceil
import scala.math.{max,min} import scala.math.{max,min}
object AddressDecoder object AddressDecoder

View File

@ -1,9 +1,8 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import freechips.rocketchip.config.Field
import config._
import sys.process._ import sys.process._
import java.io.{ByteArrayInputStream, ByteArrayOutputStream} import java.io.{ByteArrayInputStream, ByteArrayOutputStream}

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import scala.collection.immutable.SortedMap import scala.collection.immutable.SortedMap

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import Chisel._
import config._
import chisel3.experimental.{BaseModule, RawModule, MultiIOModule} import chisel3.experimental.{BaseModule, RawModule, MultiIOModule}
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
import freechips.rocketchip.config.Parameters
abstract class LazyModule()(implicit val p: Parameters) abstract class LazyModule()(implicit val p: Parameters)
{ {

View File

@ -1,10 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
import config._ import freechips.rocketchip.config.Parameters
abstract class MonitorBase(implicit sourceInfo: SourceInfo, p: Parameters) extends LazyModule()(p) { abstract class MonitorBase(implicit sourceInfo: SourceInfo, p: Parameters) extends LazyModule()(p) {
override val module: LazyModuleImp override val module: LazyModuleImp

View File

@ -1,12 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import Chisel._
import config._
import util.HeterogeneousBag
import scala.collection.mutable.ListBuffer
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.util.HeterogeneousBag
import scala.collection.mutable.ListBuffer
// DI = Downwards flowing Parameters received on the inner side of the node // DI = Downwards flowing Parameters received on the inner side of the node
// UI = Upwards flowing Parameters generated by the inner side of the node // UI = Upwards flowing Parameters generated by the inner side of the node

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import Chisel._

View File

@ -1,9 +1,8 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package diplomacy package freechips.rocketchip.diplomacy
import Chisel._ import Chisel.log2Ceil
import config._
import scala.collection.immutable.{ListMap,SortedMap} import scala.collection.immutable.{ListMap,SortedMap}
sealed trait ResourceValue sealed trait ResourceValue

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
import Chisel._ package freechips.rocketchip
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
package object diplomacy package object diplomacy

View File

@ -1,116 +0,0 @@
// See LICENSE.SiFive for license details.
package groundtest
import Chisel._
import uncore.tilelink._
import uncore.agents._
import uncore.coherence.{InnerTLId, OuterTLId}
import util._
import rocketchip._
import config._
/**
* An example bus mastering devices that writes some preset data to memory.
* When it receives an MMIO put request, it starts writing out the data.
* When it receives an MMIO get request, it responds with the progress of
* the write. A grant data of 1 means it is still writing, grant data 0
* means it has finished.
*/
class ExampleBusMaster(implicit val p: Parameters) extends Module
with HasTileLinkParameters {
val mmioParams = p.alterPartial({ case TLId => p(InnerTLId) })
val memParams = p.alterPartial({ case TLId => p(OuterTLId) })
val memStart = p(ExtMem).base
val memStartBlock = memStart >> p(CacheBlockOffsetBits)
val io = new Bundle {
val mmio = new ClientUncachedTileLinkIO()(mmioParams).flip
val mem = new ClientUncachedTileLinkIO()(memParams)
}
val s_idle :: s_put :: s_resp :: Nil = Enum(Bits(), 3)
val state = Reg(init = s_idle)
val send_resp = Reg(init = Bool(false))
val r_acq = Reg(new AcquireMetadata)
io.mmio.acquire.ready := !send_resp
io.mmio.grant.valid := send_resp
io.mmio.grant.bits := Grant(
is_builtin_type = Bool(true),
g_type = r_acq.getBuiltInGrantType(),
client_xact_id = r_acq.client_xact_id,
manager_xact_id = UInt(0),
addr_beat = r_acq.addr_beat,
data = Mux(state === s_idle, UInt(0), UInt(1)))
when (io.mmio.acquire.fire()) {
send_resp := Bool(true)
r_acq := io.mmio.acquire.bits
when (state === s_idle && io.mmio.acquire.bits.hasData()) { state := s_put }
}
when (io.mmio.grant.fire()) { send_resp := Bool(false) }
val (put_beat, put_done) = Counter(io.mem.acquire.fire(), tlDataBeats)
when (put_done) { state := s_resp }
when (io.mem.grant.fire()) { state := s_idle }
io.mem.acquire.valid := state === s_put
io.mem.acquire.bits := PutBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock),
addr_beat = put_beat,
data = put_beat)
io.mem.grant.ready := state === s_resp
}
class BusMasterTest(implicit p: Parameters) extends GroundTest()(p)
with HasTileLinkParameters {
val (s_idle :: s_req_start :: s_resp_start :: s_req_poll :: s_resp_poll ::
s_req_check :: s_resp_check :: s_done :: Nil) = Enum(Bits(), 8)
val state = Reg(init = s_idle)
val busMasterBlock = p(ExtBus).base >> p(CacheBlockOffsetBits)
val start_acq = Put(
client_xact_id = UInt(0),
addr_block = UInt(busMasterBlock),
addr_beat = UInt(0),
data = UInt(1))
val poll_acq = Get(
client_xact_id = UInt(0),
addr_block = UInt(busMasterBlock),
addr_beat = UInt(0))
val check_acq = GetBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock))
val acq = io.mem.head.acquire
val gnt = io.mem.head.grant
acq.valid := state.isOneOf(s_req_start, s_req_poll, s_req_check)
acq.bits := MuxLookup(state, check_acq, Seq(
s_req_start -> start_acq,
s_req_poll -> poll_acq))
gnt.ready := state.isOneOf(s_resp_start, s_resp_poll, s_resp_check)
val (get_beat, get_done) = Counter(
state === s_resp_check && gnt.valid, tlDataBeats)
when (state === s_idle) { state := s_req_start }
when (state === s_req_start && acq.ready) { state := s_resp_start }
when (state === s_resp_start && gnt.valid) { state := s_req_poll }
when (state === s_req_poll && acq.ready) { state := s_resp_poll }
when (state === s_resp_poll && gnt.valid) {
when (gnt.bits.data === UInt(0)) {
state := s_req_check
} .otherwise { state := s_req_poll }
}
when (state === s_req_check && acq.ready) { state := s_resp_check }
when (get_done) { state := s_done }
io.status.finished := state === s_done
assert(state =/= s_resp_check || !gnt.valid ||
gnt.bits.data === get_beat,
"BusMasterTest: data does not match")
}

View File

@ -1,56 +0,0 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package groundtest
import Chisel._
import coreplex.CacheBlockBytes
import uncore.tilelink._
import uncore.constants._
import uncore.util._
import util._
import config._
class CacheFillTest(implicit p: Parameters) extends GroundTest()(p)
with HasTileLinkParameters {
//val l2Config = p(CacheName("L2"))
//val capacityKb = l2Config.nSets * l2Config.nWays * l2Config.rowBits / (1024*8)
val capacityKb = 1024 // TODO
val nblocks = capacityKb * 1024 / p(CacheBlockBytes)
val s_start :: s_prefetch :: s_retrieve :: s_finished :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_start)
val active = state.isOneOf(s_prefetch, s_retrieve)
val xact_pending = Reg(init = UInt(0, tlMaxClientXacts))
val xact_id = PriorityEncoder(~xact_pending)
val (req_block, round_done) = Counter(io.mem.head.acquire.fire(), nblocks)
io.mem.head.acquire.valid := active && !xact_pending.andR
io.mem.head.acquire.bits := Mux(state === s_prefetch,
GetPrefetch(xact_id, UInt(memStartBlock) + req_block),
GetBlock(xact_id, UInt(memStartBlock) + req_block))
io.mem.head.grant.ready := xact_pending.orR
def add_pending(acq: DecoupledIO[Acquire]): UInt =
Mux(acq.fire(), UIntToOH(acq.bits.client_xact_id), UInt(0))
def remove_pending(gnt: DecoupledIO[Grant]): UInt = {
val last_grant = !gnt.bits.hasMultibeatData() ||
gnt.bits.addr_beat === UInt(tlDataBeats - 1)
~Mux(gnt.fire() && last_grant, UIntToOH(gnt.bits.client_xact_id), UInt(0))
}
xact_pending := (xact_pending |
add_pending(io.mem.head.acquire)) &
remove_pending(io.mem.head.grant)
when (state === s_start) { state := s_prefetch }
when (state === s_prefetch && round_done) { state := s_retrieve }
when (state === s_retrieve && round_done) { state := s_finished }
io.status.finished := (state === s_finished)
io.status.timeout.valid := Bool(false)
io.status.error.valid := Bool(false)
}

View File

@ -1,394 +0,0 @@
// See LICENSE.SiFive for license details.
package groundtest
import Chisel._
import uncore.tilelink._
import uncore.constants._
import junctions._
import rocket._
import util.Timer
import scala.util.Random
import config._
import util._
case class ComparatorParameters(
targets: Seq[Long],
width: Int,
operations: Int,
atomics: Boolean,
prefetches: Boolean)
case object ComparatorKey extends Field[ComparatorParameters]
trait HasComparatorParameters {
implicit val p: Parameters
val comparatorParams = p(ComparatorKey)
val targets = comparatorParams.targets
val nTargets = targets.size
val targetWidth = comparatorParams.width
val nOperations = comparatorParams.operations
val atomics = comparatorParams.atomics
val prefetches = comparatorParams.prefetches
}
object LFSR64
{
private var counter = 0
private def next: Int = {
counter += 1
counter
}
def apply(increment: Bool = Bool(true), seed: Int = next): UInt =
{
val wide = 64
val lfsr = RegInit(UInt((seed * 0xDEADBEEFCAFEBAB1L) >>> 1, width = wide))
val xor = lfsr(0) ^ lfsr(1) ^ lfsr(3) ^ lfsr(4)
when (increment) { lfsr := Cat(xor, lfsr(wide-1,1)) }
lfsr
}
}
object NoiseMaker
{
def apply(wide: Int, increment: Bool = Bool(true)): UInt = {
val lfsrs = Seq.fill((wide+63)/64) { LFSR64(increment) }
Cat(lfsrs)(wide-1,0)
}
}
object MaskMaker
{
def apply(wide: Int, bits: UInt): UInt =
Vec.tabulate(wide) {UInt(_) < bits} .asUInt
}
class ComparatorSource(implicit val p: Parameters) extends Module
with HasComparatorParameters
with HasTileLinkParameters
{
val io = new Bundle {
val out = Decoupled(new Acquire)
val finished = Bool(OUTPUT)
}
// Output exactly nOperations of Acquires
val finished = RegInit(Bool(false))
val valid = RegInit(Bool(false))
valid := Bool(true)
io.finished := finished
io.out.valid := !finished && valid
// Generate random operand sizes
val inc = io.out.fire()
val raw_operand_size = NoiseMaker(2, inc) | UInt(0, M_SZ)
val max_operand_size = UInt(log2Up(tlDataBytes))
val get_operand_size = Mux(raw_operand_size > max_operand_size, max_operand_size, raw_operand_size)
val atomic_operand_size = UInt(2) + NoiseMaker(1, inc) // word or dword
// Generate random, but valid addr_bytes
val raw_addr_byte = NoiseMaker(tlByteAddrBits, inc)
val get_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, get_operand_size)
val atomic_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, atomic_operand_size)
// Only allow some of the possible choices (M_XA_MAXU untested)
val atomic_opcode = MuxLookup(NoiseMaker(3, inc), M_XA_SWAP, Array(
UInt("b000") -> M_XA_ADD,
UInt("b001") -> M_XA_XOR,
UInt("b010") -> M_XA_OR,
UInt("b011") -> M_XA_AND,
UInt("b100") -> M_XA_MIN,
UInt("b101") -> M_XA_MAX,
UInt("b110") -> M_XA_MINU,
UInt("b111") -> M_XA_SWAP))
// Addr_block range
val addr_block_mask = MaskMaker(tlBlockAddrBits, UInt(targetWidth-tlBeatAddrBits-tlByteAddrBits))
// Generate some random values
val addr_block = NoiseMaker(tlBlockAddrBits, inc) & addr_block_mask
val addr_beat = NoiseMaker(tlBeatAddrBits, inc)
val wmask = NoiseMaker(tlDataBytes, inc)
val data = NoiseMaker(tlDataBits, inc)
val client_xact_id = UInt(0) // filled by Client
// Random transactions
val get = Get(client_xact_id, addr_block, addr_beat, get_addr_byte, get_operand_size, Bool(false))
val getBlock = GetBlock(client_xact_id, addr_block)
val put = Put(client_xact_id, addr_block, addr_beat, data, Some(wmask))
val putBlock = PutBlock(client_xact_id, addr_block, UInt(0), data)
val putAtomic = if (atomics)
PutAtomic(client_xact_id, addr_block, addr_beat,
atomic_addr_byte, atomic_opcode, atomic_operand_size, data)
else put
val putPrefetch = if (prefetches)
PutPrefetch(client_xact_id, addr_block)
else put
val getPrefetch = if (prefetches)
GetPrefetch(client_xact_id, addr_block)
else get
val a_type_sel = NoiseMaker(3, inc)
// We must initially putBlock all of memory to have a consistent starting state
val final_addr_block = addr_block_mask + UInt(1)
val wipe_addr_block = RegInit(UInt(0, width = tlBlockAddrBits))
val done_wipe = wipe_addr_block === final_addr_block
io.out.bits := Mux(!done_wipe,
// Override whatever else we were going to do if we are wiping
PutBlock(client_xact_id, wipe_addr_block, UInt(0), data),
// Generate a random a_type
MuxLookup(a_type_sel, get, Array(
UInt("b000") -> get,
UInt("b001") -> getBlock,
UInt("b010") -> put,
UInt("b011") -> putBlock,
UInt("b100") -> putAtomic,
UInt("b101") -> getPrefetch,
UInt("b110") -> putPrefetch)))
val idx = Reg(init = UInt(0, log2Up(nOperations)))
when (io.out.fire()) {
when (idx === UInt(nOperations - 1)) { finished := Bool(true) }
when (!done_wipe) {
printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n",
idx, wipe_addr_block, data)
wipe_addr_block := wipe_addr_block + UInt(1)
} .otherwise {
switch (a_type_sel) {
is (UInt("b000")) {
printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n",
idx, addr_block, addr_beat, get_addr_byte, get_operand_size)
}
is (UInt("b001")) {
printf("[acq %d]: GetBlock(addr_block = %x)\n", idx, addr_block)
}
is (UInt("b010")) {
printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n",
idx, addr_block, addr_beat, data, wmask)
}
is (UInt("b011")) {
printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n", idx, addr_block, data)
}
is (UInt("b100")) {
if (atomics) {
printf("[acq %d]: PutAtomic(addr_block = %x, addr_beat = %x, addr_byte = %x, " +
"opcode = %x, op_size = %x, data = %x)\n",
idx, addr_block, addr_beat, atomic_addr_byte,
atomic_opcode, atomic_operand_size, data)
} else {
printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n",
idx, addr_block, addr_beat, data, wmask)
}
}
is (UInt("b101")) {
if (prefetches) {
printf("[acq %d]: GetPrefetch(addr_block = %x)\n", idx, addr_block)
} else {
printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n",
idx, addr_block, addr_beat, get_addr_byte, get_operand_size)
}
}
is (UInt("b110")) {
if (prefetches) {
printf("[acq %d]: PutPrefetch(addr_block = %x)\n", idx, addr_block)
} else {
printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n",
idx, addr_block, addr_beat, data, wmask)
}
}
is (UInt("b111")) {
printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n",
idx, addr_block, addr_beat, get_addr_byte, get_operand_size)
}
}
}
idx := idx + UInt(1)
}
}
class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Module
with HasComparatorParameters
with HasTileLinkParameters
{
val io = new Bundle {
val in = Decoupled(new Acquire).flip
val tl = new ClientUncachedTileLinkIO()
val out = Decoupled(new Grant)
val finished = Bool(OUTPUT)
val timeout = Bool(OUTPUT)
}
val xacts = tlMaxClientXacts
val offset = (UInt(target) >> UInt(tlBeatAddrBits+tlByteAddrBits))
// Track the status of inflight requests
val issued = RegInit(Vec.fill(xacts) {Bool(false)})
val ready = RegInit(Vec.fill(xacts) {Bool(false)})
val result = Reg(Vec(xacts, new Grant))
val buffer = Queue(io.in, xacts)
val queue = Module(new Queue(io.tl.acquire.bits.client_xact_id, xacts))
val isMultiOut = buffer.bits.hasMultibeatData()
val isMultiIn = io.tl.grant.bits.hasMultibeatData()
val beatOut = RegInit(UInt(0, width = tlBeatAddrBits))
val lastBeat = UInt(tlDataBeats-1)
val isFirstBeatOut= Mux(isMultiOut, beatOut === UInt(0), Bool(true))
val isLastBeatOut = Mux(isMultiOut, beatOut === lastBeat, Bool(true))
val isLastBeatIn = Mux(isMultiIn, io.tl.grant.bits.addr_beat === lastBeat, Bool(true))
// Potentially issue a request, using a free xact id
// NOTE: we may retract valid and change xact_id on a !ready (allowed by spec)
val allow_acq = NoiseMaker(1)(0) && issued.map(!_).reduce(_ || _)
val xact_id = PriorityEncoder(issued.map(!_)) holdUnless isFirstBeatOut
buffer.ready := allow_acq && io.tl.acquire.ready && isLastBeatOut
io.tl.acquire.valid := allow_acq && buffer.valid
io.tl.acquire.bits := buffer.bits
io.tl.acquire.bits.addr_block := buffer.bits.addr_block + offset
io.tl.acquire.bits.client_xact_id := xact_id
when (isMultiOut) {
val dataOut = (buffer.bits.data << beatOut) + buffer.bits.data // mix the data up a bit
io.tl.acquire.bits.addr_beat := beatOut
io.tl.acquire.bits.data := dataOut
}
when (io.tl.acquire.fire()) {
issued(xact_id) := isLastBeatOut
when (isMultiOut) { beatOut := beatOut + UInt(1) }
}
// Remember the xact ID so we can return results in-order
queue.io.enq.valid := io.tl.acquire.fire() && isLastBeatOut
queue.io.enq.bits := xact_id
assert (queue.io.enq.ready || !queue.io.enq.valid) // should be big enough
// Capture the results from the manager
io.tl.grant.ready := NoiseMaker(1)(0)
when (io.tl.grant.fire()) {
val id = io.tl.grant.bits.client_xact_id
assert (!ready(id)) // got same xact_id twice?
ready(id) := isLastBeatIn
result(id) := io.tl.grant.bits
}
// Bad xact_id returned if ready but not issued!
assert ((ready zip issued) map {case (r,i) => i || !r} reduce (_ && _))
// When we have the next grant result, send it to the sink
val next_id = queue.io.deq.bits
queue.io.deq.ready := io.out.ready && ready(next_id) // TODO: only compares last getBlock
io.out.valid := queue.io.deq.valid && ready(next_id)
io.out.bits := result(queue.io.deq.bits)
when (io.out.fire()) {
ready(next_id) := Bool(false)
issued(next_id) := Bool(false)
}
io.finished := !buffer.valid && !issued.reduce(_ || _)
val (idx, acq_done) = Counter(
io.tl.acquire.fire() && io.tl.acquire.bits.last(), nOperations)
val timer = Module(new Timer(8192, xacts))
timer.io.start.valid := io.tl.acquire.fire() && io.tl.acquire.bits.first()
timer.io.start.bits := xact_id
timer.io.stop.valid := io.tl.grant.fire() && io.tl.grant.bits.first()
timer.io.stop.bits := io.tl.grant.bits.client_xact_id
assert(!timer.io.timeout.valid, "Comparator TL client timed out")
io.timeout := timer.io.timeout.valid
}
class ComparatorSink(implicit val p: Parameters) extends Module
with HasComparatorParameters
with HasTileLinkParameters
with HasGroundTestConstants
{
val io = new Bundle {
val in = Vec(nTargets, Decoupled(new Grant)).flip
val finished = Bool(OUTPUT)
val error = Valid(UInt(width = errorCodeBits))
}
// could use a smaller Queue here, but would couple targets flow controls together
val queues = io.in.map(Queue(_, nOperations))
io.finished := queues.map(!_.valid).reduce(_ && _)
val all_valid = queues.map(_.valid).reduce(_ && _)
queues.foreach(_.ready := all_valid)
val base = queues(0).bits
val idx = Reg(init = UInt(0, log2Up(nOperations)))
def check(g: Grant) = {
when (g.hasData() && base.data =/= g.data) {
printf("%d: %x =/= %x, g_type = %x\n", idx, base.data, g.data, g.g_type)
}
val assert_conds = Seq(
g.is_builtin_type,
base.g_type === g.g_type,
base.addr_beat === g.addr_beat || !g.hasData(),
base.data === g.data || !g.hasData())
// TL1 likes to duplicate 32-bits into both halves of a 64-bit value
// TL2 doesn't do this, so they compare differently when they are the same
def isDupd(x: UInt) = if (tlDataBytes != 8) Bool(false) else x(31, 0) === x(63, 32)
def safeCompare(x: UInt, y: UInt) =
Mux(!isDupd(x) && !isDupd(y), x === y, x(63,32) === y(63,32) || x(31,0) === y(31,0))
assert (g.is_builtin_type, "grant not builtin")
assert (base.g_type === g.g_type, "g_type mismatch")
assert (base.addr_beat === g.addr_beat || !g.hasMultibeatData(), "addr_beat mismatch")
assert (base.data === g.data || !g.hasMultibeatData(), "multibeat data mismatch")
assert (safeCompare(base.data, g.data) || !g.hasData(), "singlebeat data mismatch")
assert_conds.zipWithIndex.foreach { case (cond, i) =>
when (!cond) {
io.error.valid := Bool(true)
io.error.bits := UInt(i)
}
}
}
when (all_valid) {
when (base.hasData()) {
printf("[gnt %d]: g_type = %x, addr_beat = %x, data = %x\n",
idx, base.g_type, base.addr_beat, base.data)
} .otherwise {
printf("[gnt %d]: g_type = %x\n", idx, base.g_type)
}
queues.drop(1).map(_.bits).foreach(check)
idx := idx + UInt(1)
}
}
class ComparatorCore(implicit p: Parameters) extends GroundTest()(p)
with HasComparatorParameters
with HasTileLinkParameters {
require (io.mem.size == nTargets)
val source = Module(new ComparatorSource)
val sink = Module(new ComparatorSink)
val broadcast = Broadcaster(source.io.out, nTargets)
val clients = targets.zipWithIndex.map { case (target, index) =>
val client = Module(new ComparatorClient(target))
client.io.in <> broadcast(index)
io.mem(index) <> client.io.tl
sink.io.in(index) <> client.io.out
client
}
val client_timeouts = clients.map(_.io.timeout)
io.status.finished := source.io.finished && sink.io.finished && clients.map(_.io.finished).reduce(_ && _)
io.status.timeout.valid := client_timeouts.reduce(_ || _)
io.status.timeout.bits := MuxCase(UInt(0),
client_timeouts.zipWithIndex.map {
case (timeout, i) => (timeout -> UInt(i))
})
io.status.error := sink.io.error
}

View File

@ -1,161 +1,40 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import rocket._ import freechips.rocketchip.chip.{BaseConfig, ExtMem}
import diplomacy._ import freechips.rocketchip.config.Config
import uncore.tilelink._ import freechips.rocketchip.coreplex.{CacheBlockBytes, L1toL2Config, WithBufferlessBroadcastHub}
import uncore.coherence._ import freechips.rocketchip.rocket.{DCacheParams, PAddrBits}
import uncore.agents._ import freechips.rocketchip.tile.{MaxHartIdBits, XLen}
import uncore.util._
import tile.TileKey
import junctions._
import config._
import coreplex._
import rocketchip._
/** Actual testing target Configs */ /** Actual testing target Configs */
class GroundTestConfig extends Config(new WithGroundTestTiles ++ new BaseConfig) class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseConfig)
class ComparatorConfig extends Config( class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig)
new WithComparator(1) ++ new GroundTestConfig)
class ComparatorL2Config extends Config(
new WithAtomics ++ new WithPrefetches ++
new WithL2Cache ++ new ComparatorConfig)
class ComparatorBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new ComparatorConfig)
class ComparatorStatelessConfig extends Config(
new WithStatelessBridge ++ new ComparatorConfig)
class MemtestConfig extends Config(new WithMemtest(1) ++ new GroundTestConfig)
class MemtestL2Config extends Config(
new WithL2Cache ++ new MemtestConfig)
class MemtestBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new MemtestConfig)
class MemtestStatelessConfig extends Config(
new WithStatelessBridge ++ new MemtestConfig)
// Test ALL the things
class FancyMemtestConfig extends Config(
new WithMemtest(2) ++
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
new WithL2Cache ++ new GroundTestConfig)
class CacheFillTestConfig extends Config(
new WithNL2Ways(4) ++ new WithL2Capacity(4) ++
new WithCacheFillTest(1) ++ new WithL2Cache ++ new GroundTestConfig)
class BroadcastRegressionTestConfig extends Config(
new WithBroadcastRegressionTest(1) ++ new GroundTestConfig)
class BufferlessRegressionTestConfig extends Config(
new WithBufferlessBroadcastHub ++ new BroadcastRegressionTestConfig)
class CacheRegressionTestConfig extends Config(
new WithCacheRegressionTest(1) ++ new WithL2Cache ++ new GroundTestConfig)
class TraceGenConfig extends Config(
new WithTraceGen(2) ++ new GroundTestConfig)
class TraceGenBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new TraceGenConfig)
class TraceGenL2Config extends Config(
new WithNL2Ways(1) ++ new WithL2Capacity(32 * 64 / 1024) ++
new WithL2Cache ++ new TraceGenConfig)
class Edge128BitComparatorConfig extends Config(
new WithEdgeDataBits(128) ++ new ComparatorConfig)
class Edge128BitMemtestConfig extends Config(
new WithEdgeDataBits(128) ++ new MemtestConfig)
class Edge32BitComparatorConfig extends Config(
new WithEdgeDataBits(32) ++ new ComparatorL2Config)
class Edge32BitMemtestConfig extends Config(
new WithEdgeDataBits(32) ++ new MemtestConfig)
/* Composable Configs to set individual parameters */ /* Composable Configs to set individual parameters */
class WithGroundTestTiles extends Config((site, here, up) => { class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) extends Config((site, here, up) => {
case TileKey => site(GroundTestKey).head case GroundTestTilesKey => params.map { dcp => TraceGenParams(
case NTiles => site(GroundTestKey).size dcache = Some(dcp),
}) wordBits = site(XLen),
addrBits = site(PAddrBits),
class WithComparator(n: Int) extends Config((site, here, up) => { addrBag = {
case GroundTestKey => Seq.fill(n) { val nSets = 2
GroundTestTileParams(uncached = 2, dcache = None) val nWays = 1
} val blockOffset = log2Up(site(CacheBlockBytes))
case BuildGroundTest => val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes
(p: Parameters) => Module(new ComparatorCore()(p)) List.tabulate(4 * nWays) { i =>
case ComparatorKey => ComparatorParameters( Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
targets = Seq(site(ExtMem).base, testRamAddr), }.flatten
width = 8, },
operations = 1000, maxRequests = nReqs,
atomics = false, memStart = site(ExtMem).base,
prefetches = false) numGens = params.size)
})
class WithAtomics extends Config((site, here, up) => {
case ComparatorKey => up(ComparatorKey, site).copy(atomics = true)
})
class WithPrefetches extends Config((site, here, up) => {
case ComparatorKey => up(ComparatorKey, site).copy(prefetches = true)
})
class WithMemtest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(uncached = 1)
}
case GeneratorKey => TrafficGeneratorParameters(
maxRequests = 128,
startAddress = BigInt(site(ExtMem).base))
case BuildGroundTest =>
(p: Parameters) => Module(new GeneratorTest()(p))
})
class WithCacheFillTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(uncached = 1, dcache = None)
}
case BuildGroundTest =>
(p: Parameters) => Module(new CacheFillTest()(p))
})
class WithBroadcastRegressionTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(uncached = 1, maxXacts = 3)
}
case BuildGroundTest =>
(p: Parameters) => Module(new RegressionTest()(p))
case GroundTestRegressions =>
(p: Parameters) => RegressionTests.broadcastRegressions(p)
})
class WithCacheRegressionTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(uncached = 1, maxXacts = 5)
}
case BuildGroundTest =>
(p: Parameters) => Module(new RegressionTest()(p))
case GroundTestRegressions =>
(p: Parameters) => RegressionTests.cacheRegressions(p)
})
class WithTraceGen(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(dcache = Some(DCacheParams(nSets = 16, nWays = 1)))
}
case BuildGroundTest =>
(p: Parameters) => Module(new GroundTestTraceGenerator()(p))
case GeneratorKey => TrafficGeneratorParameters(
maxRequests = 8192,
startAddress = 0)
case AddressBag => {
val nSets = 2
val nWays = 1
val blockOffset = site(CacheBlockOffsetBits)
val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes
List.tabulate(4 * nWays) { i =>
Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
}.flatten
} }
case MaxHartIdBits => log2Up(params.size)
}) })

View File

@ -1,44 +1,27 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import config._
import diplomacy._ import freechips.rocketchip.config.{Field, Parameters}
import coreplex._ import freechips.rocketchip.diplomacy._
import rocket._ import freechips.rocketchip.coreplex._
import tile._ import freechips.rocketchip.tilelink._
import uncore.agents._ import freechips.rocketchip.tile._
import uncore.coherence._
import uncore.devices._
import uncore.tilelink._
import uncore.tilelink2._
import uncore.util._
import scala.math.max import scala.math.max
case object TileId extends Field[Int] case object TileId extends Field[Int]
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex { class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
val tiles = List.tabulate(p(NTiles)) { i => val tileParams = p(GroundTestTilesKey)
LazyModule(new GroundTestTile()(p.alter { (site, here, up) => { val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule(
case TileId => i c.build(i, p.alterPartial {
case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes)) case TileKey => c
case AmoAluOperandBits => site(XLen)
case SharedMemoryTLEdge => tile_splitter.node.edgesIn(0) case SharedMemoryTLEdge => tile_splitter.node.edgesIn(0)
case TLId => "L1toL2" })
case TLKey("L1toL2") => )}
TileLinkParameters(
coherencePolicy = new MESICoherence(new NullRepresentation(site(NTiles))),
nManagers = site(BankedL2Config).nBanks + 1,
nCachingClients = 1,
nCachelessClients = 1,
maxClientXacts = site(GroundTestKey).map(_.maxXacts).reduce(max(_, _)),
maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum,
maxManagerXacts = 8,
dataBeats = (8 * site(CacheBlockBytes)) / site(XLen),
dataBits = site(CacheBlockBytes)*8)
}}))
}
val fixer = LazyModule(new TLFIFOFixer) val fixer = LazyModule(new TLFIFOFixer)
tile_splitter.node :=* fixer.node tile_splitter.node :=* fixer.node
@ -55,5 +38,9 @@ class GroundTestCoreplexBundle[+L <: GroundTestCoreplex](_outer: L) extends Base
} }
class GroundTestCoreplexModule[+L <: GroundTestCoreplex, +B <: GroundTestCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) { class GroundTestCoreplexModule[+L <: GroundTestCoreplex, +B <: GroundTestCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) {
io.success := outer.tiles.map(_.module.io.success).reduce(_&&_)
outer.tiles.zipWithIndex.map { case(t, i) => t.module.io.hartid := UInt(i) }
val status = DebugCombiner(outer.tiles.map(_.module.io.status))
io.success := status.finished
} }

View File

@ -1,13 +1,14 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import config._
import rocket._ import freechips.rocketchip.config.Parameters
import tile._ import freechips.rocketchip.rocket._
import util.ParameterizedBundle import freechips.rocketchip.tile.CoreModule
import freechips.rocketchip.util.ParameterizedBundle
class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
val io = new Bundle { val io = new Bundle {

View File

@ -1,8 +1,10 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package groundtest package freechips.rocketchip.groundtest
object Generator extends util.GeneratorApp { import freechips.rocketchip.util.GeneratorApp
object Generator extends GeneratorApp {
val longName = names.topModuleProject + "." + names.configs val longName = names.topModuleProject + "." + names.configs
generateFirrtl generateFirrtl
generateTestSuiteMakefrags // TODO: Needed only for legacy make targets generateTestSuiteMakefrags // TODO: Needed only for legacy make targets

View File

@ -1,5 +1,9 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package freechips.rocketchip
package object groundtest { package object groundtest {
val testRamAddr = 0x10000 val testRamAddr = 0x10000
val timeoutCodeBits = 4
val errorCodeBits = 4
} }

View File

@ -1,789 +0,0 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package groundtest
import Chisel._
import uncore.tilelink._
import uncore.constants._
import uncore.util._
import util._
import rocket._
import rocketchip._
import config._
class RegressionIO(implicit val p: Parameters) extends ParameterizedBundle()(p) {
val start = Bool(INPUT)
val cache = new HellaCacheIO
val mem = new ClientUncachedTileLinkIO
val finished = Bool(OUTPUT)
val errored = Bool(OUTPUT)
}
abstract class Regression(implicit val p: Parameters)
extends Module with HasTileLinkParameters {
val memStart = p(ExtMem).base
val memStartBlock = memStart >> p(CacheBlockOffsetBits)
val io = new RegressionIO
def disableCache() {
io.cache.req.valid := Bool(false)
io.cache.req.bits.addr := UInt(memStart)
io.cache.req.bits.typ := UInt(0)
io.cache.req.bits.cmd := M_XRD
io.cache.req.bits.tag := UInt(0)
io.cache.req.bits.data := Bits(0)
io.cache.req.bits.phys := Bool(true)
io.cache.invalidate_lr := Bool(false)
}
def disableMem() {
io.mem.acquire.valid := Bool(false)
io.mem.grant.ready := Bool(false)
}
}
/**
* This was a bug in which the TileLinkIONarrower logic screwed up
* when a PutBlock request and a narrow Get request are sent to it at the
* same time. Repeating this sequence enough times will cause a queue to
* get filled up and deadlock the system.
*/
class IOGetAfterPutBlockRegression(implicit p: Parameters) extends Regression()(p) {
val nRuns = 7
val run = Reg(init = UInt(0, log2Up(nRuns + 1)))
val (put_beat, put_done) = Counter(
io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats)
val started = Reg(init = Bool(false))
val put_sent = Reg(init = Bool(false))
val get_sent = Reg(init = Bool(false))
val put_acked = Reg(init = Bool(false))
val get_acked = Reg(init = Bool(false))
val both_acked = put_acked && get_acked
when (!started && io.start) { started := Bool(true) }
io.mem.acquire.valid := !put_sent && started
io.mem.acquire.bits := PutBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock),
addr_beat = put_beat,
data = UInt(0))
io.mem.grant.ready := Bool(true)
io.cache.req.valid := !get_sent && started
io.cache.req.bits.addr := UInt(testRamAddr)
io.cache.req.bits.typ := MT_WU
io.cache.req.bits.cmd := M_XRD
io.cache.req.bits.tag := UInt(0)
io.cache.invalidate_lr := Bool(false)
when (put_done) { put_sent := Bool(true) }
when (io.cache.req.fire()) { get_sent := Bool(true) }
when (io.mem.grant.fire()) { put_acked := Bool(true) }
when (io.cache.resp.valid) { get_acked := Bool(true) }
when (both_acked) {
when (run < UInt(nRuns - 1)) {
put_sent := Bool(false)
get_sent := Bool(false)
}
put_acked := Bool(false)
get_acked := Bool(false)
run := run + UInt(1)
}
io.finished := (run === UInt(nRuns))
}
/* This was a bug with merging two PutBlocks to the same address in the L2.
* The transactor would start accepting beats of the second transaction but
* acknowledge both of them when the first one finished.
* This caused the state to go funky since the next time around it would
* start the put in the middle */
class PutBlockMergeRegression(nSets: Int)(implicit p: Parameters)
extends Regression()(p) with HasTileLinkParameters {
val s_idle :: s_put :: s_wait :: s_done :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle)
disableCache()
val addr_blocks = Vec(Seq(0, 0, nSets).map(num => UInt(num + memStartBlock)))
val nSteps = addr_blocks.size
val (acq_beat, acq_done) = Counter(io.mem.acquire.fire(), tlDataBeats)
val (send_cnt, send_done) = Counter(acq_done, nSteps)
val (ack_cnt, ack_done) = Counter(io.mem.grant.fire(), nSteps)
io.mem.acquire.valid := (state === s_put)
io.mem.acquire.bits := PutBlock(
client_xact_id = send_cnt,
addr_block = addr_blocks(send_cnt),
addr_beat = acq_beat,
data = Cat(send_cnt, acq_beat))
io.mem.grant.ready := Bool(true)
when (state === s_idle && io.start) { state := s_put }
when (send_done) { state := s_wait }
when (ack_done) { state := s_done }
io.finished := (state === s_done)
}
/* Make sure the L2 does "the right thing" when a put is sent no-alloc but
* the block is already in cache. It should just treat the request as a
* regular allocating put */
class NoAllocPutHitRegression(implicit p: Parameters) extends Regression()(p) {
val (s_idle :: s_prefetch :: s_put :: s_get ::
s_wait :: s_done :: Nil) = Enum(Bits(), 6)
val state = Reg(init = s_idle)
val acq = io.mem.acquire.bits
val gnt = io.mem.grant.bits
val (put_beat, put_done) = Counter(io.mem.acquire.fire() && acq.hasData(), tlDataBeats)
val acked = Reg(init = UInt(0, tlDataBeats + 2))
val addr_block = UInt(memStartBlock + 2)
val test_data = UInt(0x3446)
val prefetch_acq = GetPrefetch(
client_xact_id = UInt(0),
addr_block = addr_block)
val put_acq = PutBlock(
client_xact_id = UInt(1),
addr_block = addr_block,
addr_beat = put_beat,
data = test_data,
alloc = Bool(false))
val get_acq = GetBlock(
client_xact_id = UInt(2),
addr_block = addr_block)
io.mem.acquire.valid := state.isOneOf(s_prefetch, s_get, s_put)
io.mem.acquire.bits := MuxCase(get_acq, Seq(
(state === s_prefetch) -> prefetch_acq,
(state === s_put) -> put_acq))
io.mem.grant.ready := Bool(true)
when (state === s_idle && io.start) { state := s_prefetch }
when (state === s_prefetch && io.mem.acquire.ready) { state := s_put }
when (put_done) { state := s_get }
when (state === s_get && io.mem.acquire.ready) { state := s_wait }
when (state === s_wait && acked.andR) { state := s_done }
when (io.mem.grant.fire()) {
switch (gnt.client_xact_id) {
is (UInt(0)) { acked := acked | UInt(1 << tlDataBeats) }
is (UInt(1)) { acked := acked | UInt(1 << (tlDataBeats + 1)) }
is (UInt(2)) { acked := acked | UIntToOH(gnt.addr_beat) }
}
}
val data_mismatch = io.mem.grant.fire() && gnt.hasData() && gnt.data =/= test_data
assert(!data_mismatch, "NoAllocPutHitRegression: data does not match")
io.finished := (state === s_done)
io.errored := data_mismatch
disableCache()
}
/** Make sure L2 does the right thing when multiple puts are sent for the
* same block, but only the first one has the alloc bit set. */
class MixedAllocPutRegression(implicit p: Parameters) extends Regression()(p) {
val (s_idle :: s_pf_send :: s_pf_wait :: s_put_send :: s_put_wait ::
s_get_send :: s_get_wait :: s_done :: Nil) = Enum(Bits(), 8)
val state = Reg(init = s_idle)
/** We have to test two cases: one when the block is already cached
* and one when the block is not yet cached.
* We use prefetching to assure the first case. */
val test_data = Vec(
UInt("h2222222211111111"),
UInt("h3333333333333333"),
UInt("h4444444444444444"),
UInt("h5555555555555555"))
val test_alloc = Vec(Bool(false), Bool(false), Bool(true), Bool(false))
val test_block = Vec(
Seq.fill(2) { UInt(memStartBlock + 15) } ++
Seq.fill(2) { UInt(memStartBlock + 16) })
val test_beat = Vec(UInt(0), UInt(2), UInt(1), UInt(2))
val (put_acq_id, put_acq_done) = Counter(
state === s_put_send && io.mem.acquire.ready, test_data.size)
val (put_gnt_cnt, put_gnt_done) = Counter(
state === s_put_wait && io.mem.grant.valid, test_data.size)
val (get_acq_id, get_acq_done) = Counter(
state === s_get_send && io.mem.acquire.ready, test_data.size)
val (get_gnt_cnt, get_gnt_done) = Counter(
state === s_get_wait && io.mem.grant.valid, test_data.size)
val pf_acquire = PutPrefetch(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock + 15))
val put_acquire = Put(
client_xact_id = put_acq_id,
addr_block = test_block(put_acq_id),
addr_beat = test_beat(put_acq_id),
data = test_data(put_acq_id),
alloc = test_alloc(put_acq_id))
val get_acquire = Get(
client_xact_id = get_acq_id,
addr_block = test_block(get_acq_id),
addr_beat = test_beat(get_acq_id))
io.mem.acquire.valid := state.isOneOf(s_pf_send, s_put_send, s_get_send)
io.mem.acquire.bits := MuxLookup(state, pf_acquire, Seq(
s_put_send -> put_acquire,
s_get_send -> get_acquire))
io.mem.grant.ready := state.isOneOf(s_pf_wait, s_put_wait, s_get_wait)
when (state === s_idle && io.start) { state := s_pf_send }
when (state === s_pf_send && io.mem.acquire.ready) { state := s_pf_wait }
when (state === s_pf_wait && io.mem.grant.valid) { state := s_put_send }
when (put_acq_done) { state := s_put_wait }
when (put_gnt_done) { state := s_get_send }
when (get_acq_done) { state := s_get_wait }
when (get_gnt_done) { state := s_done }
io.finished := (state === s_done)
val data_mismatch = state === s_get_wait && io.mem.grant.fire() &&
io.mem.grant.bits.data =/= test_data(io.mem.grant.bits.client_xact_id)
assert(!data_mismatch, "MixedAllocPutRegression: data mismatch")
io.errored := data_mismatch
disableCache()
}
/* Make sure each no-alloc put triggers a request to outer memory.
* Unfortunately, there's no way to verify that this works except by looking
* at the waveform */
class RepeatedNoAllocPutRegression(implicit p: Parameters) extends Regression()(p) {
disableCache()
val nPuts = 2
val (put_beat, put_done) = Counter(io.mem.acquire.fire(), tlDataBeats)
val (req_cnt, req_done) = Counter(put_done, nPuts)
val sending = Reg(init = Bool(false))
val acked = Reg(init = UInt(0, nPuts))
when (!sending && io.start) { sending := Bool(true) }
when (sending && req_done) { sending := Bool(false) }
io.mem.acquire.valid := sending
io.mem.acquire.bits := PutBlock(
client_xact_id = req_cnt,
addr_block = UInt(memStartBlock + 5),
addr_beat = put_beat,
data = Cat(req_cnt, UInt(0, 8)),
alloc = Bool(false))
io.mem.grant.ready := Bool(true)
when (io.mem.grant.fire()) {
acked := acked | UIntToOH(io.mem.grant.bits.client_xact_id)
}
io.finished := acked.andR
}
/* Make sure write masking works properly by writing a block of data
* piece by piece */
class WriteMaskedPutBlockRegression(implicit p: Parameters) extends Regression()(p) {
disableCache()
val (s_idle :: s_put_send :: s_put_ack :: s_stall ::
s_get_send :: s_get_ack :: s_done :: Nil) = Enum(Bits(), 7)
val state = Reg(init = s_idle)
val post_stall_state = Reg(init = s_idle)
val gnt = io.mem.grant.bits
val acq = io.mem.acquire.bits
val stage = Reg(init = UInt(0, 1))
val (put_beat, put_block_done) = Counter(
io.mem.acquire.fire() && acq.hasData(), tlDataBeats)
val put_data = UInt(0x30010040, tlDataBits) + (put_beat << UInt(2))
val put_acq = PutBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock + 7),
addr_beat = put_beat,
data = Mux(put_beat(0) === stage, put_data, UInt(0)),
wmask = Some(Mux(put_beat(0) === stage, Acquire.fullWriteMask, Bits(0))))
val get_acq = GetBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock + 6) + stage)
io.mem.acquire.valid := state.isOneOf(s_put_send, s_get_send)
io.mem.acquire.bits := Mux(state === s_get_send, get_acq, put_acq)
io.mem.grant.ready := state.isOneOf(s_put_ack, s_get_ack)
val (get_cnt, get_done) = Counter(
io.mem.grant.fire() && gnt.hasData(), tlDataBeats)
val get_data = UInt(0x30010040, tlDataBits) + (get_cnt << UInt(2))
val (stall_cnt, stall_done) = Counter(state === s_stall, 16)
when (state === s_idle && io.start) { state := s_put_send }
when (put_block_done) { state := s_put_ack }
when (state === s_put_ack && io.mem.grant.valid) {
post_stall_state := s_get_send
state := s_stall
}
when (stall_done) { state := post_stall_state }
when (state === s_get_send && io.mem.acquire.ready) { state := s_get_ack }
when (get_done) {
// do a read in-between the two put-blocks to overwrite the data buffer
when (stage === UInt(0)) {
stage := stage + UInt(1)
post_stall_state := s_put_send
state := s_stall
} .otherwise { state := s_done }
}
io.finished := (state === s_done)
val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() &&
stage =/= UInt(0) && io.mem.grant.bits.data =/= get_data
assert(!data_mismatch, "WriteMaskedPutBlockRegression: data does not match")
io.errored := data_mismatch
}
/* Make sure a prefetch that hits returns immediately. */
class PrefetchHitRegression(implicit p: Parameters) extends Regression()(p) {
disableCache()
val sending = Reg(init = Bool(false))
val nPrefetches = 2
val (pf_cnt, pf_done) = Counter(io.mem.acquire.fire(), nPrefetches)
val acked = Reg(init = UInt(0, nPrefetches))
val acq_bits = Vec(
PutPrefetch(client_xact_id = UInt(0), addr_block = UInt(memStartBlock + 12)),
GetPrefetch(client_xact_id = UInt(1), addr_block = UInt(memStartBlock + 12)))
io.mem.acquire.valid := sending
io.mem.acquire.bits := acq_bits(pf_cnt)
io.mem.grant.ready := Bool(true)
when (io.mem.grant.fire()) {
acked := acked | UIntToOH(io.mem.grant.bits.client_xact_id)
}
when (!sending && io.start) { sending := Bool(true) }
when (sending && pf_done) { sending := Bool(false) }
io.finished := acked.andR
io.errored := Bool(false)
}
/* Test that a writeback will occur by writing nWays + 1 blocks to the same
* set. This assumes that there is only a single cache bank. If we want to
* test multibank configurations, we'll have to think of some other way to
* determine which banks are conflicting */
class WritebackRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableCache()
val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(memStartBlock + i * nSets) }
val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1423) }
val (put_beat, put_done) = Counter(
io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats)
val (get_beat, get_done) = Counter(
io.mem.grant.fire() && io.mem.grant.bits.hasData(), tlDataBeats)
val (put_cnt, _) = Counter(put_done, nWays + 1)
val (get_cnt, _) = Counter(
io.mem.acquire.fire() && !io.mem.acquire.bits.hasData(), nWays + 1)
val (ack_cnt, ack_done) = Counter(
io.mem.grant.fire() && !io.mem.grant.bits.hasData() || get_done, nWays + 1)
val s_idle :: s_put :: s_get :: s_done :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle)
val sending = Reg(init = Bool(false))
io.mem.acquire.valid := sending
io.mem.acquire.bits := Mux(state === s_put,
PutBlock(
client_xact_id = UInt(0),
addr_block = addr_blocks(put_cnt),
addr_beat = put_beat,
data = data(put_cnt)),
GetBlock(
client_xact_id = UInt(0),
addr_block = addr_blocks(get_cnt)))
io.mem.grant.ready := !sending
when (state === s_idle && io.start) { state := s_put; sending := Bool(true) }
when (put_done || state === s_get && io.mem.acquire.fire()) {
sending := Bool(false)
}
when (get_done && !ack_done || state === s_put && io.mem.grant.fire()) {
sending := Bool(true)
}
when (ack_done) { state := Mux(state === s_put, s_get, s_done) }
io.finished := (state === s_done)
val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() &&
io.mem.grant.bits.data =/= data(ack_cnt)
assert(!data_mismatch, "WritebackRegression: incorrect data")
io.errored := data_mismatch
}
class ReleaseRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableMem()
val blockOffset = p(CacheBlockOffsetBits)
val startBlock = memStartBlock + 10
val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(startBlock + i * nSets) }
val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1522) }
val (req_idx, req_done) = Counter(io.cache.req.fire(), nWays + 1)
val (resp_idx, resp_done) = Counter(io.cache.resp.valid, nWays + 1)
val sending = Reg(init = Bool(false))
val s_idle :: s_write :: s_read :: s_done :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle)
io.cache.req.valid := sending && state.isOneOf(s_write, s_read)
io.cache.req.bits.addr := Cat(addr_blocks(req_idx), UInt(0, blockOffset))
io.cache.req.bits.typ := MT_D
io.cache.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD)
io.cache.req.bits.tag := UInt(0)
io.cache.req.bits.data := data(req_idx)
io.cache.req.bits.phys := Bool(true)
io.cache.invalidate_lr := Bool(false)
when (state === s_idle && io.start) {
sending := Bool(true)
state := s_write
}
when (resp_done) { state := Mux(state === s_write, s_read, s_done) }
when (io.cache.req.fire()) { sending := Bool(false) }
when (io.cache.resp.valid) { sending := Bool(true) }
io.finished := (state === s_done)
val data_mismatch = io.cache.resp.valid && io.cache.resp.bits.has_data &&
io.cache.resp.bits.data =/= data(resp_idx)
assert(!data_mismatch, "ReleaseRegression: data mismatch")
io.errored := data_mismatch
}
class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p) {
val (s_idle :: s_put :: s_putblock :: s_wait ::
s_finished :: Nil) = Enum(Bits(), 5)
val state = Reg(init = s_idle)
disableCache()
val (put_block_beat, put_block_done) = Counter(
state === s_putblock && io.mem.acquire.ready, tlDataBeats)
val put_acquire = Put(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock),
addr_beat = UInt(0),
data = UInt(0),
wmask = Some(UInt((1 << 8) - 1)))
val put_block_acquire = PutBlock(
client_xact_id = UInt(1),
addr_block = UInt(memStartBlock + 1),
addr_beat = put_block_beat,
data = UInt(0))
val put_acked = Reg(init = UInt(0, 2))
val (ack_cnt, all_acked) = Counter(io.mem.grant.fire(), 2)
io.mem.acquire.valid := state.isOneOf(s_put, s_putblock)
io.mem.acquire.bits := Mux(state === s_put, put_acquire, put_block_acquire)
io.mem.grant.ready := (state === s_wait)
when (state === s_idle && io.start) { state := s_put }
when (state === s_put && io.mem.acquire.ready) { state := s_putblock }
when (put_block_done) { state := s_wait }
when (all_acked) { state := s_finished }
io.finished := (state === s_finished)
io.errored := Bool(false)
}
/**
* Make sure that multiple gets to the same line and beat are merged
* correctly, even if it is a cache miss.
*/
class MergedGetRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableCache()
val (s_idle :: s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 4)
val state = Reg(init = s_idle)
// Write NWays + 1 different conflicting lines to force an eviction of the first line
val (put_acq_cnt, put_acq_done) = Counter(state === s_put && io.mem.acquire.fire(), nWays + 1)
val (put_gnt_cnt, put_gnt_done) = Counter(state === s_put && io.mem.grant.fire(), nWays + 1)
val put_addr = UInt(memStartBlock) + Cat(put_acq_cnt, UInt(0, log2Up(nSets)))
val (get_acq_cnt, get_acq_done) = Counter(state === s_get && io.mem.acquire.fire(), 2)
val (get_gnt_cnt, get_gnt_done) = Counter(state === s_get && io.mem.grant.fire(), 2)
val sending = Reg(init = Bool(false))
when (state === s_idle && io.start) { state := s_put; sending := Bool(true) }
when (state === s_put) {
when (io.mem.acquire.fire()) { sending := Bool(false) }
when (io.mem.grant.fire()) { sending := Bool(true) }
when (put_gnt_done) { state := s_get }
}
when (state === s_get) {
when (get_acq_done) { sending := Bool(false) }
when (get_gnt_done) { state := s_done }
}
io.mem.acquire.valid := sending
io.mem.acquire.bits := Mux(state === s_put,
Put(
client_xact_id = UInt(0),
addr_block = put_addr,
addr_beat = UInt(3),
data = UInt("hdabb9321")),
Get(
client_xact_id = get_acq_cnt,
addr_block = UInt(memStartBlock),
addr_beat = UInt(3)))
io.mem.grant.ready := !sending
val data_mismatch = io.mem.grant.valid && io.mem.grant.bits.hasData() &&
io.mem.grant.bits.data =/= UInt("hdabb9321")
assert(!data_mismatch, "RepeatedGetRegression: wrong data back")
io.finished := state === s_done
io.errored := data_mismatch
}
/**
* Make sure that multiple puts to the same line and beat are merged
* correctly, even if there is a release from the L1
*/
class MergedPutRegression(implicit p: Parameters) extends Regression()(p)
with HasTileLinkParameters {
val (s_idle :: s_cache_req :: s_cache_wait ::
s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 6)
val state = Reg(init = s_idle)
io.cache.req.valid := (state === s_cache_req)
io.cache.req.bits.cmd := M_XWR
io.cache.req.bits.typ := MT_D
io.cache.req.bits.addr := UInt(memStart)
io.cache.req.bits.data := UInt(1)
io.cache.req.bits.tag := UInt(0)
val sending = Reg(init = Bool(false))
val delaying = Reg(init = Bool(false))
val (put_cnt, put_done) = Counter(io.mem.acquire.fire(), tlMaxClientXacts)
val (delay_cnt, delay_done) = Counter(delaying, 8)
val put_acked = Reg(UInt(width = tlMaxClientXacts), init = UInt(0))
io.mem.acquire.valid := sending && !delaying
io.mem.acquire.bits := Mux(state === s_put,
Put(
client_xact_id = put_cnt,
addr_block = UInt(memStartBlock),
addr_beat = UInt(0),
data = put_cnt + UInt(2)),
Get(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock),
addr_beat = UInt(0)))
io.mem.grant.ready := Bool(true)
when (state === s_idle && io.start) { state := s_cache_req }
when (io.cache.req.fire()) { state := s_cache_wait }
when (io.cache.resp.valid) { state := s_put; sending := Bool(true) }
when (io.mem.acquire.fire()) {
delaying := Bool(true)
when (put_done || state === s_get) { sending := Bool(false) }
}
when (delay_done) { delaying := Bool(false) }
when (io.mem.grant.fire()) {
when (state === s_put) {
put_acked := put_acked | UIntToOH(io.mem.grant.bits.client_xact_id)
}
when (state === s_get) { state := s_done }
}
when (state === s_put && put_acked.andR) {
state := s_get
sending := Bool(true)
}
val expected_data = UInt(2 + tlMaxClientXacts - 1)
val data_mismatch = io.mem.grant.valid && io.mem.grant.bits.hasData() &&
io.mem.grant.bits.data =/= expected_data
assert(!data_mismatch, "MergedPutRegression: data mismatch")
io.finished := (state === s_done)
io.errored := data_mismatch
}
class PutAfterReleaseRegression(implicit p: Parameters) extends Regression()(p) {
val (s_idle :: s_cache_req :: s_cache_resp ::
s_write_first_req :: s_delay :: s_write_remaining_req :: s_write_resp ::
s_read_req :: s_read_resp :: s_finished :: Nil) = Enum(Bits(), 10)
val state = Reg(init = s_idle)
val (delay_cnt, delay_done) = Counter(state === s_delay, 100)
val (write_cnt, write_done) = Counter(
io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats)
val (read_cnt, read_done) = Counter(
io.mem.grant.fire() && io.mem.grant.bits.hasData(), tlDataBeats)
when (state === s_idle && io.start) { state := s_cache_req }
when (io.cache.req.fire()) { state := s_cache_resp }
when (state === s_cache_resp && io.cache.resp.valid) { state := s_write_first_req }
when (state === s_write_first_req && io.mem.acquire.ready) { state := s_delay }
when (delay_done) { state := s_write_remaining_req }
when (write_done) { state := s_write_resp }
when (state === s_write_resp && io.mem.grant.valid) { state := s_read_req }
when (state === s_read_req && io.mem.acquire.ready) { state := s_read_resp }
when (read_done) { state := s_finished }
io.finished := state === s_finished
io.cache.req.valid := state === s_cache_req
io.cache.req.bits.cmd := M_XWR
io.cache.req.bits.addr := UInt(memStart)
io.cache.req.bits.typ := MT_D
io.cache.req.bits.tag := UInt(0)
io.cache.req.bits.data := UInt(0)
io.mem.acquire.valid := state.isOneOf(s_write_first_req, s_write_remaining_req, s_read_req)
io.mem.acquire.bits := Mux(state === s_read_req,
GetBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock)),
PutBlock(
client_xact_id = UInt(0),
addr_block = UInt(memStartBlock),
addr_beat = write_cnt,
data = write_cnt + UInt(1)))
io.mem.grant.ready := state.isOneOf(s_write_resp, s_read_resp)
assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() ||
io.mem.grant.bits.data === read_cnt + UInt(1),
"PutAfterReleaseRegression: data mismatch")
}
object RegressionTests {
val l1sets = 16 // TODO
val l1ways = 1 // TODO
val l2sets = 32 // TODO
val l2ways = 2 // TODO
def cacheRegressions(implicit p: Parameters) = Seq(
Module(new PutBlockMergeRegression(l2sets)),
Module(new NoAllocPutHitRegression),
Module(new RepeatedNoAllocPutRegression),
Module(new WriteMaskedPutBlockRegression),
Module(new PrefetchHitRegression),
Module(new WritebackRegression(l2sets, l2ways)),
Module(new PutBeforePutBlockRegression),
Module(new MixedAllocPutRegression),
Module(new ReleaseRegression(l1sets, l1ways)),
Module(new MergedGetRegression(l2sets, l2ways)),
Module(new MergedPutRegression))
def broadcastRegressions(implicit p: Parameters) = Seq(
Module(new IOGetAfterPutBlockRegression),
Module(new WriteMaskedPutBlockRegression),
Module(new PutBeforePutBlockRegression),
Module(new ReleaseRegression(l1sets, l1ways)),
Module(new PutAfterReleaseRegression))
}
case object GroundTestRegressions extends Field[Parameters => Seq[Regression]]
class RegressionTest(implicit p: Parameters) extends GroundTest()(p) {
val regressions = p(GroundTestRegressions)(p)
val regress_idx = Reg(init = UInt(0, log2Up(regressions.size + 1)))
val cur_finished = Wire(init = Bool(false))
val all_done = (regress_idx === UInt(regressions.size))
val start = Reg(init = Bool(true))
// Some tests randomly backpressure grant; make this safe:
val grant = Queue(io.mem.head.grant, 16)
// default output values
io.mem.head.acquire.valid := Bool(false)
io.mem.head.acquire.bits := GetBlock(
client_xact_id = UInt(0),
addr_block = UInt(0))
grant.ready := Bool(false)
io.cache.head.req.valid := Bool(false)
io.cache.head.req.bits.addr := UInt(0)
io.cache.head.req.bits.typ := UInt(log2Ceil(64 / 8))
io.cache.head.req.bits.cmd := M_XRD
io.cache.head.req.bits.tag := UInt(0)
io.cache.head.req.bits.phys := Bool(true)
io.cache.head.req.bits.data := UInt(0)
io.cache.head.invalidate_lr := Bool(false)
regressions.zipWithIndex.foreach { case (regress, i) =>
val me = regress_idx === UInt(i)
regress.io.start := me && start
regress.io.mem.acquire.ready := io.mem.head.acquire.ready && me
regress.io.mem.grant.valid := grant.valid && me
regress.io.mem.grant.bits := grant.bits
regress.io.cache.req.ready := io.cache.head.req.ready && me
regress.io.cache.resp.valid := io.cache.head.resp.valid && me
regress.io.cache.resp.bits := io.cache.head.resp.bits
when (me) {
io.mem.head.acquire.valid := regress.io.mem.acquire.valid
io.mem.head.acquire.bits := regress.io.mem.acquire.bits
grant.ready := regress.io.mem.grant.ready
io.cache.head.req.valid := regress.io.cache.req.valid
io.cache.head.req.bits := regress.io.cache.req.bits
io.cache.head.invalidate_lr := regress.io.cache.invalidate_lr
io.status.error.valid := regress.io.errored
io.status.error.bits := UInt(i)
cur_finished := regress.io.finished
}
when (regress.io.start) {
printf(s"Starting regression ${regress.getClass.getSimpleName}\n")
}
}
when (cur_finished && !all_done) {
start := Bool(true)
regress_idx := regress_idx + UInt(1)
}
when (start) { start := Bool(false) }
val timeout = SimpleTimer(5000, start, cur_finished)
assert(!timeout, "Regression timed out")
io.status.finished := all_done
io.status.timeout.valid := timeout
io.status.timeout.bits := UInt(0)
assert(!(all_done && grant.valid),
"Getting grant after test completion")
when (all_done) {
io.status.error.valid := grant.valid
io.status.error.bits := UInt(regressions.size)
}
}

View File

@ -0,0 +1,23 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.groundtest
import Chisel._
import freechips.rocketchip.util.ValidMux
class GroundTestStatus extends Bundle {
val finished = Bool(OUTPUT)
val timeout = Valid(UInt(width = 4))
val error = Valid(UInt(width = 4))
}
object DebugCombiner {
def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = {
val out = Wire(new GroundTestStatus)
out.finished := debugs.map(_.finished).reduce(_ && _)
out.timeout := ValidMux(debugs.map(_.timeout))
out.error := ValidMux(debugs.map(_.error))
out
}
}

View File

@ -1,12 +1,11 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import diplomacy._
import config._ import freechips.rocketchip.config.Parameters
import rocketchip._ import freechips.rocketchip.diplomacy.LazyModule
import util._
class TestHarness(implicit p: Parameters) extends Module { class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle { val success = Bool(OUTPUT) } val io = new Bundle { val success = Bool(OUTPUT) }

View File

@ -1,123 +1,51 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import config._ import freechips.rocketchip.config._
import coreplex._ import freechips.rocketchip.coreplex._
import rocket._ import freechips.rocketchip.diplomacy._
import tile._ import freechips.rocketchip.rocket._
import uncore.tilelink._ import freechips.rocketchip.chip._
import uncore.tilelink2._ import freechips.rocketchip.tile._
import rocketchip.ExtMem import freechips.rocketchip.tilelink._
import diplomacy._
import util.ParameterizedBundle
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
case object BuildGroundTest extends Field[Parameters => GroundTest] trait GroundTestTileParams extends TileParams {
val memStart: BigInt
val maxRequests: Int
val numGens: Int
def build(i: Int, p: Parameters): GroundTestTile
case class GroundTestTileParams(
uncached: Int = 0,
ptw: Int = 0,
maxXacts: Int = 1,
dcache: Option[DCacheParams] = Some(DCacheParams())) extends TileParams {
val icache = None val icache = None
val btb = None val btb = None
val rocc = Nil val rocc = Nil
val core = rocket.RocketCoreParams(nPMPs = 0) //TODO remove this val core = RocketCoreParams(nPMPs = 0) //TODO remove this
val cached = if(dcache.isDefined) 1 else 0 val cached = if(dcache.isDefined) 1 else 0
val dataScratchpadBytes = 0 val dataScratchpadBytes = 0
} }
case object GroundTestKey extends Field[Seq[GroundTestTileParams]]
trait HasGroundTestConstants { case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]]
val timeoutCodeBits = 4
val errorCodeBits = 4 abstract class GroundTestTile(params: GroundTestTileParams)(implicit p: Parameters) extends BaseTile(params)(p) {
val slave = None
val dcacheOpt = params.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) }
dcacheOpt.foreach { tileBus.node := _.node }
override lazy val module = new GroundTestTileModule(this, () => new GroundTestTileBundle(this))
} }
trait HasGroundTestParameters { class GroundTestTileBundle[+L <: GroundTestTile](_outer: L) extends BaseTileBundle(_outer) {
implicit val p: Parameters
val tileParams = p(GroundTestKey)(p(TileId))
val nUncached = tileParams.uncached
val nCached = tileParams.cached
val nPTW = tileParams.ptw
val memStart = p(ExtMem).base
val memStartBlock = memStart >> p(CacheBlockOffsetBits)
}
class GroundTestStatus extends Bundle with HasGroundTestConstants {
val finished = Bool(OUTPUT)
val timeout = Valid(UInt(width = timeoutCodeBits))
val error = Valid(UInt(width = errorCodeBits))
}
class GroundTestIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasGroundTestParameters {
val cache = Vec(nCached, new HellaCacheIO)
val mem = Vec(nUncached, new ClientUncachedTileLinkIO)
val ptw = Vec(nPTW, new TLBPTWIO)
val status = new GroundTestStatus val status = new GroundTestStatus
} }
abstract class GroundTest(implicit val p: Parameters) extends Module class GroundTestTileModule[+L <: GroundTestTile, +B <: GroundTestTileBundle[L]](_outer: L, _io: () => B) extends BaseTileModule(_outer, _io) {
with HasGroundTestParameters {
val io = new GroundTestIO
}
class GroundTestTile(implicit p: Parameters) extends LazyModule outer.dcacheOpt foreach { dcache =>
with HasGroundTestParameters { val ptw = Module(new DummyPTW(1))
val slave = None ptw.io.requestors.head <> dcache.module.io.ptw
val dcacheOpt = tileParams.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) }
val ucLegacy = LazyModule(new TLLegacy)
val masterNode = TLOutputNode()
dcacheOpt.foreach { masterNode := _.node }
masterNode := TLHintHandler()(ucLegacy.node)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val out = masterNode.bundleOut
val success = Bool(OUTPUT)
}
val test = p(BuildGroundTest)(p)
val ptwPorts = ListBuffer.empty ++= test.io.ptw
val uncachedArbPorts = ListBuffer.empty ++= test.io.mem
dcacheOpt foreach { dcache =>
val dcacheArb = Module(new HellaCacheArbiter(nCached))
dcacheArb.io.requestor.zip(test.io.cache).foreach {
case (requestor, cache) =>
val dcacheIF = Module(new SimpleHellaCacheIF())
dcacheIF.io.requestor <> cache
requestor <> dcacheIF.io.cache
}
dcache.module.io.cpu <> dcacheArb.io.mem
// SimpleHellaCacheIF leaves invalidate_lr dangling, so we wire it to false
dcache.module.io.cpu.invalidate_lr := Bool(false)
ptwPorts += dcache.module.io.ptw
}
if (ptwPorts.size > 0) {
val ptw = Module(new DummyPTW(ptwPorts.size))
ptw.io.requestors <> ptwPorts
}
if (uncachedArbPorts.isEmpty) {
ucLegacy.module.io.legacy.acquire.valid := Bool(false)
ucLegacy.module.io.legacy.grant.ready := Bool(true)
} else {
val uncachedArb = Module(new ClientUncachedTileLinkIOArbiter(uncachedArbPorts.size))
uncachedArb.io.in <> uncachedArbPorts
ucLegacy.module.io.legacy <> uncachedArb.io.out
}
io.success := test.io.status.finished
} }
} }

View File

@ -1,11 +1,12 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import config.Parameters
import diplomacy.LazyModule import freechips.rocketchip.config.Parameters
import rocketchip._ import freechips.rocketchip.diplomacy.LazyModule
import freechips.rocketchip.chip._
class GroundTestTop(implicit p: Parameters) extends BaseSystem class GroundTestTop(implicit p: Parameters) extends BaseSystem
with HasPeripheryMasterAXI4MemPort with HasPeripheryMasterAXI4MemPort

View File

@ -17,17 +17,14 @@
// Mainstream Systems (REMS) project, funded by EPSRC grant // Mainstream Systems (REMS) project, funded by EPSRC grant
// EP/K008528/1. // EP/K008528/1.
package groundtest package freechips.rocketchip.groundtest
import Chisel._ import Chisel._
import uncore.tilelink._ import freechips.rocketchip.config.{Field, Parameters}
import uncore.constants._ import freechips.rocketchip.rocket._
import coreplex.NTiles import freechips.rocketchip.tile._
import rocket._ import freechips.rocketchip.util._
import tile._
import util.{Timer, DynamicTimer}
import scala.util.Random import scala.util.Random
import config._
// ======= // =======
// Outline // Outline
@ -59,19 +56,29 @@ import config._
// (This is a way to generate a wider range of addresses without having // (This is a way to generate a wider range of addresses without having
// to repeatedly recompile with a different address bag.) // to repeatedly recompile with a different address bag.)
case object AddressBag extends Field[List[BigInt]] case class TraceGenParams(
dcache: Option[DCacheParams] = Some(DCacheParams()),
wordBits: Int, // p(XLen)
addrBits: Int, // p(PAddrBits)
addrBag: List[BigInt], // p(AddressBag)
maxRequests: Int,
memStart: BigInt, //p(ExtMem).base
numGens: Int) extends GroundTestTileParams {
def build(i: Int, p: Parameters): GroundTestTile = new TraceGenTile(i, this)(p)
}
trait HasTraceGenParams { trait HasTraceGenParams {
implicit val p: Parameters implicit val p: Parameters
val pAddrBits = p(PAddrBits) val params: TraceGenParams
val numGens = p(NTiles) val pAddrBits = params.addrBits
val numBitsInId = log2Up(numGens) val numGens = params.numGens
val numReqsPerGen = p(GeneratorKey).maxRequests val numReqsPerGen = params.maxRequests
val memStart = params.memStart
val memRespTimeout = 8192 val memRespTimeout = 8192
val numBitsInWord = p(XLen) val numBitsInWord = params.wordBits
val numBytesInWord = numBitsInWord / 8 val numBytesInWord = numBitsInWord / 8
val numBitsInWordOffset = log2Up(numBytesInWord) val numBitsInWordOffset = log2Up(numBytesInWord)
val addressBag = p(AddressBag) val addressBag = params.addrBag
val addressBagLen = addressBag.length val addressBagLen = addressBag.length
val logAddressBagLen = log2Up(addressBagLen) val logAddressBagLen = log2Up(addressBagLen)
val genExtraAddrs = false val genExtraAddrs = false
@ -179,14 +186,13 @@ class TagMan(val logNumTags : Int) extends Module {
// Trace generator // Trace generator
// =============== // ===============
class TraceGenerator(id: Int) class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) extends Module
(implicit val p: Parameters) extends Module with HasTraceGenParams {
with HasTraceGenParams
with HasGroundTestParameters {
val io = new Bundle { val io = new Bundle {
val finished = Bool(OUTPUT) val finished = Bool(OUTPUT)
val timeout = Bool(OUTPUT) val timeout = Bool(OUTPUT)
val mem = new HellaCacheIO val mem = new HellaCacheIO
val hartid = UInt(INPUT, log2Up(numGens))
} }
val totalNumAddrs = addressBag.size + numExtraAddrs val totalNumAddrs = addressBag.size + numExtraAddrs
@ -199,8 +205,6 @@ class TraceGenerator(id: Int)
reqTimer.io.stop.valid := io.mem.resp.valid reqTimer.io.stop.valid := io.mem.resp.valid
reqTimer.io.stop.bits := io.mem.resp.bits.tag reqTimer.io.stop.bits := io.mem.resp.bits.tag
assert(!reqTimer.io.timeout.valid, s"TraceGen core ${id}: request timed out")
// Random addresses // Random addresses
// ---------------- // ----------------
@ -327,7 +331,7 @@ class TraceGenerator(id: Int)
// ------------------ // ------------------
// Hardware thread id // Hardware thread id
val tid = UInt(id, numBitsInId) val tid = io.hartid
// Request & response count // Request & response count
val reqCount = Reg(init = UInt(0, 32)) val reqCount = Reg(init = UInt(0, 32))
@ -345,7 +349,7 @@ class TraceGenerator(id: Int)
sendFreshReq := Bool(false) sendFreshReq := Bool(false)
// Used to generate unique data values // Used to generate unique data values
val nextData = Reg(init = UInt(1, numBitsInWord-numBitsInId)) val nextData = Reg(init = UInt(1, numBitsInWord-tid.getWidth))
// Registers for all the interesting parts of a request // Registers for all the interesting parts of a request
val reqValid = Reg(init = Bool(false)) val reqValid = Reg(init = Bool(false))
@ -503,6 +507,7 @@ class TraceGenerator(id: Int)
io.mem.req.bits.typ := UInt(log2Ceil(numBytesInWord)) io.mem.req.bits.typ := UInt(log2Ceil(numBytesInWord))
io.mem.req.bits.cmd := reqCmd io.mem.req.bits.cmd := reqCmd
io.mem.req.bits.tag := reqTag io.mem.req.bits.tag := reqTag
io.mem.invalidate_lr := Bool(false)
// On cycle when request is actually sent, print it // On cycle when request is actually sent, print it
when (io.mem.req.fire()) { when (io.mem.req.fire()) {
@ -569,17 +574,25 @@ class TraceGenerator(id: Int)
// Trace-generator wrapper // Trace-generator wrapper
// ======================= // =======================
class GroundTestTraceGenerator(implicit p: Parameters) class TraceGenTile(val id: Int, val params: TraceGenParams)(implicit p: Parameters) extends GroundTestTile(params) {
extends GroundTest()(p) with HasTraceGenParams { override lazy val module = new TraceGenTileModule(this)
}
require(io.mem.size <= 1) class TraceGenTileModule(outer: TraceGenTile) extends GroundTestTileModule(outer, () => new GroundTestTileBundle(outer)) {
require(io.cache.size == 1)
val traceGen = Module(new TraceGenerator(p(TileId))) val tracegen = Module(new TraceGenerator(outer.params))
io.cache.head <> traceGen.io.mem tracegen.io.hartid := io.hartid
io.status.finished := traceGen.io.finished outer.dcacheOpt foreach { dcache =>
io.status.timeout.valid := traceGen.io.timeout val dcacheIF = Module(new SimpleHellaCacheIF())
dcacheIF.io.requestor <> tracegen.io.mem
dcache.module.io.cpu <> dcacheIF.io.cache
}
io.status.finished := tracegen.io.finished
io.status.timeout.valid := tracegen.io.timeout
io.status.timeout.bits := UInt(0) io.status.timeout.bits := UInt(0)
io.status.error.valid := Bool(false) io.status.error.valid := Bool(false)
assert(!tracegen.io.timeout, s"TraceGen tile ${outer.id}: request timed out")
} }

View File

@ -1,216 +0,0 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package groundtest
import Chisel._
import uncore.tilelink._
import coreplex.NTiles
import uncore.constants._
import junctions._
import rocket._
import util.SimpleTimer
import scala.util.Random
import config._
case class TrafficGeneratorParameters(
maxRequests: Int,
startAddress: BigInt)
case object GeneratorKey extends Field[TrafficGeneratorParameters]
trait HasTrafficGeneratorParameters extends HasGroundTestParameters {
implicit val p: Parameters
val genParams = p(GeneratorKey)
val nGens = p(GroundTestKey).map(
cs => cs.uncached + cs.cached).reduce(_ + _)
val genTimeout = 8192
val maxRequests = genParams.maxRequests
val startAddress = genParams.startAddress
val genWordBits = 32
val genWordBytes = genWordBits / 8
val wordOffset = log2Ceil(genWordBytes)
val wordSize = UInt(log2Ceil(genWordBytes))
require(startAddress % BigInt(genWordBytes) == 0)
}
class UncachedTileLinkGenerator(id: Int)
(implicit p: Parameters) extends TLModule()(p) with HasTrafficGeneratorParameters {
private val tlBlockOffset = tlBeatAddrBits + tlByteAddrBits
val io = new Bundle {
val mem = new ClientUncachedTileLinkIO
val status = new GroundTestStatus
}
val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4)
val state = Reg(init = s_start)
val (req_cnt, req_wrap) = Counter(io.mem.grant.fire(), maxRequests)
val sending = Reg(init = Bool(false))
when (state === s_start) {
sending := Bool(true)
state := s_put
}
when (io.mem.acquire.fire()) { sending := Bool(false) }
when (io.mem.grant.fire()) { sending := Bool(true) }
when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) }
val timeout = SimpleTimer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
assert(!timeout, s"Uncached generator ${id} timed out waiting for grant")
io.status.finished := (state === s_finished)
io.status.timeout.valid := timeout
io.status.timeout.bits := UInt(id)
val part_of_full_addr =
if (log2Ceil(nGens) > 0) {
Cat(UInt(id, log2Ceil(nGens)),
UInt(0, wordOffset))
} else {
UInt(0, wordOffset)
}
val full_addr = UInt(startAddress) + Cat(req_cnt, part_of_full_addr)
val addr_block = full_addr >> UInt(tlBlockOffset)
val addr_beat = full_addr(tlBlockOffset - 1, tlByteAddrBits)
val addr_byte = full_addr(tlByteAddrBits - 1, 0)
val data_prefix = Cat(UInt(id, log2Up(nGens)), req_cnt)
val word_data = Wire(UInt(width = genWordBits))
word_data := Cat(data_prefix, part_of_full_addr)
val beat_data = Fill(tlDataBits / genWordBits, word_data)
val wshift = Cat(beatOffset(full_addr), UInt(0, wordOffset))
val wmask = Fill(genWordBits / 8, Bits(1, 1)) << wshift
val put_acquire = Put(
client_xact_id = UInt(0),
addr_block = addr_block,
addr_beat = addr_beat,
data = beat_data,
wmask = Some(wmask),
alloc = Bool(false))
val get_acquire = Get(
client_xact_id = UInt(0),
addr_block = addr_block,
addr_beat = addr_beat,
addr_byte = addr_byte,
operand_size = wordSize,
alloc = Bool(false))
io.mem.acquire.valid := sending && !io.status.finished
io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire)
io.mem.grant.ready := !sending && !io.status.finished
def wordFromBeat(addr: UInt, dat: UInt) = {
val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3))
(dat >> shift)(genWordBits - 1, 0)
}
val data_mismatch = io.mem.grant.fire() && state === s_get &&
wordFromBeat(full_addr, io.mem.grant.bits.data) =/= word_data
io.status.error.valid := data_mismatch
io.status.error.bits := UInt(id)
assert(!data_mismatch,
s"Get received incorrect data in uncached generator ${id}")
def beatOffset(addr: UInt) = // TODO zero-width
if (tlByteAddrBits > wordOffset) addr(tlByteAddrBits - 1, wordOffset)
else UInt(0)
}
class HellaCacheGenerator(id: Int)
(implicit val p: Parameters) extends Module with HasTrafficGeneratorParameters {
val io = new Bundle {
val mem = new HellaCacheIO
val status = new GroundTestStatus
}
val timeout = SimpleTimer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
assert(!timeout, s"Cached generator ${id} timed out waiting for response")
io.status.timeout.valid := timeout
io.status.timeout.bits := UInt(id)
val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4)
val state = Reg(init = s_start)
val sending = Reg(init = Bool(false))
val (req_cnt, req_wrap) = Counter(io.mem.resp.valid, maxRequests)
val part_of_req_addr =
if (log2Ceil(nGens) > 0) {
Cat(UInt(id, log2Ceil(nGens)),
UInt(0, wordOffset))
} else {
UInt(0, wordOffset)
}
val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr)
val req_data = Cat(UInt(id, log2Up(nGens)), req_cnt, part_of_req_addr)
io.mem.req.valid := sending && !io.status.finished
io.mem.req.bits.addr := req_addr
io.mem.req.bits.data := req_data
io.mem.req.bits.typ := wordSize
io.mem.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD)
io.mem.req.bits.tag := UInt(0)
when (state === s_start) { sending := Bool(true); state := s_write }
when (io.mem.req.fire()) { sending := Bool(false) }
when (io.mem.resp.valid) { sending := Bool(true) }
when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) }
io.status.finished := (state === s_finished)
def data_match(recv: Bits, expected: Bits): Bool = {
val recv_resized = Wire(Bits(width = genWordBits))
val exp_resized = Wire(Bits(width = genWordBits))
recv_resized := recv
exp_resized := expected
recv_resized === exp_resized
}
val data_mismatch = io.mem.resp.valid && io.mem.resp.bits.has_data &&
!data_match(io.mem.resp.bits.data, req_data)
io.status.error.valid := data_mismatch
io.status.error.bits := UInt(id)
assert(!data_mismatch,
s"Received incorrect data in cached generator ${id}")
}
class GeneratorTest(implicit p: Parameters)
extends GroundTest()(p) with HasTrafficGeneratorParameters {
val idStart = p(GroundTestKey).take(p(TileId))
.map(settings => settings.cached + settings.uncached)
.foldLeft(0)(_ + _)
val cached = List.tabulate(nCached) { i =>
val realId = idStart + i
Module(new HellaCacheGenerator(realId))
}
val uncached = List.tabulate(nUncached) { i =>
val realId = idStart + nCached + i
Module(new UncachedTileLinkGenerator(realId))
}
io.cache <> cached.map(_.io.mem)
io.mem <> uncached.map(_.io.mem)
val gen_debug = cached.map(_.io.status) ++ uncached.map(_.io.status)
io.status := DebugCombiner(gen_debug)
}

View File

@ -1,168 +0,0 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package groundtest
import Chisel._
// ============
// LCG16 module
// ============
// A 16-bit psuedo-random generator based on a linear conguential
// generator (LCG). The state is stored in an unitialised register.
// When using the C++ backend, it is straigtforward to arrange a
// random initial value for each uninitialised register, effectively
// seeding each LCG16 instance with a different seed.
class LCG16 extends Module {
val io = new Bundle {
val out = UInt(OUTPUT, 16)
val inc = Bool(INPUT)
}
val state = Reg(UInt(width = 32))
when (io.inc) {
state := state * UInt(1103515245, 32) + UInt(12345, 32)
}
io.out := state(30, 15)
}
// ==========
// LCG module
// ==========
// An n-bit psuedo-random generator made from many instances of a
// 16-bit LCG. Parameter 'width' must be larger than 0.
class LCG(val w: Int) extends Module {
val io = new Bundle {
val out = UInt(OUTPUT, w)
val inc = Bool(INPUT)
}
require(w > 0)
val numLCG16s : Int = (w+15)/16
val outs = Seq.fill(numLCG16s) { LCG16(io.inc) }
io.out := Cat(outs)
}
object LCG16 {
def apply(inc: Bool = Bool(true)): UInt = {
val lcg = Module(new LCG16)
lcg.io.inc := inc
lcg.io.out
}
}
object LCG {
def apply(w: Int, inc: Bool = Bool(true)): UInt = {
val lcg = Module(new LCG(w))
lcg.io.inc := inc
lcg.io.out
}
}
// ======================
// Frequency distribution
// ======================
// Given a list of (frequency, value) pairs, return a random value
// according to the frequency distribution. The sum of the
// frequencies in the distribution must be a power of two.
object Frequency {
def apply(dist : List[(Int, Bits)]) : Bits = {
// Distribution must be non-empty
require(dist.length > 0)
// Require that the frequencies sum to a power of two
val (freqs, vals) = dist.unzip
val total = freqs.sum
require(isPow2(total))
// First item in the distribution
val (firstFreq, firstVal) = dist.head
// Result wire
val result = Wire(Bits(width = firstVal.getWidth))
result := UInt(0)
// Random value
val randVal = LCG(log2Up(total))
// Pick return value
var count = firstFreq
var select = when (randVal < UInt(firstFreq)) { result := firstVal }
for (p <- dist.drop(1)) {
count = count + p._1
select = select.elsewhen(randVal < UInt(count)) { result := p._2 }
}
return result
}
}
object ValidMux {
def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = {
apply(v1 +: v2.toSeq)
}
def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = {
val out = Wire(Valid(valids.head.bits))
out.valid := valids.map(_.valid).reduce(_ || _)
out.bits := MuxCase(valids.head.bits,
valids.map(v => (v.valid -> v.bits)))
out
}
}
object DebugCombiner {
def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = {
val out = Wire(new GroundTestStatus)
out.finished := debugs.map(_.finished).reduce(_ && _)
out.timeout := ValidMux(debugs.map(_.timeout))
out.error := ValidMux(debugs.map(_.error))
out
}
}
/**
* Takes in data on one decoupled interface and broadcasts it to
* N decoupled output interfaces
*/
class Broadcaster[T <: Data](typ: T, n: Int) extends Module {
val io = new Bundle {
val in = Decoupled(typ).flip
val out = Vec(n, Decoupled(typ))
}
require (n > 0)
if (n == 1) {
io.out.head <> io.in
} else {
val idx = Reg(init = UInt(0, log2Up(n)))
val save = Reg(typ)
io.out.head.valid := idx === UInt(0) && io.in.valid
io.out.head.bits := io.in.bits
for (i <- 1 until n) {
io.out(i).valid := idx === UInt(i)
io.out(i).bits := save
}
io.in.ready := io.out.head.ready && idx === UInt(0)
when (io.in.fire()) { save := io.in.bits }
when (io.out(idx).fire()) {
when (idx === UInt(n - 1)) { idx := UInt(0) }
.otherwise { idx := idx + UInt(1) }
}
}
}
object Broadcaster {
def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = {
val split = Module(new Broadcaster(in.bits, n))
split.io.in <> in
split.io.out
}
}

View File

@ -1,6 +1,6 @@
// See LICENSE.jtag for license details. // See LICENSE.jtag for license details.
package jtag package freechips.rocketchip.jtag
import chisel3._ import chisel3._
import chisel3.core.DataMirror import chisel3.core.DataMirror

View File

@ -1,10 +1,10 @@
// See LICENSE.jtag for license details. // See LICENSE.jtag for license details.
package jtag package freechips.rocketchip.jtag
import util.{AsyncResetRegVec}
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.util.{AsyncResetRegVec}
object JtagState { object JtagState {
sealed abstract class State(val id: Int) { sealed abstract class State(val id: Int) {

View File

@ -1,6 +1,6 @@
// See LICENSE.jtag for license details. // See LICENSE.jtag for license details.
package jtag package freechips.rocketchip.jtag
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._

View File

@ -1,6 +1,6 @@
// See LICENSE.jtag for license details. // See LICENSE.jtag for license details.
package jtag package freechips.rocketchip.jtag
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._

View File

@ -1,6 +1,6 @@
// See LICENSE.jtag for license details. // See LICENSE.jtag for license details.
package jtag package freechips.rocketchip.jtag
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._

View File

@ -1,5 +1,7 @@
// See LICENSE.jtag for license details // See LICENSE.jtag for license details
package freechips.rocketchip
import scala.language.implicitConversions import scala.language.implicitConversions
package object jtag { package object jtag {

View File

@ -1,79 +0,0 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package junctions
import Chisel._
import config._
class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int)
(implicit p: Parameters) extends NastiModule {
val io = new Bundle {
val nasti = new NastiIO
val finished = Bool(OUTPUT)
val start = Bool(INPUT)
}
val dataBytes = dataWidth / 8
val nastiDataBytes = nastiXDataBits / 8
val (write_cnt, write_done) = Counter(io.nasti.w.fire(), burstLen)
val (read_cnt, read_done) = Counter(io.nasti.r.fire(), burstLen)
val (req_cnt, reqs_done) = Counter(read_done, nBursts)
val req_addr = Cat(req_cnt, UInt(0, log2Up(burstLen * dataBytes)))
val write_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, write_cnt)
val expected_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, read_cnt)
val (s_idle :: s_write_addr :: s_write_data :: s_write_stall :: s_write_resp ::
s_read_addr :: s_read_data :: s_read_stall :: s_done :: Nil) = Enum(Bits(), 9)
val state = Reg(init = s_idle)
val (stall_cnt, stall_done) = Counter(state === s_read_stall, 2)
io.nasti.aw.valid := (state === s_write_addr)
io.nasti.aw.bits := NastiWriteAddressChannel(
id = UInt(0),
addr = req_addr,
size = UInt(log2Up(dataBytes)),
len = UInt(burstLen - 1))
io.nasti.w.valid := (state === s_write_data)
io.nasti.w.bits := NastiWriteDataChannel(
data = Cat(write_data, write_data),
last = (write_cnt === UInt(burstLen - 1)))
io.nasti.b.ready := (state === s_write_resp)
io.nasti.ar.valid := (state === s_read_addr)
io.nasti.ar.bits := NastiReadAddressChannel(
id = UInt(0),
addr = req_addr,
size = UInt(log2Up(dataBytes)),
len = UInt(burstLen - 1))
io.nasti.r.ready := (state === s_read_data)
io.finished := (state === s_done)
when (state === s_idle && io.start) { state := s_write_addr }
when (io.nasti.aw.fire()) { state := s_write_data }
when (io.nasti.w.fire()) { state := s_write_stall }
when (state === s_write_stall) { state := s_write_data }
when (write_done) { state := s_write_resp }
when (io.nasti.b.fire()) { state := s_read_addr }
when (io.nasti.ar.fire()) { state := s_read_data }
when (io.nasti.r.fire()) { state := s_read_stall }
when (stall_done) { state := s_read_data }
when (read_done) { state := s_write_addr }
when (reqs_done) { state := s_done }
val full_addr = req_addr + (read_cnt << UInt(log2Up(dataBytes)))
val byteshift = full_addr(log2Up(nastiDataBytes) - 1, 0)
val bitshift = Cat(byteshift, UInt(0, 3))
val read_data = (io.nasti.r.bits.data >> bitshift) & Fill(dataWidth, UInt(1, 1))
assert(!io.nasti.r.valid || read_data === expected_data,
s"NastiDriver got wrong data")
}

View File

@ -1,148 +0,0 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package junctions
import Chisel._
import config._
import scala.collection.mutable.HashMap
case class MemAttr(prot: Int, cacheable: Boolean = false)
sealed abstract class MemRegion {
def start: BigInt
def size: BigInt
def numSlaves: Int
def attr: MemAttr
def containsAddress(x: UInt) = UInt(start) <= x && x < UInt(start + size)
}
case class MemSize(size: BigInt, attr: MemAttr) extends MemRegion {
def start = 0
def numSlaves = 1
}
case class MemRange(start: BigInt, size: BigInt, attr: MemAttr) extends MemRegion {
def numSlaves = 1
}
object AddrMapProt {
val R = 0x1
val W = 0x2
val X = 0x4
val RW = R | W
val RX = R | X
val RWX = R | W | X
val SZ = 3
}
class AddrMapProt extends Bundle {
val x = Bool()
val w = Bool()
val r = Bool()
}
case class AddrMapEntry(name: String, region: MemRegion)
object AddrMap {
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
}
class AddrMap(
entriesIn: Seq[AddrMapEntry],
val start: BigInt = BigInt(0),
val collapse: Boolean = false) extends MemRegion {
private val slavePorts = HashMap[String, Int]()
private val mapping = HashMap[String, MemRegion]()
def isEmpty = entries.isEmpty
def length = entries.size
def numSlaves = slavePorts.size
val (size: BigInt, entries: Seq[AddrMapEntry], attr: MemAttr) = {
var ind = 0
var base = start
var rebasedEntries = collection.mutable.ArrayBuffer[AddrMapEntry]()
var prot = 0
var cacheable = true
for (AddrMapEntry(name, r) <- entriesIn) {
require (!mapping.contains(name))
base = r.start
r match {
case r: AddrMap =>
val subMap = new AddrMap(r.entries, base, r.collapse)
rebasedEntries += AddrMapEntry(name, subMap)
mapping += name -> subMap
mapping ++= subMap.mapping.map { case (k, v) => s"$name:$k" -> v }
if (r.collapse) {
slavePorts += (name -> ind)
ind += 1
} else {
slavePorts ++= subMap.slavePorts.map {
case (k, v) => s"$name:$k" -> (ind + v)
}
ind += r.numSlaves
}
case _ =>
val e = MemRange(base, r.size, r.attr)
rebasedEntries += AddrMapEntry(name, e)
mapping += name -> e
slavePorts += name -> ind
ind += r.numSlaves
}
base += r.size
prot |= r.attr.prot
cacheable &&= r.attr.cacheable
}
(base - start, rebasedEntries, MemAttr(prot, cacheable))
}
val flatten: Seq[AddrMapEntry] = {
mapping.toSeq.map {
case (name, range: MemRange) => Some(AddrMapEntry(name, range))
case _ => None
}.flatten.sortBy(_.region.start)
}
// checks to see whether any MemRange overlaps within this AddrMap
flatten.combinations(2) foreach {
case (Seq(AddrMapEntry(an, ar), AddrMapEntry(bn, br))) =>
val arEnd = ar.start + ar.size
val brEnd = br.start + br.size
val abOverlaps = ar.start < brEnd && br.start < arEnd
require(!abOverlaps,
s"region $an@0x${ar.start.toString(16)} overlaps region $bn@0x${br.start.toString(16)}")
}
def toRange: MemRange = MemRange(start, size, attr)
def apply(name: String): MemRegion = mapping(name)
def contains(name: String): Boolean = mapping.contains(name)
def port(name: String): Int = slavePorts(name)
def subMap(name: String): AddrMap = mapping(name).asInstanceOf[AddrMap]
def isInRegion(name: String, addr: UInt): Bool = mapping(name).containsAddress(addr)
def isCacheable(addr: UInt): Bool = {
flatten.filter(_.region.attr.cacheable).map(
_.region.containsAddress(addr)
).foldLeft(Bool(false))(_ || _)
}
def isValid(addr: UInt): Bool = {
flatten.map(_.region.containsAddress(addr)).foldLeft(Bool(false))(_ || _)
}
def getProt(addr: UInt): AddrMapProt = {
val protForRegion = flatten.map { entry =>
Mux(entry.region.containsAddress(addr),
UInt(entry.region.attr.prot, AddrMapProt.SZ), UInt(0))
}
new AddrMapProt().fromBits(protForRegion.reduce(_|_))
}
override def containsAddress(x: UInt) = {
flatten.map(_.region.containsAddress(x)).reduce(_||_)
}
}

View File

@ -1,565 +0,0 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package junctions
import Chisel._
import config._
import unittest.UnitTest
import util._
object HastiConstants
{
// Values for htrans
val SZ_HTRANS = 2
def HTRANS_IDLE = UInt(0, SZ_HTRANS) // No transfer requested, not in a burst
def HTRANS_BUSY = UInt(1, SZ_HTRANS) // No transfer requested, in a burst
def HTRANS_NONSEQ = UInt(2, SZ_HTRANS) // First (potentially only) request in a burst
def HTRANS_SEQ = UInt(3, SZ_HTRANS) // Following requests in a burst
// Values for hburst
val SZ_HBURST = 3
def HBURST_SINGLE = UInt(0, SZ_HBURST) // Single access (no burst)
def HBURST_INCR = UInt(1, SZ_HBURST) // Incrementing burst of arbitrary length, not crossing 1KB
def HBURST_WRAP4 = UInt(2, SZ_HBURST) // 4-beat wrapping burst
def HBURST_INCR4 = UInt(3, SZ_HBURST) // 4-beat incrementing burst
def HBURST_WRAP8 = UInt(4, SZ_HBURST) // 8-beat wrapping burst
def HBURST_INCR8 = UInt(5, SZ_HBURST) // 8-beat incrementing burst
def HBURST_WRAP16 = UInt(6, SZ_HBURST) // 16-beat wrapping burst
def HBURST_INCR16 = UInt(7, SZ_HBURST) // 16-beat incrementing burst
// Values for hresp
val SZ_HRESP = 1
def HRESP_OKAY = UInt(0, SZ_HRESP)
def HRESP_ERROR = UInt(1, SZ_HRESP)
// Values for hsize are identical to TileLink MT_SZ
// ie: 8*2^SZ_HSIZE bit transfers
val SZ_HSIZE = 3
// Values for hprot (a bitmask)
val SZ_HPROT = 4
def HPROT_DATA = UInt("b0001") // Data access or Opcode fetch
def HPROT_PRIVILEGED = UInt("b0010") // Privileged or User access
def HPROT_BUFFERABLE = UInt("b0100") // Bufferable or non-bufferable
def HPROT_CACHEABLE = UInt("b1000") // Cacheable or non-cacheable
def dgate(valid: Bool, b: UInt) = Fill(b.getWidth, valid) & b
}
import HastiConstants._
case class HastiParameters(dataBits: Int, addrBits: Int)
case object HastiId extends Field[String]
case class HastiKey(id: String) extends Field[HastiParameters]
trait HasHastiParameters {
implicit val p: Parameters
val hastiParams = p(HastiKey(p(HastiId)))
val hastiAddrBits = hastiParams.addrBits
val hastiDataBits = hastiParams.dataBits
val hastiDataBytes = hastiDataBits/8
val hastiAlignment = log2Ceil(hastiDataBytes)
}
abstract class HastiModule(implicit val p: Parameters) extends Module
with HasHastiParameters
abstract class HastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasHastiParameters
class HastiMasterIO(implicit p: Parameters) extends HastiBundle()(p) {
val htrans = UInt(OUTPUT, SZ_HTRANS)
val hmastlock = Bool(OUTPUT)
val haddr = UInt(OUTPUT, hastiAddrBits)
val hwrite = Bool(OUTPUT)
val hburst = UInt(OUTPUT, SZ_HBURST)
val hsize = UInt(OUTPUT, SZ_HSIZE)
val hprot = UInt(OUTPUT, SZ_HPROT)
val hwdata = Bits(OUTPUT, hastiDataBits)
val hrdata = Bits(INPUT, hastiDataBits)
val hready = Bool(INPUT)
val hresp = UInt(INPUT, SZ_HRESP)
def isNSeq(dummy:Int=0) = htrans === HTRANS_NONSEQ // SEQ does not start a NEW request
def isHold(dummy:Int=0) = htrans === HTRANS_BUSY || htrans === HTRANS_SEQ
def isIdle(dummy:Int=0) = htrans === HTRANS_IDLE || htrans === HTRANS_BUSY
}
class HastiSlaveIO(implicit p: Parameters) extends HastiBundle()(p) {
val htrans = UInt(INPUT, SZ_HTRANS)
val hmastlock = Bool(INPUT)
val haddr = UInt(INPUT, hastiAddrBits)
val hwrite = Bool(INPUT)
val hburst = UInt(INPUT, SZ_HBURST)
val hsize = UInt(INPUT, SZ_HSIZE)
val hprot = UInt(INPUT, SZ_HPROT)
val hwdata = Bits(INPUT, hastiDataBits)
val hrdata = Bits(OUTPUT, hastiDataBits)
val hsel = Bool(INPUT)
val hready = Bool(OUTPUT)
val hresp = UInt(OUTPUT, SZ_HRESP)
}
/* A diverted master is told hready when his address phase goes nowhere.
* In this case, we buffer his address phase request and replay it later.
* NOTE: this must optimize to nothing when divert is constantly false.
*/
class MasterDiversion(implicit p: Parameters) extends HastiModule()(p) {
val io = new Bundle {
val in = (new HastiMasterIO).flip
val out = (new HastiMasterIO)
val divert = Bool(INPUT)
}
val full = Reg(init = Bool(false))
val buffer = Reg(new HastiMasterIO)
when (io.out.hready) {
full := Bool(false)
}
when (io.divert) {
full := Bool(true)
buffer := io.in
}
// If the master is diverted, he must also have been told hready
assert (!io.divert || io.in.hready,
"Diverted but not ready");
// Replay the request we diverted
io.out.htrans := Mux(full, buffer.htrans, io.in.htrans)
io.out.hmastlock := Mux(full, buffer.hmastlock, io.in.hmastlock)
io.out.haddr := Mux(full, buffer.haddr, io.in.haddr)
io.out.hwrite := Mux(full, buffer.hwrite, io.in.hwrite)
io.out.hburst := Mux(full, buffer.hburst, io.in.hburst)
io.out.hsize := Mux(full, buffer.hsize, io.in.hsize)
io.out.hprot := Mux(full, buffer.hprot, io.in.hprot)
io.out.hwdata := Mux(full, buffer.hwdata, io.in.hwdata)
// Pass slave response back
io.in.hrdata := io.out.hrdata
io.in.hresp := io.out.hresp
io.in.hready := io.out.hready && !full // Block master while we steal his address phase
}
/* Masters with lower index have priority over higher index masters.
* However, a lower priority master will retain control of a slave when EITHER:
* 1. a burst is in progress (switching slaves mid-burst violates AHB-lite at slave)
* 2. a transfer was waited (the standard forbids changing requests in this case)
*
* If a master raises hmastlock, it will be waited until no other master has inflight
* requests; then, it acquires exclusive control of the crossbar until hmastlock is low.
*
* To implement an AHB-lite crossbar, it is important to realize that requests and
* responses are coupled. Unlike modern bus protocols where the response data has flow
* control independent of the request data, in AHB-lite, both flow at the same time at
* the sole discretion of the slave via the hready signal. The address and data are
* delivered on two back-to-back cycles, the so-called address and data phases.
*
* Masters can only be connected to a single slave at a time. If a master had two different
* slave connections on the address and data phases, there would be two independent hready
* signals. An AHB-lite slave can assume that data flows when it asserts hready. If the data
* slave deasserts hready while the address slave asserts hready, the master is put in the
* impossible position of being in data phase on two slaves at once. For this reason, when
* a master issues back-to-back accesses to distinct slaves, we inject a pipeline bubble
* between the two requests to limit the master to just a single slave at a time.
*
* Conversely, a slave CAN have two masters attached to it. This is unproblematic, because
* the only signal which governs data flow is hready. Thus, both masters can be stalled
* safely by the single slave.
*/
class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) {
val io = new Bundle {
val masters = Vec(nMasters, new HastiMasterIO).flip
val slaves = Vec(addressMap.size, new HastiSlaveIO).flip
}
val nSlaves = addressMap.size
// Setup diversions infront of each master
val diversions = Seq.tabulate(nMasters) { m => Module(new MasterDiversion) }
(io.masters zip diversions) foreach { case (m, d) => d.io.in <> m }
// Handy short-hand
val masters = diversions map (_.io.out)
val slaves = io.slaves
// Lock status of the crossbar
val lockedM = Reg(init = Vec.fill(nMasters)(Bool(false)))
val isLocked = lockedM.reduce(_ || _)
// This matrix governs the master-slave connections in the address phase
// It is indexed by addressPhaseGrantSM(slave)(master)
// It is guaranteed to have at most one 'true' per column and per row
val addressPhaseGrantSM = Wire(Vec(nSlaves, Vec(nMasters, Bool())))
// This matrix governs the master-slave connections in the data phase
// It is guaranteed to have at most one 'true' per column and per row
val dataPhaseGrantSM = Reg (init = Vec.fill(nSlaves)(Vec.fill(nMasters)(Bool(false))))
// This matrix is the union of the address and data phases.
// It is transposed with respect to the two previous matrices.
// It is guaranteed to contain at most one 'true' per master row.
// However, two 'true's per slave column are permitted.
val unionGrantMS = Vec.tabulate(nMasters) { m => Vec.tabulate(nSlaves) { s =>
addressPhaseGrantSM(s)(m) || dataPhaseGrantSM(s)(m) } }
// Confirm the guarantees made above
def justOnce(v: Vec[Bool]) = v.fold(Bool(false)) { case (p, v) =>
assert (!p || !v)
p || v
}
addressPhaseGrantSM foreach { s => justOnce(s) }
unionGrantMS foreach { s => justOnce(s) }
// Data phase follows address phase whenever the slave is ready
(slaves zip (dataPhaseGrantSM zip addressPhaseGrantSM)) foreach { case (s, (d, a)) =>
when (s.hready) { d := a }
}
// Record the grant state from the previous cycle; needed in case we hold access
val priorAddressPhaseGrantSM = RegNext(addressPhaseGrantSM)
// If a master says BUSY or SEQ, it is in the middle of a burst.
// In this case, it MUST stay attached to the same slave as before.
// Otherwise, it would violate the AHB-lite specification as seen by
// the slave, which is guaranteed a complete burst of the promised length.
// One case where this matters is preventing preemption of low-prio masters.
// NOTE: this exposes a slave to bad addresses when a master is buggy
val holdBurstM = Vec(masters map { _.isHold() })
// Transform the burst hold requirement from master indexing to slave indexing
// We use the previous cycle's binding because the master continues the prior burst
val holdBurstS = Vec(priorAddressPhaseGrantSM map { m => Mux1H(m, holdBurstM) })
// If a slave says !hready to a request, it must retain the same master next cycle.
// The AHB-lite specification requires that a waited transfer remain unchanged.
// If we preempted a waited master, the new master's request could potentially differ.
val holdBusyS = RegNext(Vec(slaves map { s => !s.hready && s.hsel }))
// Combine the above two grounds to determine if the slave retains its prior master
val holdS = Vec((holdBurstS zip holdBusyS) map ({ case (a,b) => a||b }))
// Determine which master addresses match which slaves
val matchMS = Vec(masters map { m => Vec(addressMap map { afn => afn(m.haddr) }) })
// Detect requests to nowhere; we need to allow progress in this case
val nowhereM = Vec(matchMS map { s => !s.reduce(_ || _) })
// Detect if we need to inject a pipeline bubble between the master requests.
// Divert masters already granted a data phase different from next request.
// NOTE: if only one slave, matchMS is always true => bubble always false
// => the diversion registers are optimized away as they are unread
// NOTE: bubble => dataPhase => have an hready signal
val bubbleM =
Vec.tabulate(nMasters) { m =>
Vec.tabulate(nSlaves) { s => dataPhaseGrantSM(s)(m) && !matchMS(m)(s) }
.reduce(_ || _) }
// Block any request that requires bus ownership or conflicts with isLocked
val blockedM =
Vec((lockedM zip masters) map { case(l, m) => !l && (isLocked || m.hmastlock) })
// Requested access to slaves from masters (pre-arbitration)
// NOTE: isNSeq does NOT include SEQ; thus, masters who are midburst do not
// request access to a new slave. They stay tied to the old and do not get two.
// NOTE: if a master was waited, it must repeat the same request as last cycle;
// thus, it will request the same slave and not end up with two (unless buggy).
val NSeq = masters.map(_.isNSeq())
val requestSM = Vec.tabulate(nSlaves) { s => Vec.tabulate(nMasters) { m =>
matchMS(m)(s) && NSeq(m) && !bubbleM(m) && !blockedM(m) } }
// Select at most one master request per slave (lowest index = highest priority)
val selectedRequestSM = Vec(requestSM map { m => Vec(PriorityEncoderOH(m)) })
// Calculate new crossbar interconnect state
addressPhaseGrantSM := Vec((holdS zip (priorAddressPhaseGrantSM zip selectedRequestSM))
map { case (h, (p, r)) => Mux(h, p, r) })
for (m <- 0 until nMasters) {
// If the master is connected to a slave, the slave determines hready.
// However, if no slave is connected, for progress report ready anyway, if:
// bad address (swallow request) OR idle (permit stupid masters to move FSM)
val autoready = nowhereM(m) || masters(m).isIdle()
val hready = if (nSlaves == 1)
Mux(unionGrantMS(m)(0), slaves(0).hready ^ autoready, Bool(false)) ^ autoready
else
Mux1H(unionGrantMS(m), slaves.map(_.hready ^ autoready)) ^ autoready
masters(m).hready := hready
// If we diverted a master, we need to absorb his address phase to replay later
diversions(m).io.divert := (bubbleM(m) || blockedM(m)) && NSeq(m) && hready
}
// Master muxes (address and data phase are the same)
(masters zip unionGrantMS) foreach { case (m, g) => {
m.hrdata := Mux1H(g, slaves.map(_.hrdata))
m.hresp := Mux1H(g, slaves.map(_.hresp))
} }
// Slave address phase muxes
(slaves zip addressPhaseGrantSM) foreach { case (s, g) => {
s.htrans := Mux1H(g, masters.map(_.htrans))
s.haddr := Mux1H(g, masters.map(_.haddr))
s.hmastlock := isLocked
s.hwrite := Mux1H(g, masters.map(_.hwrite))
s.hsize := Mux1H(g, masters.map(_.hsize))
s.hburst := Mux1H(g, masters.map(_.hburst))
s.hprot := Mux1H(g, masters.map(_.hprot))
s.hsel := g.reduce(_ || _)
} }
// Slave data phase muxes
(slaves zip dataPhaseGrantSM) foreach { case (s, g) => {
s.hwdata := Mux1H(g, masters.map(_.hwdata))
} }
// When no master-slave connections are active, a master can take-over the bus
val canLock = !addressPhaseGrantSM.map({ v => v.reduce(_ || _) }).reduce(_ || _)
// Lowest index highest priority for lock arbitration
val reqLock = masters.map(_.hmastlock)
val winLock = PriorityEncoderOH(reqLock)
// Lock arbitration
when (isLocked) {
lockedM := (lockedM zip reqLock) map { case (a,b) => a && b }
} .elsewhen (canLock) {
lockedM := winLock
}
}
class HastiBus(amap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) {
val io = new Bundle {
val master = new HastiMasterIO().flip
val slaves = Vec(amap.size, new HastiSlaveIO).flip
}
val bar = Module(new HastiXbar(1, amap))
bar.io.masters(0) <> io.master
bar.io.slaves <> io.slaves
}
class HastiSlaveMux(n: Int)(implicit p: Parameters) extends HastiModule()(p) {
val io = new Bundle {
val ins = Vec(n, new HastiSlaveIO)
val out = new HastiSlaveIO().flip
}
val amap = Seq({ (_:UInt) => Bool(true)})
val bar = Module(new HastiXbar(n, amap))
io.ins <> bar.io.masters
io.out <> bar.io.slaves(0)
}
class HastiSlaveToMaster(implicit p: Parameters) extends HastiModule()(p) {
val io = new Bundle {
val in = new HastiSlaveIO
val out = new HastiMasterIO
}
io.out.htrans := Mux(io.in.hsel, io.in.htrans, HTRANS_IDLE)
io.out.hmastlock := io.in.hmastlock
io.out.haddr := io.in.haddr
io.out.hwrite := io.in.hwrite
io.out.hburst := io.in.hburst
io.out.hsize := io.in.hsize
io.out.hprot := io.in.hprot
io.out.hwdata := io.in.hwdata
io.in.hrdata := io.out.hrdata
io.in.hready := io.out.hready
io.in.hresp := io.out.hresp
}
class HastiMasterIONastiIOConverter(implicit p: Parameters) extends HastiModule()(p)
with HasNastiParameters {
val io = new Bundle {
val nasti = new NastiIO().flip
val hasti = new HastiMasterIO
}
require(hastiAddrBits == nastiXAddrBits)
require(hastiDataBits == nastiXDataBits)
val r_queue = Module(new Queue(new NastiReadDataChannel, 2, pipe = true))
val s_idle :: s_read :: s_write :: s_write_resp :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle)
val addr = Reg(UInt(width = hastiAddrBits))
val id = Reg(UInt(width = nastiXIdBits))
val size = Reg(UInt(width = nastiXSizeBits))
val len = Reg(UInt(width = nastiXLenBits))
val data = Reg(UInt(width = nastiXDataBits))
val first = Reg(init = Bool(false))
val is_rtrans = (state === s_read) &&
(io.hasti.htrans === HTRANS_SEQ ||
io.hasti.htrans === HTRANS_NONSEQ)
val rvalid = RegEnable(is_rtrans, Bool(false), io.hasti.hready)
io.nasti.aw.ready := (state === s_idle)
io.nasti.ar.ready := (state === s_idle) && !io.nasti.aw.valid
io.nasti.w.ready := (state === s_write) && io.hasti.hready
io.nasti.b.valid := (state === s_write_resp)
io.nasti.b.bits := NastiWriteResponseChannel(id = id)
io.nasti.r <> r_queue.io.deq
r_queue.io.enq.valid := io.hasti.hready && rvalid
r_queue.io.enq.bits := NastiReadDataChannel(
id = id,
data = io.hasti.hrdata,
last = (len === UInt(0)))
assert(!r_queue.io.enq.valid || r_queue.io.enq.ready,
"NASTI -> HASTI converter queue overflow")
// How many read requests have we not delivered a response for yet?
val pending_count = r_queue.io.count + rvalid
io.hasti.haddr := addr
io.hasti.hsize := size
io.hasti.hwrite := (state === s_write)
io.hasti.hburst := HBURST_INCR
io.hasti.hprot := UInt(0)
io.hasti.hwdata := data
io.hasti.hmastlock := Bool(false)
io.hasti.htrans := MuxLookup(state, HTRANS_IDLE, Seq(
s_write -> Mux(io.nasti.w.valid,
Mux(first, HTRANS_NONSEQ, HTRANS_SEQ),
Mux(first, HTRANS_IDLE, HTRANS_BUSY)),
s_read -> MuxCase(HTRANS_BUSY, Seq(
first -> HTRANS_NONSEQ,
(pending_count <= UInt(1)) -> HTRANS_SEQ))))
when (io.nasti.aw.fire()) {
first := Bool(true)
addr := io.nasti.aw.bits.addr
id := io.nasti.aw.bits.id
size := io.nasti.aw.bits.size
state := s_write
}
when (io.nasti.ar.fire()) {
first := Bool(true)
addr := io.nasti.ar.bits.addr
id := io.nasti.ar.bits.id
size := io.nasti.ar.bits.size
len := io.nasti.ar.bits.len
state := s_read
}
when (io.nasti.w.fire()) {
first := Bool(false)
addr := addr + (UInt(1) << size)
data := io.nasti.w.bits.data
when (io.nasti.w.bits.last) { state := s_write_resp }
}
when (io.nasti.b.fire()) { state := s_idle }
when (is_rtrans && io.hasti.hready) {
first := Bool(false)
addr := addr + (UInt(1) << size)
len := len - UInt(1)
when (len === UInt(0)) { state := s_idle }
}
}
class HastiTestSRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p) {
val io = new HastiSlaveIO
// This is a test SRAM with random delays
val ready = LFSR16(Bool(true))(0) // Bool(true)
// Calculate the bitmask of which bytes are being accessed
val mask_decode = Vec.tabulate(hastiAlignment+1) (UInt(_) <= io.hsize)
val mask_wide = Vec.tabulate(hastiDataBytes) { i => mask_decode(log2Ceil(i+1)) }
val mask_shift = if (hastiAlignment == 0) UInt(1) else
mask_wide.asUInt() << io.haddr(hastiAlignment-1,0)
// The request had better have been aligned! (AHB-lite requires this)
if (hastiAlignment >= 1) {
assert (io.htrans === HTRANS_IDLE || io.htrans === HTRANS_BUSY ||
(io.haddr & mask_decode.asUInt()(hastiAlignment,1)) === UInt(0),
"HASTI request not aligned")
}
// The mask and address during the address phase
val a_request = io.hsel && (io.htrans === HTRANS_NONSEQ || io.htrans === HTRANS_SEQ)
val a_mask = Wire(UInt(width = hastiDataBytes))
val a_address = io.haddr(depth-1, hastiAlignment)
val a_write = io.hwrite
// for backwards compatibility with chisel2, we needed a static width in definition
a_mask := mask_shift(hastiDataBytes-1, 0)
// The data phase signals
val d_read = RegEnable(a_request && !a_write, Bool(false), ready)
val d_mask = RegEnable(a_mask, ready && a_request)
val d_wdata = Vec.tabulate(hastiDataBytes) { i => io.hwdata(8*(i+1)-1, 8*i) }
// AHB writes must occur during the data phase; this poses a structural
// hazard with reads which must occur during the address phase. To solve
// this problem, we delay the writes until there is a free cycle.
//
// The idea is to record the address information from address phase and
// then as soon as possible flush the pending write. This cannot be done
// on a cycle when there is an address phase read, but on any other cycle
// the write will execute. In the case of reads following a write, the
// result must bypass data from the pending write into the read if they
// happen to have matching address.
// Pending write?
val p_valid = RegInit(Bool(false))
val p_address = Reg(a_address)
val p_mask = Reg(a_mask)
val p_latch_d = RegNext(ready && a_request && a_write, Bool(false))
val p_wdata = d_wdata holdUnless p_latch_d
// Use single-ported memory with byte-write enable
val mem = SeqMem(1 << (depth-hastiAlignment), Vec(hastiDataBytes, Bits(width = 8)))
// Decide is the SRAM port is used for reading or (potentially) writing
val read = ready && a_request && !a_write
// In case we are stalled, we need to hold the read data
val d_rdata = mem.readAndHold(a_address, read)
// Whenever the port is not needed for reading, execute pending writes
when (!read && p_valid) { mem.write(p_address, p_wdata, p_mask.toBools) }
when (!read) { p_valid := Bool(false) }
// Record the request for later?
when (ready && a_request && a_write) {
p_valid := Bool(true)
p_address := a_address
p_mask := a_mask
}
// Does the read need to be muxed with the previous write?
val a_bypass = a_address === p_address && p_valid
val d_bypass = RegEnable(a_bypass, ready && a_request)
// Mux in data from the pending write
val muxdata = Vec((p_mask.toBools zip (p_wdata zip d_rdata))
map { case (m, (p, r)) => Mux(d_bypass && m, p, r) })
// Wipe out any data the master should not see (for testing)
val outdata = Vec((d_mask.toBools zip muxdata)
map { case (m, p) => Mux(d_read && ready && m, p, Bits(0)) })
// Finally, the outputs
io.hrdata := outdata.asUInt
io.hready := ready
io.hresp := HRESP_OKAY
}
class HastiTest(implicit p: Parameters) extends UnitTest {
val sram = Module(new HastiTestSRAM(8))
val bus = Module(new HastiBus(Seq(a => Bool(true))))
val conv = Module(new HastiMasterIONastiIOConverter)
val driver = Module(new NastiDriver(32, 8, 2))
bus.io.slaves(0) <> sram.io
bus.io.master <> conv.io.hasti
conv.io.nasti <> driver.io.nasti
io.finished := driver.io.finished
driver.io.start := io.start
}

Some files were not shown because too many files have changed in this diff Show More