使用jinja2的自定义filter来对齐verilog自动例化的端口名字
专栏:ExASIC Nov. 10, 2024, 2:09 p.m. 75 阅读
使用jinja2的自定义filter来对齐verilog自动例化的端口名字

什么是模板语言

[文心一言] 模板语言是一种预处理语言,它是为了解析或生成可以被中间代码引用的代码而存在的。模板语言可以是任何支持模板元素(如变量、标签、过滤器和函数)的语言,例如C++、Java、Python、Ruby等。模板语言通常用于编写Web应用程序、桌面应用程序和其他系统级编程任务。

什么是jinja2

[文心一言] Jinja2是一个Python模板引擎,它是Django框架的一部分。它可以帮助开发者使用模板来渲染HTML、XML、JSON等数据,从而简化代码。Jinja2支持unicode,并具有集成的沙箱执行环境,可以安全地处理用户输入。

Jinja2的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能。其中最显著的一个是增加了沙箱执行功能和可选的自动转义功能,这对大多应用的安全性来说是非常重要的。此外,Jinja2还支持变量插值、条件语句、循环语句等高级功能。

Jinja2有两个主要的版本:Jinja2和Jinja2 for Django。Jinja2 for Django是Django默认的模板引擎,因此在创建Django项目时,通常会默认使用Jinja2。但是,如果你需要使用自定义的模板引擎,可以使用Jinja2 for Django。

总之,Jinja2是一个功能强大的模板引擎,可以大大简化Web开发和数据处理的过程。

什么是filter

https://jinja.palletsprojects.com/en/2.10.x/templates/

Variables can be modified by filters. Filters are separated from the variable by a pipe symbol (|) and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is applied to the next.

For example, {{ name|striptags|title }} will remove all HTML Tags from variable name and title-case the output (title(striptags(name))).

Filters that accept arguments have parentheses around the arguments, just like a function call. For example: {{ listx|join(', ') }} will join a list with commas (str.join(', ', listx)).

The List of Builtin Filters below describes all the builtin filters.

一个芯片设计中使用jinja2 filter的例子

比如我们要做自动例化,已经由parser取到了port list,如下:

ports = [
  {
    "name": "clk",
    "direction": "input",
    "msb": 0,
    "lsb": 0,
    "type": "wire"
  },
  {
    "name": "rst_n",
    "direction": "input",
    "msb": 0,
    "lsb": 0,
    "type": "wire"
  },
  {
    "name": "data_out",
    "direction": "output",
    "msb": 7,
    "lsb": 0,
    "type": "reg"
  }
]

目标:在模板语言里实现信号名字补空格对齐。

  .clk            (clk     ),
  .rst_n          (rst_n   )
  .data_out       (data_out)

如果不考虑对齐,我们可以写这样的模板:

{% for port in ports %}
  .{{ port.name }} ({{ port.name }})
{% endfor %}

那对齐怎么实现呢?这就要用到模板语言的filter了。具体来说,我们需要写个函数,在port.name替换之前做一些处理。

def left_align(s, l=30):
    return s.ljust(l, ' ')

然后,需要把这个函数注册到模板里,让jinja2能够实别到。

import jinja2

env = jinja2.Environment()
env.filters['left_align'] = left_align

注册之后,就可以来改进模板了,加上|,像管道一样调用filter函数。在这里我们需要提前计算出最长的端口名称,如下:

t = '''
{% for port in ports %}
  .{{ port.name | left_align(15) }} ({{ port.name | left_align(9) }})
{% endfor %}
'''

我们来做render,

template = env.from_string(t)
vlg = template.render(ports=ports)
感谢阅读,更多文章点击这里:【专栏:ExASIC】
最新20篇 开设专栏