Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

r186@horse: Agent2002 | 2005-11-27 22:52:45 +0800

 * Completed the work on doc/report.pod, which is a good overview for Salent.


git-svn-id: http://svn.berlios.de/svnroot/repos/salent@15 61cb175c-0704-0410-9cb5-98685d7901e0
  • Loading branch information...
commit 592c8f71545edee244eed1fbacc134319b1a1b6f 1 parent dbd08d4
agent authored
View
BIN  doc/image/ex_state_mac.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  doc/image/tt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
448 doc/report.html
@@ -19,116 +19,130 @@
<ul>
- <li><a href="#NAME">NAME</a></li>
- <li><a href="#AUTHOR">AUTHOR</a></li>
- <li><a href="#VERSION">VERSION</a></li>
- <li><a href="#DESCRIPTION">DESCRIPTION</a></li>
- <li><a href="#FAQ">FAQ</a></li>
+ <li><a href="#name">NAME</a></li>
+ <li><a href="#author">AUTHOR</a></li>
+ <li><a href="#version">VERSION</a></li>
+ <li><a href="#description">DESCRIPTION</a></li>
+ <li><a href="#faq">FAQ</a></li>
<ul>
- <li><a href="#baceceaa20Salent20cfeec4bfa3bf">何为 Salent 项目?</a></li>
- <li><a href="#ceaabacec3fbceaa20Salent20a3bf">为何名为 Salent ?</a></li>
- <li><a href="#Salent20cfeec4bfb5c4bfaab7a2b6afbbfacac7cab2c3b4a3bf">Salent 项目的开发动机是什么?</a></li>
- <li><a href="#Salent20cfeec4bfc4dcb4f8b8f8ced2c3c7cab2c3b4a3bf">Salent 项目能带给我们什么?</a></li>
- <li><a href="#c8e7bacebbf1b5c320Salenta3bf">如何获得 Salent?</a></li>
- <li><a href="#Salent20cab9d3c3c1cbbaced6d6d3efd1d4a3bf">Salent 使用了何种语言?</a></li>
- <li><a href="#ceaacab2c3b4b2bbb2c9d3c3bdadcbd5b4f3d1a7bdcccadab5c420VHDL20d3efd1d4a3bf">为什么不采用江苏大学教授的 VHDL 语言?</a></li>
- <li><a href="#Salent20cfeec4bfc9e8bcc6b5c4b4a6c0edc6f7bedfcce5d6a7b3d6c4c4d0a920x383620d6b8c1eebcafa3bf">Salent 项目设计的处理器具体支持哪些 x86 指令集?</a></li>
- <li><a href="#Salent20cfeec4bfd3c9c4c4bcb8b2bfb7d6d7e9b3c9a3bf">Salent 项目由哪几部分组成?</a></li>
+ <li><a href="#baceceaa20salent20cfeec4bfa3bf">何为 Salent 项目?</a></li>
+ <li><a href="#ceaabacec3fbceaa20salent20a3bf">为何名为 Salent ?</a></li>
+ <li><a href="#salent20cfeec4bfb5c4bfaab7a2b6afbbfacac7cab2c3b4a3bf">Salent 项目的开发动机是什么?</a></li>
+ <li><a href="#salent20cfeec4bfc4dcb4f8b8f8ced2c3c7cab2c3b4a3bf">Salent 项目能带给我们什么?</a></li>
+ <li><a href="#c8e7bacebbf1b5c320salenta3bf">如何获得 Salent?</a></li>
+ <li><a href="#salent20cab9d3c3c1cbbaced6d6d3efd1d4a3bf">Salent 使用了何种语言?</a></li>
+ <li><a href="#ceaacab2c3b4b2bbb2c9d3c3bdadcbd5b4f3d1a7bdcccadab5c420vhdl20d3efd1d4a3bf">为什么不采用江苏大学教授的 VHDL 语言?</a></li>
+ <li><a href="#salent20cfeec4bfc9e8bcc6b5c4b4a6c0edc6f7bedfcce5d6a7b3d6c4c4d0a920x8620d6b8c1eebcafa3bf">Salent 项目设计的处理器具体支持哪些 x86 指令集?</a></li>
+ <li><a href="#salent20cfeec4bfd3c9c4c4bcb8b2bfb7d6d7e9b3c9a3bf">Salent 项目由哪几部分组成?</a></li>
<li><a href="#c4e3d4dabfaab7a2b9fdb3ccd6d0b5c3b5bdc1cbc4c4d0a9c8cbb5c4b0efd6faa3bf">你在开发过程中得到了哪些人的帮助?</a></li>
- <li><a href="#Salent20c4bfc7b0b5c4bdf8d5b9c8e7bacea3bf">Salent 目前的进展如何?</a></li>
+ <li><a href="#salent20c4bfc7b0b5c4bdf8d5b9c8e7bacea3bf">Salent 目前的进展如何?</a></li>
<li><a href="#d5e2c6aacec4b5b5cac7c8e7baceb2fac9fab5c4a3bf">这篇文档是如何产生的?</a></li>
</ul>
<li><a href="#cfeec4bfc9e8bcc6c4bfb1ea">项目设计目标</a></li>
- <li><a href="#RAM20b5c4bfaab7a2">RAM 的开发</a></li>
- <li><a href="#ALU20b5c4bfaab7a2">ALU 的开发</a></li>
- <li><a href="#MMU20b5c4bfaab7a2">MMU 的开发</a></li>
- <li><a href="#IDU20b5c4bfaab7a2">IDU 的开发</a></li>
+ <li><a href="#baeab9dbb5c4c9e8bcc6d3ebbfaab7a2bef6b2df">宏观的设计与开发决策</a></li>
+ <li><a href="#ram20b5c4bfaab7a2">RAM 的开发</a></li>
+ <li><a href="#alu20b5c4bfaab7a2">ALU 的开发</a></li>
+ <ul>
+
+ <li><a href="#b4d3c4a3b0e5c9fab3c9d3b2bcfec9e8bcc6">从模板生成硬件设计</a></li>
+ </ul>
+
+ <li><a href="#ram20bacd20alu20d3b2bcfec9e8bcc6b5c4d7d4b6afbbafb2e2cad4">RAM 和 ALU 硬件设计的自动化测试</a></li>
+ <li><a href="#mmu20b5c4bfaab7a2">MMU 的开发</a></li>
+ <li><a href="#idu20b5c4bfaab7a2">IDU 的开发</a></li>
<ul>
<li><a href="#d3f6b5bdb5c4c0a7c4d1">遇到的困难</a></li>
<li><a href="#d7bcb1b8b9a4d7f7">准备工作</a></li>
- <li><a href="#d7d4b6afc9fab3c920IDU">自动生成 IDU</a></li>
+ <li><a href="#d7d4b6afc9fab3c920idu">自动生成 IDU</a></li>
<ul>
- <li><a href="#c9fab3c920Perl20IDU">生成 Perl IDU</a></li>
- <li><a href="#c9fab3c920C20IDU">生成 C IDU</a></li>
- <li><a href="#c9fab3c920Verilog20IDU">生成 Verilog IDU</a></li>
- </ul>
+ <li><a href="#b9d8d3dad7b4ccacbbfa">关于状态机</a></li>
+ <li><a href="#perl20idu">Perl IDU</a></li>
+ <ul>
- <li><a href="#d7d4b6afb2e2cad420IDU">自动测试 IDU</a></li>
- <ul>
+ <li><a href="#perl20idu20b5c4d7d4b6afbbafb2e2cad4">Perl IDU 的自动化测试</a></li>
+ <li><a href="#b8fcb6e0b9d8">更多关</a></li>
+ </ul>
+
+ <li><a href="#c20idu">C IDU</a></li>
+ <ul>
- <li><a href="#SMOKE20bcbccaf5">SMOKE 技术</a></li>
+ <li><a href="#c20idu20b5c4d7d4b6afbbafb2e2cad4">C IDU 的自动化测试</a></li>
+ </ul>
+
+ <li><a href="#c9fab3c920verilog20idu">生成 Verilog IDU</a></li>
+ <li><a href="#smoke20bcbccaf5">SMOKE 技术</a></li>
</ul>
</ul>
- <li><a href="#IEU20b5c4bfaab7a2">IEU 的开发</a></li>
- <li><a href="#Extension20of20Salent">Extension of Salent</a></li>
+ <li><a href="#ieu20b5c4bfaab7a2">IEU 的开发</a></li>
+ <li><a href="#extension20of20salent">Extension of Salent</a></li>
<ul>
- <li><a href="#Salent20Virtual20Machine2028SVM29">Salent Virtual Machine (SVM)</a></li>
+ <li><a href="#salent20virtual20machine2028svm29">Salent Virtual Machine (SVM)</a></li>
</ul>
- <li><a href="#BIBLIOGRAPHY">BIBLIOGRAPHY</a></li>
- <li><a href="#COPYRIGHT">COPYRIGHT</a></li>
+ <li><a href="#bibliography">BIBLIOGRAPHY</a></li>
+ <li><a href="#copyright">COPYRIGHT</a></li>
</ul>
<!-- INDEX END -->
<hr />
<p>
</p>
-<h1><a name="NAME">NAME</a></h1>
+<h1><a name="name">NAME</a></h1>
<p>report - Computer Organization Design Report for Salent</p>
<p>
</p>
<hr />
-<h1><a name="AUTHOR">AUTHOR</a></h1>
+<h1><a name="author">AUTHOR</a></h1>
<p>Agent Zhang (章亦春) &lt;<a href="mailto:agent2002@126.com">agent2002@126.com</a>&gt;</p>
<p>3030602110 计算机0304班</p>
<p>计算机科学与通信工程学院 江苏大学</p>
<p>
</p>
<hr />
-<h1><a name="VERSION">VERSION</a></h1>
+<h1><a name="version">VERSION</a></h1>
<p>本文档描述了于 2005 年 10 月底发布的 Salent 0.08</p>
<p>
</p>
<hr />
-<h1><a name="DESCRIPTION">DESCRIPTION</a></h1>
+<h1><a name="description">DESCRIPTION</a></h1>
<p>本次计算机组成课程设计的基本方向是计算机系统的硬件设计。在征得指导老
师的同意之后,我将自己的 Salent 项目作为本设计的题目。本报告概括地
介绍了Salent 项目的主要方面,描述了项目基本的开发过程。</p>
<p>
</p>
<hr />
-<h1><a name="FAQ">FAQ</a></h1>
+<h1><a name="faq">FAQ</a></h1>
<p>以下列举了有关 Salent 项目的常见问题及其解答。如果你的问题未出
现在该列表中,或者对某个问题有更好的答案,请告诉我。</p>
<p>
</p>
-<h2><a name="baceceaa20Salent20cfeec4bfa3bf">何为 Salent 项目?</a></h2>
+<h2><a name="baceceaa20salent20cfeec4bfa3bf">何为 Salent 项目?</a></h2>
<p>Salent 项目是章亦春为
适应学校计算机组成课程设计的要求开发的支持
x86 常用指令集的计算机硬件系统,简单地说,就是自己设计一台电子计算机。
该项目自 2005 年 6 月底启动以来,开发工作一直延续至今。</p>
<p>
</p>
-<h2><a name="ceaabacec3fbceaa20Salent20a3bf">为何名为 Salent ?</a></h2>
+<h2><a name="ceaabacec3fbceaa20salent20a3bf">为何名为 Salent ?</a></h2>
<p>Salent 是本项目最初的两个开发人员仲伟祥 (sal) 和章亦春 (agent) 的
英文名的字母组合: SAL-ENT。</p>
<p>
</p>
-<h2><a name="Salent20cfeec4bfb5c4bfaab7a2b6afbbfacac7cab2c3b4a3bf">Salent 项目的开发动机是什么?</a></h2>
+<h2><a name="salent20cfeec4bfb5c4bfaab7a2b6afbbfacac7cab2c3b4a3bf">Salent 项目的开发动机是什么?</a></h2>
<p>开发该项目的初衷是为了通过动手实作一台 32 位的计算机系统,加深对
教科书上学到的计算机组成方面的知识、原理和技术的理解,同时也为了
探索用软件方式自动化硬件设计与测试过程的具体途径,熟悉硬件设计的
细节。</p>
<p>
</p>
-<h2><a name="Salent20cfeec4bfc4dcb4f8b8f8ced2c3c7cab2c3b4a3bf">Salent 项目能带给我们什么?</a></h2>
+<h2><a name="salent20cfeec4bfc4dcb4f8b8f8ced2c3c7cab2c3b4a3bf">Salent 项目能带给我们什么?</a></h2>
<p>Salent 项目的开发过程充满了创新与活力。我有意识地效仿唐宗汉 (Autrijus
Tang) 的 Pugs 项目``optimize for fun''的做法,以不断向四围发散的方
式领导整个项目的开发。因此该项目的创新至上,乐趣至上的文化是最值得我
@@ -160,7 +174,7 @@
网络。我们可以利用这个 Perl 实现做许多有趣的事情。:=)</p>
<p>
</p>
-<h2><a name="c8e7bacebbf1b5c320Salenta3bf">如何获得 Salent?</a></h2>
+<h2><a name="c8e7bacebbf1b5c320salenta3bf">如何获得 Salent?</a></h2>
<p>Salent 项目已处于现代的版本控制系统 Subversion (SVN) 的管理之下,因此
你总是可以从 Salent 位于德国的 SVN 中央服务器</p>
<p><a href="https://svn.berlios.de/svnroot/repos/salent">https://svn.berlios.de/svnroot/repos/salent</a></p>
@@ -170,14 +184,14 @@
操作,SVK 则是非常不错的选择。</p>
<p>
</p>
-<h2><a name="Salent20cab9d3c3c1cbbaced6d6d3efd1d4a3bf">Salent 使用了何种语言?</a></h2>
+<h2><a name="salent20cab9d3c3c1cbbaced6d6d3efd1d4a3bf">Salent 使用了何种语言?</a></h2>
<p>Salent 项目的最终产品是硬件设计,当然会使用到硬件描述语言。我经
过权衡,最终选择了 Verilog HDL。不过,值得一提的是,在设计与测试
环节中,我还广泛使用了众多软件编程语言以辅助硬件开发。这其中包括
Perl5,C/C++,Tcl,以及 MASM。</p>
<p>
</p>
-<h2><a name="ceaacab2c3b4b2bbb2c9d3c3bdadcbd5b4f3d1a7bdcccadab5c420VHDL20d3efd1d4a3bf">为什么不采用江苏大学教授的 VHDL 语言?</a></h2>
+<h2><a name="ceaacab2c3b4b2bbb2c9d3c3bdadcbd5b4f3d1a7bdcccadab5c420vhdl20d3efd1d4a3bf">为什么不采用江苏大学教授的 VHDL 语言?</a></h2>
<p>说实话,从学校教授 VHDL 的第一天起,我就对它没有什么好感。即便是很简
单的设计,用 VHDL 描述起来也显得相当笨拙。在学习 Verilog HDL 之前
我在 Google 中稍稍搜索了一下“Verilog vs. VHDL”,结果看到 Verilog
@@ -185,13 +199,13 @@
当初的选择是明智的。</p>
<p>
</p>
-<h2><a name="Salent20cfeec4bfc9e8bcc6b5c4b4a6c0edc6f7bedfcce5d6a7b3d6c4c4d0a920x383620d6b8c1eebcafa3bf">Salent 项目设计的处理器具体支持哪些 x86 指令集?</a></h2>
+<h2><a name="salent20cfeec4bfc9e8bcc6b5c4b4a6c0edc6f7bedfcce5d6a7b3d6c4c4d0a920x8620d6b8c1eebcafa3bf">Salent 项目设计的处理器具体支持哪些 x86 指令集?</a></h2>
<p>按照计划,Salent 芯片将支持整个“非 64 位通用目的指令集”和“FPU 浮点
运算指令集”。至本文档编写之时,Salent 的指令译码器(IDU)已能正确
解译上述两个指令集的所有指令了。</p>
<p>
</p>
-<h2><a name="Salent20cfeec4bfd3c9c4c4bcb8b2bfb7d6d7e9b3c9a3bf">Salent 项目由哪几部分组成?</a></h2>
+<h2><a name="salent20cfeec4bfd3c9c4c4bcb8b2bfb7d6d7e9b3c9a3bf">Salent 项目由哪几部分组成?</a></h2>
<p>Salent 由以下模块组成:</p>
<ul>
<li></li>
@@ -250,7 +264,7 @@
来源。</p>
<p>
</p>
-<h2><a name="Salent20c4bfc7b0b5c4bdf8d5b9c8e7bacea3bf">Salent 目前的进展如何?</a></h2>
+<h2><a name="salent20c4bfc7b0b5c4bdf8d5b9c8e7bacea3bf">Salent 目前的进展如何?</a></h2>
<p>目前,逻辑算术单元 ALU 和随机访问存储器 RAM 已经完成设计与测试。指令
译码器 IDU 已完成状态机和基本算法的测试(通过 IDU 的 Perl 和 C 版本
的纯软件实现),并且已经得到了 Verilog HDL 的实现代码。但是 Verilog
@@ -285,13 +299,58 @@
<p>
</p>
<hr />
-<h1><a name="RAM20b5c4bfaab7a2">RAM 的开发</a></h1>
-<p>32位的 RAM 已经设计完成,使用 Verilog HDL,而且用基于 Perl Template
-Toolkit 的自动化测试框架对其进行了比较彻底的测试。</p>
+<h1><a name="baeab9dbb5c4c9e8bcc6d3ebbfaab7a2bef6b2df">宏观的设计与开发决策</a></h1>
+<p>我在项目开始之初就考虑了一下模型机的设计与测试的总策略。</p>
+<ul>
+<li></li>
+仿真与可综合性
+<p>我想如果在一开始就考虑哪些东东是 Synthesizable,哪些不可以,那么我将
+寸步难行。所以我决定
+只要我的设计能单纯地进行仿真就可以了。日后有机会再把不能综合(synthesis)
+的代码改成可以综合的。事实上我现在也搞不清到底哪些是可以综合的,因为这是
+由 Vendors (供应商)自己决定的。</p>
+<p></p>
+<li></li>
+硬件描述语言 (HDL) 的选择
+<p>另外,我决定不使用 VHDL 语言,它实在
+是太难看了。经过比较,我发现 Verilog HDL 是更好的选择,它不仅记法很干
+净,而且没有 VHDL 中类型转换方面的困挠,更重要的是它也是 IEEE 标准的一
+部分,呵呵。</p>
+<p>我在网上找到一个名为 X-HDL 的工具,它可以在两种 HDL 语言之
+间进行自动转换——嗯,非常有趣的东东哦。不过还是有些限制的。如果我使用
+Verilog 语言的高级特性,在翻译到对应的 VHDL 语言时可能没有对应的等价物。
+因此我被限制在一个子集之中。不过如果我能自己提供 Verilog 在 VHDL 中的
+“等价物”(比如 ShiftRight函数)的库实现的话,可以使我能使用的子集接近
+全集。但后来我还是放弃了同时维护 Verilog 和 VHDL 两种语言的实现版本的
+想法。</p>
+<p></p></ul>
<p>
</p>
<hr />
-<h1><a name="ALU20b5c4bfaab7a2">ALU 的开发</a></h1>
+<h1><a name="ram20b5c4bfaab7a2">RAM 的开发</a></h1>
+<p>设计 RAM 时遇到的一个简单的问题是,如果地址是 32 位,而且是 byte-addressable,
+那么 RAM 是否应该自己推导到“字”(word)的地址(即忽略掉32位地址的最后两个bit)?
+唔,还是由处理器负责将字节地址转换为字地址?不过那样的话,地址总线上的地址就不再
+是 32 位长,而是 30 位长了。</p>
+<p>在设计计算机系统的时候我必须把这个问题考虑清楚,特别是将“字”切片为“字节”的问题。再
+有就是“字”的地址与“字节”的地址之间的相互转换。</p>
+<p>目前的 RAM 内部按字存放,同时地址的长度也是一个字。因对 RAM 的直接读写都是按
+字进行的,即便传递给 RAM 的地址都是字节地址。RAM 在内部忽略地址的最后 2 个比
+特(对于 32 位 RAM 而言),自己推导出字节所在的字的地址。</p>
+<p>RAM 的 Verilog 实现是通过 Perl Template Toolkit 的模块自动生成的,因此它的
+位数是可以配置的。</p>
+<p>RAM 使用基于 Perl Template
+Toolkit 的自动化测试框架对其进行了比较彻底的测试。应用测试台已对 8 位 RAM,16
+位 RAM,32 位 RAM 和 64 位 RAM 进行了测试。</p>
+<p>
+</p>
+<hr />
+<h1><a name="alu20b5c4bfaab7a2">ALU 的开发</a></h1>
+<p>在设计 ALU 的时候,遇到一个问题是 PSW (Process Status Word) 是作为一个单
+独的模块来实现呢,还是作为其他模块,比如 ALU 的一部分。众所周知,PSW 与 ALU 有
+关联,ALU 每计算出一个结果都应当设置 PSW 中的相应的位(bit)。但是 Intel 文档
+对每一条 x86 指令对 PSW 的影响都作了具体的说明,因此更合适的做法是将 PSW 作为
+一个独立的模块,由 ALU 和指令执行单元 IEU 来对 PSW 进行读写。</p>
<p>我们的 ALU 支持以下操作:</p>
<pre>
ADD ADC SUB SBB MUL IMUL DIV IDIV
@@ -309,14 +368,162 @@
那么多机器指令了,除非我能得到更多人的帮助。</p>
<p>
</p>
+<h2><a name="b4d3c4a3b0e5c9fab3c9d3b2bcfec9e8bcc6">从模板生成硬件设计</a></h2>
+<p>ALU 的 Verilog 源代码是从模板自动生成的。Salent 项目中使用的模板都
+是 Perl Template Toolkit 的模块(又称为 TT2 模板)。</p>
+<p>下面是一个例子(来自 ALU Verilog 实现的模板文件):</p>
+<pre>
+ <img src="image/tt.png">
+</pre><p>
+</p>
<hr />
-<h1><a name="MMU20b5c4bfaab7a2">MMU 的开发</a></h1>
+<h1><a name="ram20bacd20alu20d3b2bcfec9e8bcc6b5c4d7d4b6afbbafb2e2cad4">RAM 和 ALU 硬件设计的自动化测试</a></h1>
+<p>我为 Salent 的 RAM 和 ALU 设计出了一个通用的自动化<strong>硬件</strong>测试框架,从测试输
+入的生成,到测试结果的验证,全部自动化,无需人的干预。</p>
+<p>我们酷酷的基于 ModelSim 的测试台的构建技术可是真正意义上的自动化测试:随机产生合
+法的输入信号,然后自动检查仿真器的输出……</p>
+<p>我们已经用该框架对 Salent
+模型机的 RAM 和 ALU 部件进行了彻底的测试。测试找出了许多很微妙的 bug,有的是我
+的 Verilog 实现的,有的是我的测试代码本身的问题,还有的是 ModelSim 仿真器的
+BUG. 无论如何,由于输入信号是测试台随机生成的,只要运行足够长的时间,便可以发现
+几乎所有的 bug. 只要捕捉到 bug,纠正一般都是很直截了当的。</p>
+<p>我现在对我们的 RAM
+和 ALU 已建立起了足够的信心。诚然!测试台迫使项目总是在正确的可以控制的轨道上前进。
+我们每作一处改动,就运行整个测试集,确保所作的修改没有碰坏其他原本可以工作的东西。
+同时这也可以通过测试台生成的报表,评价所作修改的实际效果。</p>
+<p>不过,测试台运行时间比
+较长,大约是十几秒到几十秒不等。比如 ALU 的测试集,运行一次,将进行 6887 个测试。
+我注意到 ModelSim SE 6.0 的仿真器在性能上远不及 5.7d 这个较老的版本。真奇怪。
+在我这台装有 ModelSim 6.0 的 Pentium4 2.6GHz 的机器上运行 ALU 的测试集还不
+及我家那台装有 5.7d 的 赛扬 330 的破机器。我估计原因可能是 6.0 做得太庞大了。</p>
+<p>每次运行,测试台实际执行的测试都不一样,因为输入都是随机生成的,而且种子是使用的系
+统时间。我们用模板生成任何东西,从 Verilog 代码到 Perl 程序,从 Tcl 仿真脚本到
+POD 和 HTML 文档,还有写程序的程序……</p>
+<pre>
+ I'd rather write programs to write programs to write programs.
+
+下面是 ALU 测试台的一次典型运行所生成的测试报表:</pre>
+<pre>
+ alu.........ok
+ talu1.op....ok
+ talu2.op....ok
+ talu3.op....ok
+ talu4.op....ok
+ talu5.op....ok
+ All tests successful.
+ Files=6, Tests=6887, 12 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
+ Timing Result: 525.359000 sec on average.</pre>
+<p>一共花了 525 秒耶!</p>
+<p>在测试中,如果发生错误,测试台会报告发生错误的具体位置,比如文件名、行号、仿真时
+间区间、ALU 输入信号的取值、等等。这些信息给排错带来了极大的便利。</p>
+<p>下面是 RAM 的一个早期版本因 64 位问题而让我们的测试台“报怨”的例子:</p>
+<pre>
+ ...</pre>
+<pre>
+ tramX_5.rw..........ok
+ tramX_6.rw..........ok
+ tramX_7.rw..........ok
+ tramX_8.rw..........NOK 8
+ # Failed test 'tramX_8.rw: line 7: r 'd0 0*abcd (@ 55 ~ 103)'
+ # in tramX_8.rw.t at line 26.
+ # '00000000zzzzzzzz'
+ # doesn't match '(?i-xsm:^z+$)'</pre>
+<pre>
+ tramX_8.rw..........NOK 12# Failed test
+ 'tramX_8.rw: line 8: r 'd15 ? (@ 103 ~ 141)'
+ # in tramX_8.rw.t at line 31.
+ # '00000000zzzzzzzz'
+ # doesn't match '(?i-xsm:^z+$)'</pre>
+<pre>
+ ...</pre>
+<pre>
+ Failed Test Stat Wstat Total Fail Failed List of Failed
+ -------------------------------------------------------------------------------
+ ...
+ tramX_4.rw.t 17 4352 54 17 31.48% 8 12-13 17-18 25-26 30-31 35-
+ 36 43-44 48-49 53-54
+ tramX_8.rw.t 49 12544 140 49 35.00% 8 12-13 17-18 22-23 27-28 35-
+ 36 40-41 45-46 50-51 55-56
+ 63-64 68-69 73-74 78-79 83-84
+ 91-92 96-97 101-102 106-107
+ 111-112 119-120 124-125 129-
+ 130 134-135 139-140
+ Failed 4/18 test scripts, 77.78% okay. 238/3627 subtests failed, 93.44% okay.</pre>
+<p>仲伟祥同学在我的框架基础上编写的RAM 的“随机应力测试台”捕捉到了 ModelSim 仿真器的一个 bug.
+太棒了!这种高强度的随机测试对包
+括仿真器在内的每一个部件,每一行代码都施加了巨大的压力,不是么? Well done! Sal++</p>
<p>
</p>
<hr />
-<h1><a name="IDU20b5c4bfaab7a2">IDU 的开发</a></h1>
+<h1><a name="mmu20b5c4bfaab7a2">MMU 的开发</a></h1>
+<p>MMU 是 Memory Management Unit 的首字母缩写,目前的主要功能是将“字”切片为“字节”。
+毕竟我们的 RAM 是按“字”来存取的,而处理器却时常按照“字节”来读写。MMU 的作用就是协调
+这种差异。它在处理器和 RAM 之间扮演着“中间人”的角色。</p>
+<p>我在 MMU 的 specification 中这样写道:</p>
+<p>The MMU in Salent is reponsible for slicing ``words'' to ``bytes''. It bridges
+the gap between the processor and RAM. The RAM operates in words, but the
+processor usually wants to access one single byte, two successive bytes,
+or a whole word.</p>
+<p>MMU will play such a role that from the viewpoint of the processor,
+the memory is byte-addressable, and it is only word-addressable from the
+viewpoint of RAM.</p>
+<p>The I/O ports for the MMU can be divided into two separate sub-interface,
+one for the processor, and one for RAM:</p>
+<pre>
+ RAM &lt;=&gt; MMU &lt;=&gt; Processor</pre>
+<p>The sub-interface of MMU for RAM is exactly the same as the interface of RAM.
+MMU should take the full reponsibility to interact with RAM, including setting
+data bus, address bus, rw and strb control signals.</p>
+<ul>
+<li></li>
+bus_strb - out
+<p>Strobe signal issued by MMU itself to start the RAM.</p>
+<p></p>
+<li></li>
+bus_rw - out
+<p>Read or write signal issued by MMU</p>
+<p></p>
+<li></li>
+bus_data - inout
+<p></p>
+<li></li>
+bus_addr - out
+<p></p>
+<li></li>
+bus_mfc - in
+<p></p></ul>
+<p>The sub-interface of MMU for processor is very simple, consisting of only four signals:</p>
+<ul>
+<li></li>
+mar - in, reg
+<p>Memory Address Register storing the address of the leading byte</p>
+<p></p>
+<li></li>
+byte - inout, reg
+<p>Memory Data Register storing the byte accessed or written by processor</p>
+<p></p>
+<li></li>
+strb - in
+<p>Strobe signal issued by procssor to start the MMU.</p>
+<p></p>
+<li></li>
+rw - in
+<p>Read/Write'</p>
+<p></p>
+<li></li>
+mfc - out
+<p></p></ul>
+<p>
+</p>
+<hr />
+<h1><a name="idu20b5c4bfaab7a2">IDU 的开发</a></h1>
<p>IA-32 指令集还有一种 64 位的扩展模式,名为 IA-32e,对 64 位指令的支持并
不在我的 TODO 列表中。</p>
+<p>我们的 IDU 设计以及建立在它之上的 x86 反汇编器是由
+代码生成器自动生成的,而且其支持的指令集可以动态地进行配置。我们在一个配置
+文件中添加一条机器指令的编码模式及对应的汇编语言格式,运行Make 之后,反汇
+编器将自动对新增指令提供支持。这个配置文件的格式就是 Intel IA-32 手册的
+指令码表的格式。在 Salent 项目目录中,名为 <em>encoding.txt</em>.</p>
<p>
</p>
<h2><a name="d3f6b5bdb5c4c0a7c4d1">遇到的困难</a></h2>
@@ -340,7 +547,7 @@
程完全自动化,无需人的干预。用这种方法得到的状态机是与具体的实现语言无关的,
所以不仅可用于生成 Verilog 描述,也能生成 C/C++/Perl 程序。</p>
<p>为了理解 IA-32 的指令码表,开始的几周我一直在研读 Intel 的
-``IA-32 Intel ArchitectureSoftware Developer's Manual''.
+``IA-32 Intel Architecture Software Developer's Manual''.
此外,我还精读了英文版的``Computer Organization'',NASM 的帮助,还有 MASM
方面的的基础知识…… 即便如此,我还是经过很多天的冥思苦想才最终搞清楚
了 Intel 文档中的几章的内容。本项目的一个重要合作者仲伟祥也花费了大量的时间
@@ -352,7 +559,7 @@
以及 ModelSim SE 仿真系统的高级特性。</p>
<p>
</p>
-<h2><a name="d7d4b6afc9fab3c920IDU">自动生成 IDU</a></h2>
+<h2><a name="d7d4b6afc9fab3c920idu">自动生成 IDU</a></h2>
<p>具体说来,即让我的 perl 程序自己读 Intel 的文档,然后输出译码器的实现,
可以是 perl 版本的,也可以是硬件描述语言的版本(比如 Verilog HDL)。
基本过程是解析指令模式,生成模式匹配的抽象语法树(AST),再通过对 AST
@@ -361,7 +568,9 @@
<p>这是典型的“写程序的程序”。由于状态机模型是与输出的实现语言无关的,因此
提供 Perl 代码的模板就产生 Perl 版本的译码器程序,提供 Verilog 代码
的模型就产生 Verilog 版本的译码器描述,C/C++ 还有 Java 还有 VHDL 都
-依此类推。</p>
+依此类推。我有计划再在 Salent IDU 项目中引入 Java, C#, JavaScript,
+Visual Basi, 甚至于 Haskell 和 Perl6 这些语言。如此之多的语言和文化
+在 Salent 项目中交汇成一股伟大的洪流,势不可当!</p>
<p>这意味着一旦我们得到了一种语言下的译码器实现,就可以轻而易举地获得其他
语言的实现。要做的只是提供这种语言下的模板文件就可以了。而模板文件都是
大同小异,代码很少的。</p>
@@ -373,13 +582,14 @@
时候曾经在 QQ 中这样向他解释如何将我们已有的 Perl 实现的模板改写为
Java 实现的模板:</p>
<p>``Well, it's quite straightforward. The two versions of IDU implementations
-(the Perl one and Java one) will share the same AST, I mean Abstract Semantic
-Tree. The best way to comprehend ASTs is simply reguard it as a complex data
-structure. Hmm...maybe something like a tree, an array, a hash, or so so...
+(the Perl one and Java one) will share the same AST, I mean Abstract Syntax
+Tree. The best way to comprehend ASTs is to simply reguard it as a complex
+data structure. Hmm...maybe something like a tree, an array, a hash, or so.
To generate the final implementation, an AST is not enough. The info stored in
the AST is only concerned with the state machine (or the state graph), hence
There is nothing specific to the programming language we finally choose.</p>
-<p>``In order to generate the IDU programs automatically, we provide a full-fledged
+<p>``In order to generate the IDU programs automatically, we provide a
+full-fledged
AST and a well defined program template to the computer. The computer will
combine the two to generate the final implementation, say, the final program.
The key is combining an AST with a program template. So it's another example of
@@ -389,14 +599,49 @@
program's source code. The Perl template we've already obtained, the Java
template you'll write, and even more templates in the future will have a similar
appearance. They'll be pretty alike. ''</p>
-<p><strong>关于状态机</strong></p>
+<p>当我对我们班的一个同学说,Intel 手册的指令码表中有很多 typo (键入错误)的时候,他反驳
+我说,这是“难免”的。我反驳道,我们 Salent 项目中的码表文件却可以完全避免 typo。
+他很怀疑我的说法,问我为什么?我告诉他,我们的文档,IDU 实现,以及我们
+的 IDU 测试台都是根据一棵 AST 由程序自动生成的呀!而这棵 AST (Abstract
+Syntax Tree) 又是从 Intel 的文档自动转换过来的。因此 Intel 文档中的所有
+typo 都会反映到我们的 idu 实现和 idu 测试台的代码中,并最终被测试台捕捉到。
+由此可见,我们使用的真的是一种神奇的技术!</p>
+<p>
+</p>
+<h3><a name="b9d8d3dad7b4ccacbbfa">关于状态机</a></h3>
<p>记得“数字逻辑电路”课程中接触到的“状态机”么?就是那种东西。我们在当时用
状态机构造“二进制序列检测器”的? 状态图? 你可能还不知道它有多么强大、多
么通用呢!在编译理论中我们还会以更近的距离接近它。它对译码器、编译器或者
类似的识别模式的程序和硬件设计而言简直是无价之宝!非常优美,非常抽象,非
常简洁。更重要的是:非常实用。</p>
-<p>熟练掌握状态机模型却仍需要大量的实践和思考。我们在写处理输入的 Perl 程序
-时很难不去用它。只不过大多数时候我们用到了,却并不知觉。</p>
+<p>状态机是这样一种抽象的机器,这个机器能够维护并且切换当前的状态。它根据
+外部的输入和内部产生的输出来得到状态切换的条件。状态机是设计软件和设计硬件的基
+本工具。与其说它是一台“机器”,不如说它是一种数学模型。其实状态机的核心思想非常
+简单,我想打一个比方来加以说明。</p>
+<p>比如我想“识别”出两个单词 add 和 and,现在我们可以用状态机来完成“识别”的任务。
+令状态 0 为初始状态。
+首先,我们读取未知单词的第一个字母,比如说是 a,我们便切换到状态1,否则跳转到出
+错状态,因为两个词都是由 a 起始的。接着,我们读
+取第二个字母,这时就要分三种情况进行讨论,如果得到的是 d,就跳转到状态 2;如果
+是 n ,则跳转到状态 3;否则就跳到出错状态。然后,我们读取第三个字母,如果当前
+状态是 2,而且当前的字符是 d,则完成对 add 的识别。如果当前状态是 3,而当前的
+字符是 d ,则完成对 and 的识别。其余情况,跳转到出错状态,即匹配失败。上面这个
+例子可以用来识别英语单词。</p>
+<p>下面是这个例子中的状态机的示意图:</p>
+<pre>
+ <img src="image/ex_state_mac.png" alt="Sample State Machine">
+</pre><p>图中的每一个节点(圆圈)都代表一个独立的“状态”,节点之间的箭头表示状态之间的转
+换条件。</p>
+<p>我的一位高中同学由此想到了“文曲星”的工作原理。呵呵,
+我也觉得有点儿类似哦——嗯,真的很相似。</p>
+<p>事实上,状态机是无处不在的。状态机在编写识别性质的程序和电路的时候,简直是无价之
+宝。比如识别机器语言的集成电路,识别各种高级编程语言的编译器和解释器,还有很多一
+般性的程序,状态机无处不在!有时候我们即时自己使用了,可能还未发觉。这并不是我在
+开发 Salent 项目的过程中刚刚学到的知识,事实上,我已经使用了多年了。从高三开始
+我就有意识地在自己编写的代码中大量地使用。状态机是编程领域比较有趣的东东。我从高
+一开始自学编程,在高二时学习了计算机专业的《编译原理》课程,在那儿我首次接触了状
+态机理论。不久我就发现它是如此地强大,并最终在 Salent 的 IDU 中将这种威力发挥
+到了近乎神奇的地步。</p>
<p>IDU 的状态机规模非常庞大,共有 590 个状态。我不认为用手工的方式能够在可
以接受的时间之内圆满地完成它。下面是用 Graphviz 自动根据 IDU 状态机的
XML 描述生成的示意图:</p>
@@ -407,7 +652,7 @@
<img src="image/mini_state_mac.png" alt="Mini State Machine">
</pre><p>
</p>
-<h3><a name="c9fab3c920Perl20IDU">生成 Perl IDU</a></h3>
+<h3><a name="perl20idu">Perl IDU</a></h3>
<p>Perl IDU 是我得到的第一版本的 IDU 实现。它的开发过程完全是测试驱动的
(test-driven)。在不断地提高 Perl IDU 的测试通过率的过程之中,我也不断
地修正状态机乃至于指令码表中的错误。而这正是开发 Perl 版本的 IDU 的主要
@@ -415,7 +660,35 @@
提高。</p>
<p>
</p>
-<h3><a name="c9fab3c920C20IDU">生成 C IDU</a></h3>
+<h4><a name="perl20idu20b5c4d7d4b6afbbafb2e2cad4">Perl IDU 的自动化测试</a></h4>
+<p>为了对我们的指令译码器进行应用测试,我自然需要根据机器指令的码表,编写一个能
+随机生成合法的 IA-32 机器码的Perl 程序。码表仍然来自 Intel 手册 2B 卷的
+Appendix B, 因此严格覆盖了整个``非64位通用目的指令集”和整个“x87 FPU 浮点
+指令集”。事实上,每次运行生成器,每一种指令模式都会生成至少一条机器指令,而
+每一种寻址方式、每一个可能操作数组合,都有<strong>可能</strong>生成。这对于测试我们的反汇编
+器而言,简直是无价之宝,因为一般的 EXE 文件代码段中的指令在整个 x86 指令集中
+的覆盖率只有 30 ~ 50%,而且重复率高,用于应力测试,效果很不理想。但使用一些
+典型的 EXE 文件的代码段中的机器指令序列来测试我们的 IDU 仍是测试台的一个
+重要的组成部分。</p>
+<p>我已用一些第三方的反汇编器对我的 Perl 脚本生成的 x86 机器指令进行了测试。</p>
+<p>一开始,我们只是测试 IDU 译码得到的指令名和指令长度,因为这比较简单(当然了,
+Intel 指令集中众多的“别名”和前缀码 (prefix byte) 是比较难处理的部分)。
+指令名测试虽然简单,但却非常有效,能状态机和 IDU 模板的大部分问题。</p>
+<p>然而,指令名测试毕竟是不全面的,我们无法对一些寻址方式和取数结果进行检验。因
+此,我们又在 IDU 的基础上实现了一个汇编代码的输出后端。只有让 IDU 将译码的
+结果输出为 NASM 汇编代码的形式,我们才能直接将之与 NASM 的反汇编器输出进行
+精确比较。事实上,一个生成汇编代码的后端加上 IDU 指令译码器本身,便构成了一个
+x86 反汇编器。其实,支持如此之大的指令集的 x86 反汇编器本身就已经是一个极端复
+杂的项目了。我们不得不为自己的工作而感到骄傲。</p>
+<p>由于有了如此完美的指令应力测试台,我们的反汇编器的正确性与稳定性毫不亚于 NASM
+自带的反汇编器。事实上,我们的测试台居然捕捉到了 NASM 的 FPU 指令集处理部分的
+一个微妙的 bug. 自动化测试万岁!应力测试万岁!</p>
+<p>
+</p>
+<h4><a name="b8fcb6e0b9d8">更多关</a></h4>
+<p>
+</p>
+<h3><a name="c20idu">C IDU</a></h3>
<p>在 Perl IDU 通过全部的测试集之后,我们又得到了 C 语言的指令译码器实现。
C 版本的测试过程相对于 Perl 版本而言就比较麻烦,比较繁琐了。
我花了不少时间来琢磨如何让我的 C 版本的 IDU 面对非法输入时能够不崩溃。
@@ -426,7 +699,10 @@
美的追求那样。确实,C 的出错处理太难错了,我真怀念 Perl 中强大的文本处理能力。</p>
<p>当然,必须指出的是,因为有了经过彻底测试的 Perl 版本的实现在手,C 版本的 IDU
的开发已经变得容易许多了。</p>
-<p>一开始,我的 C IDU 和我原来的 Perl IDU 共享了绝大部分的测试集,但不是全部。嗯,
+<p>
+</p>
+<h4><a name="c20idu20b5c4d7d4b6afbbafb2e2cad4">C IDU 的自动化测试</a></h4>
+<p>最初,我的 C IDU 和我原来的 Perl IDU 共享了绝大部分的测试集,但不是全部。嗯,
就是机器指令随机生成器驱动的 NASM 应力测试集 (pat_cover).
后来,在吴元斌的鼓励下,我又更进一步,让两种语言版本的 IDU 共享全部 100% 的测试集。
事后我分析了一下,无论从理论还是从技术上这都不成问题,只要我的 C IDU 提供和原来的
@@ -439,31 +715,10 @@
是通过 COM 接口、Inline::* 模块或者 C 进行语言之间的“过渡”。</p>
<p>
</p>
-<h3><a name="c9fab3c920Verilog20IDU">生成 Verilog IDU</a></h3>
-<p>
-</p>
-<h2><a name="d7d4b6afb2e2cad420IDU">自动测试 IDU</a></h2>
-<p>为了对我们的指令译码器进行应用测试,我自然需要根据机器指令的码表,编写一个能
-随机生成合法的 IA-32 机器码的Perl 程序。码表仍然来自 Intel 手册 2B 卷的
-Appendix B, 因此严格覆盖了整个``非64位通用目的指令集”和整个“x87 FPU 浮点
-指令集”。事实上,每次运行生成器,每一种指令模式都会生成至少一条机器指令,而
-每一种寻址方式、每一个可能操作数组合,都有<strong>可能</strong>生成。我已用一些第三方的反汇
-编器对我的 Perl 脚本生成的 x86 机器指令进行了测试。</p>
-<p>一开始,我们只是测试 IDU 译码得到的指令名和指令长度,因为这比较简单(当然了,
-Intel 指令集中众多的“别名”和前缀码 (preffix byte) 是比较难处理的部分)。
-指令名测试虽然简单,但却非常有效,能状态机和 IDU 模板的大部分问题。</p>
-<p>然而,指令名测试毕竟是不全面的,我们无法对一些寻址方式和取数结果进行检验。因
-此,我们又在 IDU 的基础上实现了一个汇编代码的输出后端。只有让 IDU 将译码的
-结果输出为 NASM 汇编代码的形式,我们才能直接将之与 NASM 的反汇编器输出进行
-精确比较。事实上,一个生成汇编代码的后端加上 IDU 指令译码器本身,便构成了一个
-x86 反汇编器。其实,支持如此之大的指令集的 x86 反汇编器本身就已经是一个极端复
-杂的项目了。我们不得不为自己的工作而感到骄傲。</p>
-<p>由于有了如此完美的指令应力测试台,我们的反汇编器的正确性与稳定性毫不亚于 NASM
-自带的反汇编器。事实上,我们的测试台居然捕捉到了 NASM 的 FPU 指令集处理部分的
-一个微妙的 bug. 自动化测试万岁!应力测试万岁!</p>
+<h3><a name="c9fab3c920verilog20idu">生成 Verilog IDU</a></h3>
<p>
</p>
-<h3><a name="SMOKE20bcbccaf5">SMOKE 技术</a></h3>
+<h3><a name="smoke20bcbccaf5">SMOKE 技术</a></h3>
<p>我们的 IDU 项目测试台能够生成完美的 HTML 测试报表。该项技术称之为 SMOKE.
我曾经兴奋地在 QQ 中写道:</p>
<pre>
@@ -516,17 +771,17 @@
</pre><p>
</p>
<hr />
-<h1><a name="IEU20b5c4bfaab7a2">IEU 的开发</a></h1>
-<p>XXX</p>
+<h1><a name="ieu20b5c4bfaab7a2">IEU 的开发</a></h1>
+<p>尚未开始。</p>
<p>
</p>
<hr />
-<h1><a name="Extension20of20Salent">Extension of Salent</a></h1>
+<h1><a name="extension20of20salent">Extension of Salent</a></h1>
<p>Salent 项目是如此丰富多彩,以至于从它出发,我们可以引出许多更为有趣的项目与方向。
SVM 便是其中最迷人的一个例子。</p>
<p>
</p>
-<h2><a name="Salent20Virtual20Machine2028SVM29">Salent Virtual Machine (SVM)</a></h2>
+<h2><a name="salent20virtual20machine2028svm29">Salent Virtual Machine (SVM)</a></h2>
<p>大三上学期,我开始着手 SVM 虚拟机的构建问题。SVM 与 Salent 既是相互独立的两个项目,
又是相互关联的两个项目。关键是我们能从 SVM 中得到什么特别的好处。一个完成了“自举”过
程的 VM 会拥有怎样的优势,会具有怎么的奇异特性呢?我的哥们仲伟祥给了我四个字:“妙不
@@ -570,9 +825,12 @@
<p>
</p>
<hr />
-<h1><a name="BIBLIOGRAPHY">BIBLIOGRAPHY</a></h1>
+<h1><a name="bibliography">BIBLIOGRAPHY</a></h1>
<ul>
<li></li>
+``Verilog 高级数学电路设计''
+<p></p>
+<li></li>
IA-32 Intel Architecture Software Developer's Manuals
<p><a href="http://www.intel.com/design/pentium4/manuals/index_new.htm">http://www.intel.com/design/pentium4/manuals/index_new.htm</a></p>
<p></p>
@@ -601,7 +859,7 @@
<p>
</p>
<hr />
-<h1><a name="COPYRIGHT">COPYRIGHT</a></h1>
+<h1><a name="copyright">COPYRIGHT</a></h1>
<p>Copyright (c) 2005 Agent Zhang</p>
<p>This document is free. You can modify and/or redistribute it under the
same terms as Perl.</p>
View
392 doc/report.pod
@@ -230,13 +230,70 @@ Mozilla
这台机算机除了 CPU 之外,还有一些外部设备,比如 RAM、I/O 等等。
+=head1 宏观的设计与开发决策
+
+我在项目开始之初就考虑了一下模型机的设计与测试的总策略。
+
+=over
+
+=item *
+
+仿真与可综合性
+
+我想如果在一开始就考虑哪些东东是 Synthesizable,哪些不可以,那么我将
+寸步难行。所以我决定
+只要我的设计能单纯地进行仿真就可以了。日后有机会再把不能综合(synthesis)
+的代码改成可以综合的。事实上我现在也搞不清到底哪些是可以综合的,因为这是
+由 Vendors (供应商)自己决定的。
+
+=item *
+
+硬件描述语言 (HDL) 的选择
+
+另外,我决定不使用 VHDL 语言,它实在
+是太难看了。经过比较,我发现 Verilog HDL 是更好的选择,它不仅记法很干
+净,而且没有 VHDL 中类型转换方面的困挠,更重要的是它也是 IEEE 标准的一
+部分,呵呵。
+
+我在网上找到一个名为 X-HDL 的工具,它可以在两种 HDL 语言之
+间进行自动转换——嗯,非常有趣的东东哦。不过还是有些限制的。如果我使用
+Verilog 语言的高级特性,在翻译到对应的 VHDL 语言时可能没有对应的等价物。
+因此我被限制在一个子集之中。不过如果我能自己提供 Verilog 在 VHDL 中的
+“等价物”(比如 ShiftRight函数)的库实现的话,可以使我能使用的子集接近
+全集。但后来我还是放弃了同时维护 Verilog 和 VHDL 两种语言的实现版本的
+想法。
+
+=back
+
=head1 RAM 的开发
-32位的 RAM 已经设计完成,使用 Verilog HDL,而且用基于 Perl Template
-Toolkit 的自动化测试框架对其进行了比较彻底的测试。
+设计 RAM 时遇到的一个简单的问题是,如果地址是 32 位,而且是 byte-addressable,
+那么 RAM 是否应该自己推导到“字”(word)的地址(即忽略掉32位地址的最后两个bit)?
+唔,还是由处理器负责将字节地址转换为字地址?不过那样的话,地址总线上的地址就不再
+是 32 位长,而是 30 位长了。
+
+在设计计算机系统的时候我必须把这个问题考虑清楚,特别是将“字”切片为“字节”的问题。再
+有就是“字”的地址与“字节”的地址之间的相互转换。
+
+目前的 RAM 内部按字存放,同时地址的长度也是一个字。因对 RAM 的直接读写都是按
+字进行的,即便传递给 RAM 的地址都是字节地址。RAM 在内部忽略地址的最后 2 个比
+特(对于 32 位 RAM 而言),自己推导出字节所在的字的地址。
+
+RAM 的 Verilog 实现是通过 Perl Template Toolkit 的模块自动生成的,因此它的
+位数是可以配置的。
+
+RAM 使用基于 Perl Template
+Toolkit 的自动化测试框架对其进行了比较彻底的测试。应用测试台已对 8 位 RAM,16
+位 RAM,32 位 RAM 和 64 位 RAM 进行了测试。
=head1 ALU 的开发
+在设计 ALU 的时候,遇到一个问题是 PSW (Process Status Word) 是作为一个单
+独的模块来实现呢,还是作为其他模块,比如 ALU 的一部分。众所周知,PSW 与 ALU 有
+关联,ALU 每计算出一个结果都应当设置 PSW 中的相应的位(bit)。但是 Intel 文档
+对每一条 x86 指令对 PSW 的影响都作了具体的说明,因此更合适的做法是将 PSW 作为
+一个独立的模块,由 ALU 和指令执行单元 IEU 来对 PSW 进行读写。
+
我们的 ALU 支持以下操作:
ADD ADC SUB SBB MUL IMUL DIV IDIV
@@ -255,13 +312,206 @@ ALU
我们的指令译码器支持 419 条 x86 常用指令。指令执行单元就不可能支持
那么多机器指令了,除非我能得到更多人的帮助。
+=head2 从模板生成硬件设计
+
+ALU 的 Verilog 源代码是从模板自动生成的。Salent 项目中使用的模板都
+是 Perl Template Toolkit 的模块(又称为 TT2 模板)。
+
+下面是一个例子(来自 ALU Verilog 实现的模板文件):
+
+=begin html
+
+<pre>
+ <img src="image/tt.png">
+</pre>
+
+=end html
+
+=head1 RAM 和 ALU 硬件设计的自动化测试
+
+我为 Salent 的 RAM 和 ALU 设计出了一个通用的自动化B<硬件>测试框架,从测试输
+入的生成,到测试结果的验证,全部自动化,无需人的干预。
+
+我们酷酷的基于 ModelSim 的测试台的构建技术可是真正意义上的自动化测试:随机产生合
+法的输入信号,然后自动检查仿真器的输出……
+
+我们已经用该框架对 Salent
+模型机的 RAM 和 ALU 部件进行了彻底的测试。测试找出了许多很微妙的 bug,有的是我
+的 Verilog 实现的,有的是我的测试代码本身的问题,还有的是 ModelSim 仿真器的
+BUG. 无论如何,由于输入信号是测试台随机生成的,只要运行足够长的时间,便可以发现
+几乎所有的 bug. 只要捕捉到 bug,纠正一般都是很直截了当的。
+
+我现在对我们的 RAM
+和 ALU 已建立起了足够的信心。诚然!测试台迫使项目总是在正确的可以控制的轨道上前进。
+我们每作一处改动,就运行整个测试集,确保所作的修改没有碰坏其他原本可以工作的东西。
+同时这也可以通过测试台生成的报表,评价所作修改的实际效果。
+
+不过,测试台运行时间比
+较长,大约是十几秒到几十秒不等。比如 ALU 的测试集,运行一次,将进行 6887 个测试。
+我注意到 ModelSim SE 6.0 的仿真器在性能上远不及 5.7d 这个较老的版本。真奇怪。
+在我这台装有 ModelSim 6.0 的 Pentium4 2.6GHz 的机器上运行 ALU 的测试集还不
+及我家那台装有 5.7d 的 赛扬 330 的破机器。我估计原因可能是 6.0 做得太庞大了。
+
+每次运行,测试台实际执行的测试都不一样,因为输入都是随机生成的,而且种子是使用的系
+统时间。我们用模板生成任何东西,从 Verilog 代码到 Perl 程序,从 Tcl 仿真脚本到
+POD 和 HTML 文档,还有写程序的程序……
+
+ I'd rather write programs to write programs to write programs.
+
+下面是 ALU 测试台的一次典型运行所生成的测试报表:
+
+ alu.........ok
+ talu1.op....ok
+ talu2.op....ok
+ talu3.op....ok
+ talu4.op....ok
+ talu5.op....ok
+ All tests successful.
+ Files=6, Tests=6887, 12 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
+ Timing Result: 525.359000 sec on average.
+
+一共花了 525 秒耶!
+
+在测试中,如果发生错误,测试台会报告发生错误的具体位置,比如文件名、行号、仿真时
+间区间、ALU 输入信号的取值、等等。这些信息给排错带来了极大的便利。
+
+下面是 RAM 的一个早期版本因 64 位问题而让我们的测试台“报怨”的例子:
+
+ ...
+
+ tramX_5.rw..........ok
+ tramX_6.rw..........ok
+ tramX_7.rw..........ok
+ tramX_8.rw..........NOK 8
+ # Failed test 'tramX_8.rw: line 7: r 'd0 0*abcd (@ 55 ~ 103)'
+ # in tramX_8.rw.t at line 26.
+ # '00000000zzzzzzzz'
+ # doesn't match '(?i-xsm:^z+$)'
+
+ tramX_8.rw..........NOK 12# Failed test
+ 'tramX_8.rw: line 8: r 'd15 ? (@ 103 ~ 141)'
+ # in tramX_8.rw.t at line 31.
+ # '00000000zzzzzzzz'
+ # doesn't match '(?i-xsm:^z+$)'
+
+ ...
+
+ Failed Test Stat Wstat Total Fail Failed List of Failed
+ -------------------------------------------------------------------------------
+ ...
+ tramX_4.rw.t 17 4352 54 17 31.48% 8 12-13 17-18 25-26 30-31 35-
+ 36 43-44 48-49 53-54
+ tramX_8.rw.t 49 12544 140 49 35.00% 8 12-13 17-18 22-23 27-28 35-
+ 36 40-41 45-46 50-51 55-56
+ 63-64 68-69 73-74 78-79 83-84
+ 91-92 96-97 101-102 106-107
+ 111-112 119-120 124-125 129-
+ 130 134-135 139-140
+ Failed 4/18 test scripts, 77.78% okay. 238/3627 subtests failed, 93.44% okay.
+
+仲伟祥同学在我的框架基础上编写的RAM 的“随机应力测试台”捕捉到了 ModelSim 仿真器的一个 bug.
+太棒了!这种高强度的随机测试对包
+括仿真器在内的每一个部件,每一行代码都施加了巨大的压力,不是么? Well done! Sal++
+
=head1 MMU 的开发
+MMU 是 Memory Management Unit 的首字母缩写,目前的主要功能是将“字”切片为“字节”。
+毕竟我们的 RAM 是按“字”来存取的,而处理器却时常按照“字节”来读写。MMU 的作用就是协调
+这种差异。它在处理器和 RAM 之间扮演着“中间人”的角色。
+
+我在 MMU 的 specification 中这样写道:
+
+The MMU in Salent is reponsible for slicing "words" to "bytes". It bridges
+the gap between the processor and RAM. The RAM operates in words, but the
+processor usually wants to access one single byte, two successive bytes,
+or a whole word.
+
+MMU will play such a role that from the viewpoint of the processor,
+the memory is byte-addressable, and it is only word-addressable from the
+viewpoint of RAM.
+
+The I/O ports for the MMU can be divided into two separate sub-interface,
+one for the processor, and one for RAM:
+
+ RAM <=> MMU <=> Processor
+
+The sub-interface of MMU for RAM is exactly the same as the interface of RAM.
+MMU should take the full reponsibility to interact with RAM, including setting
+data bus, address bus, rw and strb control signals.
+
+=over
+
+=item *
+
+bus_strb - out
+
+Strobe signal issued by MMU itself to start the RAM.
+
+=item *
+
+bus_rw - out
+
+Read or write signal issued by MMU
+
+=item *
+
+bus_data - inout
+
+=item *
+
+bus_addr - out
+
+=item *
+
+bus_mfc - in
+
+=back
+
+The sub-interface of MMU for processor is very simple, consisting of only four signals:
+
+=over
+
+=item *
+
+mar - in, reg
+
+Memory Address Register storing the address of the leading byte
+
+=item *
+
+byte - inout, reg
+
+Memory Data Register storing the byte accessed or written by processor
+
+=item *
+
+strb - in
+
+Strobe signal issued by procssor to start the MMU.
+
+=item *
+
+rw - in
+
+Read/Write'
+
+=item *
+
+mfc - out
+
+=back
+
=head1 IDU 的开发
IA-32 指令集还有一种 64 位的扩展模式,名为 IA-32e,对 64 位指令的支持并
不在我的 TODO 列表中。
+我们的 IDU 设计以及建立在它之上的 x86 反汇编器是由
+代码生成器自动生成的,而且其支持的指令集可以动态地进行配置。我们在一个配置
+文件中添加一条机器指令的编码模式及对应的汇编语言格式,运行Make 之后,反汇
+编器将自动对新增指令提供支持。这个配置文件的格式就是 Intel IA-32 手册的
+指令码表的格式。在 Salent 项目目录中,名为 F<encoding.txt>.
+
=head2 遇到的困难
x86 指令集的机器码格式在开发初期曾让我感到非常头痛,因为指令长度居然是变长的,
@@ -311,7 +561,9 @@ Appendix B.
这是典型的“写程序的程序”。由于状态机模型是与输出的实现语言无关的,因此
提供 Perl 代码的模板就产生 Perl 版本的译码器程序,提供 Verilog 代码
的模型就产生 Verilog 版本的译码器描述,C/C++ 还有 Java 还有 VHDL 都
-依此类推。
+依此类推。我有计划再在 Salent IDU 项目中引入 Java, C#, JavaScript,
+Visual Basi, 甚至于 Haskell 和 Perl6 这些语言。如此之多的语言和文化
+在 Salent 项目中交汇成一股伟大的洪流,势不可当!
这意味着一旦我们得到了一种语言下的译码器实现,就可以轻而易举地获得其他
语言的实现。要做的只是提供这种语言下的模板文件就可以了。而模板文件都是
@@ -327,14 +579,15 @@ Appendix B.
Java 实现的模板:
"Well, it's quite straightforward. The two versions of IDU implementations
-(the Perl one and Java one) will share the same AST, I mean Abstract Semantic
-Tree. The best way to comprehend ASTs is simply reguard it as a complex data
-structure. Hmm...maybe something like a tree, an array, a hash, or so so...
+(the Perl one and Java one) will share the same AST, I mean Abstract Syntax
+Tree. The best way to comprehend ASTs is to simply reguard it as a complex
+data structure. Hmm...maybe something like a tree, an array, a hash, or so.
To generate the final implementation, an AST is not enough. The info stored in
the AST is only concerned with the state machine (or the state graph), hence
There is nothing specific to the programming language we finally choose.
-"In order to generate the IDU programs automatically, we provide a full-fledged
+"In order to generate the IDU programs automatically, we provide a
+full-fledged
AST and a well defined program template to the computer. The computer will
combine the two to generate the final implementation, say, the final program.
The key is combining an AST with a program template. So it's another example of
@@ -346,6 +599,14 @@ program's source code. The Perl template we've already obtained, the Java
template you'll write, and even more templates in the future will have a similar
appearance. They'll be pretty alike. "
+当我对我们班的一个同学说,Intel 手册的指令码表中有很多 typo (键入错误)的时候,他反驳
+我说,这是“难免”的。我反驳道,我们 Salent 项目中的码表文件却可以完全避免 typo。
+他很怀疑我的说法,问我为什么?我告诉他,我们的文档,IDU 实现,以及我们
+的 IDU 测试台都是根据一棵 AST 由程序自动生成的呀!而这棵 AST (Abstract
+Syntax Tree) 又是从 Intel 的文档自动转换过来的。因此 Intel 文档中的所有
+typo 都会反映到我们的 idu 实现和 idu 测试台的代码中,并最终被测试台捕捉到。
+由此可见,我们使用的真的是一种神奇的技术!
+
=head3 关于状态机
记得“数字逻辑电路”课程中接触到的“状态机”么?就是那种东西。我们在当时用
@@ -354,8 +615,45 @@ appearance. They'll be pretty alike. "
类似的识别模式的程序和硬件设计而言简直是无价之宝!非常优美,非常抽象,非
常简洁。更重要的是:非常实用。
-熟练掌握状态机模型却仍需要大量的实践和思考。我们在写处理输入的 Perl 程序
-时很难不去用它。只不过大多数时候我们用到了,却并不知觉。
+状态机是这样一种抽象的机器,这个机器能够维护并且切换当前的状态。它根据
+外部的输入和内部产生的输出来得到状态切换的条件。状态机是设计软件和设计硬件的基
+本工具。与其说它是一台“机器”,不如说它是一种数学模型。其实状态机的核心思想非常
+简单,我想打一个比方来加以说明。
+
+比如我想“识别”出两个单词 add 和 and,现在我们可以用状态机来完成“识别”的任务。
+令状态 0 为初始状态。
+首先,我们读取未知单词的第一个字母,比如说是 a,我们便切换到状态1,否则跳转到出
+错状态,因为两个词都是由 a 起始的。接着,我们读
+取第二个字母,这时就要分三种情况进行讨论,如果得到的是 d,就跳转到状态 2;如果
+是 n ,则跳转到状态 3;否则就跳到出错状态。然后,我们读取第三个字母,如果当前
+状态是 2,而且当前的字符是 d,则完成对 add 的识别。如果当前状态是 3,而当前的
+字符是 d ,则完成对 and 的识别。其余情况,跳转到出错状态,即匹配失败。上面这个
+例子可以用来识别英语单词。
+
+下面是这个例子中的状态机的示意图:
+
+=begin html
+
+<pre>
+ <img src="image/ex_state_mac.png" alt="Sample State Machine">
+</pre>
+
+=end html
+
+图中的每一个节点(圆圈)都代表一个独立的“状态”,节点之间的箭头表示状态之间的转
+换条件。
+
+我的一位高中同学由此想到了“文曲星”的工作原理。呵呵,
+我也觉得有点儿类似哦——嗯,真的很相似。
+
+事实上,状态机是无处不在的。状态机在编写识别性质的程序和电路的时候,简直是无价之
+宝。比如识别机器语言的集成电路,识别各种高级编程语言的编译器和解释器,还有很多一
+般性的程序,状态机无处不在!有时候我们即时自己使用了,可能还未发觉。这并不是我在
+开发 Salent 项目的过程中刚刚学到的知识,事实上,我已经使用了多年了。从高三开始
+我就有意识地在自己编写的代码中大量地使用。状态机是编程领域比较有趣的东东。我从高
+一开始自学编程,在高二时学习了计算机专业的《编译原理》课程,在那儿我首次接触了状
+态机理论。不久我就发现它是如此地强大,并最终在 Salent 的 IDU 中将这种威力发挥
+到了近乎神奇的地步。
IDU 的状态机规模非常庞大,共有 590 个状态。我不认为用手工的方式能够在可
以接受的时间之内圆满地完成它。下面是用 Graphviz 自动根据 IDU 状态机的
@@ -380,14 +678,7 @@ XML
=end html
-=head3 关于模板
-
-Salent 项目中使用的模板都是 Perl Template Toolkit 的模块(又称为 TT2
-模板)。
-
-XXX Add something more about TT2 template.
-
-=head3 生成 Perl IDU
+=head3 Perl IDU
Perl IDU 是我得到的第一版本的 IDU 实现。它的开发过程完全是测试驱动的
(test-driven)。在不断地提高 Perl IDU 的测试通过率的过程之中,我也不断
@@ -395,7 +686,38 @@ Perl IDU
目的之一。如果我首先编写 Verilog HDL 的模板,则测试与排错的难度都会大大
提高。
-=head3 生成 C IDU
+=head4 Perl IDU 的自动化测试
+
+为了对我们的指令译码器进行应用测试,我自然需要根据机器指令的码表,编写一个能
+随机生成合法的 IA-32 机器码的Perl 程序。码表仍然来自 Intel 手册 2B 卷的
+Appendix B, 因此严格覆盖了整个"非64位通用目的指令集”和整个“x87 FPU 浮点
+指令集”。事实上,每次运行生成器,每一种指令模式都会生成至少一条机器指令,而
+每一种寻址方式、每一个可能操作数组合,都有B<可能>生成。这对于测试我们的反汇编
+器而言,简直是无价之宝,因为一般的 EXE 文件代码段中的指令在整个 x86 指令集中
+的覆盖率只有 30 ~ 50%,而且重复率高,用于应力测试,效果很不理想。但使用一些
+典型的 EXE 文件的代码段中的机器指令序列来测试我们的 IDU 仍是测试台的一个
+重要的组成部分。
+
+我已用一些第三方的反汇编器对我的 Perl 脚本生成的 x86 机器指令进行了测试。
+
+一开始,我们只是测试 IDU 译码得到的指令名和指令长度,因为这比较简单(当然了,
+Intel 指令集中众多的“别名”和前缀码 (prefix byte) 是比较难处理的部分)。
+指令名测试虽然简单,但却非常有效,能状态机和 IDU 模板的大部分问题。
+
+然而,指令名测试毕竟是不全面的,我们无法对一些寻址方式和取数结果进行检验。因
+此,我们又在 IDU 的基础上实现了一个汇编代码的输出后端。只有让 IDU 将译码的
+结果输出为 NASM 汇编代码的形式,我们才能直接将之与 NASM 的反汇编器输出进行
+精确比较。事实上,一个生成汇编代码的后端加上 IDU 指令译码器本身,便构成了一个
+x86 反汇编器。其实,支持如此之大的指令集的 x86 反汇编器本身就已经是一个极端复
+杂的项目了。我们不得不为自己的工作而感到骄傲。
+
+由于有了如此完美的指令应力测试台,我们的反汇编器的正确性与稳定性毫不亚于 NASM
+自带的反汇编器。事实上,我们的测试台居然捕捉到了 NASM 的 FPU 指令集处理部分的
+一个微妙的 bug. 自动化测试万岁!应力测试万岁!
+
+=head4 更多关
+
+=head3 C IDU
在 Perl IDU 通过全部的测试集之后,我们又得到了 C 语言的指令译码器实现。
C 版本的测试过程相对于 Perl 版本而言就比较麻烦,比较繁琐了。
@@ -409,7 +731,9 @@ read".
当然,必须指出的是,因为有了经过彻底测试的 Perl 版本的实现在手,C 版本的 IDU
的开发已经变得容易许多了。
-一开始,我的 C IDU 和我原来的 Perl IDU 共享了绝大部分的测试集,但不是全部。嗯,
+=head4 C IDU 的自动化测试
+
+最初,我的 C IDU 和我原来的 Perl IDU 共享了绝大部分的测试集,但不是全部。嗯,
就是机器指令随机生成器驱动的 NASM 应力测试集 (pat_cover).
后来,在吴元斌的鼓励下,我又更进一步,让两种语言版本的 IDU 共享全部 100% 的测试集。
事后我分析了一下,无论从理论还是从技术上这都不成问题,只要我的 C IDU 提供和原来的
@@ -424,30 +748,6 @@ Perl IDU ȫ
=head3 生成 Verilog IDU
-=head2 自动测试 IDU
-
-为了对我们的指令译码器进行应用测试,我自然需要根据机器指令的码表,编写一个能
-随机生成合法的 IA-32 机器码的Perl 程序。码表仍然来自 Intel 手册 2B 卷的
-Appendix B, 因此严格覆盖了整个"非64位通用目的指令集”和整个“x87 FPU 浮点
-指令集”。事实上,每次运行生成器,每一种指令模式都会生成至少一条机器指令,而
-每一种寻址方式、每一个可能操作数组合,都有B<可能>生成。我已用一些第三方的反汇
-编器对我的 Perl 脚本生成的 x86 机器指令进行了测试。
-
-一开始,我们只是测试 IDU 译码得到的指令名和指令长度,因为这比较简单(当然了,
-Intel 指令集中众多的“别名”和前缀码 (preffix byte) 是比较难处理的部分)。
-指令名测试虽然简单,但却非常有效,能状态机和 IDU 模板的大部分问题。
-
-然而,指令名测试毕竟是不全面的,我们无法对一些寻址方式和取数结果进行检验。因
-此,我们又在 IDU 的基础上实现了一个汇编代码的输出后端。只有让 IDU 将译码的
-结果输出为 NASM 汇编代码的形式,我们才能直接将之与 NASM 的反汇编器输出进行
-精确比较。事实上,一个生成汇编代码的后端加上 IDU 指令译码器本身,便构成了一个
-x86 反汇编器。其实,支持如此之大的指令集的 x86 反汇编器本身就已经是一个极端复
-杂的项目了。我们不得不为自己的工作而感到骄傲。
-
-由于有了如此完美的指令应力测试台,我们的反汇编器的正确性与稳定性毫不亚于 NASM
-自带的反汇编器。事实上,我们的测试台居然捕捉到了 NASM 的 FPU 指令集处理部分的
-一个微妙的 bug. 自动化测试万岁!应力测试万岁!
-
=head3 SMOKE 技术
我们的 IDU 项目测试台能够生成完美的 HTML 测试报表。该项技术称之为 SMOKE.
@@ -513,7 +813,7 @@ TODO
=head1 IEU 的开发
-XXX
+尚未开始。
=head1 Extension of Salent
@@ -577,6 +877,10 @@ SVM
=item *
+"Verilog 高级数学电路设计"
+
+=item *
+
IA-32 Intel Architecture Software Developer's Manuals
L<http://www.intel.com/design/pentium4/manuals/index_new.htm>
View
80 ram/ram.v.tt.bak
@@ -1,80 +0,0 @@
-[% DEFAULT
- version = '0.13'
- word_size = 32
- addr_size = 32
- ram = {
- capacity = 64 * 1024 # in words, not in bytes
- delay = 10
- }
--%]
-[% USE Perl;
- USE date;
- SET
- last_mod = date.format(template.modtime, '20%y-%m-%d', 'en_GB')
- year = date.format(template.modtime, '20%y', 'en_GB')
-
- bytes_per_word = word_size / 8
- temp = Perl.log(bytes_per_word) / Perl.log(2)
- byte_addr_size = Perl.sprintf("%.0f", temp) # rounding
--%]
-//: ram.v
-//: Random Access Memory (RAM)
-//: Salent v[% version %]
-//: Copyright (c) [% year %] Agent Zhang. All rights reserved.
-//: 2005-06-22 [% last_mod %]
-
-module ram (mfc, strb, rw, addr, data);
- parameter ADDR_SIZE = [% addr_size %],
- WORD_SIZE = [% word_size %],
- MEM_SIZE = [% ram.capacity %],
- DELAY = [% ram.delay %];
-
- output mfc; // Memory Function Completed (MFC)
- input strb, rw; // strobe and r/w' control bus
- input [ADDR_SIZE-1:0] addr; // address bus
- inout [WORD_SIZE-1:0] data; // data bus
-
- reg mfc;
- reg [WORD_SIZE-1:0] l_data; // Latched output data
- reg l_rw; // Latched bus rw value
- reg [ADDR_SIZE-[% byte_addr_size + 1 %]:0] word_addr; // Latched bus word address value
- reg [WORD_SIZE-1:0] mem[0:MEM_SIZE-1]; // The contents of the RAM
-
- assign data = l_data;
-
- always @ (posedge strb) begin : ram
-
- forever begin
- ;
-
- // Latch address and rw at address strobe
- word_addr = addr[ADDR_SIZE-1:[% byte_addr_size %]];
- l_rw = rw;
-
- if (word_addr < MEM_SIZE) begin
- if (l_rw) // read
- #(DELAY) l_data = mem[word_addr];
- else // write
- #(DELAY) mem[word_addr] = data;
-
- mfc = 1'b1;
- @ (negedge strb);
- mfc = 1'b0;
- [%- IF word_size > 32 # adapt to vlog-1995 %]
- if (l_rw) l_data = [% word_size %]'bz;
- [%- ELSE %]
- if (l_rw) l_data = 'bz;
- [%- END %]
- end
- end
- end
-
- initial begin
- mfc = 1'b0;
- [%- IF word_size > 32 # adapt to vlog-1995 %]
- l_data = [% word_size %]'bz;
- [%- ELSE %]
- l_data = 'bz;
- [%- END %]
- end
-endmodule
Please sign in to comment.
Something went wrong with that request. Please try again.