Vec
一、描述(Description)
Vec
是定义了一组带有标号的信号的复合信号(基于SpinalHDL基础类别)
二、声明(Declaration)
声明向量的语法如下:
声明 | 描述 |
---|---|
Vec(type: Data, size: Int) | 创建一个能容纳size 个data 类元素的向量 |
Vec(x, y, ...) | 创建一个标号对应给定元素的向量, 这种方式支持混合元素宽度 |
Examples
//创建一个有两个有符号整型的向量
val myVecOfSInt = Vec(SInt(8 bits), 2)
myVecOfSInt(0) := 2
myVecOfSInt(1) := myVecOfSInt(0) + 3
//创建一个有三个不同类型元素的向量
val myVecOfMixedInt = Vec(UInt(3 bits), UInt(5 bits), UInt(8 bits))
val x, y, z = UInt(8 bits)
val myVecOf_xyz_ref = Vec(x, y, z)
//向量的迭代
for(element <- myVecOf_xyz_ref) {
element := 0 //给所有元素赋值0
}
//向量Map映射
myVecOfMixedInt.map(_ := 0) //给所有元素赋值0
//给向量的第一个元素赋值3
myVecOf_xyz_ref(1) := 3
Verilog:
wire [7:0] _zz_myVecOfSInt_1;
wire [7:0] myVecOfSInt_0;
wire [7:0] myVecOfSInt_1;
wire [2:0] myVecOfMixedInt_0;
wire [4:0] myVecOfMixedInt_1;
wire [7:0] myVecOfMixedInt_2;
wire [7:0] x;
wire [7:0] y;
wire [7:0] z;
reg [7:0] counter;
assign _zz_myVecOfSInt_1 = 8'h03;
assign myVecOfSInt_0 = 8'h02;
assign myVecOfSInt_1 = ($signed(myVecOfSInt_0) + $signed(_zz_myVecOfSInt_1));
assign x = 8'h0;
assign y = 8'h0;
assign z = 8'h0;
assign myVecOfMixedInt_0 = 3'b000;
assign myVecOfMixedInt_1 = 5'h0;
assign myVecOfMixedInt_2 = 8'h0;
三、操作符(Operators)
以下操作符是Vec
类型所支持的:
比较操作(Comparison)
操作符 | 描述 | 返回类型 |
---|---|---|
x===y | 相等 | Bool |
x=/=y | 不相等 | Bool |
//创建一个有两个有符号整型的向量
val vec2 = Vec(SInt(8 bits), 2)
val vec1 = Vec(SInt(8 bits), 2)
myBool := vec2 === vec1 //比较两个向量
Verilog:
wire [7:0] vec2_0;
wire [7:0] vec2_1;
wire [7:0] vec1_0;
wire [7:0] vec1_1;
wire myBool;
assign myBool = (($signed(vec2_0) == $signed(vec1_0)) && ($signed(vec2_1) == $signed(vec1_1)));
类型转换(Type cast)
操作符 | 描述 | 返回类型 |
---|---|---|
x.asBits | 二进制转换为Bits | Bits(w(x) bits) |
//创建一个有两个有符号整型的向量
val vec1 = Vec(SInt(8 bits), 2)
myBits_16bits := vec1.asBits
Misc
操作符 | 描述 | 返回类型 |
---|---|---|
x.getBitsWidth | 返回Vec的长度 | Int |
//创建一个有两个有符号整型的向量
val vec1 = Vec(SInt(8 bits), 2)
println(vec1.getBitsWidth) //16
4. 库辅助函数(Lib Helper functions)
> 使用这些函数, 需要`import spinal.lib._`
<table border="1" class="docutils">
<thead>
<tr>
<th style="text-align: center;">操作符</th>
<th style="text-align: center;">描述</th>
<th style="text-align: center;">返回类型</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">x.sCount(condition: T=>Bool)</td>
<td style="text-align: center;">计算Vec中与给定条件相匹配的个数</td>
<td style="text-align: center;">UInt</td>
</tr>
<tr>
<td style="text-align: center;">x.sCount(value: T)</td>
<td style="text-align: center;">计算与给定值相等的个数</td>
<td style="text-align: center;">UInt</td>
</tr>
<tr>
<td style="text-align: center;">x.sExists(condition: T=>Bool)</td>
<td style="text-align: center;">检查Vec中是否有匹配的条件</td>
<td style="text-align: center;">Bool</td>
</tr>
<tr>
<td style="text-align: center;">x.sContains(value: T)</td>
<td style="text-align: center;">检查Vec中是否有给定的值存在</td>
<td style="text-align: center;">Bool</td>
</tr>
<tr>
<td style="text-align: center;">x.sFindFirst(condition: T=>Bool)</td>
<td style="text-align: center;">找到Vec中第一个与给定条件相匹配的元素, 返回那个元素的标号</td>
<td style="text-align: center;">UInt</td>
</tr>
<tr>
<td style="text-align: center;">x.reduceBalancedTree(op:(T, T)=>T)</td>
<td style="text-align: center;">平衡化的归约函数, 能尽量减小生成电路的深度。<code>op</code>应该是可交换的且可结合的</td>
<td style="text-align: center;">T</td>
</tr>
<tr>
<td style="text-align: center;">x.shuffle(indexMapping: Int=>Int)</td>
<td style="text-align: center;">用一个Map函数把旧索引映射到新索引上, 对Vec重组</td>
<td style="text-align: center;">Vec[T]</td>
</tr>
</tbody>
</table>
```Scala
import spinal.lib._
//创建有4个无符号整型的向量
val vec1 = Vec(UInt(8bits), 4)
//...向量在某些地方被赋值后
val c1: UInt = vec1.sCount(_ < 128) //向量中有多少值小于128
val c2: UInt = vec1.sCount(0) //向量中有多少0值
val b1: Bool = vec1.sExist(_ > 250) //向量中有没有比250大的
val b2: Bool = vec1.sContains(0) //向量中有没有0
val u1: UInt = vec1.sFindFirst(_ < 10) //得到第一个比10小的元素的标号, 该函数在转化时有问题, 有待商榷
val u2: UInt = vec1.reduceBalancedTree(_ + _) //向量求和
Verilog:
wire [1:0] _zz_c1;
wire [1:0] _zz_c1_1;
wire [0:0] _zz_c1_2;
wire [2:0] _zz_c1_3;
wire [1:0] _zz_c1_4;
wire [1:0] _zz_c1_5;
wire [0:0] _zz_c1_6;
wire [1:0] _zz_c2;
wire [1:0] _zz_c2_1;
wire [0:0] _zz_c2_2;
wire [2:0] _zz_c2_3;
wire [1:0] _zz_c2_4;
wire [1:0] _zz_c2_5;
wire [0:0] _zz_c2_6;
wire [7:0] _zz_u2;
wire [7:0] _zz_u2_1;
wire [7:0] vec1_0;
wire [7:0] vec1_1;
wire [7:0] vec1_2;
wire [7:0] vec1_3;
wire [2:0] c1;
wire [2:0] c2;
wire b1;
wire b2;
wire [7:0] u2;
reg [7:0] counter;
assign _zz_c1 = ({1'b0,(vec1_0 < 8'h80)} + _zz_c1_1);
assign _zz_c1_2 = (vec1_1 < 8'h80);
assign _zz_c1_1 = {1'd0, _zz_c1_2};
assign _zz_c1_4 = ({1'b0,(vec1_2 < 8'h80)} + _zz_c1_5);
assign _zz_c1_3 = {1'd0, _zz_c1_4};
assign _zz_c1_6 = (vec1_3 < 8'h80);
assign _zz_c1_5 = {1'd0, _zz_c1_6};
assign _zz_c2 = ({1'b0,(vec1_0 == 8'h0)} + _zz_c2_1);
assign _zz_c2_2 = (vec1_1 == 8'h0);
assign _zz_c2_1 = {1'd0, _zz_c2_2};
assign _zz_c2_4 = ({1'b0,(vec1_2 == 8'h0)} + _zz_c2_5);
assign _zz_c2_3 = {1'd0, _zz_c2_4};
assign _zz_c2_6 = (vec1_3 == 8'h0);
assign _zz_c2_5 = {1'd0, _zz_c2_6};
assign _zz_u2 = (vec1_0 + vec1_1);
assign _zz_u2_1 = (vec1_2 + vec1_3);
assign c1 = ({1'b0,_zz_c1} + _zz_c1_3);
assign c2 = ({1'b0,_zz_c2} + _zz_c2_3);
assign b1 = ((((1'b0 || (8'hfa < vec1_0)) || (8'hfa < vec1_1)) || (8'hfa < vec1_2)) || (8'hfa < vec1_3));
assign b2 = ((((1'b0 || (vec1_0 == 8'h0)) || (vec1_1 == 8'h0)) || (vec1_2 == 8'h0)) || (vec1_3 == 8'h0));
assign u2 = (_zz_u2 + _zz_u2_1);
备注:sXXX前缀用来与接受lambda函数作为参数的同名Scala函数的歧义