05. Computer Architecture
术语
冯诺依曼体系结构的基础是一个 CPU,它与记忆设备(memory device)即内存进行交互,负责从输入设备(input device)接收输入,向输出设备(output device)发送数据。内存不仅要存储要进行操作的数据,还要存储指示计算机运行的指令。
算术逻辑单元(ALU)执行所有底层的算术和逻辑运算
寄存器(Registers)存储 CPU 内部的临时数据
控制单元(Control Unit)解码指令,还负责决定下一步要取出和执行哪条指令
数据寄存器(Data Registers)为 CPU 提供短期记忆。
寻址寄存器(Address Registers)存储内存地址。
程序计数寄存器(Program Counter Registers)存储下一条要执行的指令的地址。
I/O 映像(Memory Mapped I/O)为输入输出设备分配内存地址。通过访问这些地址,CPU 可以与输入输出设备进行交互。
Chip API
chip
芯片名: CPU
输入: inM[16], // 输入值 M(M=RAM(A))
instruction[16], // 用于执行的指令
reset // 决定是重启当前程序(reset=1)
// 还是继续执行当前程序(reset=0)的 rest 信号
输出: outM[16], // 输出值 M
writeM, // 写入 M ?
addressM[15], // M 在数据内存中的地址
pc[15] // 下一条指令的地址
功能: 根据 Hack 机器语言规范执行指令,该语言规范指定 D 和 A 为 CPU 中的寄存器,
M 代表内存单元,其地址由寄存器 A 中的内容确定(该内存单元的值从 inM 端输出)。
如果指令希望将一个数值写入 M 中,该数值会从 outM 端输出,同时 M 的地址会被
置于 addressM 端,而且 writeM 位被置位(当 writeM=0,任何值都可能出现
在 outM)。如果 reset=1,那么 CPU 跳转到地址 0(也就是,在下一个时间单元
设置 pc=0),而不是执行当前指令所确定的下一条指令。chip
芯片名: ROM32K // 容量为 32K 的 16-位只读内存
输入: address[15] // ROM 中的地址
输出: out[16] // ROM[address] 中存储的数值
功能: out=ROM[address] // 16-bit 数值的赋值
说明: 指令内存,用机器语言编写的程序被预先加载到 ROM 中。硬件实现可以将 ROM 当做一个
内置芯片,而软件模拟器必须提供一种将程序载入 ROM 的机制。chip
芯片名: Screen // 物理屏幕的内存映像
输入: in[16], // 要写入的内容
load, // 写使能位
address[13] // 写入的目的内存单元
输出: out[16] // 给定地址的屏幕值
功能: 功能与一个 8K 的 16-位 RAM 相似:
1. out(t)=Screen[address(t)](t)
2. If load(t-1) then Screen[address(t-1)](t)=in(t-1)chip
芯片名: Keyboard // 物理键盘的内存映像,输出当前按下键的代码
输出: out[16] // 输出按键的 ASCII 码
// 或者之前提到的特殊码
// 或者 0(没有任何按键按下)Project 05
CPU 还是有难度的,写了很多注释,更详细的内容可以参考 第四章笔记。
hdl
/**
* The complete address space of the Hack computer's memory,
* including RAM and memory-mapped I/O.
* The chip facilitates read and write operations, as follows:
* Read: out(t) = Memory[address(t)](t)
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
* In words: the chip always outputs the value stored at the memory
* location specified by address. If load=1, the in value is loaded
* into the memory location specified by address. This value becomes
* available through the out output from the next time step onward.
* Address space rules:
* Only the upper 16K+8K+1 words of the Memory chip are used.
* Access to address>0x6000 is invalid. Access to any address in
* the range 0x4000-0x5FFF results in accessing the screen memory
* map. Access to address 0x6000 results in accessing the keyboard
* memory map. The behavior in these addresses is described in the Screen
* and Keyboard chip specifications given in the lectures and the book.
*/
CHIP Memory {
IN in[16], load, address[15];
OUT out[16];
PARTS:
// address[14..13]
// 00/01 -> RAM16K (0x0000-0x3FFF)
// 10 -> Screen (0x4000-0x5FFF)
// 11 -> Keyboard (0x6000)
Not(in=address[14], out=not14);
Not(in=address[13], out=not13);
And(a=load, b=not14, out=loadram);
And(a=address[14], b=not13, out=screen);
And(a=load, b=screen, out=loadscreen);
RAM16K(in=in, load=loadram, address=address[0..13], out=ramout);
Screen(in=in, load=loadscreen, address=address[0..12], out=screenout);
Keyboard(out=keyboardout);
Mux4Way16(a=ramout, b=ramout, c=screenout, d=keyboardout,
sel[0]=address[13], sel[1]=address[14], out=out);
}hdl
/**
* The Hack Central Processing unit (CPU).
* Parses the binary code in the instruction input and executes it according to the
* Hack machine language specification. In the case of a C-instruction, computes the
* function specified by the instruction. If the instruction specifies to read a memory
* value, the inM input is expected to contain this value. If the instruction specifies
* to write a value to the memory, sets the outM output to this value, sets the addressM
* output to the target address, and asserts the writeM output (when writeM = 0, any
* value may appear in outM).
* If the reset input is 0, computes the address of the next instruction and sets the
* pc output to that value. If the reset input is 1, sets pc to 0.
* Note: The outM and writeM outputs are combinational: they are affected by the
* instruction's execution during the current cycle. The addressM and pc outputs are
* clocked: although they are affected by the instruction's execution, they commit to
* their new values only in the next cycle.
*/
CHIP CPU {
IN inM[16], // M value input (M = contents of RAM[A])
instruction[16], // Instruction for execution
reset; // Signals whether to re-start the current
// program (reset==1) or continue executing
// the current program (reset==0).
OUT outM[16], // M value output
writeM, // Write to M?
addressM[15], // Address in data memory (of M)
pc[15]; // address of next instruction
PARTS:
// A 指令,直接写入
// C 指令且 dest 包含 A,也就是 d1 == 1 时写入
// addressM 永远来自 A,M = contents of RAM[A]
Not(in=instruction[15], out=isA);
Mux16(a=instruction, b=aluout, sel=instruction[15], out=Ain);
Or(a=isA, b=instruction[5], out=loadA);
ARegister(in=Ain, load=loadA, out=Aout, out[0..14]=addressM);
// C 指令且 dest 包含 D,也就是 d2 == 1 时写入
And(a=instruction[15], b=instruction[4], out=loadD);
DRegister(in=aluout, load=loadD, out=Dout);
// ALU 左输入永远是 D 寄存器的输出
// 右输入看 C 指令的 a 位,a == 0 时是 A 寄存器的输出,a == 1 时是 inM
Mux16(a=Aout, b=inM, sel=instruction[12], out=aluy);
ALU(x=Dout, y=aluy,
zx=instruction[11], nx=instruction[10],
zy=instruction[9], ny=instruction[8],
f=instruction[7], no=instruction[6],
out=aluout, zr=zr, ng=ng);
// outM 就是 ALU 的输出
// C 指令且 dest 包含 M,也就是 d3 == 1 时,writeM 才为 1
Or16(a=aluout, b=false, out=outM);
And(a=instruction[15], b=instruction[3], out=writeM);
// ALU 结果 为 0 时 zr=1,结果为负数时 ng=1
// 任何 jump 操作都是跳转到 A 寄存器中存储的地址
And(a=instruction[2], b=ng, out=jlt);
And(a=instruction[1], b=zr, out=jeq);
Not(in=ng, out=notng);
And(a=instruction[0], b=notng, out=ge);
Not(in=zr, out=notzr);
And(a=notzr, b=ge, out=jgt);
Or(a=jlt, b=jeq, out=jlteq);
Or(a=jlteq, b=jgt, out=jump);
And(a=instruction[15], b=jump, out=loadPC);
PC(in=Aout, load=loadPC, inc=true, reset=reset, out[0..14]=pc);
}hdl
/**
* The Hack computer, consisting of CPU, ROM and RAM.
* When reset = 0, the program stored in the ROM executes.
* When reset = 1, the program's execution restarts.
* Thus, to start running the currently loaded program,
* set reset to 1, and then set it to 0.
* From this point onwards, the user is at the mercy of the software.
* Depending on the program's code, and whether the code is correct,
* the screen may show some output, the user may be expected to enter
* some input using the keyboard, or the program may do some procerssing.
*/
CHIP Computer {
IN reset;
PARTS:
ROM32K(address=pc, out=pcout);
CPU(inM=memout, instruction=pcout, reset=reset,
outM=outM, writeM=writeM, addressM=addressM, pc=pc);
Memory(in=outM, load=writeM, address=addressM, out=memout);
}