简介
Vivado 工程中的块设计(block design)由一个文件名以 .bd 结尾的文件来表示,例如 vivado_system.bd。这个文件以人类可读的文本格式包含块设计的全部信息。在旧版本的 Vivado 中,这个文件采用 XML 格式编写。而现在,块设计使用 JSON 格式来表示。
得益于这种文本格式,我们可以用常见的文本比较工具(diff 及类似的图形化工具)来比较两个块设计文件。这样就可以跟踪块设计到底做了哪些修改。
然而,JSON 格式在文本比较方面有一个明显的缺点:在对象的定义中,属性及其值的排列顺序可以是任意的。因此,即使两个 JSON 文件包含完全相同的信息,diff 之类的工具也可能显示它们的文本内容存在显著差异。
不幸的是,Vivado 生成的块设计文件中有一部分恰好存在这个问题。其结果是,对两个 .bd 文件进行文本比较时会出现很多误导性的差异,这些差异完全是由信息的排列顺序不一致造成的。
JSON 文件的规范化
处理文本文件中随机排序问题的自然办法,是把这个文件转换成规范形式(canonical form)。RFC 8785 对如何执行这种规范化(canonicalization)给出了严格的定义,不过就比较两个文件这一目的而言,我们没有必要遵循那个标准。只要避免随机重排就够了。
一种简单的解决办法是,按照属性名的字母顺序对对象中的属性进行排序。这能保证 JSON 文件内部的信息表示保持一致。不过,用这种方式重排信息也有一个缺点。属性原本往往按照便于阅读的顺序排列:重要属性通常放在前面,而且属性会按照含义分组。因此,阅读规范形式的 JSON 文件会稍微困难一些。
一个 Perl 脚本
得益于 JSON Perl 模块,编写一个对 JSON 文件进行规范化的 Perl 脚本(script)相当容易:
#!/usr/bin/perl
use warnings;
use strict;
use JSON;
local $/; # Slurp mode
my $json = JSON->new->allow_nonref->space_after->indent->canonical;
my $in = <>;
my $h = $json->decode($in);
my $out = $json->encode($h);
print $out;
用类似下面的命令来使用这个脚本:
$ ./jsonize.pl vivado_system.bd > canonicalized.bd
为了比较块设计,请对两个经过规范化处理的 JSON 文件进行文本比较。