chisel安装和使用+联合体union的tagged属性+sv读取文件和显示+sv获取系统时间+vcs编译时改动parameter的值+tree-PLRU和bit-PLRU

发布时间 2023-10-05 21:29:39作者: 大浪淘沙、

chisel安装和使用

sbt:scala build tool,是scala的默认构建工具,配置文件是build.sbt。
mill:一个新的java/scala构建工具,运行较快,与sbt可以共存,配置文件是build.sc。

chisel的安装可以参考这篇文章。安装过程务必联网,而没有联网情况下的安装,按照其它的说明,如移动缓存文件等,并无法正常使用。
https://zhuanlan.zhihu.com/p/357342948


scala这门语言一方面用的人并不多,另一方面敏捷开发本身有点和传统芯片设计有点相悖,加之不同的scala版本库差异很大,学习难度、成本、资料、迁移性、环境搭建等并不顺畅,所以我觉得还是不要学这种东西好些。

如果是出于位宽,连接等基本语法容易错误的问题,那么EDA工具自带了各种APP,可以扫描RTL。
如果是出于架构设计的问题,那么前期把方案完整做好,则后期书写代码是更为清晰。


安装完毕建立工程,以下是测试代码。
in_a宽度是2,in_b的宽度是1。加到的结果的宽度是3。

import chisel3._
import chisel3.Driver

class hello extends Module{
  var io = IO(new Bundle() {
    var in_a = Input(UInt(2.W))
    var in_b = Input(UInt(1.W))
    var out = Output(UInt(3.W))
  })
  io.out := io.in_a + io.in_b
}

object hello extends App{
  Driver.emitVerilog(new hello())
}

有如下生成的verilog代码:
in_b的宽度是1,in_a宽度是2,out宽度是3。

module hello(
  input        clock,
  input        reset,
  input  [1:0] io_in_a,
  input        io_in_b,
  output [2:0] io_out
);
  wire [1:0] _GEN_0 = {{1'd0}, io_in_b}; // @[hello.scala 10:21]
  wire [1:0] _T_1 = io_in_a + _GEN_0; // @[hello.scala 10:21]
  assign io_out = {{1'd0}, _T_1}; // @[hello.scala 10:21]
endmodule

联合体union的tagged属性

https://www.elecfans.com/d/1922920.html

tagged union包含一个隐式成员,该成员存储tag,也就是标记,它表示这个union最终存储的到底是哪一个成员。

如果从不同的union成员中读取值,仿真器则会报错:

module tagged_union_example;
	logic [31:0] x;
	typedef union tagged {
		int a;
		byte b;
		bit [15:0] c;
	} data;

	data d1;
	initial begin
		d1 = tagged a 32'hffff_ffff; //write to 'a'
		//read from 'b'. Since 'a' was written last, cannot access
		//'b'. - Error
		x = d1.b;
		$display("x = %h",x);
	end
endmodule

所以,tagged其实是属性检查的作用,在实际的应用中不多。
另外,union的实际用途不明:
在编译和仿真的时候,即便是unpacked union,也会出现数值完全覆盖的情况,
似乎是被当做packed联合体使用了。

应该尽量避免unpacked联合体使用,防止出现意外。

sv读取文件和显示

https://blog.eetop.cn/blog-12852-21369.html


integer file;
string  variable;
reg [31:0] value;

file=$fopen("file.txt","r");
while(!$feof(file))
begin
    $fscanf(file,"%s %h",variable,value);
    h_array[variable] = value;
end
$fclose(file);

sv获取系统时间

以下命令提取不到值:

initial begin
    $system("date");
end

用DPI方法可以提取到值,但是是一个格式化的字符串:

#include <time.h> 
wallclock() { 
    time_t t; 
    t = time(NULL); 
    return (ctime(&t)); 
    //return time(NULL); 
} 

import "DPI-C" function string wallclock(); 

module try; 

    //int unsigned t; 
    string t; 

    initial begin 
     t = wallclock(); 
     $write("time=%0s\n", t); 
    end 
endmodule 

如果需要更详细的自定义的时钟,那么可以先打通C语言的获取,然后再用SV调用。注意调用的格式正确性,而EDA工具有时候并不检查import等形参、返回值的正确性。

https://www.runoob.com/w3cnote/c-time-func-summary.html

vcs编译时改动parameter的值

vcs手册提供两种方案,一种是-pvalue+value_path=value的方法,另一种是-parameters filename的方法。
以第一种方法为例:

module module_name();
  	parameter a= 3;
    initial begin
      	#10;
      	$display("%0d", a)
    end
endmodule

编译时候添加了如下,则输出的a是1.

-pvalue+module_name.a=1

tree-PLRU和bit-PLRU

tree-PLRU

https://en.wikipedia.org/wiki/Pseudo-LRU
2bit的索引,从00-11一直循环,下一轮访问的被替换。
每次访问过的位置,1变成0,0变成1,将最旧的数据被替换。 如果访问顺序是C, B, D, A, 那么下图中,E替换的位置是B,而不是C。这是因为A和C都在相同的一半,DBD访问后,所有值重新变成0,而最后一次访问A,将算法替换位置定向到C。

填充过程的数值变化:
0指向左边,填充以后变成1指向右边。1指向右边,填充以后变成0指向左边。

访问过程的数值变化:
访问过程的路径如果是和原值相同,则变换数值指向另一方。如果和原值不同,则不变。

image

bit-PLRU

每个条目上有1bitLRU值,每次访问设置这个值,满了以后变成全0,替换时候选择最左边为0的那个条目替换。