diff --git a/src/main/scala/protocol/Common.scala b/src/main/scala/protocol/Common.scala index 3d07169..0624e2b 100644 --- a/src/main/scala/protocol/Common.scala +++ b/src/main/scala/protocol/Common.scala @@ -12,6 +12,7 @@ import tilelink._ case class ProtocolLayerParams() { val ucieFlitWidth = 64 // flit width val ucieFlitSize = 4 // number of ucie flits + val ucieNonEccWidth = 448 // width of the actual data bits val ucieEccWidth = 64 // width of the ECC bits val hostIDWidth = 8 // hostID of the initiator chiplet val partnerIDWidth = 8 // partnerID of the consumer chiplet @@ -28,6 +29,7 @@ object UCIProtoMsgTypes extends ChiselEnum { val Reserved0 = Value(0x5.U(4.W)) val Reserved1 = Value(0x6.U(4.W)) val Reserved2 = Value(0x7.U(4.W)) + val Reserved3 = Value(0x8.U(4.W)) } /** @@ -106,12 +108,12 @@ class d2dConfig() extends Bundle { class sbConfig() extends Bundle { // SideBand Control Status Registers - val sideband_mailbox_index_low = Output(UInt(32.W)) - val sideband_mailbox_index_high = Output(UInt(32.W)) - val sideband_mailbox_data_low = Output(UInt(32.W)) - val sideband_mailbox_data_high = Output(UInt(32.W)) + val sideband_mailbox_index_low = Input(UInt(32.W)) + val sideband_mailbox_index_high = Input(UInt(32.W)) + val sideband_mailbox_data_low = Input(UInt(32.W)) + val sideband_mailbox_data_high = Input(UInt(32.W)) val sideband_mailbox_ready = Output(UInt(1.W)) - val sideband_mailbox_valid = Output(UInt(1.W)) + val sideband_mailbox_valid = Input(UInt(1.W)) val sideband_mailbox_sw_to_node_index_low = Output(UInt(32.W)) val sidebank_mailbox_sw_to_node_index_high = Output(UInt(32.W)) diff --git a/src/main/scala/protocol/HammingCode.scala b/src/main/scala/protocol/HammingCode.scala new file mode 100644 index 0000000..d77e8ef --- /dev/null +++ b/src/main/scala/protocol/HammingCode.scala @@ -0,0 +1,111 @@ +package edu.berkeley.cs.ucie.digital +package protocol + +import chisel3._ +import chisel3.util._ + +class HammingEncode(val protoParams: ProtocolLayerParams) extends Module { + val io = IO(new Bundle { + val data = Input(UInt(protoParams.ucieNonEccWidth.W)) + val checksum = Output(UInt(protoParams.ucieEccWidth.W)) + }) + + def hammingEncode(data: Vec[UInt]): UInt = { + val p1 = Wire(UInt(1.W)) + val p1_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 2 >= 1 match { + case true => p1_taps(i) := 1.U + case false => p1_taps(i) := 0.U + } + } + p1 := (p1_taps.asUInt & data.asUInt).xorR + val p2 = Wire(UInt(1.W)) + val p2_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 4 >= 2 match { + case true => p2_taps(i) := 1.U + case false => p2_taps(i) := 0.U + } + } + p2 := (p2_taps.asUInt & data.asUInt).xorR + val p4 = Wire(UInt(1.W)) + val p4_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 8 >= 4 match { + case true => p4_taps(i) := 1.U + case false => p4_taps(i) := 0.U + } + } + p4 := (p4_taps.asUInt & data.asUInt).xorR + val p8 = Wire(UInt(1.W)) + val p8_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 16 >= 8 match { + case true => p8_taps(i) := 1.U + case false => p8_taps(i) := 0.U + } + } + p8 := (p8_taps.asUInt & data.asUInt).xorR + val p16 = Wire(UInt(1.W)) + val p16_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 32 >= 16 match { + case true => p16_taps(i) := 1.U + case false => p16_taps(i) := 0.U + } + } + p16 := (p16_taps.asUInt & data.asUInt).xorR + val p32 = Wire(UInt(1.W)) + val p32_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 64 >= 32 match { + case true => p32_taps(i) := 1.U + case false => p32_taps(i) := 0.U + } + } + p32 := (p32_taps.asUInt & data.asUInt).xorR + val p64 = Wire(UInt(1.W)) + val p64_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 128 >= 64 match { + case true => p64_taps(i) := 1.U + case false => p64_taps(i) := 0.U + } + } + p64 := (p64_taps.asUInt & data.asUInt).xorR + val p128 = Wire(UInt(1.W)) + val p128_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 256 >= 128 match { + case true => p128_taps(i) := 1.U + case false => p128_taps(i) := 0.U + } + } + p128 := (p128_taps.asUInt & data.asUInt).xorR + val p256 = Wire(UInt(1.W)) + val p256_taps = Wire(Vec(protoParams.ucieNonEccWidth, UInt(1.W))) + data.zipWithIndex.map { case (d, i) => + i % 512 >= 256 match { + case true => p256_taps(i) := 1.U + case false => p256_taps(i) := 0.U + } + } + p256 := (p256_taps.asUInt & data.asUInt).xorR + Cat(p1, p2, p4, p8, p16, p32, p64, p128, p256) + } + + io.checksum := hammingEncode(io.data.asTypeOf(Vec(protoParams.ucieNonEccWidth, UInt(1.W)))) +} + +class HammingDecode(val protoParams: ProtocolLayerParams) extends Module { + val io = IO(new Bundle { + val data = Input(UInt(protoParams.ucieNonEccWidth.W)) + val checksum = Input(UInt(protoParams.ucieEccWidth.W)) + val matches = Output(Bool()) + }) + val hammingEncode = Module(new HammingEncode(protoParams)) + hammingEncode.io.data := io.data + io.matches := hammingEncode.io.checksum === io.checksum +} + diff --git a/src/main/scala/protocol/ProtocolLayer.scala b/src/main/scala/protocol/ProtocolLayer.scala index 5ac1a97..2610dfe 100644 --- a/src/main/scala/protocol/ProtocolLayer.scala +++ b/src/main/scala/protocol/ProtocolLayer.scala @@ -5,6 +5,7 @@ import chisel3._ import chisel3.util._ import interfaces._ +import javax.swing.InputMap /** * Class to handle the FDI signalling between the D2D adapter and protocol layer. The class @@ -23,6 +24,9 @@ class ProtocolLayer(val fdiParams: FdiParams) extends Module { val TLlpData_irdy = Input(Bool()) val TLplData_bits = Output(Bits((8 * fdiParams.width).W)) val TLplData_valid = Output(Bool()) + val TLready_to_rcv = Input(Bool()) + val fault = Input(Bool()) + val soft_reset = Input(Bool()) }) io.fdi.lpData.bits := io.TLlpData_bits @@ -39,8 +43,8 @@ class ProtocolLayer(val fdiParams: FdiParams) extends Module { io.fdi.lpDllp.bits := 0.U io.fdi.lpDllpOfc := false.B // Dynamic clock gating feature not supported in v1 - io.fdi.lpClkAck := false.B - io.fdi.lpWakeReq := false.B + io.fdi.lpClkAck := true.B + io.fdi.lpWakeReq := true.B // Tie lpStream to streaming protocol on stack 0 val streaming = Wire(new ProtoStream()) @@ -48,16 +52,17 @@ class ProtocolLayer(val fdiParams: FdiParams) extends Module { streaming.protoType := ProtoStreamType.Stream io.fdi.lpStream <> streaming - val sb_linkReset_req = RegInit(false.B) + val sb_linkReset_req = io.soft_reset // Refer to section 8.2.7 for rx_active_req/sts handshake val lp_rx_active_sts_reg = RegInit(false.B) // lpRxActiveStatus can change before the plStateStatus becomes Active - val lp_rx_active_pl_state = (io.fdi.plStateStatus === PhyState.reset || - io.fdi.plStateStatus === PhyState.retrain || - io.fdi.plStateStatus === PhyState.active) + // val lp_rx_active_pl_state = (io.fdi.plStateStatus === PhyState.reset || + // io.fdi.plStateStatus === PhyState.retrain || + // io.fdi.plStateStatus === PhyState.active) + val lp_rx_active_pl_state = (io.fdi.plStateStatus === PhyState.active) - when(io.fdi.plRxActiveReq && io.fdi.lpData.irdy && lp_rx_active_pl_state) { + when(io.fdi.plRxActiveReq && io.TLready_to_rcv && lp_rx_active_pl_state) { lp_rx_active_sts_reg := true.B } io.fdi.lpRxActiveStatus := lp_rx_active_sts_reg @@ -65,21 +70,21 @@ class ProtocolLayer(val fdiParams: FdiParams) extends Module { // Refer to section 8.2.8 for FDI bringup and state req logic val lp_state_req_reg = RegInit(PhyStateReq.nop) - val reqActive = (io.fdi.plStateStatus === PhyState.reset & + val reqActive = ((io.fdi.plStateStatus === PhyState.reset & lp_state_req_reg === PhyStateReq.nop & - io.fdi.plInbandPres) + io.fdi.plInbandPres) || io.fdi.plStateStatus === PhyState.linkReset) when(reqActive) { lp_state_req_reg := PhyStateReq.active - }.elsewhen(sb_linkReset_req) {// TODO: SB register to initiate LinkReset + }.elsewhen(~reqActive && sb_linkReset_req) {// TODO: SB register to initiate LinkReset lp_state_req_reg := PhyStateReq.linkReset }.otherwise { lp_state_req_reg := PhyStateReq.nop } io.fdi.lpStateReq := lp_state_req_reg - // TODO: lpLinkError should be asserted when there is an error detected by protocol layer + // lpLinkError should be asserted when there is an error detected by protocol layer // should be done as a ECC check in UCIe flit - io.fdi.lpLinkError := false.B + io.fdi.lpLinkError := io.fault // Refer to section 8.3.2 // Whent he lpStallAck is asserted the TL A channel is stalled and the lp irdy and valid @@ -88,6 +93,18 @@ class ProtocolLayer(val fdiParams: FdiParams) extends Module { lp_stall_reg := io.fdi.plStallReq io.fdi.lpStallAck := lp_stall_reg + /** pl_protocol + * saves pl_protocol and flitfmt, resets and negotiates if protocol/flitfmt is not raw + * Expects ProtocolID.STREAM and ProtocolFlitFmt.RAW if implemented + * WARNING: HAS NOT IMPLEMENTED RENEGOTIATION LOGIC, the d2d ties these to raw + */ + val pl_protocol_reg = RegInit(0.U(3.W)) + val pl_protocol_flitfmt_reg = RegInit(0.U(4.W)) + when (io.fdi.plProtocolValid) { + pl_protocol_reg := io.fdi.plProtocol.asUInt + pl_protocol_flitfmt_reg := io.fdi.plProtocolFlitFormat.asUInt + } + // TODO: these are SB messaging signals io.fdi.lpConfig.bits := 0.asUInt(fdiParams.sbWidth.W) io.fdi.lpConfig.valid := false.B diff --git a/src/main/scala/tilelink/UCIConfigRF.scala b/src/main/scala/tilelink/UCIConfigRF.scala index dbb7a4f..e9dd789 100644 --- a/src/main/scala/tilelink/UCIConfigRF.scala +++ b/src/main/scala/tilelink/UCIConfigRF.scala @@ -110,17 +110,17 @@ class UCIConfigRF(val beatBytes: Int, val address: BigInt)(implicit p: Parameter io.d2d_csrs.d2d_state_can_reset := d2d_state_can_reset io.d2d_csrs.d2d_flush_and_reset := d2d_flush_and_reset - io.sb_csrs.sideband_mailbox_index_low := sideband_mailbox_index_low - io.sb_csrs.sideband_mailbox_index_high := sideband_mailbox_index_high - io.sb_csrs.sideband_mailbox_data_low := sideband_mailbox_data_low - io.sb_csrs.sideband_mailbox_data_high := sideband_mailbox_data_high - io.sb_csrs.sideband_mailbox_ready := sideband_mailbox_ready - io.sb_csrs.sideband_mailbox_valid := sideband_mailbox_valid - io.sb_csrs.sideband_mailbox_sw_to_node_index_low := sideband_mailbox_sw_to_node_index_low - io.sb_csrs.sidebank_mailbox_sw_to_node_index_high := sidebank_mailbox_sw_to_node_index_high - io.sb_csrs.sideband_mailbox_sw_to_node_data_low := sideband_mailbox_sw_to_node_data_low - io.sb_csrs.sideband_mailbox_sw_to_node_data_high := sideband_mailbox_sw_to_node_data_high - io.sb_csrs.sideband_mailbox_sw_ready := sideband_mailbox_sw_ready - io.sb_csrs.sideband_mailbox_sw_valid := sideband_mailbox_sw_valid + sideband_mailbox_index_low := io.sb_csrs.sideband_mailbox_index_low + sideband_mailbox_index_high := io.sb_csrs.sideband_mailbox_index_high + sideband_mailbox_data_low := io.sb_csrs.sideband_mailbox_data_low + sideband_mailbox_data_high := io.sb_csrs.sideband_mailbox_data_high + io.sb_csrs.sideband_mailbox_ready := sideband_mailbox_ready + sideband_mailbox_valid := io.sb_csrs.sideband_mailbox_valid + io.sb_csrs.sideband_mailbox_sw_to_node_index_low := sideband_mailbox_sw_to_node_index_low + io.sb_csrs.sidebank_mailbox_sw_to_node_index_high := sidebank_mailbox_sw_to_node_index_high + io.sb_csrs.sideband_mailbox_sw_to_node_data_low := sideband_mailbox_sw_to_node_data_low + io.sb_csrs.sideband_mailbox_sw_to_node_data_high := sideband_mailbox_sw_to_node_data_high + io.sb_csrs.sideband_mailbox_sw_ready := sideband_mailbox_sw_ready + io.sb_csrs.sideband_mailbox_sw_valid := sideband_mailbox_sw_valid } } diff --git a/src/main/scala/tilelink/UCITLFront.scala b/src/main/scala/tilelink/UCITLFront.scala index b75140b..22de435 100644 --- a/src/main/scala/tilelink/UCITLFront.scala +++ b/src/main/scala/tilelink/UCITLFront.scala @@ -13,7 +13,7 @@ import freechips.rocketchip.util._ import protocol._ import interfaces._ -//import sideband._ +import sideband._ // TODO: Sideband messaging /** Main class to generate manager, client and register nodes on the tilelink diplomacy. @@ -66,24 +66,44 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { val fdi = new Fdi(outer.fdiParams) }) + val fault = RegInit(false.B) // if fault in ecc code + // Instantiate the agnostic protocol layer val protocol = Module(new ProtocolLayer(outer.fdiParams)) io.fdi <> protocol.io.fdi - - // Sideband node for protocol layer - //val protocol_sb_node = Module(new SidebandNode(new SidebandParams)) - - // protocol_sb_node.io.inner.layer_to_node.bits := Cat(sideband_mailbox_sw_to_node_data_high.q, sideband_mailbox_sw_to_node_data_low.q, - // sidebank_mailbox_sw_to_node_index_high.q, sideband_mailbox_sw_to_node_index_low.q) - // protocol_sb_node.io.inner.layer_to_node.valid := sideband_mailbox_sw_valid.q + protocol.io.fault := fault + + // Hamming encode and decode + val hammingEncoder = Module(new HammingEncode(outer.protoParams)) + val hammingDecoder = Module(new HammingDecode(outer.protoParams)) + // Defaults + hammingEncoder.io.data := 0.U + hammingDecoder.io.data := 0.U + hammingDecoder.io.checksum := 0.U + + //Sideband node for protocol layer + val protocol_sb_node = Module(new SidebandNode((new SidebandParams), outer.fdiParams)) + + protocol_sb_node.io.outer.rx.bits := protocol.io.fdi.lpConfig.bits + protocol_sb_node.io.outer.rx.valid := protocol.io.fdi.lpConfig.valid + protocol.io.fdi.lpConfigCredit := protocol_sb_node.io.outer.rx.credit + + protocol.io.fdi.plConfig.bits := protocol_sb_node.io.outer.tx.bits + protocol.io.fdi.plConfig.valid := protocol_sb_node.io.outer.tx.valid + protocol_sb_node.io.outer.tx.credit := protocol.io.fdi.plConfigCredit + + protocol_sb_node.io.inner.layer_to_node.bits := Cat(outer.regNode.module.io.sb_csrs.sideband_mailbox_sw_to_node_data_high, + outer.regNode.module.io.sb_csrs.sideband_mailbox_sw_to_node_data_low, + outer.regNode.module.io.sb_csrs.sidebank_mailbox_sw_to_node_index_high, + outer.regNode.module.io.sb_csrs.sideband_mailbox_sw_to_node_index_low) + protocol_sb_node.io.inner.layer_to_node.valid := outer.regNode.module.io.sb_csrs.sideband_mailbox_sw_valid - - // sideband_mailbox_index_low.d := protocol_sb_node.io.inner.node_to_layer.bits(31, 0) - // sideband_mailbox_index_high.d := protocol_sb_node.io.inner.node_to_layer.bits(63, 32) - // sideband_mailbox_data_low.d := protocol_sb_node.io.inner.node_to_layer.bits(95, 64) - // sideband_mailbox_data_high.d := protocol_sb_node.io.inner.node_to_layer.bits(127, 96) - // sideband_mailbox_ready.d := protocol_sb_node.io.inner.node_to_layer.ready - // sideband_mailbox_valid.d := protocol_sb_node.io.inner.node_to_layer.valid + outer.regNode.module.io.sb_csrs.sideband_mailbox_index_low := protocol_sb_node.io.inner.node_to_layer.bits(31, 0) + outer.regNode.module.io.sb_csrs.sideband_mailbox_index_high := protocol_sb_node.io.inner.node_to_layer.bits(63, 32) + outer.regNode.module.io.sb_csrs.sideband_mailbox_data_low := protocol_sb_node.io.inner.node_to_layer.bits(95, 64) + outer.regNode.module.io.sb_csrs.sideband_mailbox_data_high := protocol_sb_node.io.inner.node_to_layer.bits(127, 96) + protocol_sb_node.io.inner.node_to_layer.ready := outer.regNode.module.io.sb_csrs.sideband_mailbox_ready + outer.regNode.module.io.sb_csrs.sideband_mailbox_valid := protocol_sb_node.io.inner.node_to_layer.valid val tlBundleParams = new TLBundleParameters(addressBits = outer.tlParams.addressWidth, dataBits = outer.tlParams.dataWidth, @@ -210,13 +230,18 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { manager_tl.d.valid := outwardD.io.out.fire // ============ Below code should run on the UCIe clock? ============== + val checksum_reg = RegInit(0.U(64.W)) + checksum_reg := hammingEncoder.io.checksum + val tx_pipe = Module(new Pipe(new UCIRawPayloadFormat(outer.tlParams, outer.protoParams), 1)) + tx_pipe.io.enq.bits := uciTxPayload + tx_pipe.io.enq.valid := txArbiter.io.out.fire // Dequeue the TX TL packets and translate to UCIe flit txArbiter.io.out.ready := protocol.io.fdi.lpData.ready // if pl_trdy is asserted // specs implies that these needs to be asserted at the same time - protocol.io.TLlpData_valid := txArbiter.io.out.fire & (~protocol.io.fdi.lpStallAck) - protocol.io.TLlpData_irdy := txArbiter.io.out.fire & (~protocol.io.fdi.lpStallAck) - protocol.io.TLlpData_bits := uciTxPayload.asUInt // assign uciTXPayload to the FDI lp data signa + protocol.io.TLlpData_valid := tx_pipe.io.deq.valid & (~protocol.io.fdi.lpStallAck) + protocol.io.TLlpData_irdy := tx_pipe.io.deq.valid & (~protocol.io.fdi.lpStallAck) + protocol.io.TLlpData_bits := Cat(tx_pipe.io.deq.bits.asUInt(511,64), checksum_reg.asUInt) // assign uciTXPayload to the FDI lp data signa val creditA = (txArbiter.io.out.bits.msgType === UCIProtoMsgTypes.TLA) val creditB = (txArbiter.io.out.bits.msgType === UCIProtoMsgTypes.TLB) @@ -224,8 +249,8 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { val creditD = (txArbiter.io.out.bits.msgType === UCIProtoMsgTypes.TLD) val creditE = (txArbiter.io.out.bits.msgType === UCIProtoMsgTypes.TLE) - outwardA.io.credit.ready := txArbiter.io.out.fire && creditA - outwardD.io.credit.ready := txArbiter.io.out.fire && creditD + outwardA.io.credit.ready := tx_pipe.io.deq.valid && creditA + outwardD.io.credit.ready := tx_pipe.io.deq.valid && creditD val txACredit = WireDefault(0.U(outer.protoParams.creditWidth.W)) val txDCredit = WireDefault(0.U(outer.protoParams.creditWidth.W)) @@ -267,16 +292,16 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { uciTxPayload.data(2) := txArbiter.io.out.bits.data(191,128) uciTxPayload.data(3) := txArbiter.io.out.bits.data(255,192) // TODO: add ECC/checksum functionality, for now tieing to 0 + hammingEncoder.io.data := uciTxPayload.asUInt(511,64) uciTxPayload.ecc := 0.U } - + + // ======================= // TL RX packets coming from the UCIe stack to the System, push on the outward queue // ======================= val rxTLPayload = Wire(new TLBundleAUnionD(outer.tlParams)) rxTLPayload := 0.U.asTypeOf(new TLBundleAUnionD(outer.tlParams)) - dontTouch(rxTLPayload) - dontTouch(uciRxPayload) // protocol.io.fdi.lpData.irdy := outward.io.enq.ready // map the uciRxPayload and the plData based on the uciPayload formatting @@ -295,7 +320,9 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { uciRxPayload.data(0) := protocol.io.TLplData_bits(127,64) // ucie ecc uciRxPayload.ecc := protocol.io.TLplData_bits(63,0) - + hammingDecoder.io.data := protocol.io.TLplData_bits(511,64) + hammingDecoder.io.checksum := protocol.io.TLplData_bits(63,0) + // map the uciRxPayload to the rxTLPayload rxTLPayload.address := uciRxPayload.header1.address rxTLPayload.opcode := uciRxPayload.header2.opcode @@ -309,6 +336,7 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { rxTLPayload.data := Cat(uciRxPayload.data(0), uciRxPayload.data(1), uciRxPayload.data(2), uciRxPayload.data(3)) rxTLPayload.msgType := uciRxPayload.cmd.msgType } + fault := ~(hammingDecoder.io.matches) outwardA.io.in.bits.address := rxTLPayload.address outwardA.io.in.bits.opcode := rxTLPayload.opcode @@ -338,4 +366,12 @@ class UCITLFrontImp(outer: UCITLFront) extends LazyModuleImp(outer) { outwardD.io.in.valid := true.B } } + // when the RX queues are ready to get data + val TLready_to_rcv = outwardA.io.in.ready || outwardD.io.in.ready + protocol.io.TLready_to_rcv := TLready_to_rcv + + // soft resets: can be reset or flush and reset, in flush and reset, the packets are + // sent out before triggering reset + protocol.io.soft_reset := (outer.regNode.module.io.d2d_csrs.d2d_state_can_reset | + outer.regNode.module.io.d2d_csrs.d2d_flush_and_reset) } \ No newline at end of file diff --git a/src/test/scala/Configs.scala b/src/test/scala/protocol/Configs.scala similarity index 97% rename from src/test/scala/Configs.scala rename to src/test/scala/protocol/Configs.scala index 25c1fbb..fbe0d4b 100644 --- a/src/test/scala/Configs.scala +++ b/src/test/scala/protocol/Configs.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import org.chipsalliance.cde.config.{Field, Parameters, Config} import scala.collection.immutable.ListMap diff --git a/src/test/scala/FdiLoopback.scala b/src/test/scala/protocol/FdiLoopback.scala similarity index 99% rename from src/test/scala/FdiLoopback.scala rename to src/test/scala/protocol/FdiLoopback.scala index 4e52956..354f315 100644 --- a/src/test/scala/FdiLoopback.scala +++ b/src/test/scala/protocol/FdiLoopback.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import chisel3._ import chisel3.util._ diff --git a/src/test/scala/FdiLoopbackTest.scala b/src/test/scala/protocol/FdiLoopbackTest.scala similarity index 99% rename from src/test/scala/FdiLoopbackTest.scala rename to src/test/scala/protocol/FdiLoopbackTest.scala index 316471f..85bb556 100644 --- a/src/test/scala/FdiLoopbackTest.scala +++ b/src/test/scala/protocol/FdiLoopbackTest.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import chisel3._ import chisel3.util._ @@ -11,7 +12,7 @@ import freechips.rocketchip.diplomacy._ import edu.berkeley.cs.ucie.digital.interfaces.FdiParams import org.scalatest.flatspec.AnyFlatSpec import tilelink._ -import protocol._ +//import protocol._ class FdiLoopbackTester (implicit p: Parameters) extends LazyModule { val fdiParams = FdiParams(width=64, dllpWidth=64, sbWidth=32) diff --git a/src/test/scala/ProtoFDILBTestHarness.scala b/src/test/scala/protocol/ProtoFDILBTestHarness.scala similarity index 99% rename from src/test/scala/ProtoFDILBTestHarness.scala rename to src/test/scala/protocol/ProtoFDILBTestHarness.scala index f85db69..8342092 100644 --- a/src/test/scala/ProtoFDILBTestHarness.scala +++ b/src/test/scala/protocol/ProtoFDILBTestHarness.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import chisel3._ import chisel3.util._ diff --git a/src/test/scala/ProtoFDILoopback.scala b/src/test/scala/protocol/ProtoFDILoopback.scala similarity index 99% rename from src/test/scala/ProtoFDILoopback.scala rename to src/test/scala/protocol/ProtoFDILoopback.scala index 5163301..a02fffb 100644 --- a/src/test/scala/ProtoFDILoopback.scala +++ b/src/test/scala/protocol/ProtoFDILoopback.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import chisel3._ import chisel3.util._ diff --git a/src/test/scala/ProtoFDILoopbackTest.scala b/src/test/scala/protocol/ProtoFDILoopbackTest.scala similarity index 98% rename from src/test/scala/ProtoFDILoopbackTest.scala rename to src/test/scala/protocol/ProtoFDILoopbackTest.scala index 42ffce7..2f04605 100644 --- a/src/test/scala/ProtoFDILoopbackTest.scala +++ b/src/test/scala/protocol/ProtoFDILoopbackTest.scala @@ -1,4 +1,5 @@ package edu.berkeley.cs.ucie.digital +package protocol import chiseltest._ import org.scalatest.freespec.AnyFreeSpec diff --git a/src/test/scala/protocol/ProtocolLayerTest.scala b/src/test/scala/protocol/ProtocolLayerTest.scala new file mode 100644 index 0000000..1af3d93 --- /dev/null +++ b/src/test/scala/protocol/ProtocolLayerTest.scala @@ -0,0 +1,130 @@ +package edu.berkeley.cs.ucie.digital +package protocol + +import chisel3._ +import chisel3.util._ +import chiseltest._ +import org.scalatest.flatspec.AnyFlatSpec +import scala.collection.immutable._ +import scala.math._ + +import interfaces._ + +class ProtocolLayerTest extends AnyFlatSpec with ChiselScalatestTester { + val protoParams = new ProtocolLayerParams + val fdiParams = new FdiParams(width = 8, dllpWidth = 8, sbWidth = 32) + behavior of "Protocol layer" + it should "test hamming encode and decode" in { + test(new HammingWrapper(protoParams)){ c => + println("Instantiating pattern buffer") + val tuvok = "hBADDCAFE".U + val neelix = "hDEADBEEF".U + + println("Test matching transport") + c.io.tx_data.poke(tuvok) + c.io.rx_data.poke(tuvok) + c.io.checksum.poke("hFFFFFFFF".U) + c.io.matches.expect(true.B) + c.clock.step() + + c.io.tx_data.poke(neelix) + c.io.rx_data.poke(neelix) + c.io.checksum.poke("hFFFFFFFF".U) + c.io.matches.expect(true.B) + c.clock.step() + + println("Test checksum error") + c.io.tx_data.poke(tuvok) + c.io.rx_data.poke(tuvok) + c.io.checksum.poke("h1234ABCD".U) + c.io.matches.expect(false.B) + c.clock.step() + + c.io.tx_data.poke(neelix) + c.io.rx_data.poke(neelix) + c.io.checksum.poke("h1234ABCD".U) + c.io.matches.expect(false.B) + c.clock.step() + + println("Test mismatch transport") + c.io.tx_data.poke(tuvok) + c.io.rx_data.poke(neelix) + c.io.checksum.poke("hFFFFFFFF".U) + c.io.matches.expect(false.B) + c.clock.step() + + c.io.tx_data.poke(neelix) + c.io.rx_data.poke(tuvok) + c.io.checksum.poke("hFFFFFFFF".U) + c.io.matches.expect(false.B) + c.clock.step() + } + } + + it should "test ProtocolLayer fdi.plRxActiveReq and lp_rx_active_sts" in { + test(new ProtocolLayer(fdiParams)){ c => + c.io.TLready_to_rcv.poke(true.B) + c.io.fdi.plRxActiveReq.poke(true.B) + c.io.fdi.plStateStatus.poke(PhyState.active) + c.clock.step() + + c.io.TLready_to_rcv.poke(false.B) + c.io.fdi.plRxActiveReq.poke(true.B) + c.io.fdi.plStateStatus.poke(PhyState.active) + c.clock.step() + + c.io.TLready_to_rcv.poke(true.B) + c.io.fdi.plRxActiveReq.poke(false.B) + c.io.fdi.plStateStatus.poke(PhyState.active) + c.clock.step() + + c.io.TLready_to_rcv.poke(true.B) + c.io.fdi.plRxActiveReq.poke(true.B) + c.io.fdi.plStateStatus.poke(PhyState.reset) + c.clock.step() + + c.io.TLready_to_rcv.poke(true.B) + c.io.fdi.plRxActiveReq.poke(true.B) + c.io.fdi.plStateStatus.poke(PhyState.linkReset) + c.clock.step() + } + } + + it should "test ProtocolLayer stall req/ack" in { + test(new ProtocolLayer(fdiParams)){ c => + c.io.fdi.plStallReq.poke(false.B) + c.clock.step() + c.io.fdi.lpStallAck.expect(false.B) + c.io.fdi.plStallReq.poke(true.B) + c.io.fdi.lpStallAck.expect(false.B) + c.clock.step() + c.io.fdi.lpStallAck.expect(true.B) + } + } + + it should "test ProtocolLayer link_error" in { + test(new ProtocolLayer(fdiParams)){ c => + c.io.fault.poke(true.B) + c.io.fdi.lpLinkError.expect(true.B) + + c.io.fault.poke(false.B) + c.io.fdi.lpLinkError.expect(false.B) + } + } +} + +class HammingWrapper(val protoParams: ProtocolLayerParams) extends Module { + val io = IO(new Bundle{ + val tx_data = Input(UInt(protoParams.ucieNonEccWidth.W)) + val rx_data = Input(UInt(protoParams.ucieNonEccWidth.W)) + val checksum = Input(UInt(protoParams.ucieEccWidth.W)) + val matches = Output(Bool()) + }) + val encoder = Module(new HammingEncode(protoParams)) + val decoder = Module(new HammingDecode(protoParams)) + + encoder.io.data := io.tx_data + decoder.io.data := io.rx_data + decoder.io.checksum := encoder.io.checksum & io.checksum + io.matches := decoder.io.matches +}