下图为程序储存器侧面图,是立体8层叠加式结构,每一层128byte。
储存器阵列是3D的,也就是具有长宽高三个向量。为了给一个长方体的每一个单元编码,我采用的是先用地址码的低4位给个面编码,再用地址码的高5位给一条线编码,一个面乘以一条线正好覆盖了整个长方体。
通往储存器的地址线是总线分出来的支线,数据线也是一样的。这两列线分别连到储存器的3D结构里。地址线就连到刚才说的译码高5位和低4位,数据线的16个bit每一根连到每一个储存单元的对应bit。数据线先分散后集中。
本工程因为体积和延时问题的特殊性,主程序储存器只有1.5kb,访存速度相对于真实的计算机快多了,所以这个并不是瓶颈,可以在相对较短的时间内取到想要的指令。所以本想借这个优势实现指令全流水,也就是依靠复杂的分支预测机制将流水线漏洞封死。后来尝试做了一下,发现问题还是很多,比如预译码,预跳转中PC的占用冲突和布线困难,前一条跳转指令和后一条跳转指令的冲突,如果想要做出来,开销过于巨大,基本上CU的体积要增加0.5倍,这对我之后的工作影响很大故弃之,改为二位动态分支预测器来执行分支预测,这样流水线会冒气泡,但是损失不大。为了最大限度的缩小流水线气泡,我前后进行了相当多细微的改进。
流水线:取指→预译码,预执行→译码(→间指)→执行(→写回)
完整的流水线,一条指令会经历如下过程:当指令缓冲队列的指令条数小于4条时,先加载已经处于载入端的下一地址的指令,然后发出一个信号往PC,PC将当前储存的地址传送至程序储存器MAR,然后PC+1,地址译码器将相应地址的指令A传送至程序储存器MDR的载入端,如果是跳转指令等需要修改PC的指令则预执行指令。意思是将程序指针类指令全部放在另一个流水线分叉上执行。如果不是跳转指令,则MDR将A指令压入指令缓冲队列。如果此时缓冲队列里有ABC三条指令按这个顺序排列,那么等待C先弹出,然后B弹出,最后轮到A弹出至IR,IR将A送往指令译码器,控制信号通完各EU单元前端。等待前面的B指令执行完了 ,然后正式执行A指令。此时如果有间指周期,则将数据地址输送至地址译码器,从寄存器或数据储存器读取数据送到相应单元。然后执行指令。执行完毕如果有写回周期则执行写回。一条指令执行完毕。期间在指令缓冲队列和IR中如果前面有一条指令是条件跳转指令并且分支预测错误,会使缓冲队列和IR清存。PC发射正确的地址重新取指。
流水线流程图如下:
蓝线是控制信号,绿线是数据信号,红色字母和橙色箭头是指令队列的顺序压进方式。
另:本工程的所谓内存实际上是硬盘,因为我的程序是储存在这里面的,关机的时候我不会把储存器清空。不过这个问题无关紧要。
指令集架构
指令格式和取指方式:
ALU Instruction Formats
更多相关资讯请关注:我的世界专区