ahb: ignore hrdata on an AHB error
From the AHB spec: "A slave only has to provide valid data when a transfer completes with an OKAY response. ERROR responses do not require valid read data."
This commit is contained in:
		@@ -49,7 +49,7 @@ class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  val node  = AHBIdentityNode()
 | 
					  val node  = AHBIdentityNode()
 | 
				
			||||||
  val fuzz  = LazyModule(new TLFuzzer(txns, overrideAddress = Some(fuzzAddr)))
 | 
					  val fuzz  = LazyModule(new TLFuzzer(txns, overrideAddress = Some(fuzzAddr)))
 | 
				
			||||||
  val model = LazyModule(new TLRAMModel("AHBFuzzMaster"))
 | 
					  val model = LazyModule(new TLRAMModel("AHBFuzzMaster", ignoreErrorData=true))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (node
 | 
					  (node
 | 
				
			||||||
     := TLToAHB(aFlow)
 | 
					     := TLToAHB(aFlow)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,7 +106,14 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule
 | 
				
			|||||||
      out.a.bits.mask    := MaskGen(d_addr, d_size, beatBytes)
 | 
					      out.a.bits.mask    := MaskGen(d_addr, d_size, beatBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      out.d.ready  := d_recv // backpressure AccessAckData arriving faster than AHB beats
 | 
					      out.d.ready  := d_recv // backpressure AccessAckData arriving faster than AHB beats
 | 
				
			||||||
      in.hrdata    := out.d.bits.data
 | 
					
 | 
				
			||||||
 | 
					      // NOTE: on error, we present the read result on the hreadyout LOW cycle
 | 
				
			||||||
 | 
					      // This means that if you latch hrdata from an error, the result is garbage.
 | 
				
			||||||
 | 
					      // To fix this would require a bus-wide register, and the AHB spec says this:
 | 
				
			||||||
 | 
					      // "A slave only has to provide valid data when a transfer completes with an OKAY
 | 
				
			||||||
 | 
					      //  response. ERROR responses do not require valid read data."
 | 
				
			||||||
 | 
					      // Therefore, we choose to accept this slight TL-AHB infidelity.
 | 
				
			||||||
 | 
					      in.hrdata := out.d.bits.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // In a perfect world, we'd use these signals
 | 
					      // In a perfect world, we'd use these signals
 | 
				
			||||||
      val hresp = d_error || (out.d.valid && out.d.bits.error)
 | 
					      val hresp = d_error || (out.d.valid && out.d.bits.error)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ import freechips.rocketchip.util._
 | 
				
			|||||||
// put, get, getAck, putAck => ok: detected by getAck (it sees busy>0)		impossible for FIFO
 | 
					// put, get, getAck, putAck => ok: detected by getAck (it sees busy>0)		impossible for FIFO
 | 
				
			||||||
// If FIFO, the getAck should check data even if its validity was wiped
 | 
					// If FIFO, the getAck should check data even if its validity was wiped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
 | 
					class TLRAMModel(log: String = "", ignoreErrorData: Boolean = false)(implicit p: Parameters) extends LazyModule
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  val node = TLAdapterNode()
 | 
					  val node = TLAdapterNode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -288,6 +288,8 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
 | 
				
			|||||||
                printf(", undefined (concurrent incomplete puts #%d)\n", d_inc(i) - d_dec(i))
 | 
					                printf(", undefined (concurrent incomplete puts #%d)\n", d_inc(i) - d_dec(i))
 | 
				
			||||||
              } .elsewhen (!d_fifo && !d_valid) {
 | 
					              } .elsewhen (!d_fifo && !d_valid) {
 | 
				
			||||||
                printf(", undefined (concurrent completed put)\n")
 | 
					                printf(", undefined (concurrent completed put)\n")
 | 
				
			||||||
 | 
					              } .elsewhen (Bool(ignoreErrorData) && d.error) {
 | 
				
			||||||
 | 
					                printf(", undefined (error result)\n")
 | 
				
			||||||
              } .otherwise {
 | 
					              } .otherwise {
 | 
				
			||||||
                printf("\n")
 | 
					                printf("\n")
 | 
				
			||||||
                when (shadow.value =/= got) { printf("EXPECTED: 0x%x\n", shadow.value) }
 | 
					                when (shadow.value =/= got) { printf("EXPECTED: 0x%x\n", shadow.value) }
 | 
				
			||||||
@@ -303,8 +305,9 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
 | 
				
			|||||||
          when ((Cat(race.reverse) & d_mask).orR) { d_no_race := Bool(false) }
 | 
					          when ((Cat(race.reverse) & d_mask).orR) { d_no_race := Bool(false) }
 | 
				
			||||||
          when (d_last) {
 | 
					          when (d_last) {
 | 
				
			||||||
            val must_match = d_crc_valid && (d_fifo || (d_valid && d_no_race))
 | 
					            val must_match = d_crc_valid && (d_fifo || (d_valid && d_no_race))
 | 
				
			||||||
 | 
					            val error = Bool(ignoreErrorData) && d.error
 | 
				
			||||||
            printf(log + " crc = 0x%x %d\n", d_crc, must_match.asUInt)
 | 
					            printf(log + " crc = 0x%x %d\n", d_crc, must_match.asUInt)
 | 
				
			||||||
            when (must_match && d_crc =/= d_crc_check) { printf("EXPECTED: 0x%x\n", d_crc_check) }
 | 
					            when (!error && must_match && d_crc =/= d_crc_check) { printf("EXPECTED: 0x%x\n", d_crc_check) }
 | 
				
			||||||
            assert (!must_match || d_crc === d_crc_check)
 | 
					            assert (!must_match || d_crc === d_crc_check)
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user