分形计算器
简介
此示例将展示使用数据流和定点计算实现一个未经优化的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
}
}
}