diff --git a/src/main/scala/Switch/MacRegisters.scala b/src/main/scala/Switch/MacRegisters.scala index 2a5bd3f..6a704cc 100644 --- a/src/main/scala/Switch/MacRegisters.scala +++ b/src/main/scala/Switch/MacRegisters.scala @@ -76,6 +76,8 @@ class Mac_Config_Bundle extends Bundle{ class MacRegIO extends Mac_Config_Bundle{ val asyncReset = Input(AsyncReset()) + + val triTx = Output(Bool()) } class MacReg(implicit p: Parameters) extends LazyModule{ @@ -320,6 +322,11 @@ class MacRegImp(outer: MacReg)(implicit p: Parameters) extends LazyModuleImp(out RegField.bytes(txPauseTV, Some(RegFieldDesc("TxPauseTV", "Tx Pause Timer Value", reset=Some(0x0)))) ++ Seq( RegField(1, txPauseRq, RegFieldDesc("TxPauseRQ", "Tx Pause Request", reset=Some(0x0))), )), + + ( 30 << 2 ) -> + RegFieldGroup("BD", Some("bd"), + RegField.w(1, RegWriteFn((valid, data) => { io.triTx := (valid & (data === 1.U)) ; true.B} ),Some(RegFieldDesc("bd", "bd", reset=Some(0x0)))) ++ Seq( + )), ) diff --git a/src/main/scala/Switch/RxBuff.scala b/src/main/scala/Switch/RxBuff.scala new file mode 100644 index 0000000..854245a --- /dev/null +++ b/src/main/scala/Switch/RxBuff.scala @@ -0,0 +1,167 @@ +package Switch + +import chisel3._ +import chisel3.util._ + +class Receive_Enq_Ctrl_Bundle extends Bundle{ + val LatchedRxLength = UInt(16.W) + val RxStatusInLatched = UInt(9.W) + val isRxAbort = Bool() +} + +class Receive_Deq_Ctrl_Bundle extends Receive_Enq_Ctrl_Bundle{ + +} + +class Receive_Enq_Bundle extends Bundle{ + val data = Decoupled(UInt(32.W)) + val ctrl = Decoupled(new Receive_Enq_Ctrl_Bundle) +} + + +class Receive_Deq_Bundle extends Bundle{ + val data = Decoupled(UInt(32.W)) + val ctrl = Decoupled(new Receive_Deq_Ctrl_Bundle) + val header = Decoupled(Vec( 5, UInt(32.W) ) ) +} + + +class RxBuffIO extends Bundle{ + val enq = Flipped(new Receive_Enq_Bundle) + val deq = new Receive_Deq_Bundle +} + + +// class Packet_Info_Bundle extends Bundle{ +// val LatchedRxLength = UInt(16.W) +// val RxStatusInLatched = UInt(9.W) + +// } + + +class RxBuffBase extends Module{ + val io: RxBuffIO = IO(new RxBuffIO) + + val isEnqPi = RegInit(true.B) + val isEnqPo = ~isEnqPi + + val isDeqPi = RegInit(true.B) + val isDeqPo = ~isEnqPi + + + val buff = for( i <- 0 until 2 ) yield { Module(new Queue( UInt(32.W), 2048/4 )) } + val info = for( i <- 0 until 2 ) yield { Reg(new Receive_Enq_Ctrl_Bundle) } + // dontTouch(buff(0).io.enq) + // dontTouch(info(0)) + // dontTouch(buff(1).io.enq) + // dontTouch(info(1)) + + val header = for( i <- 0 until 2 ) yield { Reg(Vec( 5, UInt(32.W) )) } + val hValid = for( i <- 0 until 2 ) yield { RegInit(false.B) } + + val cValid = for( i <- 0 until 2 ) yield { RegInit(false.B) } + + + val recCnt = RegInit(0.U(3.W)) + + +} + + +trait RxBuffEnq{ this: RxBuffBase => + + + + buff(0).io.enq.valid := isEnqPi & io.enq.data.valid + buff(0).io.enq.bits := io.enq.data.bits + + buff(1).io.enq.valid := isEnqPo & io.enq.data.valid + buff(1).io.enq.bits := io.enq.data.bits + + io.enq.data.ready := (isEnqPi & buff(0).io.enq.ready) | (isEnqPo & buff(1).io.enq.ready) + io.enq.ctrl.ready := true.B + + buff(0).reset := reset.asBool | (isEnqPi & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort) + buff(1).reset := reset.asBool | (isEnqPo & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort) + + when( io.enq.ctrl.fire & ~io.enq.ctrl.bits.isRxAbort){ + isEnqPi := ~isEnqPi + when( isEnqPi ){ + info(0) := io.enq.ctrl.bits + } .elsewhen( isEnqPo ){ + info(1) := io.enq.ctrl.bits + } + } + + + + when( io.enq.ctrl.fire ){ + recCnt := 0.U + } .elsewhen( io.enq.data.fire ){ + when( recCnt < 5.U ){ + recCnt := recCnt + 1.U + when( isEnqPi ){ + header(0)(recCnt) := io.enq.data.bits + } .elsewhen( isEnqPo ){ + header(1)(recCnt) := io.enq.data.bits + } .otherwise{ + assert(false.B, "Assert Failed, Rx Under Run") + } + } + } + +} + +trait RxBuffDeq{ this: RxBuff => + + when( io.deq.header.fire ){ + when( isDeqPi ) { hValid(0) := false.B } + when( isDeqPo ) { hValid(1) := false.B } + } .elsewhen( recCnt === 5.U ){ + when( isEnqPi ) { hValid(0) := true.B } + when( isEnqPo ) { hValid(1) := true.B } + } + + + Mux1H(Seq( isDeqPi -> hValid(0), isDeqPo -> hValid(1) )) + io.header.bits := Mux1H(Seq( isDeqPi -> hValid(0), isDeqPo -> hValid(1) )) + + + + when( io.deq.ctrl.fire ){ + isDeqPi := ~isDeqPi + when( isDeqPi ) { cValid(0) := false.B } + when( isDeqPo ) { cValid(1) := false.B } + } .elsewhen( io.enq.ctrl.fire ){ + when( isEnqPi ) { cValid(0) := true.B } + when( isEnqPo ) { cValid(1) := true.B } + } + + + when( isDeqPi ){ + io.deq <> buff(0).io.deq + + io.header.valid := hValid(0) + io.header.bits := header(0) + + io.deq.ctrl.valid := cValid(0) & ~buff(0).io.deq.valid + io.deq.ctrl.bits := info(0) + } .elsewhen( isDeqPo ){ + io.deq <> buff(1).io.deq + + io.header.valid := hValid(1) + io.header.bits := header(1) + + io.deq.ctrl.valid := cValid(1) & ~buff(1).io.deq.valid + io.deq.ctrl.bits := info(1) + } + + + +} + + +class RxBuff extends RxBuffRxBuff with RxBuffEnq with RxBuffDeq{ + +} + diff --git a/src/main/scala/Switch/Switch.scala b/src/main/scala/Switch/Switch.scala index 72f52c9..cc2076e 100644 --- a/src/main/scala/Switch/Switch.scala +++ b/src/main/scala/Switch/Switch.scala @@ -23,6 +23,15 @@ class SwitchIO(implicit p: Parameters) extends SwitchBundle{ class Switch(implicit p: Parameters) extends LazyModule with HasSwitchParameters{ + val tlClientNode = TLClientNode(Seq(TLMasterPortParameters.v1( + Seq(TLMasterParameters.v1( + name = "DMA", + sourceId = IdRange(0, chn), + )) + ))) + + + val ethReg = LazyModule(new MacReg) @@ -32,6 +41,7 @@ class Switch(implicit p: Parameters) extends LazyModule with HasSwitchParameters class SwitchImp(outer: Switch)(implicit p: Parameters) extends LazyModuleImp(outer) with HasSwitchParameters{ val io = IO(new SwitchIO) + val ( dma_bus, dma_edge ) = outer.tlClientNode.out.head val mac = ( 0 until chn ).map{ i => Module(new Mac) @@ -46,6 +56,10 @@ class SwitchImp(outer: Switch)(implicit p: Parameters) extends LazyModuleImp(out outer.ethReg.module.io.asyncReset := io.asyncReset outer.ethReg.module.io.viewAsSupertype(new Mac_Config_Bundle) <> mac(0).io.cfg + val switchMux = Module(new SwitchMux) + + switchMux.io.rxEnq(0) <> mac(0).io.rxEnq + switchMux.io.txDeq(0) <> mac(0).io.txDeq @@ -62,18 +76,6 @@ class SwitchImp(outer: Switch)(implicit p: Parameters) extends LazyModuleImp(out - val rxBuff = Module(new RxBuff) - - rxBuff.io.enq <> mac(0).io.rxEnq - rxBuff.io.deq.data.ready := false.B - rxBuff.io.deq.ctrl.ready := false.B - - val txBuff = Module(new TxBuff) - txBuff.io.deq <> mac(0).io.txDeq - txBuff.io.enq.ctrl.valid := false.B - txBuff.io.enq.data.valid := false.B - txBuff.io.enq.data.bits := 0.U - diff --git a/src/main/scala/Switch/SwitchMux.scala b/src/main/scala/Switch/SwitchMux.scala new file mode 100644 index 0000000..ad56632 --- /dev/null +++ b/src/main/scala/Switch/SwitchMux.scala @@ -0,0 +1,153 @@ +package Switch + +import chisel3._ +import chisel3.util._ + + + + + + + +class SwitchMux(edgeOut: TLEdgeOut)(implicit p: Parameters) extends SwitchModule{ + + class MacTileLinkMasterIO extends Bundle{ + val A = Decoupled(new TLBundleA(edgeOut.bundle)) + val D = Flipped(Decoupled(new TLBundleD(edgeOut.bundle))) + } + + class SwitchMuxIO(implicit p: Parameters) extends SwitchBundle{ + val dmaMst = new MacTileLinkMasterIO + + val triTx = Input(Bool()) + + val rxEnq = Vec(chn, new Receive_Enq_Bundle) + val txDeq = Vec(chn, Flipped(new Transmit_Deq_Bundle)) + + } + + val io: SwitchMuxIO = IO(new SwitchMuxIO) + + + def stateIdle = 0.U + def stateRx = 1.U + def stateTx = 2.U + + val stateNxt = Wire(UInt(2.W)) + val stateCur = RegNext(stateNxt, stateIdle) + + stateNxt := + Mux1H(Seq( + ( stateCur === stateIdle ) -> Mux( rxBuff.io.deq.header.fire, stateRx, Mux( txBuff.io.enq.req.fire, stateTx, stateIdle ) ), + ( stateCur === stateRx ) -> Mux( rxBuff.io.deq.ctrl.fire, stateIdle, stateRx ), + ( stateCur === stateTx ) -> Mux( txBuff.io.enq.resp.fire, stateIdle, stateTx ), + )) + + + def ptr = 0x8002000 + def txLength = 8 + def PerPacketCrcEn = true.B + def PerPacketPad = true.B + + + + val rxBuff = Module(new RxBuff) + rxBuff.io.enq <> io.rxEnq(0) + + + + + val txBuff = Module(new TxBuff) + txBuff.io.deq <> mac.io.txDeq(0) + + + rxBuff.io.deq.ctrl.ready := stateCur === stateRx + + + val txReqValid = RegInit(false.B) + + when( txBuff.io.enq.req.fire ){ + txReqValid := false.B + } .elsewhen( io.triTx ){ + txReqValid := true.B + } + + txBuff.io.enq.req.valid := txReqValid && stateCur === stateIdle + txBuff.io.enq.bits.txLength := txLength + txBuff.io.enq.bits.PerPacketCrcEn := PerPacketCrcEn + txBuff.io.enq.bits.PerPacketPad := PerPacketPad + + + + + txBuff.io.enq.resp.ready := true.B + + + + + + val dmaTxAValid = RegInit(false.B) + val dmaTxABits = Reg(new TLBundleA(edgeOut.bundle)) + + + val dmaAddress = Reg( UInt(32.W) ) + + when( stateCur === stateIdle && stateNxt =/= stateIdle ){ + dmaAddress := ptr.U + } .elsewhen( io.A.fire ){ + dmaAddress := dmaAddress + 4.U + } + + rxBuff.io.deq.data.ready := io.A.ready & stateCur === stateRx + rxBuff.io.deq.header.ready := ~io.io.triTx && ~txReqValid + + when( io.A.fire ){ + dmaTxAValid := false.B + } .elsewhen( txBuff.io.enq.req.fire ){ + dmaTxAValid := true.B + dmaTxABits := + edgeOut.Get( + fromSource = 0.U, + toAddress = dmaAddress >> 2 << 2, + lgSize = log2Ceil(txLength).U, + )._2 + } + + + io.A.valid := + Mux1H(Seq( + stateCur === stateRx -> rxBuff.io.deq.data.valid, + stateCur === stateTx -> dmaTxAValid, + )) + + when( stateCur === stateRx ){ + io.A.bits := + edgeOut.Put( + fromSource = 0.U, + toAddress = dmaAddress >> 2 << 2, + lgSize = log2Ceil(32/8).U, + data = rxBuff.io.deq.data.bits, + mask = "b1111".U, + )._2 + } .elsewhen( stateCur === stateTx ){ + io.A.bits := dmaTxABits + } .otherwise{ + io.A.bits := DontCare + } + + + txBuff.io.enq.data.valid := io.D.valid & stateCur === stateTx + txBuff.io.enq.data.bits := io.D.bits.data + + + io.D.ready := + Mux1H(Seq( + stateCur === stateRx -> true.B, + stateCur === stateTx -> txBuff.io.enq.data.ready, + )) + + + +} + + diff --git a/src/main/scala/Switch/mac/TxBuff.scala b/src/main/scala/Switch/TxBuff.scala similarity index 58% rename from src/main/scala/Switch/mac/TxBuff.scala rename to src/main/scala/Switch/TxBuff.scala index ce1076f..1ebf4a2 100644 --- a/src/main/scala/Switch/mac/TxBuff.scala +++ b/src/main/scala/Switch/TxBuff.scala @@ -4,18 +4,16 @@ import chisel3._ import chisel3.util._ -class Transmit_Enq_Ctrl_Bundle extends Bundle{ - -} -class Transmit_Deq_Req_Bundle extends Bundle{ + +class Transmit_Req_Bundle extends Bundle{ val txLength = UInt(16.W) val PerPacketCrcEn = Bool() val PerPacketPad = Bool() } -class Transmit_Deq_Resp_Bundle extends Bundle{ +class Transmit_Resp_Bundle extends Bundle{ val RetryCntLatched = UInt(4.W) val RetryLimit = Bool() val LateCollLatched = Bool() @@ -25,22 +23,15 @@ class Transmit_Deq_Resp_Bundle extends Bundle{ val isClear = Bool() } -class Transmit_Enq_Bundle extends Bundle{ +class Transmit_Bundle extends Bundle{ val data = Decoupled(UInt(32.W)) - val ctrl = Decoupled(new Transmit_Enq_Ctrl_Bundle) + val req = Decoupled(new Transmit_Req_Bundle) + val resp = Flipped(Decoupled(new Transmit_Resp_Bundle)) } - -class Transmit_Deq_Bundle extends Bundle{ - val data = Decoupled(UInt(32.W)) - val req = Decoupled(new Transmit_Deq_Req_Bundle) - val resp = Flipped(Decoupled(new Transmit_Deq_Resp_Bundle)) -} - - class TxBuffIO extends Bundle{ - val enq = Flipped(new Transmit_Enq_Bundle) - val deq = new Transmit_Deq_Bundle + val enq = Flipped(new Transmit_Bundle) + val deq = new Transmit_Bundle } diff --git a/src/main/scala/Switch/mac/AsyncFifo.scala.bk b/src/main/scala/Switch/mac/AsyncFifo.scala.bk deleted file mode 100644 index 2a5d5c3..0000000 --- a/src/main/scala/Switch/mac/AsyncFifo.scala.bk +++ /dev/null @@ -1,74 +0,0 @@ - - -package MAC - -import chisel3._ -import chisel3.util._ - - - val write = Input(Bool()) - val read = Input(Bool()) - val clear = Input(Bool()) - val data_in = Input(UInt(dw.W)) - - val data_out = Output(UInt(dw.W)) - val almost_full = Output(Bool()) - val full = Output(Bool()) - val almost_empty = Output(Bool()) - val empty = Output(Bool()) - - - val cnt = Output(UInt(cntw.W)) - - -class AsyncFifo(dw: Int, aw: Int) extends RawModule{ - - def dp: Int = { var res = 1; for ( i <- 0 until aw ) { res = res * 2 }; return res } - - class AsyncFifoIO extends Bundle{ - val clockEnq = Input(Bool()) - val clockDeq = Input(Bool()) - val resetEnq = Input(Bool()) - val resetDeq = Input(Bool()) - - val enq = Flipped(Decoupled(UInt(dw.W))) - val deq = Decoupled( UInt(dw.W) ) - - val almost_full = Output(Bool()) - val almost_empty = Output(Bool()) - - def full = ~enq.ready - def empty = ~deq.valid - - } - - val io: AsyncFifoIO = IO(new AsyncFifoIO) - - val fifo = withClockAndReset( io.clockEnq.asClock, io.reset ) (Mem( dp, UInt(dw.W) )) - - - val wrPtr = withClockAndReset( io.clockEnq.asClock, io.resetEnq ) (RegInit(0.U((aw+1).W))) - val wrPrtGray = BinaryToGray(wrPtr) - - val rdPtr = withClockAndReset( io.clockDeq.asClock, io.resetDeq ) (RegInit(0.U((aw+1).W))) - val rdPrtGray = BinaryToGray(rdPtr) - - val wrPrtGraySync = withClockAndReset( io.clockDeq.asClock, io.resetDeq ) ( ShiftRegister( wrPrtGray, 2, 0.U, true.B ) ) - val rdPrtGraySync = withClockAndReset( io.clockEnq.asClock, io.resetEnq ) ( ShiftRegister( rdPrtGray, 2, 0.U, true.B ) ) - - val isEmpty = wrPrtGraySync === rdPrtGray - val isFull = (wrPrtGray(aw-2, 0) === rdPrtGraySync(aw-2, 0)) & (wrPrtGray.extract(aw-1) =/= rdPrtGraySync.extract(aw-1)) - - io.enq.ready := ~isFull - io.deq.valid := ~isEmpty - - withClockAndReset( io.clockEnq.asClock, io.resetEnq ){ - when( io.enq.fire ){ - fifo(wrPtr) := io.enq.bits - } - } - - io.deq.bits := fifo(rdPtr) - - -} diff --git a/src/main/scala/Switch/MacRx.scala b/src/main/scala/Switch/mac/MacRx.scala similarity index 100% rename from src/main/scala/Switch/MacRx.scala rename to src/main/scala/Switch/mac/MacRx.scala diff --git a/src/main/scala/Switch/MacTx.scala b/src/main/scala/Switch/mac/MacTx.scala similarity index 100% rename from src/main/scala/Switch/MacTx.scala rename to src/main/scala/Switch/mac/MacTx.scala diff --git a/src/main/scala/Switch/mac/RxBuff.scala b/src/main/scala/Switch/mac/RxBuff.scala deleted file mode 100644 index 2cb6bc5..0000000 --- a/src/main/scala/Switch/mac/RxBuff.scala +++ /dev/null @@ -1,108 +0,0 @@ -package Switch - -import chisel3._ -import chisel3.util._ - -class Receive_Enq_Ctrl_Bundle extends Bundle{ - val LatchedRxLength = UInt(16.W) - val RxStatusInLatched = UInt(9.W) - val isRxAbort = Bool() -} - -class Receive_Deq_Ctrl_Bundle extends Bundle{ - -} - -class Receive_Enq_Bundle extends Bundle{ - val data = Decoupled(UInt(32.W)) - val ctrl = Decoupled(new Receive_Enq_Ctrl_Bundle) -} - - -class Receive_Deq_Bundle extends Bundle{ - val data = Decoupled(UInt(32.W)) - val ctrl = Decoupled(new Receive_Deq_Ctrl_Bundle) -} - - -class RxBuffIO extends Bundle{ - val enq = Flipped(new Receive_Enq_Bundle) - val deq = new Receive_Deq_Bundle -} - - -class Packet_Info_Bundle extends Bundle{ - val LatchedRxLength = UInt(16.W) - val RxStatusInLatched = UInt(9.W) - val header = Vec( 5, UInt(32.W) ) -} - - -class RxBuff extends Module{ - val io: RxBuffIO = IO(new RxBuffIO) - - val isPing = RegInit(true.B) - val isPong = ~isPing - - val pipoBuff = for( i <- 0 until 2 ) yield { Module(new Queue( UInt(32.W), 2048/4 )) } - val pipoInfo = for( i <- 0 until 2 ) yield { Reg(new Packet_Info_Bundle) } - dontTouch(pipoBuff(0).io.enq) - dontTouch(pipoInfo(0)) - dontTouch(pipoBuff(1).io.enq) - dontTouch(pipoInfo(1)) - - val recCnt = RegInit(0.U(3.W)) - - pipoBuff(0).io.enq.valid := isPing & io.enq.data.valid - pipoBuff(0).io.enq.bits := io.enq.data.bits - - pipoBuff(1).io.enq.valid := isPong & io.enq.data.valid - pipoBuff(1).io.enq.bits := io.enq.data.bits - - io.enq.data.ready := (isPing & pipoBuff(0).io.enq.ready) | (isPong & pipoBuff(1).io.enq.ready) - io.enq.ctrl.ready := true.B - - pipoBuff(0).reset := reset.asBool | (isPing & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort) - pipoBuff(1).reset := reset.asBool | (isPong & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort) - - when( io.enq.ctrl.fire & ~io.enq.ctrl.bits.isRxAbort){ - isPing := ~isPing - when( isPing ){ - pipoInfo(0).LatchedRxLength := io.enq.ctrl.bits.LatchedRxLength - pipoInfo(0).RxStatusInLatched := io.enq.ctrl.bits.RxStatusInLatched - } .elsewhen( isPong ){ - pipoInfo(1).LatchedRxLength := io.enq.ctrl.bits.LatchedRxLength - pipoInfo(1).RxStatusInLatched := io.enq.ctrl.bits.RxStatusInLatched - } - } - - - - when( io.enq.ctrl.fire ){ - recCnt := 0.U - } .elsewhen( io.enq.data.fire ){ - when( recCnt < 5.U ){ - recCnt := recCnt + 1.U - when( isPing ){ - pipoInfo(0).header(recCnt) := io.enq.data.bits - } .elsewhen( isPong ){ - pipoInfo(1).header(recCnt) := io.enq.data.bits - } .otherwise{ - assert(false.B, "Assert Failed, Rx Under Run") - } - } - } - - - - pipoBuff(0).io.deq.ready := false.B - pipoBuff(1).io.deq.ready := false.B - - io.deq.data.valid := false.B - io.deq.data.bits := 0.U - - io.deq.ctrl.valid := false.B - io.deq.ctrl.bits := 0.U.asTypeOf(new Receive_Deq_Ctrl_Bundle) - -} -