写在前面

SpinalHDL这个语言,我是在了解了香山处理器Chisel才知道的,一直想用一用,SpinalHDL和Chisel师承一脉,都是基于Scala来进行电路描述。其本质上仍旧是HDL而非HLS,在设计之前依旧需要有清晰的电路结构,在电路描述上更加方便和快捷。
本文主要对spinal HDL的参考文档进行了翻译,后期打算应用spinal HDL进行简单的模块的改写。本文中内容主要对scala编程进行了简单的介绍。

环境搭建

参考大佬知乎文章搭建环境:
环境搭建文章参考

数据类型

在 Scala 中,有 5 种主要数据类型:

类型 示例 描述
Boolean true, false
Int 3, 0x32 32位整数
Float 3.14f 32 位浮点数
Double 3.14 64 位浮点数
String “Hello world” UTF-16 字符串

变量

在 Scala 中,可以使用 var 关键字定义变量:

var number : Int = 0
number = 6
number += 4
println(number) // 10

Scala 能够自动推断类型。 如果变量是在声明时分配的,则不需要指定它:

var number = 0 //'number'的类型在编译时被推断为Int。

但在 Scala 中使用 var 并不常见。 相反,通常使用 val 定义的常量值:

val two   = 2
val three = 3
val six   = two * three

函数

例如,如果您想定义一个函数,如果它的两个参数之和大于零,则返回 true,您可以执行以下操作:

def sumBiggerThanZero(a: Float, b: Float): Boolean = {return (a + b) > 0
}

然后,要调用此函数,可以按顺序进行传参数,或者按名字进行传参数:

sumBiggerThanZero(2.3f, 5.4f)orsumBiggerThanZero(a = 2.3f,b = 5.4f
)

Return

不需要 return 关键字。 如果没有它,Scala 将函数的最后一条语句作为返回值。返回类型推断 Scala 能够自动推断返回类型,不需要指定。

def sumBiggerThanZero(a: Float, b: Float) = {(a + b) > 0
}

如果你的函数只包含一个语句,Scala 函数不需要花括号。同时可以为函数的每个参数指定一个默认值:

def sumBiggerThanZero(a: Float, b: Float = 0.0f) = (a + b) > 0

不返回任何内容的函数 如果您希望函数不返回任何内容,则应将返回类型设置为 Unit。 它等效于 C/C++ void 类型。

def printer(): Unit = {println("1234")println("5678")
}

Apply

apply 的函数很特别,因为可以调用它们而无需键入它们的名称:

class Array() {def apply(index: Int): Int = index + 3
}val array = new Array()
val value = array(4)   //array(4) is interpreted as array.apply(4) and will return 7

这个概念也适用于 Scala 对象(static):

object MajorityVote {def apply(value: Int): Int = ...
}val value = MajorityVote(4) // Will call MajorityVote.apply(4)

Object

在 Scala 中,没有 static 关键字。 取而代之的是对象。 对象定义中定义的所有内容都是静态的。

下面的例子定义了一个名为 pow2 的静态函数,它接受一个浮点值作为参数并返回一个浮点值。

object MathUtils {def pow2(value: Float): Float = value * value
}

然后你可以通过写来调用它:

MathUtils.pow2(42.0f)

入口点(main)

Scala 程序的入口点(主函数)应该在对象内部定义为名为 main 的函数。

object MyTopLevelMain{def main(args: Array[String]) {println("Hello world")}
}

class

类语法与 Java 非常相似。 想象一下,您要定义一个 Color 类,该类将三个 Float 值 (r,g,b) 作为构造参数:

class Color(r: Float, g: Float, b: Float) {def getGrayLevel(): Float = r * 0.3f + g * 0.4f + b * 0.4f
}

然后,实例化上一个示例中的类并使用其 getGrayLevel 函数:

val blue = new Color(0, 0, 1)
val grayLevelOfBlue = blue.getGrayLevel()

注意,如果你想从外部访问类的一个构造参数,这个构造参数应该定义为一个val:

class Color(val r: Float, val g: Float, val b: Float) { ... }
...
val blue = new Color(0, 0, 1)
val redLevelOfBlue = blue.r

继承

例如,假设您要定义两个类,Rectangle 和 Square,它们扩展了类 Shape:

class Shape {def getArea(): Float
}class Square(sideLength: Float) extends Shape {override def getArea() = sideLength * sideLength
}class Rectangle(width: Float, height: Float) extends Shape {override def getArea() = width * height
}

案例类

Case 类是声明类的另一种方式。

case class Rectangle(width: Float, height: Float) extends Shape {override def getArea() = width * height
}

然后 case class 和 class 之间有一些区别:

  • case 类不需要 new 关键字来实例化。
  • 参数可从外部访问; 您不需要将它们定义为 val。

在 SpinalHDL 中,这解释了编码约定背后的原因:通常建议使用案例类而不是类,以减少输入和提高一致性。

模板/类型参数化

想象一下,你想设计一个类,它是给定数据类型的队列,在这种情况下,你需要为类提供一个类型参数:

class  Queue[T](){def push(that: T) : Unit = ...def pop(): T = ...
}

如果要将 T 类型限制为给定类型(例如 Shape)的子类,可以使用 <:Shape 语法:

class Shape() {def getArea(): Float
}
class Rectangle() extends Shape { ... }class  Queue[T <: Shape]() {def push(that: T): Unit = ...def pop(): T = ...
}

函数也是如此:

def doSomething[T <: Shape](shape: T): Something = { shape.getArea() }

编程约定

类与案例类

定义 aBundle或 a Component时,最好将其声明为 case 类。

原因是:

  • 它避免使用new关键字。在某些情况下,永远不必使用它比有时更好。
  • 一个案例类提供了一个克隆功能。 当需要克隆 Bundle 时,这在 SpinalHDL 中很有用,例如,当您定义新的 Reg 或某种新的 Stream 时。
  • 参数从外面直接可见。

[case]class

所有类名都应该以大写字母开头。

class Fifo extends Component {}class Counter extends Area {}case class Color extends Bundle {}

伴生对象

一个伴生对象应以大写字母开头。

object Fifo {def apply(that: Stream[Bits]): Stream[Bits] = {...}
}object MajorityVote {def apply(that: Bits): UInt = {...}
}

此规则的一个例外是当伴随对象用作函数时(仅apply在内部),并且这些apply函数不生成硬件:

object log2 {def apply(value: Int): Int = {...}
}

函数

函数应始终以小写字母开头:

def sinTable = (0 until sampleCount).map(sampleIndex => {val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)S((sinValue * ((1 << resolutionWidth) / 2 - 1)).toInt, resolutionWidth bits)
})val rom =  Mem(SInt(resolutionWidth bit), initialContent = sinTable)

例化

类的实例化应始终以小写字母开头:

val fifo   = new Fifo()
val buffer = Reg(Bits(8 bits))

if / when

Scala if 和 SpinalHDL when 通常应按以下方式编写:

if(cond) {...
} else if(cond) {...
} else {...
}when(cond) {...
}.elseWhen(cond) {...
}.otherwise {...
}

switch

SpinalHDLswitch通常应按以下方式编写:

switch(value) {is(key) {}is(key) {}default {}
}

如果可以使代码更具可读性,则可以将is/default语句压缩到一行中。

参数

通常在 case 类中对Component/Bundle的参数进行分组是比较实用的,因为:

  • 更易于携带/操作以配置设计
  • 更好的可维护性
case class RgbConfig(rWidth: Int, gWidth: Int, bWidth: Int) {def getWidth = rWidth + gWidth + bWidth
}case class Rgb(c: RgbConfig) extends Bundle {val r = UInt(c.rWidth bit)val g = UInt(c.gWidth bit)val b = UInt(c.bWidth bit)
}

但这不应该适用于所有情况。例如:在 FIFO 中,将dataType参数与depthfifo的参数分组是没有意义的,因为一般来说,thedataType与设计相关,而 thedepth与设计配置相关。

class Fifo[T <: Data](dataType: T, depth: Int) extends Component {}

spinal HDL - 01 - 环境搭建与Scala编程指南相关推荐

  1. 微信点餐系统01——环境搭建

    微信点餐系统01--环境搭建 一.创建数据库表 ​ 微信点餐系统一共需要5个表. 商品表:商品编号.商品名称.商品价格.商品库存.商品描述.商品图片.商品情况(上架还是下架).它属于哪个类目(热销?男 ...

  2. 学习笔记0 Linux环境搭建与脚本编程

    临近毕业方觉,自己当初凭着一腔热血选择的专业,最后似乎什么也没学到. 签了个还算凑合的工作,却莫名有种空虚,如果要给自己评个级,现在的编程水平大概不及自己大二时候,括弧笑. 于是不惜花了大价钱报了个班 ...

  3. Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)

    0613 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.1.1 项目介绍 4.1.2 开发环境搭建 ①安装Linux系统.XSHELL.XFTP.Visual Stu ...

  4. (01)ORB-SLAM2源码无死角解析-(01) 环境搭建,demo运行,ROS一键安装_清除各种疑难杂症

    讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解的(01)ORB-SLAM2源码无死角解析-接如下(本文内容来自计算机视觉life ORB-SLAM2 课程课件): (0 ...

  5. Intellij IDEA开发环境搭建,scala配置及打包,jar包在spark中的运行

    1. Intellij IDEA 开发环境搭建 最近在学习scala,除需要编写scala程序外,同时还需要创建maven工程,打成Jar包,而Eclipse在这方面显得使用的不是那么方面,同时由于I ...

  6. (02)Cartographer源码无死角解析-(01) 环境搭建,demo运行,ROS一键安装_清除各种疑难杂症

    讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解(02)Cartographer源码无死角解析链接如下: (02)Cartographer源码无死角解析-(00)目录_最 ...

  7. 中科世为 Z6S Linux HMI 屏幕模组上手记录 | 01 - 环境搭建

    1. 中科世为Z6S串口屏 中科世为官网 最近到手一块中科世为的串口屏,开搞! Z6S串口屏中运行的是 FlyThings OS 嵌入式物联网界面系统,FlyThings OS是中科世为基于Linux ...

  8. 微信小程序——聊天小程序——01环境搭建

    一.环境搭建 总来的来说,初始化搭建一般有两部: 1.环境的初始化 2.基本页面的搭建 一.环境的初始化 1.1首先新建有关云函数的文件夹 编辑 1.2在project中配置云环境目录,配置完成后点保 ...

  9. 使用Spring boot搭建Wechat(企业微信)Demo -图文教程 -01 环境搭建

    ** Spring Boot-Wachat Demo [1] 环境搭建[适用小白的哥哥大白,高手跳过本节,内容主要记录个人搭建所遇到的坑和分享过程] ** Spring boot简介.特点等这里就不过 ...

最新文章

  1. kvm--virsh命令行下管理虚拟机
  2. 性能超越图神经网络,将标签传递和简单模型结合实现SOTA
  3. 自定义CSS博客皮肤
  4. Eclipse-配置workspace路径
  5. cake-build -.Net Core 跨平台构建自动化系统。
  6. spring boot中的注解
  7. unity, Gizmos.DrawMesh一个坑
  8. 《Scala机器学习》一一
  9. 获取数据库链接Junit
  10. python 桌面数据库_python数据库操作笔记
  11. 【odoo15】如何使用 python xmlrpc 连接 odoo
  12. 1-JavaScript高级程序设计-简介
  13. 最大流 Ford-Fulkerson 算法
  14. [概率论与数理统计-1]: 总体架构、知识结构、知识体系
  15. Ubuntu下的几种常见输入法
  16. cruisecontrol 持续化集成(运行bat脚本)
  17. 三极管实现的锁存电路
  18. 局域网内交换机VLAN隔离设置
  19. FORCESPRO的使用教程
  20. 成都拓嘉启远:拼多多下单后地址错误能改吗

热门文章

  1. vscode 程序员鼓励师_程序员鼓励师插件Rainbow Fart(彩虹屁)
  2. POJ2187-最远点对-旋转卡壳(怎么开心怎么读)
  3. 计算机教案三维目标,“三维目标”的三个问题 教学设计三维目标模板
  4. 【计算机网络】湖科大微课堂笔记 p7-10 计算机网络体系结构:常见的计算机网络体系结构、必要性、分层思想、专业术语
  5. 光纤收发器在安装使用过程所遇到的问题及解决办法
  6. 屏幕录像机(bb flashback pro 4)pjb v4.1.21
  7. Task Office for Mac(GTD办公软件)
  8. 解决浏览器驱动和浏览器版本不匹配的报错:This version of ChromeDriver only supports Chrome version 97
  9. 【SpringBoot深入浅出系列】SpringBoot之集成MyBatis-Plus
  10. SecureRandom的江湖偏方与真实效果