1
0
Fork 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:
- 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
- <<: *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
MODEL ?= TestHarness
PROJECT ?= rocketchip
PROJECT ?= freechips.rocketchip.chip
CFG_PROJECT ?= $(PROJECT)
CONFIG ?= DefaultConfig
# 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.
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**
This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped
parameterization library.
* **coreplex**
This RTL package generates a complete coreplex by gluing together a variety of other components,
including tiled Rocket cores, an L1-to-L2 network, L2 coherence agents, and internal devices
such as the debug unit and interrupt handlers.
This RTL package generates a complete coreplex by gluing together a variety of components from other packages,
including: tiled Rocket cores, a system bus network, coherence agents, debug devices, interrupt handlers, externally-facing peripherals,
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**
This utility package extends Chisel by allowing for two-phase hardware elaboration, in which certain parameters
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.
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.
* **uncore**
This RTL package generates a variety of uncore logic and devices, such as
such as the L2 coherence hub and Debug modules, as well as defining their interfaces and protocols.
Contains implementations of both TileLink and AXI4.
* **tile**
This RTL package contains components that can be combined with cores to construct tiles, such as FPUs and accelerators.
* **tilelink**
This RTL package uses diplomacy to generate bus implementations of the TileLink protocol. It also contains a variety
of adapters and protocol converters.
* **unittest**
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**
This utility package provides a variety of common Scala and Chisel constructs that are re-used across
multiple other packages,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details.
package uncore.ahb
package freechips.rocketchip.amba.ahb
import Chisel._
import config._
import diplomacy._
import regmapper._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max}
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_read := !ahb.hwrite
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)
@ -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
{
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
{

View File

@ -1,11 +1,11 @@
// See LICENSE.SiFive for license details.
package uncore.ahb
package freechips.rocketchip.amba.ahb
import Chisel._
import config._
import diplomacy._
import util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util._
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
val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ
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_write = in.hwrite

View File

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

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details.
package uncore.ahb
package freechips.rocketchip.amba.ahb
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import config._
import diplomacy._
import uncore.tilelink2._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.MaskGen
case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)(
dFn = { case AHBMasterPortParameters(masters) =>
@ -108,7 +109,7 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule
out.a.bits.source := UInt(0)
out.a.bits.address := d_addr
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
in.hrdata := out.d.bits.data

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details.
package uncore.apb
package freechips.rocketchip.amba.apb
import Chisel._
import config._
import diplomacy._
import regmapper._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.HeterogeneousBag
import scala.math.{min,max}
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
{
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
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,13 @@
// See LICENSE.SiFive for license details.
package uncore.axi4
package freechips.rocketchip.amba.axi4
import Chisel._
import config._
import diplomacy._
import regmapper._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max}
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 in_extra = Mux(ar.valid, ar_extra, aw_extra)
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.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
{
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
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,15 +1,17 @@
// See LICENSE.SiFive for license details.
package rocketchip
package freechips.rocketchip.chip
import Chisel._
import config._
import coreplex._
import diplomacy._
import jtag.JTAGIO
import uncore.tilelink2._
import uncore.devices._
import util._
import freechips.rocketchip.config._
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.coreplex._
import freechips.rocketchip.diplomacy._
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
* 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 {
val outer: HasPeripheryRTCCounter
val period = p(rocketchip.RTCPeriod)
val period = p(RTCPeriod)
val rtcCounter = RegInit(UInt(0, width = log2Up(period)))
val rtcWrap = rtcCounter === UInt(period-1)

View File

@ -1,10 +1,11 @@
// See LICENSE.SiFive for license details.
package rocketchip
package freechips.rocketchip.chip
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 */
trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,14 @@
// See LICENSE.SiFive for license details.
package coreplex
package freechips.rocketchip.coreplex
import Chisel._
import config._
import diplomacy._
import uncore.tilelink2._
import uncore.util._
import util._
import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.rocket.PAddrBits
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
trait CoreplexNetwork extends HasCoreplexParameters {
val module: CoreplexNetworkModule
@ -112,7 +113,7 @@ trait CoreplexNetworkModule extends HasCoreplexParameters {
val io: CoreplexNetworkBundle
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 def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = {

View File

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

View File

@ -1,17 +1,17 @@
// See LICENSE.SiFive for license details.
package coreplex
package freechips.rocketchip.coreplex
import Chisel._
import config.Field
import diplomacy._
import tile._
import uncore.tilelink2._
import uncore.devices._
import util._
/** Number of tiles */
case object NTiles extends Field[Int]
import freechips.rocketchip.config.Field
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 ClintKey extends Field[ClintParams]

View File

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

View File

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

View File

@ -1,16 +1,15 @@
// See LICENSE.SiFive for license details.
package uncore.devices
package freechips.rocketchip.devices.debug
import Chisel._
import junctions._
import util._
import regmapper._
import tile.XLen
import uncore.tilelink2._
import config._
import diplomacy._
import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
import freechips.rocketchip.rocket.Instructions
import freechips.rocketchip.tile.XLen
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
/** 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 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)
when (~io.dmactive){
@ -838,20 +837,20 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
val abstractGeneratedS = Wire(new GeneratedS())
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.funct3 := accessRegisterCommandReg.size
abstractGeneratedI.rs1 := 0.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.funct3 := accessRegisterCommandReg.size
abstractGeneratedS.rs1 := 0.U
abstractGeneratedS.rs2 := (accessRegisterCommandReg.regno & 0x1F.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.rs1 := 0.U
nop.imm := 0.U
@ -867,7 +866,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
)
abstractGeneratedMem(1) := Mux(accessRegisterCommandReg.postexec,
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.
package uncore.devices
package freechips.rocketchip.devices.debug
object DebugRomContents {

View File

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

View File

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

View File

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

View File

@ -1,11 +1,12 @@
// See LICENSE.SiFive for license details.
package uncore.tilelink2
package freechips.rocketchip.devices.tilelink
import Chisel._
import config._
import diplomacy._
import util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
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.
package uncore.devices
package freechips.rocketchip.devices.tilelink
import Chisel._
import Chisel.ImplicitConversions._
import junctions._
import diplomacy._
import regmapper._
import uncore.tilelink2._
import config._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tile.XLen
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
import scala.math.min
import tile.XLen
import util._
class GatewayPLICIO extends Bundle {
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.
package uncore.tilelink2
package freechips.rocketchip.devices.tilelink
import Chisel._
import config._
import diplomacy._
import util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
// Do not use this for synthesis! Only for simulation.
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 */
import unittest._
import freechips.rocketchip.unittest._
class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule {
val fuzz = LazyModule(new TLFuzzer(txns))

View File

@ -1,10 +1,11 @@
// See LICENSE.SiFive for license details.
package uncore.tilelink2
package freechips.rocketchip.devices.tilelink
import Chisel._
import config._
import diplomacy._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
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.
package diplomacy
package freechips.rocketchip.diplomacy
import Chisel._
import Chisel.log2Ceil
import scala.math.{max,min}
object AddressDecoder

View File

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

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
// See LICENSE.SiFive for license details.
package diplomacy
package freechips.rocketchip.diplomacy
import Chisel._
import config._
import util.HeterogeneousBag
import scala.collection.mutable.ListBuffer
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
// UI = Upwards flowing Parameters generated by the inner side of the node

View File

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

View File

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

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details.
import Chisel._
package freechips.rocketchip
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
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.Berkeley for license details.
package groundtest
package freechips.rocketchip.groundtest
import Chisel._
import rocket._
import diplomacy._
import uncore.tilelink._
import uncore.coherence._
import uncore.agents._
import uncore.util._
import tile.TileKey
import junctions._
import config._
import coreplex._
import rocketchip._
import freechips.rocketchip.chip.{BaseConfig, ExtMem}
import freechips.rocketchip.config.Config
import freechips.rocketchip.coreplex.{CacheBlockBytes, L1toL2Config, WithBufferlessBroadcastHub}
import freechips.rocketchip.rocket.{DCacheParams, PAddrBits}
import freechips.rocketchip.tile.{MaxHartIdBits, XLen}
/** 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(
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)
class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig)
/* Composable Configs to set individual parameters */
class WithGroundTestTiles extends Config((site, here, up) => {
case TileKey => site(GroundTestKey).head
case NTiles => site(GroundTestKey).size
})
class WithComparator(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(n) {
GroundTestTileParams(uncached = 2, dcache = None)
}
case BuildGroundTest =>
(p: Parameters) => Module(new ComparatorCore()(p))
case ComparatorKey => ComparatorParameters(
targets = Seq(site(ExtMem).base, testRamAddr),
width = 8,
operations = 1000,
atomics = false,
prefetches = false)
})
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
}
class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) extends Config((site, here, up) => {
case GroundTestTilesKey => params.map { dcp => TraceGenParams(
dcache = Some(dcp),
wordBits = site(XLen),
addrBits = site(PAddrBits),
addrBag = {
val nSets = 2
val nWays = 1
val blockOffset = log2Up(site(CacheBlockBytes))
val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes
List.tabulate(4 * nWays) { i =>
Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
}.flatten
},
maxRequests = nReqs,
memStart = site(ExtMem).base,
numGens = params.size)
}
case MaxHartIdBits => log2Up(params.size)
})

View File

@ -1,44 +1,27 @@
// See LICENSE.SiFive for license details.
package groundtest
package freechips.rocketchip.groundtest
import Chisel._
import config._
import diplomacy._
import coreplex._
import rocket._
import tile._
import uncore.agents._
import uncore.coherence._
import uncore.devices._
import uncore.tilelink._
import uncore.tilelink2._
import uncore.util._
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.coreplex._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.tile._
import scala.math.max
case object TileId extends Field[Int]
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
val tiles = List.tabulate(p(NTiles)) { i =>
LazyModule(new GroundTestTile()(p.alter { (site, here, up) => {
case TileId => i
case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes))
case AmoAluOperandBits => site(XLen)
val tileParams = p(GroundTestTilesKey)
val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule(
c.build(i, p.alterPartial {
case TileKey => c
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)
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) {
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.Berkeley for license details.
package groundtest
package freechips.rocketchip.groundtest
import Chisel._
import config._
import rocket._
import tile._
import util.ParameterizedBundle
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.rocket._
import freechips.rocketchip.tile.CoreModule
import freechips.rocketchip.util.ParameterizedBundle
class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
val io = new Bundle {

View File

@ -1,8 +1,10 @@
// 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
generateFirrtl
generateTestSuiteMakefrags // TODO: Needed only for legacy make targets

View File

@ -1,5 +1,9 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip
package object groundtest {
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.
package groundtest
package freechips.rocketchip.groundtest
import Chisel._
import diplomacy._
import config._
import rocketchip._
import util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.LazyModule
class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle { val success = Bool(OUTPUT) }

View File

@ -1,123 +1,51 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package groundtest
package freechips.rocketchip.groundtest
import Chisel._
import config._
import coreplex._
import rocket._
import tile._
import uncore.tilelink._
import uncore.tilelink2._
import rocketchip.ExtMem
import diplomacy._
import util.ParameterizedBundle
import freechips.rocketchip.config._
import freechips.rocketchip.coreplex._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.rocket._
import freechips.rocketchip.chip._
import freechips.rocketchip.tile._
import freechips.rocketchip.tilelink._
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
case class GroundTestTileParams(
uncached: Int = 0,
ptw: Int = 0,
maxXacts: Int = 1,
dcache: Option[DCacheParams] = Some(DCacheParams())) extends TileParams {
def build(i: Int, p: Parameters): GroundTestTile
val icache = None
val btb = None
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 dataScratchpadBytes = 0
}
case object GroundTestKey extends Field[Seq[GroundTestTileParams]]
trait HasGroundTestConstants {
val timeoutCodeBits = 4
val errorCodeBits = 4
case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]]
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 {
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)
class GroundTestTileBundle[+L <: GroundTestTile](_outer: L) extends BaseTileBundle(_outer) {
val status = new GroundTestStatus
}
abstract class GroundTest(implicit val p: Parameters) extends Module
with HasGroundTestParameters {
val io = new GroundTestIO
}
class GroundTestTileModule[+L <: GroundTestTile, +B <: GroundTestTileBundle[L]](_outer: L, _io: () => B) extends BaseTileModule(_outer, _io) {
class GroundTestTile(implicit p: Parameters) extends LazyModule
with HasGroundTestParameters {
val slave = None
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
outer.dcacheOpt foreach { dcache =>
val ptw = Module(new DummyPTW(1))
ptw.io.requestors.head <> dcache.module.io.ptw
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
// See LICENSE.jtag for license details
package freechips.rocketchip
import scala.language.implicitConversions
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