1
0
rocket-chip/src/main/scala/tilelink/SRAM.scala
Wesley W. Terpstra 9804bdc34e tilelink: remove obsolete addr_lo signal (#895)
When we first implemented TL, we thought this was helpful, because
it made WidthWidgets stateless in all cases. However, it put too
much burden on all other masters and slaves, none of which benefitted
from this signal. Furthermore, even with addr_lo, WidthWidgets were
information lossy because when they widen, they have no information
about what to fill in the new high bits of addr_lo.
2017-07-26 16:01:21 -07:00

112 lines
4.0 KiB
Scala

// See LICENSE.SiFive for license details.
package freechips.rocketchip.tilelink
import Chisel._
import chisel3.experimental.chiselName
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util._
class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, name: Option[String] = None, errors: Seq[AddressSet] = Nil)(implicit p: Parameters) extends LazyModule
{
private val resources =
name.map(new SimpleDevice(_, Seq("sifive,sram0")).reg("mem")).getOrElse(new MemoryDevice().reg)
val node = TLManagerNode(Seq(TLManagerPortParameters(
Seq(TLManagerParameters(
address = List(address) ++ errors,
resources = resources,
regionType = RegionType.UNCACHED,
executable = executable,
supportsGet = TransferSizes(1, beatBytes),
supportsPutPartial = TransferSizes(1, beatBytes),
supportsPutFull = TransferSizes(1, beatBytes),
fifoId = Some(0))), // requests are handled in order
beatBytes = beatBytes,
minLatency = 1))) // no bypass needed for this device
// We require the address range to include an entire beat (for the write mask)
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new Implementation
@chiselName class Implementation extends LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val edge = node.edgesIn(0)
val addrBits = (mask zip edge.addr_hi(in.a.bits).toBools).filter(_._1).map(_._2)
val a_legal = address.contains(in.a.bits.address)
val memAddress = Cat(addrBits.reverse)
val mem = SeqMem(1 << addrBits.size, Vec(beatBytes, Bits(width = 8)))
val d_full = RegInit(Bool(false))
val d_read = Reg(Bool())
val d_size = Reg(UInt())
val d_source = Reg(UInt())
val d_data = Wire(UInt())
val d_legal = Reg(Bool())
// Flow control
when (in.d.fire()) { d_full := Bool(false) }
when (in.a.fire()) { d_full := Bool(true) }
in.d.valid := d_full
in.a.ready := in.d.ready || !d_full
in.d.bits := edge.AccessAck(d_source, d_size, !d_legal)
// avoid data-bus Mux
in.d.bits.data := d_data
in.d.bits.opcode := Mux(d_read, TLMessages.AccessAckData, TLMessages.AccessAck)
val read = in.a.bits.opcode === TLMessages.Get
val rdata = Wire(Vec(beatBytes, Bits(width = 8)))
val wdata = Vec.tabulate(beatBytes) { i => in.a.bits.data(8*(i+1)-1, 8*i) }
d_data := Cat(rdata.reverse)
when (in.a.fire()) {
d_read := read
d_size := in.a.bits.size
d_source := in.a.bits.source
d_legal := a_legal
}
// exactly this pattern is required to get a RWM memory
when (in.a.fire() && !read && a_legal) {
mem.write(memAddress, wdata, in.a.bits.mask.toBools)
}
val ren = in.a.fire() && read
rdata := mem.readAndHold(memAddress, ren)
// Tie off unused channels
in.b.valid := Bool(false)
in.c.ready := Bool(true)
in.e.ready := Bool(true)
}
}
/** Synthesizeable unit testing */
import freechips.rocketchip.unittest._
class TLRAMSimple(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule {
val fuzz = LazyModule(new TLFuzzer(txns))
val model = LazyModule(new TLRAMModel("SRAMSimple"))
val ram = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff), beatBytes = ramBeatBytes))
model.node := fuzz.node
ram.node := TLDelayer(0.25)(model.node)
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
io.finished := fuzz.module.io.finished
}
}
class TLRAMSimpleTest(ramBeatBytes: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) {
io.finished := Module(LazyModule(new TLRAMSimple(ramBeatBytes, txns)).module).io.finished
}