diff --git a/src/main/scala/amba/ahb/SRAM.scala b/src/main/scala/amba/ahb/SRAM.scala index ca783184..8c9fbab7 100644 --- a/src/main/scala/amba/ahb/SRAM.scala +++ b/src/main/scala/amba/ahb/SRAM.scala @@ -7,26 +7,28 @@ 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, errors: Seq[AddressSet] = Nil)(implicit p: Parameters) extends LazyModule +class AHBRAM( + address: AddressSet, + executable: Boolean = true, + beatBytes: Int = 4, + fuzzHreadyout: Boolean = false, + devName: Option[String] = None, + errors: Seq[AddressSet] = Nil) + (implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName) { val node = AHBSlaveNode(Seq(AHBSlavePortParameters( Seq(AHBSlaveParameters( address = List(address) ++ errors, + resources = resources, regionType = RegionType.UNCACHED, executable = executable, supportsRead = TransferSizes(1, beatBytes * AHBParameters.maxTransfer), supportsWrite = TransferSizes(1, beatBytes * AHBParameters.maxTransfer))), beatBytes = beatBytes))) - // 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 LazyModuleImp(this) { - 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, _) = node.in(0) + val mem = makeSinglePortedByteWriteSeqMem(1 << mask.filter(b=>b).size) // The mask and address during the address phase val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ @@ -57,9 +59,6 @@ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4 val p_latch_d = Reg(Bool()) val p_wdata = d_wdata holdUnless p_latch_d - // Use single-ported memory with byte-write enable - val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8))) - // Decide if the SRAM port is used for reading or (potentially) writing val read = a_request && !a_write // In case we choose to stall, we need to hold the read data diff --git a/src/main/scala/amba/apb/SRAM.scala b/src/main/scala/amba/apb/SRAM.scala index 1da18bb4..91e1f210 100644 --- a/src/main/scala/amba/apb/SRAM.scala +++ b/src/main/scala/amba/apb/SRAM.scala @@ -7,32 +7,31 @@ import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.util._ -class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, errors: Seq[AddressSet] = Nil)(implicit p: Parameters) extends LazyModule +class APBRAM( + address: AddressSet, + executable: Boolean = true, + beatBytes: Int = 4, + devName: Option[String] = None, + errors: Seq[AddressSet] = Nil) + (implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName) { val node = APBSlaveNode(Seq(APBSlavePortParameters( Seq(APBSlaveParameters( address = List(address) ++ errors, + resources = resources, regionType = RegionType.UNCACHED, executable = executable, supportsRead = true, supportsWrite = true)), beatBytes = beatBytes))) - // 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 LazyModuleImp(this) { val (in, _) = node.in(0) + val mem = makeSinglePortedByteWriteSeqMem(1 << mask.filter(b=>b).size) - 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 paddr = Cat((mask zip (in.paddr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) val legal = address.contains(in.paddr) - // Use single-ported memory with byte-write enable - val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8))) - val read = in.psel && !in.penable && !in.pwrite when (in.psel && !in.penable && in.pwrite && legal) { mem.write(paddr, Vec.tabulate(beatBytes) { i => in.pwdata(8*(i+1)-1, 8*i) }, in.pstrb.toBools) diff --git a/src/main/scala/amba/axi4/SRAM.scala b/src/main/scala/amba/axi4/SRAM.scala index 21be636e..09c8321c 100644 --- a/src/main/scala/amba/axi4/SRAM.scala +++ b/src/main/scala/amba/axi4/SRAM.scala @@ -7,11 +7,18 @@ import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.util._ -class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, errors: Seq[AddressSet] = Nil)(implicit p: Parameters) extends LazyModule +class AXI4RAM( + address: AddressSet, + executable: Boolean = true, + beatBytes: Int = 4, + devName: Option[String] = None, + errors: Seq[AddressSet] = Nil) + (implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName) { val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters( Seq(AXI4SlaveParameters( address = List(address) ++ errors, + resources = resources, regionType = RegionType.UNCACHED, executable = executable, supportsRead = TransferSizes(1, beatBytes), @@ -20,16 +27,9 @@ class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = beatBytes = beatBytes, minLatency = 1))) - // 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 LazyModuleImp(this) { - 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, _) = node.in(0) - val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8))) + val mem = makeSinglePortedByteWriteSeqMem(1 << mask.filter(b=>b).size) val r_addr = Cat((mask zip (in.ar.bits.addr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) val w_addr = Cat((mask zip (in.aw.bits.addr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) diff --git a/src/main/scala/diplomacy/SRAM.scala b/src/main/scala/diplomacy/SRAM.scala new file mode 100644 index 00000000..8add66d4 --- /dev/null +++ b/src/main/scala/diplomacy/SRAM.scala @@ -0,0 +1,30 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.diplomacy + +import Chisel._ +import freechips.rocketchip.config.Parameters + +abstract class DiplomaticSRAM( + address: AddressSet, + beatBytes: Int, + devName: Option[String])(implicit p: Parameters) extends LazyModule +{ + protected val resources = devName + .map(new SimpleDevice(_, Seq("sifive,sram0")).reg("mem")) + .getOrElse(new MemoryDevice().reg) + + def bigBits(x: BigInt, tail: List[Boolean] = Nil): List[Boolean] = + if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) + + def mask: List[Boolean] = bigBits(address.mask >> log2Ceil(beatBytes)) + + // Use single-ported memory with byte-write enable + def makeSinglePortedByteWriteSeqMem(size: Int) = { + // We require the address range to include an entire beat (for the write mask) + require ((address.mask & (beatBytes-1)) == beatBytes-1) + val mem = SeqMem(size, Vec(beatBytes, Bits(width = 8))) + devName.foreach(n => mem.suggestName(n.split("-").last)) + mem + } +} diff --git a/src/main/scala/tilelink/SRAM.scala b/src/main/scala/tilelink/SRAM.scala index a3845c9a..08cc0b1e 100644 --- a/src/main/scala/tilelink/SRAM.scala +++ b/src/main/scala/tilelink/SRAM.scala @@ -8,11 +8,14 @@ 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 +class TLRAM( + address: AddressSet, + executable: Boolean = true, + beatBytes: Int = 4, + devName: Option[String] = None, + errors: Seq[AddressSet] = Nil) + (implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName) { - 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, @@ -26,20 +29,13 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, 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 LazyModuleImp(this) { - 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, edge) = node.in(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 mem = makeSinglePortedByteWriteSeqMem(1 << addrBits.size) val d_full = RegInit(Bool(false)) val d_read = Reg(Bool())