package BACK import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.interrupts._ import freechips.rocketchip.tile._ class RocCC2CDRInIO extends Bundle{ val overCLK = Bool() val dDatIn = Bool() val uDatIn = Bool() val isLast = Bool() } class RocCC2CDROutIO extends Bundle{ val dDatOut = Bool() val uDatOut = Bool() val isOnline = Bool() } class RoCC2CDRIO extends Bundle{ val overCLK = Input(Bool()) val dDatIn = Input(Bool()) val dDatOut = Output(Bool()) val uDatIn = Input(Bool()) val uDatOut = Output(Bool()) val isOnline = Output(Bool()) val isLast = Input(Bool()) } class RoCC2CDR()(implicit p: Parameters) extends LazyModule { val opcodes: OpcodeSet = OpcodeSet.custom0 val roccCSRs: Seq[CustomCSR] = Nil lazy val module: RoCC2CDRImpl = new RoCC2CDRImpl(this) } abstract class RoCC2CDRImplBase(outer: RoCC2CDR)(implicit p: Parameters) extends LazyModuleImp(outer) { val io = IO(new RoCCIO(0, 0)) // val cdrio: RoCC2CDRIO = IO(new RoCC2CDRIO) val cdrInio = IO(Input(new RocCC2CDRInIO)) val cdrOutio = IO(Output(new RocCC2CDROutIO)) val CDRIn = for( i <- 0 until 2 ) yield { Module(new CDRIn) } CDRIn(0).io.serDat := cdrInio.dDatIn CDRIn(1).io.serDat := cdrInio.uDatIn CDRIn(0).io.overCLK := cdrInio.overCLK CDRIn(1).io.overCLK := cdrInio.overCLK val CDROut = for( i <- 0 until 2 ) yield { Module(new CDROut) } cdrOutio.dDatOut := CDROut(0).io.serDat cdrOutio.uDatOut := CDROut(1).io.serDat val txFifo = for( i <- 0 until 2 ) yield { Module(new Queue(UInt(32.W), 16)) } val rxFifo = for( i <- 0 until 2 ) yield { Module(new Queue(UInt(32.W), 16)) } val isTLWriteSoftReset = for( i <- 0 until 4 ) yield { Wire(Bool()) } val isTLReadStatus = Wire( Bool() ) val txLeft = for( i <- 0 until 2 ) yield { RegInit(0.U(5.W)) } val rxLeft = for( i <- 0 until 2 ) yield { RegInit(0.U(5.W)) } val wdata = Wire(UInt(32.W)) } trait RoCC2CDRImplTx{ this: RoCC2CDRImplBase => val isTLWriteTxLen = for( i <- 0 until 2 ) yield { Wire( Bool()) } val isTLWriteTxFifo = for( i <- 0 until 2 ) yield { Wire( Bool()) } val isTxFifoRelease = for( i <- 0 until 2 ) yield { Wire( Bool()) } val txLen = for( i <- 0 until 2 ) yield { RegInit(0.U(12.W)) } val isTxBusy = for( i <- 0 until 2 ) yield { RegInit(false.B) } val isTxFull = for( i <- 0 until 2 ) yield { ~txFifo(i).io.enq.ready } val intTxFifoFull = for( i <- 0 until 2 ) yield { ~RegNext(isTxFull(i), false.B) & isTxFull(i) } val intTxFinish = for( i <- 0 until 2 ) yield { CDROut(i).io.axis.fire & CDROut(i).io.axis.bits.tlast } val intTxEnd = for( i <- 0 until 2 ) yield { ShiftRegister( intTxFinish(i), 6, false.B, true.B) } val intTxFifoDeq = for( i <- 0 until 2 ) yield { txFifo(i).io.deq.fire } val txCnt = for( i <- 0 until 2 ) yield { Reg(UInt(2.W)) } val txData = for( i <- 0 until 2 ) yield { Reg(UInt(32.W)) } for( i <- 0 until 2 ) { when( txFifo(i).io.deq.fire ){ //txCnt(i) === 3.U txData(i) := txFifo(i).io.deq.bits when( isTxBusy(i) ){ assert(CDROut(i).io.axis.fire) } } .elsewhen( CDROut(i).io.axis.fire ){ txData(i) := txData(i) << 8 } txFifo(i).io.deq.ready := isTxFifoRelease(i) & Mux( isTxBusy(i), CDROut(i).io.axis.fire & txCnt(i) === 3.U, true.B ) txFifo(i).reset := reset.asBool | isTLWriteSoftReset(0+i) CDROut(i).reset := reset.asBool | isTLWriteSoftReset(0+i) CDROut(i).io.axis.bits.tdata := txData(i).head(8) CDROut(i).io.axis.bits.tlast := ~txFifo(i).io.deq.valid & txCnt(i) === 3.U CDROut(i).io.axis.bits.tuser := false.B CDROut(i).io.axis.valid := isTxBusy(i) when( isTLWriteSoftReset(i) ){ isTxBusy(i) := false.B }.elsewhen( txFifo(i).io.deq.fire & ~isTxBusy(i) ){ isTxBusy(i) := true.B } .elsewhen( CDROut(i).io.axis.fire & CDROut(i).io.axis.bits.tlast ){ isTxBusy(i) := false.B } when( isTLWriteSoftReset(0+i) ){ txCnt(i) := 0.U } .elsewhen( CDROut(i).io.axis.fire ){ txCnt(i) := txCnt(i) + 1.U } when( isTLWriteTxLen(i) ){ txLen(i) := wdata } .elsewhen( CDROut(i).io.axis.fire ){ txLen(i) := txLen(i) - 1.U } txFifo(i).io.enq.bits := wdata txFifo(i).io.enq.valid := isTLWriteTxFifo(i) & txLen(i) =/= 0.U when( isTLWriteSoftReset(0+i) ){ txLeft(i) := 0.U } .elsewhen( txFifo(i).io.enq.fire & txFifo(i).io.deq.fire ){ txLeft(i) := txLeft(i) } .elsewhen( txFifo(i).io.enq.fire ){ txLeft(i) := txLeft(i) + 1.U } .elsewhen( txFifo(i).io.deq.fire ){ txLeft(i) := txLeft(i) - 1.U } } } trait RoCC2CDRImplRx{ this: RoCC2CDRImplBase => val isTLReadRxLen = for( i <- 0 until 2 ) yield { Wire(Bool()) } val isTLReadRxFifo = for( i <- 0 until 2 ) yield { Wire(Bool()) } val rxLen = for( i <- 0 until 2 ) yield { RegInit(0.U(12.W)) } val isRxValid = for( i <- 0 until 2 ) yield { rxFifo(i).io.deq.valid } val isRxError = for( i <- 0 until 2 ) yield { RegInit(false.B) } val isAxisEnd = for( i <- 0 until 2 ) yield { RegInit(false.B) } val isRxEnd = for( i <- 0 until 2 ) yield { isAxisEnd(i) & ~rxFifo(i).io.deq.valid } val intRxError = for( i <- 0 until 2 ) yield { ~RegNext(isRxError(i), false.B) & isRxError(i) } val intRxStart = for( i <- 0 until 2 ) yield { rxLen(i) === 0.U & CDRIn(i).io.axis.fire } val intRxEnd = for( i <- 0 until 2 ) yield { ~RegNext(isRxEnd(i), false.B) & isRxEnd(i) } val intRxFifoEnq = for( i <- 0 until 2 ) yield { rxFifo(i).io.enq.fire } val rxCnt = for( i <- 0 until 2 ) yield { RegInit(0.U(2.W)) } val rxData = for( i <- 0 until 2 ) yield { Reg(UInt(24.W)) } for( i <- 0 until 2 ) { when( isTLWriteSoftReset(2+i) ){ isAxisEnd(i) := false.B } .elsewhen( CDRIn(i).io.axis.fire & CDRIn(i).io.axis.bits.tlast ){ isAxisEnd(i) := true.B } when( isTLWriteSoftReset(2+i) ){ rxCnt(i) := 0.U } .elsewhen( CDRIn(i).io.axis.fire ){ rxCnt(i) := rxCnt(i) + 1.U rxData(i) := Cat( rxData(i), CDRIn(i).io.axis.bits.tdata ) } when( isTLWriteSoftReset(2+i) ){ rxLen(i) := 0.U } .elsewhen( CDRIn(i).io.axis.fire ){ rxLen(i) := rxLen(i) + 1.U } rxFifo(i).io.enq.valid := CDRIn(i).io.axis.fire & rxCnt(i) === 3.U rxFifo(i).io.enq.bits := Cat( rxData(i)(23, 0) , CDRIn(i).io.axis.bits.tdata ) assert( ~(( CDRIn(i).io.axis.fire & CDRIn(i).io.axis.bits.tlast) & rxCnt(i) =/= 3.U), "Assert Failed! Rx must 4-byte Align!" ) CDRIn(i).io.axis.ready := true.B rxFifo(i).reset := reset.asBool | isTLWriteSoftReset(2+i) CDRIn(i).reset := reset.asBool | isTLWriteSoftReset(2+i) rxFifo(i).io.deq.ready := isTLReadRxFifo(i) when( isTLWriteSoftReset(2+i) ){ isRxError(i) := false.B } .elsewhen( rxFifo(i).io.enq.valid & ~rxFifo(i).io.enq.ready ){ isRxError(i) := true.B printf(s"Warning, RxFifo$i Overflow!\n") } when( isTLWriteSoftReset(2+i) ){ rxLeft(i) := 0.U } .elsewhen( rxFifo(i).io.enq.fire & rxFifo(i).io.deq.fire ){ rxLeft(i) := rxLeft(i) } .elsewhen( rxFifo(i).io.enq.fire ){ rxLeft(i) := rxLeft(i) + 1.U } .elsewhen( rxFifo(i).io.deq.fire ){ rxLeft(i) := rxLeft(i) - 1.U } } } trait RoCC2CDRImplIsLast{ this: RoCC2CDRImplBase => cdrOutio.isOnline := false.B val isReadIsLast = Wire(Bool()) } trait RoCC2CDRImplUserCRC{ this: RoCC2CDRImplBase => val isTLWriteTxFifo: Seq[Bool] val isTLReadRxFifo: Seq[Bool] val isTLReadTxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) } val isTLReadRxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) } val txCrc = for( i <- 0 until 2 ) yield { Module(new crc32_32) } val rxCrc = for( i <- 0 until 2 ) yield { Module(new crc32_32) } for( i <- 0 until 2 ) { txCrc(i).io.enq.valid := isTLWriteTxFifo(i) txCrc(i).io.enq.bits := wdata rxCrc(i).io.enq.valid := isTLReadRxFifo(i) rxCrc(i).io.enq.bits := rxFifo(i).io.deq.bits txCrc(i).reset := reset.asBool | isTLWriteSoftReset(0+i) rxCrc(i).reset := reset.asBool | isTLWriteSoftReset(2+i) } } trait RoCC2CDRImplLimitTimmer{ this: RoCC2CDRImplBase => val intRxStart: Seq[Bool] val isTLWriteSoftReset: Seq[Bool] val isTxFifoRelease: Seq[Bool] val isTLWriteLimitTimerAim = for( i <- 0 until 2 ) yield { Wire(Bool()) } val isTLWriteLimitTxPair = for( i <- 0 until 2 ) yield { Wire(Bool()) } val limitTimerCnt = for( i <- 0 until 2 ) yield { RegInit(0.U(16.W)) } val limitTimerAim = for( i <- 0 until 2 ) yield { RegInit(0.U(16.W)) } val isLimitTimerTrigger = for( i <- 0 until 2 ) yield { RegInit(false.B) } val txPairSel = for( i <- 0 until 2 ) yield { RegInit((i.U)(2.W)) } for( i <- 0 until 2 ){ when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){ limitTimerCnt(i) := 0.U } .elsewhen( limitTimerCnt(i) =/= limitTimerAim(i) ){ when( isLimitTimerTrigger(i) ){ limitTimerCnt(i) := limitTimerCnt(i) + 1.U } } when( isTLWriteLimitTimerAim(i) ){ limitTimerAim(i) := wdata } when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){ isLimitTimerTrigger(i) := false.B } .elsewhen( intRxStart(i) ){ isLimitTimerTrigger(i) := true.B } when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){ txPairSel(i) := i.U } .elsewhen( isTLWriteLimitTxPair(i) ){ txPairSel(i) := wdata } isTxFifoRelease(i) := ( 0 until 2).map{ lmt => ((txPairSel(lmt) =/= i.U) | (limitTimerCnt(lmt) === limitTimerAim(lmt))) }.reduce(_&_) } } trait RoCC2CDRImplOutTimmer{ this: RoCC2CDRImplBase => val isTxBusy: Seq[Bool] val timeOutCnt = for( _ <- 0 until 2 ) yield { RegInit(0.U(32.W)) } val isTLClearTimeOut = for( _ <- 0 until 2 ) yield { Wire(Bool()) } val isTLReadTimeOut = for( _ <- 0 until 2 ) yield { Wire(Bool()) } val isTxClearTimeOut = for( i <- 0 until 2 ) yield { ~RegNext(isTxBusy(i)) & isTxBusy(i) } for( i <- 0 until 2 ) { when( isTLClearTimeOut(i) | isTxClearTimeOut(i) ){ timeOutCnt(i) := 0.U } .otherwise{ timeOutCnt(i) := timeOutCnt(i) + 1.U } } } class RoCC2CDRImpl(outer: RoCC2CDR)(implicit p: Parameters) extends RoCC2CDRImplBase(outer) with RoCC2CDRImplTx with RoCC2CDRImplRx with RoCC2CDRImplIsLast with RoCC2CDRImplUserCRC with RoCC2CDRImplLimitTimmer with RoCC2CDRImplOutTimmer { io.mem.req.valid := false.B io.mem.req.bits := DontCare io.mem.s1_kill := false.B io.mem.s1_data := DontCare io.mem.s2_kill := false.B io.mem.keep_clock_enabled := false.B io.fpu_req.valid := false.B io.fpu_req.bits := DontCare io.fpu_resp.ready := true.B isTLWriteSoftReset(0) := io.cmd.fire & io.cmd.bits.inst.funct === 0.U isTLWriteTxLen(0) := io.cmd.fire & io.cmd.bits.inst.funct === 1.U isTLWriteTxFifo(0) := io.cmd.fire & io.cmd.bits.inst.funct === 2.U isTLReadTxCrc(0) := io.cmd.fire & io.cmd.bits.inst.funct === 3.U isTLClearTimeOut(0) := io.cmd.fire & io.cmd.bits.inst.funct === 4.U & io.cmd.bits.inst.xs1 isTLReadTimeOut(0) := io.cmd.fire & io.cmd.bits.inst.funct === 4.U & io.cmd.bits.inst.xd isTLWriteSoftReset(1) := io.cmd.fire & io.cmd.bits.inst.funct === 5.U isTLWriteTxLen(1) := io.cmd.fire & io.cmd.bits.inst.funct === 6.U isTLWriteTxFifo(1) := io.cmd.fire & io.cmd.bits.inst.funct === 7.U isTLReadTxCrc(1) := io.cmd.fire & io.cmd.bits.inst.funct === 8.U isTLClearTimeOut(1) := io.cmd.fire & io.cmd.bits.inst.funct === 9.U & io.cmd.bits.inst.xs1 isTLReadTimeOut(1) := io.cmd.fire & io.cmd.bits.inst.funct === 9.U & io.cmd.bits.inst.xd isTLWriteSoftReset(2) := io.cmd.fire & io.cmd.bits.inst.funct === 10.U isTLReadRxLen(0) := io.cmd.fire & io.cmd.bits.inst.funct === 11.U isTLReadRxFifo(0) := io.cmd.fire & io.cmd.bits.inst.funct === 12.U isTLReadRxCrc(0) := io.cmd.fire & io.cmd.bits.inst.funct === 13.U isTLWriteLimitTimerAim(0) := io.cmd.fire & io.cmd.bits.inst.funct === 14.U isTLWriteLimitTxPair(0) := io.cmd.fire & io.cmd.bits.inst.funct === 15.U isTLWriteSoftReset(3) := io.cmd.fire & io.cmd.bits.inst.funct === 16.U isTLReadRxLen(1) := io.cmd.fire & io.cmd.bits.inst.funct === 17.U isTLReadRxFifo(1) := io.cmd.fire & io.cmd.bits.inst.funct === 18.U isTLReadRxCrc(1) := io.cmd.fire & io.cmd.bits.inst.funct === 19.U isTLWriteLimitTimerAim(1) := io.cmd.fire & io.cmd.bits.inst.funct === 20.U isTLWriteLimitTxPair(1) := io.cmd.fire & io.cmd.bits.inst.funct === 21.U isTLReadStatus := io.cmd.fire & io.cmd.bits.inst.funct === 22.U val isTLReadInterrupt = io.cmd.fire & io.cmd.bits.inst.funct === 23.U & io.cmd.bits.inst.xd val isTLClearInterrupt = io.cmd.fire & io.cmd.bits.inst.funct === 23.U & io.cmd.bits.inst.xs1 isReadIsLast := io.cmd.fire & io.cmd.bits.inst.funct === 24.U val interruptReg = RegInit(0.U(32.W)) when(true.B){ interruptReg := (interruptReg & Mux( isTLClearInterrupt, ~wdata, "hFFFFFFFF".U)) | Cat( intTxEnd(1), intTxEnd(0), intRxError(1), intRxError(0), intRxStart(1), intRxStart(0), intRxEnd(1), intRxEnd(0), intTxFifoDeq(1), intTxFifoDeq(0), intRxFifoEnq(1), intRxFifoEnq(0) ) } io.interrupt := intTxEnd(0) | intTxEnd(1) | intRxError(0) | intRxError(1) | intRxStart(0) | intRxStart(1) | intRxEnd(0) | intRxEnd(1) | intTxFifoDeq(0) | intTxFifoDeq(1) | intRxFifoEnq(0) | intRxFifoEnq(1) wdata := io.cmd.bits.rs1 val cmdInfo = RegEnable(io.cmd.bits, io.cmd.fire) val rdata = Reg(UInt(32.W)) // val cmdReady = RegInit(true.B) val respValid = RegInit(false.B) io.busy := respValid io.cmd.ready := ~respValid io.resp.valid := respValid io.resp.bits.rd := cmdInfo.inst.rd io.resp.bits.data := rdata printf("Warning, no protection on tx rx fifo!\n") // MuxCase( true.B, Array( // ( io.cmd.bits.inst.funct === 2.U ) -> txFifo(0).io.enq.ready, // ( io.cmd.bits.inst.funct === 6.U ) -> txFifo(1).io.enq.ready, // ( bus.a.bits.address(7,0) === "h28".U ) -> rxFifo(0).io.deq.valid, // ( bus.a.bits.address(7,0) === "h48".U ) -> rxFifo(1).io.deq.valid, // )) when( isTLReadStatus ){ rdata := Cat( txLeft(1), txLeft(0), rxLeft(1), rxLeft(0), isRxValid(1), isRxValid(0), isRxError(1), isRxError(0), isTxBusy(1), isTxBusy(0), isTxFull(1), isTxFull(0) ) } .elsewhen(isTLReadRxLen(0) ){ rdata := rxLen(0) } .elsewhen(isTLReadRxLen(1) ){ rdata := rxLen(1) } .elsewhen(isTLReadRxFifo(0) ){ rdata := rxFifo(0).io.deq.bits } .elsewhen(isTLReadRxFifo(1) ){ rdata := rxFifo(1).io.deq.bits } .elsewhen(isReadIsLast){ rdata := cdrInio.isLast } .elsewhen(isTLReadTxCrc(0)){ rdata := txCrc(0).io.crc } .elsewhen(isTLReadTxCrc(1)){ rdata := txCrc(1).io.crc } .elsewhen(isTLReadRxCrc(0)){ rdata := rxCrc(0).io.crc } .elsewhen(isTLReadRxCrc(1)){ rdata := rxCrc(1).io.crc } .elsewhen(isTLReadInterrupt){ rdata := interruptReg } .elsewhen(isTLReadTimeOut(0)){ rdata := timeOutCnt(0) } .elsewhen(isTLReadTimeOut(1)){ rdata := timeOutCnt(1) } when( io.resp.fire ){ //允许连续触发 respValid := false.B } .elsewhen( isTLReadStatus ){ respValid := true.B } .elsewhen(isTLReadRxLen(0) ){ respValid := true.B } .elsewhen(isTLReadRxLen(1) ){ respValid := true.B } .elsewhen(isTLReadRxFifo(0) ){ respValid := true.B } .elsewhen(isTLReadRxFifo(1) ){ respValid := true.B } .elsewhen(isReadIsLast){ respValid := true.B } .elsewhen(isTLReadTxCrc(0)){ respValid := true.B } .elsewhen(isTLReadTxCrc(1)){ respValid := true.B } .elsewhen(isTLReadRxCrc(0)){ respValid := true.B } .elsewhen(isTLReadRxCrc(1)){ respValid := true.B } .elsewhen(isTLReadInterrupt){ respValid := true.B } .elsewhen(isTLReadTimeOut(0)){ respValid := true.B } .elsewhen(isTLReadTimeOut(1)){ respValid := true.B } } trait HasLazyRoCC2CDR { this: BaseTile => val roccs = LazyModule(new RoCC2CDR()) val roccCSRs = Seq(roccs.roccCSRs) // the set of custom CSRs requested by all roccs } trait HasLazyRoCC2CDRModule extends HasCoreParameters { this: RocketTileModuleImp with HasFpuOpt => // val (respArb, cmdRouter) = { // val respArb = Module(new RRArbiter(new RoCCResponse()(outer.p), outer.roccs.size)) val cmdRouter = Module(new Queue( new RoCCCommand, 2, false, true ))//Module(new RoccCommandRouter( Seq(outer.roccs.opcodes) )(outer.p)) // outer.roccs.module.io.ptw ++=: ptwPorts outer.roccs.module.io.cmd <> cmdRouter.io.deq // val dcIF = Module(new SimpleHellaCacheIF()(outer.p)) // dcIF.io.requestor <> outer.roccs.module.io.mem // dcachePorts += dcIF.io.cache //respArb.io.in(0) <> Queue(outer.roccs.module.io.resp) fpuOpt foreach { fpu => fpu.io.cp_req.valid := false.B fpu.io.cp_resp.ready := false.B } // (Some(respArb), Some(cmdRouter)) // } // val roccCSRIOs = Seq(outer.roccs.module.io.csrs) // (core.io.rocc.csrs zip roccCSRIOs.flatten).foreach { t => t._2 := t._1 } val cdrInio = IO(Input(new RocCC2CDRInIO)) val cdrOutio = IO(Output(new RocCC2CDROutIO)) // val cdrio: RoCC2CDRIO = IO(new RoCC2CDRIO) // dontTouch(cdrio) cdrInio <> outer.roccs.module.cdrInio cdrOutio <> outer.roccs.module.cdrOutio }