Search code examples
chiselrocket-chip

How to add a sbus master to rocket-chip periphery


I'm trying to implement a DMA like periphery to the rocket chip. Meaning a module that is hooked to the pbus, and controlled by registers. it also has a master hooked to the sbus.

I followed the sifive format to attach registers controlled peripheries without any problems. My question is how do I add the sbus master ?, the bellow is what I've tried before getting to dead end.

To the attach parameters class I've added the sbus:

case class dmaAttachParams(
    dma       : dmaParams,
    controlBus: TLBusWrapper,
    masterBus : TLBusWrapper, // <-- my addition 
    ....
) (implicit val p: Parameters) 

Then I modified the attach method in the factory object:

def attach(params: dmaAttachParams): TLdma = {
    implicit val p = params.p
    val name = s"dma_${nextId()}"
    val cbus = params.controlBus
    val mbus = params.masterBus  // <- my addition 
    val dma = LazyModule(new TLdma(params.dma))
    dma.suggestName(name)

    cbus.coupleTo(s"slave_named_name") {
        dma.controlXing(params.controlXType) := TLFragmenter(cbus.beatBytes, cbus.blockBytes) := _
    }

    InModuleBody { dma.module.clock := params.mclock.map(_.getWrappedValue).getOrElse(cbus.module.clock) }
    InModuleBody { dma.module.reset := params.mreset.map(_.getWrappedValue).getOrElse(cbus.module.reset) }

    // this section is my problem // <-- this section is my addition
    mbus.from(s"master_named_name") {
        mbus.inwardNode := TLBuffer() :=  dma.mnode // <- what should i do here ??? 
    }
    dma
}

The mndoe is a node I have add to the dma class like this:

val mnode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = "dmaSbusMaster")))))

what should be the body of the mbus.from() method that will do the work? trying to build this code gives this error:

Caused by: java.lang.IllegalArgumentException: requirement failed: buffer.node (A adapter node with parent buffer inside coupler_from_master_named_name) has 1 inputs and 0 outputs; they must match (Buffer.scala:69:28)

Any help will appreciated, in the rocket chip github issue forum, they no longer answer support questions. So if someone from there can answer here it will be great, as I am really stuck here.

P.S. just adding the way the attach method is invoked:

 trait HasPeripheryDma { this: BaseSubsystem =>
        val dmaNodes = p(PeripheryDmaKey).map { ps =>
            dma.attach(dmaAttachParams(ps, pbus, sbus))
        }
    }

Update:

Implementing the body of the mbus.from() method as below:

mbus.from(s"master_named_name") {
    mbus.inwardNode := TLBuffer(BufferParams.default)  := dma.mnode
}  

Does create a coupler from the dma on the SBUS , but it is not connected to the dma periphery. Any Ideas ?


Solution

  • I have managed to attach the SBUS by reverse engineering of the way the slave is attached. If someone can/wants to elaborate more feel free to do so.

    I have added a "TLOutwardCrossingHelper" field to the DMA periphery like this:

    class TLdma(params : dmaParams) (implicit p: Parameters) extends dma(params) with HasTLControlRegMap {
      val controlXingMaster : TLOutwardCrossingHelper = this.crossOut(mnode)
    }  
    

    please note that equivalent "TLInwardCrossingHelper" is defined in the "HasTLControlRegMap " trait that we extending.

    Then,In the attach method, the next line did the work:

    _ := TLBuffer(BufferParams.default) := dma.controlXingMaster(params.controlXType)
    

    In this way I was able to also hook the periphery to the coupler on the sbus. I assume the crossing object does something to the node , but I don't know what.