[Weekly Review] 2020/02/10-16

Published: by Creative Commons Licence (Last updated: )

2020/02/10-16

This week, I continued my survey at AI for HPC and the implementation of Eyeriss V2.

I found a visualization tool named Netron to translate the Neural Network from .onnx etc. files to graphs.

Matrix Multiply

A Geometrical View

A Geometrical View of Matrix Multiply

Chisel Syntax

DataMirror

Defined there.

object DataMirror {
  def widthOf(target: Data): Width = target.width
  def specifiedDirectionOf(target: Data): SpecifiedDirection = target.specifiedDirection
  def directionOf(target: Data): ActualDirection = {
    requireIsHardware(target, "node requested directionality on")
    target.direction
  }

  // Returns the top-level module ports
  // TODO: maybe move to something like Driver or DriverUtils, since this is mainly for interacting
  // with compiled artifacts (vs. elaboration-time reflection)?
  def modulePorts(target: BaseModule): Seq[(String, Data)] = target.getChiselPorts

  // Returns all module ports with underscore-qualified names
  def fullModulePorts(target: BaseModule): Seq[(String, Data)] = {
    def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match {
      case _: Element => Seq()
      case r: Record => r.elements.toSeq flatMap { case (eltName, elt) => getPortNames(s"${name}_${eltName}", elt) }
      case v: Vec[_] => v.zipWithIndex flatMap { case (elt, index) => getPortNames(s"${name}_${index}", elt) }
    })
    modulePorts(target).flatMap { case (name, data) =>
      getPortNames(name, data).toList
    }
  }
}

// usage
DataMirror.modulePorts(adder).foreach { case (name, port) => {
  println(s"Found port $name: $port")
}}
assert(DataMirror.directionOf(flippedVec.head.a) == Direction.Output)

val specifiedDirs = Seq(
    a.fizz.foo -> SpecifiedDirection.Input,
    a.fizz.bar -> SpecifiedDirection.Output,
    a.fizz -> SpecifiedDirection.Unspecified,
    a.buzz.foo -> SpecifiedDirection.Input,
    a.buzz.bar -> SpecifiedDirection.Output,
    a.buzz -> SpecifiedDirection.Flip
)
val actualDirs = Seq(
    b.fizz.foo -> Direction.Input,
    b.fizz.bar -> Direction.Output,
    b.fizz -> Direction.Bidirectional(Direction.Default),
    b.buzz.foo -> Direction.Output,
    b.buzz.bar -> Direction.Input,
    b.buzz -> Direction.Bidirectional(Direction.Flipped)
)
for ((data, dir) <- specifiedDirs) {
    DataMirror.specifiedDirectionOf(data) shouldBe (dir)
}
for ((data, dir) <- actualDirs) {
    DataMirror.directionOf(data) shouldBe (dir)
}

Chipyard

How to Access DMA

From this post at chisel China, the RoCC accelerators can communicate with main memory via DMA with TileLink's help. I got that post from this issue blog.

I found one DMA project written in Chisel with TileLink protocol. So maybe I will utilize this design directedly.

How to Access Level 2 Cache

Although an earlier document shows that RoCC accelerators can communicate with L2 memory via Uncached Tile Link(UTL), but we can not find this port now from the class RoCCIO.

Old RoCC Interface

From the discussing in HW Dev Google Group, one said that we can learn the details from Hwacha and Gemmini, so I fetched some details in those projects.

Hwacha

From the document Hardware Acceleration for Memory to Memory Copies, we can see that the submodules of Hwacha: SMU, VMU, VRU and one L1 cache connect to L1-to-L2 TileLink Crossbar, which might be SystemBus now. So maybe we can find some common ports in those modules and then we can get the method to communicate with L2 cache.

Hwacha Design

Hwacha.smu.scala

class SMUReq(implicit p: Parameters) extends SMUBundle()(p)
  with SMUData {
  val fn = new SMUFn
  val addr = UInt(width = bVAddrExtended)
  val status = new freechips.rocketchip.rocket.MStatus
}

class SMUResp(implicit p: Parameters) extends SMUBundle()(p)
  with SMUData {
  val store = Bool()
}

class SMUIO(implicit p: Parameters) extends HwachaBundle()(p) {
  val req = Decoupled(new SMUReq)
  val resp = Decoupled(new SMUResp).flip
  val confirm = Bool(INPUT)
}

Hwacha.vmu-memif.scala

class VMUMemReq(implicit p: Parameters) extends VMUMemOp
  with VMUTag with VMUData {
  val mask = UInt(width = tlDataBytes)
  val pred = Bool()
}

class VMUMemResp(implicit p: Parameters) extends VMULoadData()(p) {
  val store = Bool()
}

class VMUMemIO(implicit p: Parameters) extends VMUBundle()(p) {
  val req = Decoupled(new VMUMemReq)
  val resp = Decoupled(new VMUMemResp).flip
}

Hwacha.types-vmu.scala

abstract class HwachaBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
  with UsesHwachaParameters

abstract class VMUBundle(implicit p: Parameters)
  extends HwachaBundle()(p) with VMUParameters

trait VMUAddr extends VMUBundle {
  val addr = UInt(width = bPAddr)
}

trait VMUMemOp extends VMUAddr {
  val fn = new VMUMemFn
}

trait VMUTag extends VMUBundle {
  val tag = UInt(width = bVMUTag)
}

trait VMUData extends VMUBundle {
  val data = Bits(width = tlDataBits)
}

class VMULoadData(implicit p: Parameters) extends VMUData with VMUTag
Back to Top
Share Post: