在做逻辑实现及后期调试维护里,在维护文档中的寄存器列表和真实设计中的唯一性往往是一件令人“痛苦”的事情(一个字,懒)。在SpinalHDL的设计里,slaveFactory是寄存器实现的一个不错的方法(还有一个是RegIf库),虽然两者都能够打印寄存器列表,但终究是分散的。
slaveFactory中的dataModel
slaveFactory中提供了printDataModel方法可以用于打印寄存器列表,如下面的例子所示:

在生成RTL时控制台会打印寄存器列表:

不妨看下printDataModel背后的逻辑:

上面的代码来自BusSlaveFactory.scala文件,在slaveFactory中我们注册声明的寄存器列表均存储在 elementPerAddress(LinkedHashMap)中,而printDataModel中则是将elementPerAddress转换成字符串打印出来而已,那么基于elementPerAddress,我们可以一键生成寄存器文档,所要解决的只是如何将各分散的slaveFactory如何“集中”到一起。
隐式转换
Scala的隐式转换可以方便的对类进行方法扩展(关于隐式转换可以参考《Scala编程》),如下例所示:

上面的代码里为Int隐式扩展了multi方法,执行程序将会打印6,借助隐式扩展功能,我们可以为BusSlaveFactoryDelayed扩展addDataModel方法用于注册每个slaveFactory的dataModel。
addPrePopTask
字如其名,在SpinalHDL中可以为每个模块添加addPrePopTask方法,在编译生成RTL时每当处理完成一个模块后就会执行改方法,如下所示:

基于该方法,我们可以在顶层注册genRegFileByMarkdown()方法用于生成Markdown形式的寄存器文档。
实现
贴出一个比较粗糙的实现逻辑:


这里为BusSlaveFactoryDelayed隐式扩展了一个addDataModel方法,用于向regContent中注册寄存器列表,genRegFileByMarkdown()则用于生成Markdown文档(有关Markdown相关使用可以参照公众号中Markdown文章)。
example
使用方式如下:

最终执行编译时会生成一个regFile.md文件,包含了各个模块的寄存器列表。效果如下:

原作者:玉骐
|