Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only punch realistic subset of DebugIO through chiptop | default to JTAG+Serial #664

Merged
merged 7 commits into from
Sep 4, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ jobs:
steps:
- prepare-rtl:
project-key: "chipyard-rocket"
prepare-chipyard-dmirocket:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-dmirocket"
prepare-chipyard-sha3:
executor: main-env
steps:
Expand All @@ -225,11 +230,6 @@ jobs:
steps:
- prepare-rtl:
project-key: "chipyard-boom"
prepare-rocketchip:
executor: main-env
steps:
- prepare-rtl:
project-key: "rocketchip"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "rocketchip" set of tests did the exact same thing as the "chipyard-rocket" set of tests, so I removed these.

prepare-chipyard-blkdev:
executor: main-env
steps:
Expand Down Expand Up @@ -297,6 +297,11 @@ jobs:
steps:
- run-tests:
project-key: "chipyard-rocket"
chipyard-dmirocket-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-dmirocket"
chipyard-sha3-run-tests:
executor: main-env
steps:
Expand All @@ -323,11 +328,6 @@ jobs:
steps:
- run-tests:
project-key: "chipyard-boom"
rocketchip-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "rocketchip"
chipyard-hwacha-run-tests:
executor: main-env
steps:
Expand Down Expand Up @@ -451,6 +451,11 @@ workflows:
- install-riscv-toolchain
- install-verilator

- prepare-chipyard-dmirocket:
requires:
- install-riscv-toolchain
- install-verilator

- prepare-chipyard-sha3:
requires:
- install-riscv-toolchain
Expand All @@ -476,11 +481,6 @@ workflows:
- install-riscv-toolchain
- install-verilator

- prepare-rocketchip:
requires:
- install-riscv-toolchain
- install-verilator

- prepare-chipyard-blkdev:
requires:
- install-riscv-toolchain
Expand Down Expand Up @@ -547,6 +547,10 @@ workflows:
requires:
- prepare-chipyard-rocket

- chipyard-dmirocket-run-tests:
requires:
- prepare-chipyard-dmirocket

- chipyard-sha3-run-tests:
requires:
- prepare-chipyard-sha3
Expand All @@ -567,10 +571,6 @@ workflows:
requires:
- prepare-chipyard-boom

- rocketchip-run-tests:
requires:
- prepare-rocketchip

- chipyard-hwacha-run-tests:
requires:
- prepare-chipyard-hwacha
Expand Down
1 change: 1 addition & 0 deletions .circleci/defaults.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
# key value store to get the build strings
declare -A mapping
mapping["chipyard-rocket"]=""
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
Expand Down
3 changes: 3 additions & 0 deletions .circleci/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ case $1 in
chipyard-rocket)
run_bmark ${mapping[$1]}
;;
chipyard-dmirocket)
run_bmark ${mapping[$1]}
;;
chipyard-boom)
run_bmark ${mapping[$1]}
;;
Expand Down
33 changes: 1 addition & 32 deletions docs/Advanced-Concepts/Chip-Communication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,38 +130,7 @@ Using the JTAG Interface
------------------------

The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM)
and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above).

Creating a DTM+JTAG Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

First, a DTM config must be created for the system that you want to create.
This step is similar to the DMI simulation section within the :ref:`Starting the TSI or DMI Simulation` section.
The configuration is very similar to a DMI-based configuration. The main difference
is the addition of the ``WithJtagDTM`` config fragment that configures the instantiated DTM to use the JTAG protocol as the
bringup method.

.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala
:language: scala
:start-after: DOC include start: JtagRocket
:end-before: DOC include end: JtagRocket

Building a DTM+JTAG Simulator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After creating the config, call the ``make`` command like the following to build a simulator for your RTL:

.. code-block:: bash

cd sims/verilator
# or
cd sims/vcs

make CONFIG=jtagRocketConfig

In this example, the simulation will use the config that you previously specified, as well as set
the other parameters that are needed to satisfy the build system. After that point, you
should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB!
and configure it to use a JTAG interface. The default Chipyard designs configure the DTM to use JTAG. you may attach OpenOCD and GDB to any of the default JTAG-enabled designs.
jerryz123 marked this conversation as resolved.
Show resolved Hide resolved

Debugging with JTAG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
9 changes: 8 additions & 1 deletion generators/chipyard/src/main/scala/ConfigFragments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import freechips.rocketchip.config.{Field, Parameters, Config}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.diplomacy.{LazyModule, ValName}
import freechips.rocketchip.devices.tilelink.{BootROMLocated}
import freechips.rocketchip.devices.debug.{Debug}
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
import freechips.rocketchip.tile._
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
Expand Down Expand Up @@ -163,3 +163,10 @@ class WithTileDividedClock extends Config((site, here, up) => {
case ClockingSchemeKey => ClockingSchemeGenerators.harnessDividedClock
})

class WithDMIDTM extends Config((site, here, up) => {
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
})

class WithNoDebug extends Config((site, here, up) => {
case DebugModuleKey => None
})
137 changes: 92 additions & 45 deletions generators/chipyard/src/main/scala/IOBinders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package chipyard
package object iobinders {

import chisel3._
import chisel3.util.experimental.{BoringUtils}
import chisel3.experimental.{Analog, IO}

import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
Expand Down Expand Up @@ -163,30 +165,62 @@ object AddIOCells {
}

/**
* Add IO cells to a debug module and name the IO ports.
* @param psd A PSDIO bundle
* @param resetctrlOpt An optional ResetCtrlIO bundle
* @param debugOpt An optional DebugIO bundle
* @return Returns a tuple3 of (Top-level PSDIO IO; Optional top-level DebugIO IO; a list of IOCell module references)
* Add IO cells to a debug module and name the IO ports, for debug IO which must go off-chip
* For on-chip debug IO, drive them appropriately
* Mostly copied from rocket-chip/src/main/scala/devices/debug/Periphery.scala
* @param system A BaseSubsystem that might have a debug module
* @return Returns a tuple2 of (Generated debug io ports, Generated IOCells)
*/
def debug(psd: PSDIO, resetctrlOpt: Option[ResetCtrlIO], debugOpt: Option[DebugIO])(implicit p: Parameters):
(PSDIO, Option[ResetCtrlIO], Option[DebugIO], Seq[IOCell]) = {
val (psdPort, psdIOs) = IOCell.generateIOFromSignal(
psd, Some("iocell_psd"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
val debugTuple = debugOpt.map(d =>
IOCell.generateIOFromSignal(d, Some("iocell_debug"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
val debugPortOpt: Option[DebugIO] = debugTuple.map(_._1)
val debugIOs: Seq[IOCell] = debugTuple.map(_._2).toSeq.flatten
debugPortOpt.foreach(_.suggestName("debug"))

val resetctrlTuple = resetctrlOpt.map(d =>
IOCell.generateIOFromSignal(d, Some("iocell_resetctrl"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
val resetctrlPortOpt: Option[ResetCtrlIO] = resetctrlTuple.map(_._1)
val resetctrlIOs: Seq[IOCell] = resetctrlTuple.map(_._2).toSeq.flatten
resetctrlPortOpt.foreach(_.suggestName("resetctrl"))

psdPort.suggestName("psd")
(psdPort, resetctrlPortOpt, debugPortOpt, psdIOs ++ debugIOs ++ resetctrlIOs)
def debug(system: HasPeripheryDebugModuleImp)(implicit p: Parameters): (Seq[Bundle], Seq[IOCell]) = {
system.debug.map { debug =>
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
val debug_clock = Wire(Clock()).suggestName("debug_clock")
val debug_reset = Wire(Reset()).suggestName("debug_reset")
debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error
debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error
BoringUtils.bore(tlbus.module.clock, Seq(debug_clock))
BoringUtils.bore(tlbus.module.reset, Seq(debug_reset))

// We never use the PSDIO, so tie it off on-chip
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
system.debug.map { d =>
// Tie off extTrigger
d.extTrigger.foreach { t =>
t.in.req := false.B
t.out.ack := t.out.req
}
// Tie off disableDebug
d.disableDebug.foreach { d => d := false.B }
// Drive JTAG on-chip IOs
d.systemjtag.map { j =>
j.reset := debug_reset
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
}
}
Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)

// Add IOCells for the DMI/JTAG/APB ports
val dmiTuple = debug.clockeddmi.map { d =>
IOCell.generateIOFromSignal(d, Some("iocell_dmi"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
dmiTuple.map(_._1).foreach(_.suggestName("dmi"))

val jtagTuple = debug.systemjtag.map { j =>
IOCell.generateIOFromSignal(j.jtag, Some("iocell_jtag"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
jtagTuple.map(_._1).foreach(_.suggestName("jtag"))

val apbTuple = debug.apb.map { a =>
IOCell.generateIOFromSignal(a, Some("iocell_apb"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
apbTuple.map(_._1).foreach(_.suggestName("apb"))

val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
}.getOrElse((Nil, Nil))
}

/**
Expand Down Expand Up @@ -364,40 +398,53 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({
}
})

// TODO we need to rethink what "Tie-off-debug" means. The current system punches out
// excessive IOs.
class WithTiedOffDebug extends OverrideIOBinder({
class WithSimDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val (ports, iocells) = AddIOCells.debug(system)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
Debug.tieoffDebug(debugPortOpt, resetctrlOpt, Some(psdPort))(system.p)
// tieoffDebug doesn't actually tie everything off :/
debugPortOpt.foreach { d =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare; cdmi.dmiClock := th.harnessClock })
d.dmactiveAck := DontCare
d.clock := th.harnessClock // TODO fix: This should be driven from within the chip
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
ports.map {
case d: ClockedDMIIO =>
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
case j: JTAGIO =>
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
case _ =>
require(false, "We only support DMI or JTAG simulated debug connections")
}
Nil
}
Seq((Seq(psdPort) ++ resetctrlOpt ++ debugPortOpt.toSeq, Nil, Some(harnessFn)))
Seq((ports, iocells, Some(harnessFn)))
}
})

// TODO we need to rethink what this does. The current system punches out excessive IOs.
// Some of the debug clock/reset should be driven from on-chip
class WithSimDebug extends OverrideIOBinder({
class WithTiedOffDebug extends OverrideIOBinder({
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val (ports, iocells) = AddIOCells.debug(system)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
val dtm_success = Wire(Bool())
Debug.connectDebug(debugPortOpt, resetctrlPortOpt, psdPort, th.harnessClock, th.harnessReset.asBool, dtm_success)(system.p)
when (dtm_success) { th.success := true.B }
th.dutReset := th.harnessReset.asBool | debugPortOpt.map { debug => AsyncResetReg(debug.ndreset).asBool }.getOrElse(false.B)
ports.map {
case d: ClockedDMIIO =>
d.dmi.req.valid := false.B
d.dmi.req.bits := DontCare
d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case j: JTAGIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
j.TRSTn.foreach { r => r := true.B }
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
case a: ClockedAPBBundle =>
a.tieoff()
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
case _ => require(false)
}
Nil
}
Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn)))
Seq((ports, iocells, Some(harnessFn)))
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ class AbstractConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter
new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model
new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing)
new chipyard.iobinders.WithSimDebug ++ // attach SimJTAG
new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing
new testchipip.WithTSI ++ // use testchipip serial offchip link
new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ class ArianeConfig extends Config(

class dmiArianeConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation, override default tie-off debug
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new ariane.WithNArianeCores(1) ++ // single Ariane core
new chipyard.config.AbstractConfig)
12 changes: 2 additions & 10 deletions generators/chipyard/src/main/scala/config/RocketConfigs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,10 @@ class GemminiRocketConfig extends Config(
new chipyard.config.AbstractConfig)
// DOC include end: GemminiRocketConfig

// DOC include start: JtagRocket
class jtagRocketConfig extends Config(
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, in addition to default SimSerial
new freechips.rocketchip.subsystem.WithJtagDTM ++ // sets DTM communication interface to JTAG
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: JtagRocket

// DOC include start: DmiRocket
class dmiRocketConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // tie-off serial, override default add SimSerial
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, override default tie-off debug
new chipyard.iobinders.WithTiedOffSerial ++ // don't use serial to drive the chip, since we use DMI instead
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: DmiRocket
Expand Down
Loading