我最近开始以业余爱好者的身份从事逻辑级设计工作,但现在发现自己遇到了软件问题,而我在这方面的能力要差得多。我已经根据 Etienne Sicard 的论文“A Very Simple Microprocessor”在 Logisim 中松散地设计了一个定制的 4 位 CPU。现在它完成了我内置的非常有限的功能(加法、逻辑 AND、OR 和 XOR)而没有任何可检测到的错误(交叉手指),我遇到了为它编写程序的问题。Logisim 具有将十六进制数字脚本导入 RAM 或 ROM 模块的功能,因此我可以使用自己的微指令代码为其编写程序,但我从哪里开始呢?从字面上看,我处于软件设计的最基本可能级别,并且真的不知道从这里去哪里。关于学习这种低水平编程的资源的任何好的建议或关于我应该从这里尝试什么的建议?提前非常感谢,我知道这可能不是这个论坛上最直接适用的问题。
3 回答
我不知道你提到的那篇论文。但是,如果您设计了自己的定制 CPU,那么如果您想为它编写软件,您有两种选择:a) 用机器代码编写,或者 b) 编写自己的汇编程序。
显然我会选择b。这将需要您稍微换档并进行一些高级编程。您的目标是编写一个在 PC 上运行的汇编程序,并将一些简单的汇编语言转换为您的自定义机器代码。汇编器本身将是一个高级程序,因此,我建议用一种同时擅长字符串操作和二进制操作的高级编程语言编写它。我会推荐Python。
您基本上希望您的汇编程序能够读取这样的文本文件:
mov a, 7
foo:
mov b, 20
add a, b
cmp a, b
jg foo
(我只是编了这个程序;这是胡说八道。)
并将每一行代码转换为该指令的二进制模式,输出一个二进制文件(或者可能是一个十六进制文件,因为你说你的微控制器可以读取十六进制值)。从那里,您将能够将程序加载到 CPU 上。
所以,我建议你:
- 提出(在纸上)一种汇编语言,它是您机器支持的每个操作码的简单书面表示(您可能已经这样做了),
- 学习简单的Python,
sys.stdin.readline()
编写一个 Python 脚本,每次读取一行(- 用您的汇编语言编写一些将在您的 CPU 上运行的汇编代码。
听起来是个有趣的项目。
我做过类似的事情,你可能会觉得有趣。我还从头开始创建了自己的 CPU 设计。它是一个基于哈佛架构的具有可变长度指令的 8 位多周期 RISC CPU。
我从 Logisim 开始,然后在 Verilog 中编写所有代码,并在 FPGA 中进行了综合。
为了回答你的问题,我做了一个简单而基本的汇编程序,它将程序(指令,即助记符 + 数据)翻译成相应的机器语言,然后可以加载到 PROG 内存中。我已经用 shell 脚本编写了它并使用了 awk,这让我很舒服。
我基本上做了两遍:首先将助记符翻译成相应的操作码,然后将数据(操作数)翻译成十六进制,这里我跟踪所有标签地址。第二遍将所有标签替换为其对应的地址。(标签和地址用于跳转)
您可以在此处查看所有项目,包括汇编程序:https ://github.com/adumont/hrm-cpu
因为您的指令集非常小,并且基于 mguica 答案中的线程,我想说下一步是继续和/或全面测试您的指令集。你有旗帜吗?你有分支指令吗?现在只需手动生成机器代码。标志很棘手,尤其是溢出 (V) 位。您必须检查进位并在 msbit 加法器上执行以使其正确。因为指令集足够小,您可以尝试背靠背指令的各种组合,然后是或,然后是异或,然后是加法,或者后是和或,然后是异或等。并在分支中混合。回到旗帜,如果异或和或例如不接触进位和溢出,那么请确保您看到进位和溢出是零并且没有被逻辑指令触及,并且进位和溢出是一并且没有被触及,并且还独立地显示进位和溢出是分开的,一对一关闭,不涉及逻辑等。确保所有条件分支仅在一个条件下运行,引导到具有在两种状态下都被忽略的标志位的各种条件分支,以确保条件分支忽略它们。还要验证条件分支是否不应该修改它们。同样,如果条件不会导致未触及条件标志的分支... 确保所有条件分支仅在一个条件下运行,引导到带有标志位的各种条件分支,这些标志位在两种状态下都被忽略,以确保条件分支忽略它们。还要验证条件分支是否不应该修改它们。同样,如果条件不会导致未触及条件标志的分支... 确保所有条件分支仅在一个条件下运行,引导到带有标志位的各种条件分支,这些标志位在两种状态下都被忽略,以确保条件分支忽略它们。还要验证条件分支是否不应该修改它们。同样,如果条件不会导致未触及条件标志的分支...
我喜欢使用随机化,但它可能比你所追求的要多。我喜欢独立开发指令集的软件模拟器,我发现它更容易使用,逻辑有时也更容易在批量测试中使用。然后,您可以随机化一些简短的指令列表,改变指令和寄存器,自然地通过手动计算一些结果来测试测试仪,包括测试完成后寄存器的状态和标志位的状态。然后使该随机列表更长,在某些时候,您可以获取一个长指令列表并在逻辑模拟器上运行它,看看逻辑是否与指令集模拟器具有相同的寄存器结果和标志位,如果它们不同,请弄清楚为什么。如果不尝试另一个随机序列,另一个。
回到单独的指令测试和标志遍历所有极端情况 0xFFFF + 0x0000 0xFFFF+1,诸如此类的事情仅放置在操作数的两侧和右侧,并且结果与标志更改的位置相差一个计数旗帜改变了,只是另一面。对于逻辑,例如,如果他们使用零标志,那么有各种数据模式来测试结果在零的两侧和零处 0x0000、0xFFFF 0xFFFE 0x0001 0x0002 等。可能还有一个行走的结果 0x0001 结果 0x0002、ox0004 , ETC。
希望我理解您的问题,并且没有指出明显的或您迄今为止已经做过的事情。