From 3797385a8cfaa1cccec1d0d13d91047accf548ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klemens=20Sch=C3=B6lhorn?= Date: Wed, 9 May 2018 23:17:08 +0200 Subject: [PATCH] Import ml507 mig TL implementation stub --- .../xilinxml507mig/XilinxML507MIG.scala | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala diff --git a/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala new file mode 100644 index 0000000..32d584a --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala @@ -0,0 +1,104 @@ +// See LICENSE.SiFive for license details. + +package sifive.fpgashells.devices.xilinx.xilinxml507mig + +import Chisel._ +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ + +case class MemoryML507Params( + address: Seq[AddressSet] +) + +case object MemoryML507Key extends Field[MemoryML507Params] + +trait HasMemoryML507 { this: BaseSubsystem => + val memory = LazyModule(new TLMemoryML507(p(MemoryML507Key))) + + // The Fragmenter will not fragment messages <= 32 bytes, so all + // slaves have to support this size. 64 byte specifies the maximum + // supported transfer size that the slave side of the fragmenter supports + // against the master (here the main memory bus). Specifying alwaysMin as + // true results in all messages being fragmented to the minimal size + // (32 byte). In TL1 terms, slaves + // correspond roughly to managers and masters to clients (confusingly…). + val fragmenter = TLFragmenter(32, 64, alwaysMin=true) + + // TODO: right TL/memory node chain? + memory.node := fragmenter := memBuses.head.toDRAMController(Some("ml507mig"))() +} + +class TLMemoryML507(c: MemoryML507Params)(implicit p: Parameters) extends LazyModule { + // Corresponds to MIG interface with 64 bit width and a burst length of 4 + val width = 256 + val beatBytes = width/8 // 32 byte (half a cache-line, fragmented) + + val device = new MemoryDevice + val node = TLManagerNode( + Seq(TLManagerPortParameters( + Seq(TLManagerParameters( + address = c.address, + resources = device.reg, + regionType = RegionType.UNCACHED, + executable = true, + supportsGet = TransferSizes(1, beatBytes), + supportsPutFull = TransferSizes(1, beatBytes), + fifoId = Some(0) // in-order + )), + beatBytes = beatBytes + )) + ) + // We could possibly also support supportsPutPartial, as we need support + // for masks anyway because of the possibility of transfers smaller that + // the data width (size signal, see below). + + lazy val module = new LazyModuleImp(this) { + // in: TLBundle, edge: TLEdgeIn + val (in, edge) = node.in(0) + + // Due to the Fragmenter defined above, all messages are 32 bytes or + // smaller. The data signal of the TL channels is also 32 bytes, so + // all messages will be transfered in a single beat. + // Also, TL guarantees (see TL$4.6) that the payload of a data message + // is always aligned to the width of the beat, e.g. in case of a 32 + // byte data signal, data[7:0] will always have address 0x***00000 and + // data[255:247] address 0x***11111. It is also guaranteed that the + // mask bits always correctly reflect the active bytes inside the beat + // with respect to the size and address. + // So we can directly forward the mask, (relative) address and possibly + // data to the MIG interface. + // Put requests can be acknowledged as soon as they are latched into + // the write fifo of the MIG (possibly combinatorily). + // For read requests, we have to store the source id and size in a + // queue for later acknowledgment. + // We are ready if both the MIG and the response data queue are not + // full. + + // Widths of the A channel: + // addressBits: 32 + // dataBits: 256 + // sourceBits: 6 + // sinkBits: 1 + // sizeBits: 3 + + // source (from): in.a.bits.source + // adresse (to): edgeIn.address(in.a.bits) + // size: edgeIn.size(in.a.bits) + // isPut: edgeIn.hasData(in.a.bits) + + // bits kommt von Decoupled: ready, valid + bits + + println("a parameters: " + in.a.bits.params) + + in.a.ready := Bool(false) + in.d.valid := Bool(false) + + // Tie off unused channels + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + } +}