赛灵思 Spartan-3开发板成为作者改进其软件教育用的Oberon 编程语言和编译器的基础。
1988 年,Jürg Gutknecht 和我一起完成并出版了Oberon 编程语言[1,2],其为我职业生涯早期开发的另外两种编程语言Pascal 和Modula-2 的后续版本。与Modula-2 相比,我们最初设计Oberon 编程语言力求更加精简和高效,以便能够更好地帮助教学人员为计算机科学专业的学生教授系统编程。我们再接再励,于1990 年针对可采用windows 系统和具有字处理能力的工作站开发了Oberon 操作系统(OS),以此作为工作站的现代实现方式。接着,我们出版了一本书,名为《Project Oberon》,详细讲解了Oberon 编译器以及与之同名的操作系统。此外,书中还包括详细的指令和源代码。
几年前,我的朋友Paul Reed 建议我重新修订并再次出版这本书,不仅因为这本书对系统设计教学具有重要价值,同时还因为这本书可以作为良好的切入点,帮助那些想要成为创新者的人们从零基础构建可靠的系统。
然而,我当时实际上是遇到了很大的困难。我最初开发的编译器是将已基本消失了的处理器作为目标。因此,我的解决办法就是为现代处理器重新编写编译器。但在做了不少研究之后,我无法找到一款能够在清晰度、规律性和简洁性上符合我标准的处理器。因此,我自己设计了这款编译器。而我之所以能够将该想法付诸实现,都是因为现代FPGA 能够帮助我设计硬件以及系统软件。更重要的是,选择赛灵思FPGA 能帮助我更新系统,同时让设计尽可能接近自1990 年以来的原始版本。
实现在低成本Digilent Spartan®-3开发板上的新型处理器RISC 负责托管1MB 静态RAM (SRAM) 内存。我唯一添加的系统硬件就是一个鼠标接口和一个用来替换旧系统中硬盘驱动器的SD 卡。
这本书和面向整个系统的源代码可在projectoberon.com[3,4,5] 中查阅,也可在该网站上名为 S3RISCinstall.zip. 的单个文件中进行查阅。该文件包含指令、SD 卡文件系统图像和FPGA 配置比特文件(对于Spartan-3开发板的 Platform Flash,此为PROM文件形式),以及SD 卡/ 鼠标接口硬件的构造详图。
RISC处理器
该处理器由算术逻辑单元、由16 个32 位寄存器组成的阵列和带指令寄存器、IR 及程序计数器PC 的控制单元组成。Verilog 模块RISC5 就是该处理器的典型代表。
该处理器具有20 种指令:4 种用于移动、偏移和旋转;4 种用于逻辑运算;4 种用于整数运算;4 种用于浮点运算;2 种用于存储器访问;2 种用于分支。
RISC5 通过运行环境RISC5Top导入。该运行环境包括到各种(内存映射)器件和SRAM(256M×32 位)的接口。整个系统(图1)包括以下Verilog 模块(见行统计):
图1 – 该系统及其所含Verilog模块的方框图
我将内存映射到黑白VGA 显示器中,这样它只占用1024×768×1位/ 像素=98304 字节,基本上占 1MB 可用主内存的10%。该SD 卡将取代初始系统中80MB 的硬盘驱动器,其可通过能够接受并序列化字节或32 位字的标准SPI 接口进行存取。键盘和鼠标通过标准PS-2 串行接口连接。此外,还提供一根串行异步的RS-232 线和一个通用8 位并行的I/O接口。模块RISC5Top 还带有一个每毫秒采用增量式计数的计数器。
OBERON操作系统
该操作系统软件由包括内存分配器(带垃圾回收器)的内核、文件系统以及引导载入程序、文本系统、浏览器系统和文本编辑器组成。
名为“Oberon”的模块是中心任务调度程序,而“System”是基础命令模块。通过点击显示器上任何浏览器文本“M.P”上的中间按钮即可触发动作,其中P 是模块M 声明的程序名。如果M 不存在,则会自动加载。但是,大多数文本编辑命令是通过简单的鼠标点击触发的。其中,左边一栏按钮用来设置" 脱字" 符,标记文本位置,右边一栏按钮用来选择文本字段(text stretch)。
“Kernel”模块包括磁盘存储管理和垃圾回收器。我保证观察浏览器是平铺的,不重叠。标准布局显示了多个浏览器的两条垂直轨迹。只需拖动标题栏,就可以放大、缩小或移动它们。图2 显示了在显示器上运行的用户界面以及Spartan-3 开发板、键盘及鼠标。
图2 - 显示用户界面的显示器(Spartan-3开发板在右侧)
加载时系统占用模块空间112640字节(21%),占堆(heap) 的16128字节(3%)。系统包括所以下几个模块(见行统计),如图3 所示:
图3 - 系统及其模块
值得注意的是,该系统在加电或重置时,完成初始化仅需两秒钟。这包括文件目录中垃圾回收扫描。
OBERON编译器
系统自带的编译器采用简单的自上而下递归下降分析法。用户使用ORP.Compile @ 命令即可激活模块选定的源文本上的编译器。 包解析器通过扫描仪输入各种符号,包括识别符、数字和特殊符号(如BEGIN、END、+等)。该方案已被证明在许多应用中有效且均表现不凡。这点在我著的书《编译器结构》[6,7] 中有详细说明。
该包解析器调用代码生成程序模块中的程序。这些程序直接将指令添加在代码阵列上。如果已知所有分支目的地,向前跳转指令(forwardbranch instructions)在模块编译结束时则会提供跳转地址(修正)。
所有可变地址都与基址寄存器关联。这就是用于局部变量(运行时设置在程序输入)的R14(堆栈指示器)或用于全局和输入变量的R13。
基址地址按要求通过地址保存在寄存器R12 内的系统全局模块表载入。R15 用于RISC 架构确定的返回地址(链接)。因此,R0-R11 可用于表达式评估和传递过程参数。
整个编译器由4 个相对较小的有效模块组成(见行统计):
编译器占用115912 字节(22%)的模块空间和17508 字节(4%)的堆空间(编译之前)。其源代码长约65KB。编译器自身的编译在25 MHzRISC 处理器上只需几秒钟[8]。
编译器通常使用值为NIL 的指示检查数组索引和基准值。如果违反规定,这会造成陷阱。这种技术具有高度的安全性,防止错误和崩溃。事实上,只能通过采用伪模块SYSTEM 中的操作,即PUT 和COPY,才能防碍系统的完整性。这些操作必须局限于接入器件接口的驱动模块。在输入列表中,通过SYSTEM 很容易识别它们。整个系统采用Oberon 编程,无需使用汇编码。
我选择Digilent Spartan-3 开发板是由于其成本低、操作简便,这使其适于教育机构,以获得整套课堂教学套件。一个重大优势就是该开发板上有静态RAM,使得接口连接非常简单直观(甚至用于字节选择)。遗憾的是,所有新开发板均采用动态RAM,虽然存储空间更大,但接口连接复杂得多,因此刷新和初始化(校准)需要电路。这一电路与带静态RAM 的整个处理器一样复杂。即使控制器以单片式提供,这有悖于我们的开放检查原则。
最后的想法
40 多年前,C.A.R. Hoare 说,在科学技术的所有分支学科中,学生在被要求用实验尝试自己的想法之前,容易受到许多示范性设计实例的影响。编程和软件设计与这种明智模式形成了鲜明对比。这里,在阅读任何实例之前,要求学生从一开始就编写程序。
这种可怕事实的原因就是:几乎不存在大小合适的示范实例。因此,我决定稍微修正这种情形,我在1975年编写了《算法与数据结构》一书。随后(与J. Gut-knecht)负责操作系统教学任务,我设计了Oberon 系统(1986-88)。
此后,编程教学并没有明显提高,而系统的规模和复杂性显著增加。虽然开源的努力颇受欢迎,但它并没有真正改变这种形势,因为大多数程序已经建成“运行”,但却没有真正投入使用。
我继续大胆提议,应重新设计所有程序,不光是计算机,还有读取方式。这些程序应是可发行的。即便这种方法正确而有效,但这是一项比创建可执行程序更为艰难的任务。这意味着,没有任何部分必须用汇编码指定。
忽略在这种“人为因素”的结果就是,在许多地方,新的应用没有得到精心设计,而是通过消除程序中错误来实现,其结果有时是令人担忧的。要做到“易懂”的关键就是坚持简单性和规律性,放弃不必要的修饰,避免花里胡哨,正确区分传统与便捷。
该系统所占空间小,是小资源实现大作为的见证。虽然Oberon 系统包含一个文件系统、文本编辑器和浏览器(Windows)管理程序,但相比多数现代操作系统而言,其占用的空间少得可怜。意外的是它仅仅依靠一些简单规则,因此便于学习如何使用。
最后,这种简单的系统的另一大优势就是,用户可以在该基础系统上安全构建所需程序,而不必担心是否存在未知特征与功能,如后门程式(back door)。从系统完整性易受到攻击的角度看,这是一个基本属性,是关键安全型应用不可或缺的。值得注意的是,我们的系统硬件没有这种隐藏元件。毕竟,在如此之大而又没人能够完全了解的基础上构建的任何系统也不能予以保证。
致谢
我衷心感谢Paul Reed 所做的宝贵贡献。他建议我重新编撰《Oberon 项目》一书,还建议在FPGA 上重新实现整个系统。Paul 一直激励着我。他想到过用SD 卡替代磁盘,他为SPI、PS-2 和Verilog 中的VID 接口做出了卓越贡献。
评论
查看更多