在SystemVerilog中,输出信息显示时间时,经常会在输出信息格式中指定“%t”格式符,一般情况下“%t”输出的格式都是固定的,但是这样固定的输出显示的时间可能有时会让用户看起来感觉比较诧异,例如下面的示例。
【示例】
【仿真结果】
示例中,设置的timescale是“10ns/1ps”,在$monitor中将$realtime返回的时间通过格式符“%t”输出,但是此时显示的时间数值很大,并且没有单位,这可能会让用户不知所措,例如在sig为“11”时,此时显示的时间为12343,但是这个数字的单位是什么,并且我们通过前一文关于《SystemVerilog中的time、time的一些事儿》知道,$relatime本身返回的值并不是这里的12343,示例中显示的结果为什么与$realtime返回值不同呢,这是为什么呢?其实这主要是因为“%t”的输出格式受了任务$timeformat(注意是任务不是函数与!)的影响,虽然这里没有显式的调用$timeformat,但是其默认值还是会影响到“%t”显示的时间值,即“%t”默认显示的时间是按照当前module的timescale设置的精度作为单位的,并且默认情况下显式的时间后是没有时间单位字符串的,所以此时就可以理解为什么“%t”在sig为“11”时显示的时间是12343了,这是因为这个此时显示的数字的单位是1ps。其实在SystemVerilog中,通过$timeformat可以约束“%t”显示的时间格式,其中具体参数对应关系如下图。
其中units_number 是 0 到-15 之间的整数值,表示打印的时间值如下表:
Unit Number | Time Unit | Unit Number | Time Unit |
0 | 1 s | -8 | 10 ns |
-1 | 100 ms | -9 | 1 ns |
-2 | 10 ms | -10 | 100 ps |
-3 | 1 ms | -11 | 10 ps |
-4 | 100 us | -12 | 1 ps |
-5 | 10 us | -13 | 100 fs |
-6 | 1 us | -14 | 10 fs |
-7 | 100 ns | -15 | 1 fs |
precision_number 是在打印时间值时,小数点后保留的位数,其默认值为0。
suffix_string 是在时间值后面打印的后缀字符串,其默认值为空字符串。
MinFieldWidth 是时间值字符串与后缀字符串合起来的这部分字符串的最小长度,若这部分字符串不足这个长度,则在这部分字符串左侧补空格,直到总长度达到设置的值,如果总字符串比设置的值大,将按照字符串实际长度输出,其默认值为20。
下面我们通过一个示例进一步理解下$timeformat是如何使用的。
【示例】
【仿真结果】
示例中,通过$timeformat指定了“%t”输出时间的格式,“-9”表示要显示的时间是按照“1ns”为单位得到的,“3”表示显示的时间中小数部分的位数,“HaHaHa”为时间字符串之后的后缀字符串,这个字符串一般指定为时间的单位,最后一个参数“2”表示“%t”显示的整个字符串长度的最小值,因为此时的时间字符串和后缀字符串的长度大于设置的最小值,所以此时按照实际字符串长度显示,当然也可以把这个字符串最小长度的值设置的大于实际字符串长度,如下例。
【示例】
【仿真结果】
示例中,通过$timeformat设置了显示时间字符串的最小长度为13,仿真结果可以看出,实际字符串的长度没有13个字符串那么长,所以此时字符串按照左对齐,并在字符串左侧补空格直到字符船总长度达到$timeformat设置的字符串的最小长度要求为止。另一方面,$timeformat设置了显示时间保留小数点后的位数为2,所以时间显示的最终结果保留了2位小数,同时需要注意,此处进行两位小数保留时会进行四舍五入操作。
通过上述几个示例,如果我们期望“%t”显示的时间值与当前仿真时间一致,那么需要给$timeformat设置对应合适的参数或者在输出时间时在格式字符串中不要指定“%t”,而是直接将其位置空留出来,这样输出的数据将完全取决于用户使用的时间函数(可参见《SystemVerilog中的time、time的一些事儿》)
最后,在一个模块中可以设置多个$timeformat,一个$timeformat生效后会持续到下一个$timeformat,如下例。
【示例】
【仿真结果】
示例中,通过仿真结果可以看到第7行设置的$timeformat仅影响到了第8行“%t”的显示,并没有影响到第12行“%t”的显示,第7行设置的$timeformat在遇到第11行设置的$timeformat之后就退出了历史舞台,所以第12行“%t”显示的格式按照第11行设置的$timeformat显示了。