From fd7f4a4c0f0aa9ea83be81ea75e6e9e063f03211 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Thu, 13 Apr 2017 16:12:22 -0700 Subject: [PATCH] jtag: make it easier to assign MFR ID externally --- src/main/scala/jtag/JtagTap.scala | 44 +++++++++++-------- src/main/scala/jtag/JtagUtils.scala | 7 +++ .../scala/rocketchip/DebugTransport.scala | 10 ++++- src/main/scala/rocketchip/RISCVPlatform.scala | 4 ++ src/main/scala/rocketchip/TestHarness.scala | 1 + 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/main/scala/jtag/JtagTap.scala b/src/main/scala/jtag/JtagTap.scala index 53c1d1b1..50aee22c 100644 --- a/src/main/scala/jtag/JtagTap.scala +++ b/src/main/scala/jtag/JtagTap.scala @@ -32,17 +32,19 @@ class JtagControl extends Bundle { /** Aggregate JTAG block IO. */ -class JtagBlockIO(irLength: Int) extends Bundle { +class JtagBlockIO(irLength: Int, hasIdcode:Boolean = true) extends Bundle { + val jtag = Flipped(new JTAGIO()) val control = new JtagControl val output = new JtagOutput(irLength) + val idcode = if (hasIdcode) Some(Input(new JTAGIdcodeBundle())) else None - override def cloneType = new JtagBlockIO(irLength).asInstanceOf[this.type] + override def cloneType = new JtagBlockIO(irLength, hasIdcode).asInstanceOf[this.type] } /** Internal controller block IO with data shift outputs. */ -class JtagControllerIO(irLength: Int) extends JtagBlockIO(irLength) { +class JtagControllerIO(irLength: Int) extends JtagBlockIO(irLength, false) { val dataChainOut = Output(new ShifterIO) val dataChainIn = Input(new ShifterIO) @@ -140,7 +142,7 @@ object JtagTapGenerator { * @param irLength length, in bits, of instruction register, must be at least 2 * @param instructions map of instruction codes to data register chains that select that data * register; multiple instructions may map to the same data chain - * @param idcode optional idcode, tuple of (instruction code, idcode) + * @param idcode optional idcode instruction. idcode UInt will come from outside this core. * * @note all other instruction codes (not part of instructions or idcode) map to BYPASS * @note initial instruction is idcode (if supported), otherwise all ones BYPASS @@ -158,25 +160,30 @@ object JtagTapGenerator { * TODO: * - support concatenated scan chains */ - def apply(irLength: Int, instructions: Map[BigInt, Chain], idcode:Option[(BigInt, BigInt)]=None): JtagBlockIO = { + def apply(irLength: Int, instructions: Map[BigInt, Chain], icode: Option[BigInt] = None): JtagBlockIO = { + + val internalIo = Wire(new JtagBlockIO(irLength, icode.isDefined)) + + // Create IDCODE chain if needed - val allInstructions = idcode match { - case Some((icode, idcode)) => { - val idcodeChain = Module(CaptureChain(UInt(32.W))) - idcodeChain.suggestName("idcodeChain") - require(idcode % 2 == 1, "LSB must be set in IDCODE, see 12.1.1d") - require(((idcode >> 1) & ((1 << 11) - 1)) != JtagIdcode.dummyMfrId, "IDCODE must not have 0b00001111111 as manufacturer identity, see 12.2.1b") + val allInstructions = icode match { + case (Some(icode)) => { require(!(instructions contains icode), "instructions may not contain IDCODE") - idcodeChain.io.capture.bits := idcode.U(32.W) + val idcodeChain = Module(CaptureChain(new JTAGIdcodeBundle())) + idcodeChain.suggestName("idcodeChain") + val i = internalIo.idcode.get.asUInt() + assert(i % 2.U === 1.U, "LSB must be set in IDCODE, see 12.1.1d") + assert(((i >> 1) & ((1.U << 11) - 1.U)) =/= JtagIdcode.dummyMfrId.U, + "IDCODE must not have 0b00001111111 as manufacturer identity, see 12.2.1b") + idcodeChain.io.capture.bits := internalIo.idcode.get instructions + (icode -> idcodeChain) - } case None => instructions + + } + case None => instructions } val bypassIcode = (BigInt(1) << irLength) - 1 // required BYPASS instruction - val initialInstruction = idcode match { // 7.2.1e load IDCODE or BYPASS instruction after entry into TestLogicReset - case Some((icode, _)) => icode - case None => bypassIcode - } + val initialInstruction = icode.getOrElse(bypassIcode) // 7.2.1e load IDCODE or BYPASS instruction after entry into TestLogicReset require(!(allInstructions contains bypassIcode), "instructions may not contain BYPASS code") @@ -230,12 +237,11 @@ object JtagTapGenerator { chainToSelect.map(mapInSelect) - val internalIo = Wire(new JtagBlockIO(irLength)) - controllerInternal.io.jtag <> internalIo.jtag controllerInternal.io.control <> internalIo.control controllerInternal.io.output <> internalIo.output internalIo } + } diff --git a/src/main/scala/jtag/JtagUtils.scala b/src/main/scala/jtag/JtagUtils.scala index 2bfb4606..8c216a57 100644 --- a/src/main/scala/jtag/JtagUtils.scala +++ b/src/main/scala/jtag/JtagUtils.scala @@ -5,6 +5,13 @@ package jtag import chisel3._ import chisel3.util._ +class JTAGIdcodeBundle extends Bundle { + val version = UInt(4.W) + val partNumber = UInt(16.W) + val mfrId = UInt(11.W) + val always1 = UInt(1.W) +} + object JtagIdcode { /** Generates a JTAG IDCODE as a 32-bit integer, using the format in 12.1.1d. */ diff --git a/src/main/scala/rocketchip/DebugTransport.scala b/src/main/scala/rocketchip/DebugTransport.scala index 86c9bf28..c1a8b015 100644 --- a/src/main/scala/rocketchip/DebugTransport.scala +++ b/src/main/scala/rocketchip/DebugTransport.scala @@ -64,6 +64,7 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig) val dmi = new DMIIO()(p) val jtag = Flipped(new JTAGIO(hasTRSTn = false)) val jtag_reset = Bool(INPUT) + val jtag_mfr_id = UInt(INPUT, 11) val fsmReset = Bool(OUTPUT) } @@ -210,12 +211,19 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig) //-------------------------------------------------------- // Actual JTAG TAP + val idcode = Wire(init = new JTAGIdcodeBundle().fromBits(0.U)) + idcode.always1 := 1.U + idcode.version := c.idcodeVersion.U + idcode.partNumber := c.idcodePartNum.U + idcode.mfrId := io.jtag_mfr_id val tapIO = JtagTapGenerator(irLength = 5, instructions = Map(dtmJTAGAddrs.DMI_ACCESS -> dmiAccessChain, dtmJTAGAddrs.DTM_INFO -> dtmInfoChain), - idcode = Some((dtmJTAGAddrs.IDCODE, JtagIdcode(c.idcodeVersion, c.idcodePartNum, c.idcodeManufId)))) + icode = Some(dtmJTAGAddrs.IDCODE) + ) + tapIO.idcode.get := idcode tapIO.jtag <> io.jtag tapIO.control.jtag_reset := io.jtag_reset diff --git a/src/main/scala/rocketchip/RISCVPlatform.scala b/src/main/scala/rocketchip/RISCVPlatform.scala index 12c656ba..91f23639 100644 --- a/src/main/scala/rocketchip/RISCVPlatform.scala +++ b/src/main/scala/rocketchip/RISCVPlatform.scala @@ -24,6 +24,7 @@ trait PeripheryJTAGDTMBundle extends HasTopLevelNetworksBundle { val jtag = new JTAGIO(hasTRSTn = false).flip val jtag_reset = Bool(INPUT) + val jtag_mfr_id = UInt(INPUT, 11) } @@ -36,6 +37,7 @@ trait PeripheryJTAGDTMModule extends HasTopLevelNetworksModule { dtm.clock := io.jtag.TCK dtm.io.jtag_reset := io.jtag_reset + dtm.io.jtag_mfr_id := io.jtag_mfr_id dtm.reset := dtm.io.fsmReset outer.coreplex.module.io.debug.dmi <> dtm.io.dmi @@ -79,6 +81,7 @@ trait PeripheryDebugBundle extends HasTopLevelNetworksBundle { val jtag = (p(IncludeJtagDTM)).option(new JTAGIO(hasTRSTn = false).flip) val jtag_reset = (p(IncludeJtagDTM)).option(Bool(INPUT)) + val jtag_mfr_id = (p(IncludeJtagDTM)).option(UInt(INPUT, 11)) val ndreset = Bool(OUTPUT) val dmactive = Bool(OUTPUT) @@ -96,6 +99,7 @@ trait PeripheryDebugModule extends HasTopLevelNetworksModule { dtm.clock := io.jtag.get.TCK dtm.io.jtag_reset := io.jtag_reset.get + dtm.io.jtag_mfr_id := io.jtag_mfr_id.get dtm.reset := dtm.io.fsmReset outer.coreplex.module.io.debug.dmi <> dtm.io.dmi diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 8ce3956b..5c1c360e 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -28,6 +28,7 @@ class TestHarness()(implicit p: Parameters) extends Module { val dtm = Module(new SimDTM).connect(clock, reset, dut.io.debug.get, io.success) } else { val jtag = Module(new JTAGVPI).connect(dut.io.jtag.get, dut.io.jtag_reset.get, reset, io.success) + dut.io.jtag_mfr_id.get := p(JtagDTMKey).idcodeManufId.U(11.W) } val mmio_sim = Module(LazyModule(new SimAXIMem(1, 4096)).module)