当前位置: 首页 > news >正文

spatial for parallel compute 使用简介

spatial for parallel compute 使用简介

spatial 能干嘛

spatial 可以很方便地设计并行计算电路,内置了 并行计算语法和流水线语法支持。

下载与编译

官方下载地址是 https://github.com/stanford-ppl/spatial

国内的备份网址是 https://gitee.com/mirrors/Spatial

编译

简单来说,在项目目录下,直接运行sbt compile就可以了。

但实际会涉及到很多问题,比如相关库下载的问题,经常下载不了,需要使用国内的镜像,比如阿里和清华的镜像。

似乎也可以用IDEA来自动解决这些库的问题。

scala版本是scala2, scala3是不行的,因为现在spatial用了scala2的宏的一些机制,但是scala3在宏机制方面做了改变,跟scala2不一样了。

java的openjdk库的版本可能也有一些要求,具体看提示。

另外缺省的行为,很多都是基于linux或者unix的,要在windows下使用,要不装wsl,要不重新把那些sh脚本改成bat之类的脚本。简单起见,建议装wsl.

总之会要折腾一阵。

用spatial的工作过程是基本可以分为3步。

第1步,用spatial(一种scala方言)设计电路,

第2步,可以编译生成为scala代码,进行仿真运行。编译时的时候也能够检查一些错误。貌似也可以做一些时钟分析什么的,存疑。

运行 sbt "runMain apps.<AppName> --args=\"<参数>\""

# 在项目根目录下运行
sbt -mem 8192 # 建议分配足够内存

# 在 sbt 控制台中执行
run # 然后选择要运行的应用程序

# 方法1: 在 sbt 中指定
sbt "runMain <完整包名.应用名>"

# 示例
sbt "runMain apps.<AppName>"

spatial/
├── build.sbt
├── src/
│ └── main/
│ └── scala/
│ └── apps/
│ └── YourApp.scala
└── gen/ # 生成的代码和报告

带参数的仿真

# 在 sbt 控制台中
runMain apps.<AppName> --args="<参数>"

# 或者直接
sbt "runMain apps.<AppName> --args=\"<参数>\""

完整示例

# 进入 Spatial 项目目录
cd /path/to/spatial

# 启动 sbt(建议分配足够内存)
sbt -mem 8192

# 在 sbt 控制台中
> compile # 编译代码
> run # 交互式选择应用运行
> projects # 查看所有子项目
> project <项目名> # 切换到特定子项目

 

第3步,编译生成verilog,接入到后端的硬件设计平台,比如fpga或者asic.

# 在 Spatial 项目根目录下
sbt -mem 8192

# 在 sbt 控制台中运行
runMain apps.<YourAppName> --synth --fpga=<FPGA平台>

指定目标 FPGA 平台

# 对于 Xilinx FPGA
runMain apps.<AppName> --synth --fpga=ZCU

# 对于 AWS EC2 F1
runMain apps.<AppName> --synth --fpga=AWS

# 对于 DE1-SoC
runMain apps.<AppName> --synth --fpga=DE1

# 对于 Arria10
runMain apps.<AppName> --synth --fpga=A10

输出文件位置位于

spatial/gen/<AppName>/verilog/

支持的 FPGA 平台

常见的平台包括:

  • ZCU : Xilinx Zynq UltraScale+

  • AWS : Amazon EC2 F1

  • DE1 : Terasic DE1-SoC

  • A10 : Intel Arria 10

  • VCS : 用于仿真的 Verilog 编译仿真器

  • 验证生成结果

    bash
    # 检查是否生成成功
    ls -la gen/<AppName>/verilog/# 查看资源使用报告
    cat gen/<AppName>/verilog/reports/*.rpt

具体的设计也比较简单

下面简要介绍 Spatial 框架设计电路的核心概念和典型样例:

1. 项目文件结构

text
spatial-app/
├── build.sbt                 # 构建配置
├── src/main/scala/
│   └── apps/
│       ├── SimpleExample.scala    # 简单应用
│       ├── MatrixMult.scala       # 矩阵乘法
│       └── PipeLineExample.scala  # 流水线示例
└── resources/               # 资源文件

2. 基本应用模板

scala
import spatial.dsl._@spatial object SimpleExample extends SpatialApp {def main(args: Array[String]): Unit = {// 1. 定义硬件参数val tileSize = 16// 2. 创建内存val src = ArgIn[Int]val dst = ArgOut[Int]// 3. 加速器设计Accel {// 硬件电路描述dst := src + 1}// 4. 设置参数并运行setArg(src, args(0).to[Int])println("Result: " + getArg(dst))}
}

3. 并行计算模块

DRAM 和 SRAM 使用

scala
Accel {// 片外内存val data = DRAM[Int](1024)// 片内缓存val sram = SRAM[Int](64)// 并行加载sram load data(0::64 par 16)  // 16路并行加载// 并行计算Foreach(0 until 64 par 8) { i =>sram(i) = sram(i) * 2}// 并行存储data(0::64 par 16) store sram
}

4. 流水线设计

简单流水线

scala
Accel {// 三级流水线Pipe.foreach(0 until 100) { i =>val a = i * 2        // 第1级val b = a + 1        // 第2级  val c = b * 3        // 第3级}
}

带并行度的流水线

scala
Accel {// 并行流水线Foreach(0 until 64 by 8 par 2) { i =>val tile = SRAM[Int](8)// 流水线处理每个tilePipe.foreach(0 until 8) { j =>tile(j) = (i + j) * 2}}
}

5. 主要硬件模块

控制单元

scala
val ctrl = CtrlUnit {// 控制逻辑Sequential.Foreach(0 until 10) { i =>// 顺序执行}
}

计算单元

scala
// 向量计算
val result = Reg[Int]
Reduce(result)(0 until 64 par 8) { i =>i * i
} { _ + _ }// 矩阵运算
val matA = SRAM[Int](64, 64)
val matB = SRAM[Int](64, 64)
val matC = SRAM[Int](64, 64)Foreach(0 until 64 par 4, 0 until 64 par 4) { (i, j) =>matC(i, j) = matA(i, j) + matB(i, j)
}

存储层次

scala
// 多级存储
val dram = DRAM[Int](1024)        // 片外DRAM
val sram = SRAM[Int](256)         // 片内SRAM  
val regfile = RegFile[Int](32)    // 寄存器文件
val fifo = FIFO[Int](16)          // FIFO缓冲

6. 完整矩阵乘法示例

scala
@spatial object MatrixMult extends SpatialApp {def main(args: Array[String]): Unit = {val M = 64; val N = 64; val P = 64val a = DRAM[Int](M, P)val b = DRAM[Int](P, N) val c = DRAM[Int](M, N)Accel {Foreach(0 until M by 16, 0 until N by 16) { (i, j) =>val tileC = SRAM[Int](16, 16)Foreach(0 until P by 16) { k =>val tileA = SRAM[Int](16, 16)val tileB = SRAM[Int](16, 16)tileA load a(i::i+16, k::k+16 par 8)tileB load b(k::k+16, j::j+16 par 8)// 矩阵乘计算MemReduce(tileC)(k until k+16 by 1 par 4) { kk =>val partial = SRAM[Int](16, 16)Foreach(0 until 16 par 2, 0 until 16 par 2) { (ii, jj) =>partial(ii, jj) = tileA(ii, kk) * tileB(kk, jj)}partial} { _ + _ }}c(i::i+16, j::j+16 par 8) store tileC}}}
}

7. 关键特性总结

  • 并行度控制:par N 指定并行度

  • 流水线:Pipe 自动插入流水线寄存器

  • 存储层次:DRAM → SRAM → RegFile → Scalar

  • 控制结构:ForeachReduceMemReduceFSM

  • 数据传输:load/store 实现内存传输

这种设计方式让你在高级语言层面描述算法,Spatial 自动生成对应的硬件电路,大大提高了硬件开发效率。

以上资料通过ai问答和部分实践获得的,没有完整验证过。不过认为是可信的和可行的,如遇问题或有心得,欢迎反馈交流,不过问题还请自行解决。