Apple G4 搭配 Altivec 处理器初探
当我第一次读到 Apple 计划开发基于 G4 的个人电脑时,我甚至不知道 G4 是什么。超级计算机性能?以 GFlops 为单位处理?这怎么可能?G4,也称为摩托罗拉 7400,是带有 AltiVec 单元的处理器。AltiVec 是 PowerPC 处理器新系列中向量处理单元的商标名称。摩托罗拉还发布了 7410 和 7450,它们具有芯片上的 L2 缓存、大型背面 L3 缓存、更快的处理器核心和更深的七级流水线。
AltiVec 单元是一个增强的整数或浮点处理单元。它提供了一个新的 128 位处理单元、32 个向量寄存器和超过 160 条新指令,这些指令允许在流水线中处理数据。这些为在处理器中移动数据提供了巨大的机会。
在这样的描述之后,谁不想在家里拥有一个这样的东西呢?我不是 Macintosh 的狂热爱好者,也不太在意 Windows。当我读到 Cort Dugan、Paul Mackerras、Ben Herrenschmidt 和许多其他人将 Linux 移植到 PowerPC (PPC) 的工作时,我就被说服了。毕竟,这听起来像是一个尝试新事物和挑战、学习一点(或很多)以及从我的 distributed.net 客户端获得更快数字的机会(这是我上个千年开始使用 Linux 的一些原因)。
我的硬件是一台 Apple 双 G4/450MHz PowerPC,配备 512MB 内存。它配备了一个 30GB Quantum Fireball IDE 硬盘、一个 CD/DVD-ROM、两个 IEEE-1394 (火线接口)、100Mbps 以太网和比你想象的更多的 USB 集线器。键盘和鼠标都是 USB 设备。Apple 称之为新世界机器。虽然这听起来像是一个营销术语,但“新世界”用于描述 Apple 硬件,其中引导 ROM 存储在软件中(与引导管理软件存储在 PROM 中的“旧世界”机器相对)。
我选择安装的 Linux 发行版是 Yellow Dog Linux。我不知道是什么最终推动我朝这个方向发展,因为有不止一种选择——SuSE、LinuxPPC 和 Yellow Dog Linux 立即浮现在脑海。YDL 基于 Red Hat,所以它并不太陌生。
YDL 由 Terra Soft Solutions 提供。虽然 Terra Soft 提供了另一个发行版 Black Lab Linux,但 YDL 是普通用户的入门级解决方案。我从 Terra Soft 的一个镜像站点下载了 YDL Champion Server 1.2.1 的两个 ISO 镜像。第一个是安装 CD;第二个 CD 被称为“美味小点心” (Tasty Morsels)。它为 PPC 提供了救援镜像和一些额外的软件。我在我的 SuSE/i386 机器上使用 cdrecord 刻录了这些镜像,然后想知道我有什么。
在阅读了 YDL 安装指南后,我有一些想法。该指南建议我使用 yaboot,即“又一个引导加载程序”。yaboot 需要位于 HFS(原生 Mac)分区上,所以我需要使用 Mac 系统软件创建一个分区。
以下是我用于重新安装 Mac OS9 然后安装 Linux 的步骤
为 yaboot(和 OS9)创建一个 HFS 分区 (4GB)。
从发行 CD 重新安装 OS9。
从 CS 1.2.1 CD,将 yaboot、yaboot.conf 和 vmlinux.gz 复制到系统文件夹。
yaboot.conf 看起来和感觉很像 lilo.conf。每个镜像都有部分,其中有一个区域可以提供标签,以便当 yaboot 启动时,用户可以按 Tab 键查看内核配置的名称,然后在提示符下选择一个。熟悉的东西,但我必须修改 yaboot.conf,如下所示。
在这里,我应该稍微跑题谈一下 Open Firmware。Open Firmware,在 IEEE 1275 下定义,是一个为固件提供开放支持的规范。这是我对新 Apple 硬件探索的第一个有趣领域之一。直到我需要时,我才看到 Open Firmware。在启动 Mac 时,会发出 880Hz 的声音,指示您的系统刚刚通过硬件 POST 并正在准备启动操作系统。此时,可以通过按住 Command-Opt-O-F 键来停止启动过程。如果一切顺利,将显示以下欢迎语
Apple PowerMac 3,3 3.4f1 BootROM built on 08/08/00 at 22:02:19 Copyright 1994-2000 Apple Computer, Inc. Welcome to Open Firmware. To continue booting, type "mac-boot" and press return To shut down, type "shut-down" and press return ok 0 > _
0 > 是一个提示符。OF 本质上是一个 Forth 解释器。Forth 是一种基于堆栈的语言。为了对此有所了解,请在提示符下键入以下内容
0 > 3 [RETURN] 1 > 4 [RETURN] 2 > + [RETURN] 1 > . [RETURN]您将得到以下结果
0 > 7第一个命令将“3”压入堆栈。提示符在“>”之前显示堆栈上的项目数。然后我将“4”放在堆栈上,并告诉解释器添加结果。现在堆栈上只有一个项目。“.”运算符从堆栈中弹出第一个值并显示它。
您可以从这里看到很多关于您的硬件的信息。例如,要查看您机器的默认启动配置,请在提示符下键入以下内容
0 > printenv
列表 1 显示了内置的环境变量及其默认值。
列表 1. 来自 G4 的 Open Firmware 的环境变量及其默认值
可以从命令 devalias 中获得关于您的 PPC 的另一个有用的信息。在提示符下输入此命令并按回车键。注意 hd 的值。那是您的第一个 IDE 硬盘的硬件地址。hd 是通过 printenv 显示的整个地址的别名。
如果您像我一样,您可能会对更改这些值感到偏执。在 http://developer.apple.com/ 上进行了一些研究后,我遇到了一些有趣的技术说明。特别是 Technotes 2000-2004。拥有一个功能齐全的解释器和操作系统的强大功能的一些好处是能够提供查看、运行文件和显示硬件信息以进行调试。其中很多信息太详细而无法写下来,因此有了“双机”模式 (TN 2004) 的概念。在这种模式下,您可以在串行端口上显示 OF 输出。G4 PPC 没有串行端口,但在 Apple 的 OF 中有一个 Telnet 守护程序 (dæmon)。我不太确定您不能使用 USB 设备作为输出,毕竟“串行”在首字母缩略词中,但我确实知道 Telnet 守护程序有效。此外,我不知道 minicom 是否可以与 USB 端口一起使用。
守护程序很容易配置。首先,从 OF 提示符输入以下命令
0 > " enet:telnet, 192.168.2.20" io
注意空格,按回车键,现在 OF 创建了一个 Telnet 守护程序,等待 Telnet 客户端。此命令已将以太网接口配置为 IP 地址 192.168.2.20。您可能需要根据您自己的网络配置选择不同的 IP 地址。您将需要在与您的 PPC 相同的物理网段上的另一台机器。如果您没有网段,交叉以太网电缆即可。
从您的客户端机器,Telnet 到您的目标 (PPC) 机器。您应该看到与 Mac 显示的相同的“0 >”提示符。现在您有能力将 printenv、devalias 等的所有输出捕获到文件中。如果您把事情搞砸得太糟糕以至于您必须返回到默认配置,这将有所帮助。
好的,让我们安装 Linux。将 YDL CD 插入您的 DVD ROM,并在启动时按住 C 键。这是从 CD 启动的方法。您将看到 YDL 的安装屏幕。您可以在很大程度上遵循 YDL 安装指南,但关于分区,需要提醒您:除非您之前在 Mac 上安装过 Linux,否则您需要创建一些分区。您不再创建 ext2 分区,现在您将创建 Apple_UNIX_SVR2 类型的分区。此外,您将使用 pdisk 而不是 fdisk 来创建您的分区。使用 p 命令来显示分区。如果您遵循了我上面的建议,您应该看到九个分区。这些是默认创建的,如果您打算保留某种形式的运行系统(推荐),请不要管它们。
现在您需要为您的正常分区方案创建分区,我选择为挂载点 /、/usr、/opt、/home 和交换分区创建分区。您的可能有所不同,但我创建的方案如表 1 所示。
表 1. /dev/hda 上的分区图(带有 512 字节块)
在使用 w 命令将分区写入表后,并退出 pdisk(q 命令),重新启动系统。pdisk 在重新启动之前不会识别新的分区。通过按住 C 键重新开始安装;指示您新创建的挂载点,您可以开始选择软件包,就像在正常的 Red Hat Linux 安装中一样。在您完成这些步骤后,您将不得不再次重新启动。这次,不要按住任何键,因为您想要启动 Mac OS。
现在,回到 Mac OS。打开您复制到系统文件夹的 yaboot.conf 并查看一下。我的看起来像列表 2。
注意“linux”的标签。来自 CD 的 yaboot.conf 有一个错误;您需要再次将额外的“\\”添加到 yaboot 前面。这次,使用命令序列 Command-Opt-O-F 进入 OF。当您再次获得“0 >”提示符时,输入以下内容
0 > boot hd:,\\yaboot
在一些闪烁之后,您将看到一个类似 LILO 的提示符。Linux 应该开始启动。成功!您现在应该看到了 Open Firmware 的强大功能;上面的命令允许您从硬盘驱动器执行文件,而且您甚至还没有启动操作系统!
在您以 root 用户身份登录后,您应该编辑文件 /etc/modules.conf 并添加以下内容
alias sound dmasound
这将允许您使用 /dev/dsp 播放音频。但是,就目前的形式而言,dmasound 仅支持写入——您不能使用它从外部麦克风录制数据。
我使用在 Linux 安装期间运行的 XConfigurator 配置了 X (XFree86 3.3.6)。我选择了 1024 x 768 的值和 24 位颜色深度。在 yaboot.conf 中,我添加了行
append="video=aty128fb:vmode:17,cmode:24"
以便内核能够正确识别已安装的 ATI 显卡。然后我编辑了 /etc/X11/XF86Config 并在“Screen”部分添加了 DefaultBitsPerPixel 24,这样我就不必在运行 startx 时将每像素位数 (bits per pixel) 传递给它。
现在 Linux 已经安装好了,AltiVec 的乐趣开始了。正如我已经提到的,AltiVec 单元是一个额外的处理单元,就像浮点单元或整数单元一样,它处理存储在 32 个 128 位向量寄存器中的数据。向量执行单元使用单指令多数据 (SIMD) 模型处理此向量数据。处理器,通过一条指令,可以一次操作四个、八个或 16 个数据单元。稍后我将给出一个例子来说明这一点。
摩托罗拉添加了 162 条新的汇编器指令,以允许程序员使用启用 AltiVec 的处理器的新功能。这些指令在 AltiVec 技术编程环境手册 (altivec_pem) 中详细说明。使用这些新汇编器指令的更高级别的 C 指令可以在 AltiVec 技术编程接口手册 (altivec_pim) 中找到。这两份文档都可以从摩托罗拉的网站或 http://www.altivec.org/ 下载 PDF 格式。
我的下一步是从 http://www.altivec.org/ 下载并安装 AltiVec RPM。安装是通过以下方式实现的
rpm -U binutils-2.9.5.0.22-6.vec.ppc.rpm rpm -i gcc-altivec-2.95.2-1i.ppc.rpm rpm -i gcc-altivec-c++-2.95.2-1i.ppc.rpm
安装后,我能够按如下方式使用这个新的 gcc
gcc-vec program.c -o programgcc 安装到 /opt/bin 中,这样它就不会影响默认的 gcc。RPM 在 /usr/bin 中创建了一个名为 gcc-vec 的链接,该链接指向 /opt 中的向量化 gcc。
要使用新的向量化命令,您必须编写使用它们的应用程序,并使用一个知道它们的 gcc 版本。您不能在您的标准 C 源代码上使用此版本的 gcc,并期望从 AltiVec 单元获得性能提升。启用 AltiVec 的 gcc 知道新的关键字和新函数。altivec_pim 是学习 gcc-vec 中提供的新命令的第一步。新的向量数据类型如表 2 所示。
注意新的关键字 vector。这表示以下声明是一个 16 字节(128 位)向量。此外,这些类型必须在 16 字节边界上对齐,以便向量执行单元适当地处理这些值。程序员在取消引用未在 16 字节边界上对齐的数据时必须小心,并且通常会调整数据以使其对齐。
根据 altivec_pim,知道启用 AltiVec 的处理器的编译器应该提供以下宏
#define __VEC__
要构建能够在多种架构上编译但仍然能够使用 AltiVec 指令的代码,您可以执行如下操作
#ifdef __VEC__ /* Put your vector code here */ /* ... */ #else /* do it the old-fashioned way, here */ /* ... */ #endif为了说明如何开始使用启用 AltiVec 的 gcc,我将在列表 3 中提供一个示例 [请参阅 FTP 站点 ftp.linuxjournal.com/pub/lj/listings/issue86]。
首先,注意 typedef 联合定义。如前所述,AltiVec 寄存器是 128 位的。这些定义保证编译器将对齐这些类型声明的数据在 128 位边界上。其次,它们提供了一种方便的方法来访问向量数据类型的各个元素。使用联合数据类型的最后一个好处是,现在您有了一种机制来查看寄存器内部——通过使用 printf( )。altivec_pim 提供了使用 scanf( )/printf( ) 进行格式化输入/输出。
vector float f32 = (vector float)(1.1, 2.2, 3.3, 4.4); printf( "%,vf\n", f32 );
要实现这一点,您的 C 库 (glibc*) 必须知道向量格式指令。GNU C 库 (2.2) 的当前实现没有,并且可能永远不会。因此,我希望修改 GNU C 库的一个版本以达到此目的。如果您有任何建议或兴趣,请随时与我联系。
接下来,注意定义向量类型的两种不同机制。第一个声明是针对存储在 cVals、sVals、iVals 和 fVals 中的向量常量,其中向量数据类型在同一语句中声明和定义。这说明了如何在向量中存储常量(运行时不更改的值)。
下一种方法声明联合类型,并在运行时以元素方式分配向量值。此方法将允许您从缓冲区读取数据,将其复制到向量变量并将其传递给您的向量感知函数。
最后,注意 vec_add( ) 函数的形式。在所有情况下,我都使用了相同的函数 vec_add( ),并且它提供了正确的结果,无论参数是向量短整型、向量整型还是向量浮点型(参数必须是相同的类型)。在这种情况下,编译器解释了我作为参数传递给 vec_add( ) 的数据类型,并为我生成了正确形式的汇编器指令 vadd*。
vector float a,b,c; /* Assign a,b */ /* ... */ c = vec_add( a, b);
这转化为以下汇编器指令
vaddfp c,a,b这变得越来越容易了。
要编译此程序,请使用以下命令
gcc-vec -fvec vecdemo1.c -o vecdemo1
编译器的 -fvec 开关告诉它解释向量命令。如果您不使用 -fvec 开关,编译器将无法识别向量数据类型或命令,并会打印错误消息,提醒您下次使用该开关。
该程序产生列表 4 中所示的输出。
我试图介绍 PowerMac 上的 Linux 以及 Linux 程序员可用的 AltiVec 资源。我想做更多的事情。其他可能的途径是演示如何将 AltiVec 用作信号处理平台、如何使用这些处理器代替专用 DSP,或者研究 DSP 在信号处理中的常见用途,即有限脉冲响应 (FIR) 滤波器。
我想感谢 AltiVec 论坛的成员。邮件列表一直是启动和运行的宝贵资源。此外,感谢所有 AltiVec 开发人员,他们提供了如此丰富的工具集,以便在一个像 G4 这样强大的平台上开始开发。
