📄 controller.java
字号:
/**
* Controller.java 2007/11/15 version1.0
*/
package com.vmpu.core;
import com.vmpu.util.Mask16;
/**
* 控制器在时钟控制下,负责从指令寄存器中取出指令,并根据标志位把其翻译成各种控制信号并产生各种立即数。
*
* 各控制信号的含义如下: RegWr:写寄存器,RegWr=0时,禁止写;RegWr=1时,写使能 ALUCtr:选择ALU功能,参见ALU功能编码
* ALUSrc:选择ALU的源操作数,ALUSrc=0时,源操作数为SR;ALUSrc=1时,源操作数为立即数
* MemWr:写内存,MemWr=0时,禁止写;MemWr=1时,写使能
* WSrc:选择busW的值,WSrc=0时,选择ALU运算结果:WSrc=1时,选择存储器读取
* nPC_sel1:PC计算方式,nPC_sel1=0时,PC=PC+2;nPC_sel1=1时,PC=PC+OFFSET
* nPC_sel2:PC计算方式,nPC_sel2=0时,PC= PC+OFFSET;nPC_sel2=1时,PC=ADR
* Flag_C:C标志,影响JNC指令 Flag_Z:Z标志,影响JNZ指令
*
* 各控制信号的计算方式如下: RegWr=instr<15>+!instr<14>&!instr<12>+instr<14>&instr<13>&instr<12>
* ALUCtr<2>=!instr<15>+instr<14> ALUCtr<1>=!instr<15>+instr<13> ALUCtr<0>=!instr<15>+instr<12>
* ALUSrc=instr<15>&!instr<14>&instr<12>+!instr<15>&instr<14> MemWr=!instr<15>&!instr<14>&instr<12>
* WSrc=!instr<15>&!instr<14> nPC_sel1比较特殊,除了受操作码影响外,还受标志位的影响: nPC_sel1=!instr<15>&instr<14>&!instr<13>&instr<12>!Flag_C
* +!instr<15>&instr<14>&instr<13>&!instr<12>!Flag_Z nPC_sel2=!instr<15>&!instr<13>&!instr<12>
*
* 这些控制信号总共需要用9位来表示,可以设想有一个16位的控制信号寄存器,控制器完成译码后, 把各种信号寄存在该寄存器里,以供其他部件使用。
*
* 另外,会产生三种不同类型的立即数: imm10:指令低10位; imm12:指令低12位; imm2:常数2(二进制表示为10)。
*
* 这些立即数总共需要用24位表示,可以设想有两个16位的立即数寄存器,用来寄存这些立即数
*
* 还会产生SR、DR的地址 SR、DR共需要用4位来表示
*
* @author 周良
*
*/
public class Controller {
/**
* 16位的控制信号寄存器,各控制信号所占的位如下: bit15~bit9:未定义 bit8:RegWr bit7:ALUCtr<2>
* bit6:ALUCtr<1> bit5:ALUCtr<0> bit4:ALUSrc bit3:MemWr bit2:WSrc
* bit1:nPC_sel1 bit0:nPC_sel2
*
* 初始化为0,此时寄存器和内存均禁止写
*
* 控制信号寄存器只有控制器能够修改,其他部件只能读取
*/
private char ctrlSgnlReg = 0;
/**
* 16位的立即数寄存器1,用来寄存imm10和imm2: bit1~bit0:imm2 bit11~bit2:imm10
* bit13~bit12:DR地址 bit15~bit14:SR地址
*
* 初始化为2,这是因为imm2是常数2
*
* 立即数寄存器1只有控制器能够修改,其他部件只能读取
*/
private char immReg1 = 2;
/**
* 16位的立即数寄存器2,用来寄存imm12: bit0~bit11:imm12 bit12~bit15:未定义
*
* 初始化为0
*
* 立即数寄存器2只有控制器能够修改,其他部件只能读取
*/
private char immReg2 = 0;
/**
* 所属的MPU
*/
private MicroProcessingUnit owner = null;
/**
* 初始化
*/
public void init() {
ctrlSgnlReg = 0;
immReg1 = 2;
immReg2 = 0;
}
/**
* 构造函数,需要指明属于哪一个MPU
* @param owner
*/
public Controller(MicroProcessingUnit owner) {
this.owner = owner;
this.init();
}
/**
* 从指令寄存器中取出指令,并根据标志位把其翻译成各种控制信号并产生各种立即数
*/
public void decode() {
// 各寄存器恢复到初始状态
this.init();
// 修改MPU状态寄存器
owner.setStatusReg(MicroProcessingUnit.MPU_DECODE);
// ===================================================
// 获取指令和标志
// ===================================================
// 从指令寄存器中读取指令
int instr = owner.getInstrFetcher().getInstrReg();
// 异常指令,MPU停止执行
if(instr == 0) owner.halt();
// 从标志寄存器中读取标志位
int flag = owner.getExecutor().getFlagReg();
// ===================================================
// 产生控制信号
// ===================================================
// 分别取得指令的bit15~bit12(操作码部分),并全部移至最低位
int instr15 = (instr & Mask16.mask16[15]) >>> 15;// instr<15>
int instr14 = (instr & Mask16.mask16[14]) >>> 14;// instr<14>
int instr13 = (instr & Mask16.mask16[13]) >>> 13;// instr<13>
int instr12 = (instr & Mask16.mask16[12]) >>> 12;// instr<12>
// 指令的bit15,bit14,bit13,bit12取反
int not_instr15 = (~instr15) & Mask16.mask16[0];
int not_instr14 = (~instr14) & Mask16.mask16[0];
int not_instr13 = (~instr13) & Mask16.mask16[0];
int not_instr12 = (~instr12) & Mask16.mask16[0];
// 取得C、Z标志
int flag_c = (flag & Mask16.mask16[1]) >>> 1;// Flag_c
int flag_z = (flag & Mask16.mask16[0]) >>> 0;// Flag_z
// !C,!Z
int not_flag_c = (~flag_c) & Mask16.mask16[0];
int not_flag_z = (~flag_z) & Mask16.mask16[0];
// RegWr=instr<15>+!instr<14>&!instr<12>+instr<14>&instr<13>&instr<12>
int RegWr = instr15 | (not_instr14 & not_instr12)
| (instr14 & instr13 & instr12);
// ALUCtr<2>=!instr<15>+instr<14>
int ALUCtr2 = not_instr15 | instr14;
// ALUCtr<1>=!instr<15>+instr<13>
int ALUCtr1 = not_instr15 | instr13;
// ALUCtr<0>=!instr<15>+instr<12>
int ALUCtr0 = not_instr15 | instr12;
// ALUSrc=instr<15>&!instr<14>&instr<12>+!instr<15>&instr<14>
int ALUSrc = (instr15 & not_instr14 & instr12)
| (not_instr15 & instr14);
// MemWr=!instr<15>&!instr<14>&instr<12>
int MemWr = not_instr15 & not_instr14 & instr12;
// WSrc=!instr<15>&!instr<14>
int WSrc = not_instr15 & not_instr14;
// nPC_sel1=!instr<15>&instr<14>&!instr<13>&instr<12>&!Flag_C
// +!instr<15>&instr<14>&instr<13>&!instr<12>&!Flag_Z
int nPC_sel1 = (not_instr15 & instr14 & not_instr13 & instr12 & not_flag_c)
| (not_instr15 & instr14 & instr13 & not_instr12 & not_flag_z);
// nPC_sel2=!instr<15>&!instr<13>&!instr<12>
int nPC_sel2 = not_instr15 & not_instr13 & not_instr12;
// 把各控制信号寄存到控制信号寄存器的相应位
ctrlSgnlReg |= RegWr << 8;
ctrlSgnlReg |= ALUCtr2 << 7;
ctrlSgnlReg |= ALUCtr1 << 6;
ctrlSgnlReg |= ALUCtr0 << 5;
ctrlSgnlReg |= ALUSrc << 4;
ctrlSgnlReg |= MemWr << 3;
ctrlSgnlReg |= WSrc << 2;
ctrlSgnlReg |= nPC_sel1 << 1;
ctrlSgnlReg |= nPC_sel2 << 0;
// ===================================================
// 产生立即数
// ===================================================
int imm10 = instr & 0x03FF;
int imm12 = instr & 0x0FFF;
immReg1 |= imm10 << 2;
immReg2 |= imm12;
// ===================================================
// 产生SR、DR地址
// ===================================================
int dr_addr = instr & 0x0C00;
int sr_addr = instr & 0x0300;
immReg1 |= dr_addr << 2;
immReg1 |= sr_addr << 6;
}
public char getCtrlSgnlReg() {
return ctrlSgnlReg;
}
public char getImmReg1() {
return immReg1;
}
public char getImmReg2() {
return immReg2;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -