分形计算器

简介

此示例将展示使用数据流和定点计算实现一个未经优化的Mandelbrot分形计算器。

规范

该组件将接收像素任务的一个 Stream (其中包含Mandelbrot空间中的XY坐标),并将生成一个像素结果的一个 Stream (包含对应任务的迭代次数)。

定义组件的IO为:

IO名称

方向

类型

描述

cmd

slave

Stream[PixelTask]

提供XY坐标来处理

rsp

master

Stream[PixelResult]

返回对应cmd交换所需的迭代次数

让我们设计 PixelTask Bundle

元素名称

类型

描述

x

SFix

Mandelbrot空间中的坐标

y

SFix

Mandelbrot空间中的坐标

定义PixelResult Bundle

元素名称

类型

描述

iteration

UInt

求解Mandelbrot坐标所需的迭代次数

细化参数(泛型)

让我们定义为系统提供构造参数的类:

case class PixelSolverGenerics(fixAmplitude: Int,
                               fixResolution: Int,
                               iterationLimit: Int) {
  val iterationWidth = log2Up(iterationLimit+1)
  def iterationType = UInt(iterationWidth bits)
  def fixType = SFix(
    peak=fixAmplitude exp,
    resolution=fixResolution exp
  )
}

备注

iterationType和fixType是可以调用来实例化新信号的函数,它就像C语言中的typedef。

Bundle定义

case class PixelTask(g: PixelSolverGenerics) extends Bundle {
  val x, y = g.fixType
}

case class PixelResult(g: PixelSolverGenerics) extends Bundle {
  val iteration = g.iterationType
}

组件实现

现在进行实现。下面是一个非常简单的实现,没有使用流水线处理/多线程技术。

case class PixelSolver(g: PixelSolverGenerics) extends Component {
  val io = new Bundle {
    val cmd = slave  Stream(PixelTask(g))
    val rsp = master Stream(PixelResult(g))
  }

  import g._

  // Define states
  val x, y = Reg(fixType) init(0)
  val iteration = Reg(iterationType) init(0)

  // Do some shared calculation
  val xx = x*x
  val yy = y*y
  val xy = x*y

  // Apply default assignment
  io.cmd.ready := False
  io.rsp.valid := False
  io.rsp.iteration := iteration

  when(io.cmd.valid) {
    // Is the mandelbrot iteration done ?
    when(xx + yy >= 4.0 || iteration === iterationLimit) {
      io.rsp.valid := True
      when(io.rsp.ready) {
        io.cmd.ready := True
        x := 0
        y := 0
        iteration := 0
      }
    } otherwise {
      x := (xx - yy + io.cmd.x).truncated
      y := (((xy) << 1) + io.cmd.y).truncated
      iteration := iteration + 1
    }
  }
}