我们的目标是┏ (゜ω゜)=☞芯片前端全栈工程师~喵!
系列文章目录
【驯服野生verilog-mode全记录】day3 —— 基于vim自动生成verilog-mode格式初始文件模板_尼德兰的喵的博客-CSDN博客
【驯服野生verilog-mode全记录】day2 —— 模块的例化_尼德兰的喵的博客-CSDN博客_verilog模块例化格式
【驯服野生verilog-mode全记录】day1 —— 常用链接与基本命令模板_尼德兰的喵的博客-CSDN博客
【驯服野生verilog-mode全记录】day0 —— verilog-mode的安装_尼德兰的喵的博客-CSDN博客
前言
时间2022年12月19日02点28分,恭喜煤老板终于圆梦!
回归主题,其实我最初想在本地尝试安装verilog-mode,除了想使用自动连线功能外,就是想使用这个循环展开的功能。装完之后一打听,原来这并不是verilog-mode的原生功能。这就非常尴尬了,而我又没有去改原生工具的能力,万般无奈只能通过外挂python脚本的手段来补充这个功能点了。
循环展开功能其实主要是避免手写复制类似如下代码时出现错误笔误:
assign start_addr = (conv_bitmap[0] ? cfg_param0_start_addr : 8'b0) | //{{{
(conv_bitmap[1] ? cfg_param1_start_addr : 8'b0) |
(conv_bitmap[2] ? cfg_param2_start_addr : 8'b0) |
(conv_bitmap[3] ? cfg_param3_start_addr : 8'b0) |
(conv_bitmap[4] ? cfg_param4_start_addr : 8'b0) |
(conv_bitmap[5] ? cfg_param5_start_addr : 8'b0) |
(conv_bitmap[6] ? cfg_param6_start_addr : 8'b0) |
(conv_bitmap[7] ? cfg_param7_start_addr : 8'b0) |
(conv_bitmap[8] ? cfg_param8_start_addr : 8'b0) |
(conv_bitmap[9] ? cfg_param9_start_addr : 8'b0) |
(conv_bitmap[10] ? cfg_param10_start_addr : 8'b0) |
(conv_bitmap[11] ? cfg_param11_start_addr : 8'b0) |
(conv_bitmap[12] ? cfg_param12_start_addr : 8'b0) |
(conv_bitmap[13] ? cfg_param13_start_addr : 8'b0) |
(conv_bitmap[14] ? cfg_param14_start_addr : 8'b0) |
(conv_bitmap[15] ? cfg_param15_start_addr : 8'b0) |
(conv_bitmap[16] ? cfg_param16_start_addr : 8'b0) |
(conv_bitmap[17] ? cfg_param17_start_addr : 8'b0) |
(conv_bitmap[18] ? cfg_param18_start_addr : 8'b0) |
(conv_bitmap[19] ? cfg_param19_start_addr : 8'b0) |
(conv_bitmap[20] ? cfg_param20_start_addr : 8'b0) |
(conv_bitmap[21] ? cfg_param21_start_addr : 8'b0) |
(conv_bitmap[22] ? cfg_param22_start_addr : 8'b0) |
(conv_bitmap[23] ? cfg_param23_start_addr : 8'b0) |
(conv_bitmap[24] ? cfg_param24_start_addr : 8'b0) |
(conv_bitmap[25] ? cfg_param25_start_addr : 8'b0) |
(conv_bitmap[26] ? cfg_param26_start_addr : 8'b0) |
(conv_bitmap[27] ? cfg_param27_start_addr : 8'b0) |
(conv_bitmap[28] ? cfg_param28_start_addr : 8'b0) |
(conv_bitmap[29] ? cfg_param29_start_addr : 8'b0) |
(conv_bitmap[30] ? cfg_param30_start_addr : 8'b0) |
(conv_bitmap[31] ? cfg_param31_start_addr : 8'b0) ; //}}}
以及替代generate的一些功能,因为generate有时会导致代码结构层次的不易识别以及对后端eco的一些困扰(这个是我听说的),所以在循环数为定值时直接展开写也是一种不错的选择。
效果演示
假设我的.v文件中有这样一段代码:
/* AUTO_UNFOLD
#for i 0..4
dffre u_dff#i#(
.clk(clk),
.rst_n(rst_n),
.d(in_d[#i#]),
.q(in_q[#i#]),
.en(in_en[#i#])
);
END */
在vim中键入:U回车,得到如下代码:
/* AUTO_UNFOLD
#for i 0..4
dffre u_dff#i#(
.clk(clk),
.rst_n(rst_n),
.d(in_d[#i#]),
.q(in_q[#i#]),
.en(in_en[#i#])
);
END */
//AUTO_UNFOLD_START
dffre u_dff0(
.clk(clk),
.rst_n(rst_n),
.d(in_d[0]),
.q(in_q[0]),
.en(in_en[0])
);
dffre u_dff1(
.clk(clk),
.rst_n(rst_n),
.d(in_d[1]),
.q(in_q[1]),
.en(in_en[1])
);
dffre u_dff2(
.clk(clk),
.rst_n(rst_n),
.d(in_d[2]),
.q(in_q[2]),
.en(in_en[2])
);
dffre u_dff3(
.clk(clk),
.rst_n(rst_n),
.d(in_d[3]),
.q(in_q[3]),
.en(in_en[3])
);
//AUTO_UNFOLD_END
展开循环的规则遵循python中的规则,i 0..4的话会将i依次赋值为0 1 2 3。再次键入:UD后,生成的代码被删除;
再如有下面一段代码:
/* AUTO_UNFOLD
#for i 2..4
#for j 1..3
#for k 1..4
assign undg_vipi#i#_j#j#_k#k#_#i*j+k# = 0;
END */
键入:U回车后,得到最后的代码为:
/* AUTO_UNFOLD
#for i 2..4
#for j 1..3
#for k 1..4
assign undg_vipi#i#_j#j#_k#k#_#i*j+k# = 0;
END */
//AUTO_UNFOLD_START
assign undg_vipi2_j1_k1_3 = 0;
assign undg_vipi3_j1_k1_4 = 0;
assign undg_vipi2_j2_k1_5 = 0;
assign undg_vipi3_j2_k1_7 = 0;
assign undg_vipi2_j1_k2_4 = 0;
assign undg_vipi3_j1_k2_5 = 0;
assign undg_vipi2_j2_k2_6 = 0;
assign undg_vipi3_j2_k2_8 = 0;
assign undg_vipi2_j1_k3_5 = 0;
assign undg_vipi3_j1_k3_6 = 0;
assign undg_vipi2_j2_k3_7 = 0;
assign undg_vipi3_j2_k3_9 = 0;
//AUTO_UNFOLD_END
还能支持数学运算哈哈哈哈!当有多层for循环体的时候,上面为最内层循环下面为外层循环依次展开(这块代码可难写了,我带着刚羊完的脑子一边看决赛一边想到了半夜1点)。
最后再比如上文提到的怕错的代码,可以先写成这个形式:
assign start_addr = (conv_bitmap[0] ? cfg_param0_start_addr : 8'b0)
/* AUTO_UNFOLD
#for i 1..32
| (conv_bitmap[#i#] ? cfg_param#i#_start_addr : 8'b0)
END */
;
然后直接一手展开:
assign start_addr = (conv_bitmap[0] ? cfg_param0_start_addr : 8'b0)
/* AUTO_UNFOLD
#for i 1..32
| (conv_bitmap[#i#] ? cfg_param#i#_start_addr : 8'b0)
END */
//AUTO_UNFOLD_START
| (conv_bitmap[1] ? cfg_param1_start_addr : 8'b0)
| (conv_bitmap[2] ? cfg_param2_start_addr : 8'b0)
| (conv_bitmap[3] ? cfg_param3_start_addr : 8'b0)
| (conv_bitmap[4] ? cfg_param4_start_addr : 8'b0)
| (conv_bitmap[5] ? cfg_param5_start_addr : 8'b0)
| (conv_bitmap[6] ? cfg_param6_start_addr : 8'b0)
| (conv_bitmap[7] ? cfg_param7_start_addr : 8'b0)
| (conv_bitmap[8] ? cfg_param8_start_addr : 8'b0)
| (conv_bitmap[9] ? cfg_param9_start_addr : 8'b0)
| (conv_bitmap[10] ? cfg_param10_start_addr : 8'b0)
| (conv_bitmap[11] ? cfg_param11_start_addr : 8'b0)
| (conv_bitmap[12] ? cfg_param12_start_addr : 8'b0)
| (conv_bitmap[13] ? cfg_param13_start_addr : 8'b0)
| (conv_bitmap[14] ? cfg_param14_start_addr : 8'b0)
| (conv_bitmap[15] ? cfg_param15_start_addr : 8'b0)
| (conv_bitmap[16] ? cfg_param16_start_addr : 8'b0)
| (conv_bitmap[17] ? cfg_param17_start_addr : 8'b0)
| (conv_bitmap[18] ? cfg_param18_start_addr : 8'b0)
| (conv_bitmap[19] ? cfg_param19_start_addr : 8'b0)
| (conv_bitmap[20] ? cfg_param20_start_addr : 8'b0)
| (conv_bitmap[21] ? cfg_param21_start_addr : 8'b0)
| (conv_bitmap[22] ? cfg_param22_start_addr : 8'b0)
| (conv_bitmap[23] ? cfg_param23_start_addr : 8'b0)
| (conv_bitmap[24] ? cfg_param24_start_addr : 8'b0)
| (conv_bitmap[25] ? cfg_param25_start_addr : 8'b0)
| (conv_bitmap[26] ? cfg_param26_start_addr : 8'b0)
| (conv_bitmap[27] ? cfg_param27_start_addr : 8'b0)
| (conv_bitmap[28] ? cfg_param28_start_addr : 8'b0)
| (conv_bitmap[29] ? cfg_param29_start_addr : 8'b0)
| (conv_bitmap[30] ? cfg_param30_start_addr : 8'b0)
| (conv_bitmap[31] ? cfg_param31_start_addr : 8'b0)
//AUTO_UNFOLD_END
;
这效果不是完美吗!
使用说明
auto_unfold.py · 尼德兰的喵/myscript_python - Gitee.com
把脚本搞到本地,然后根据脚本路径在.vimrc中加入两句话:
command! U :execute '%! /home/ICer/auto_unfold.py -f %'
command! UD :execute '%! /home/ICer/auto_unfold.py -d -f %'
之后重新打开.v文件就可以使用这个功能了。
关键实现
python中可以通过eval("2*4+5*4")来计算一个字符串输入的运算式~