Міністерство освіти і науки України
Національний університет «Львівська політехніка»
Кафедра ЕОМ
Звіт
до лабораторної роботи № 6
з курсу «Комп’ютерні системи»
на тему:
Дослідження функціональних блоків програмної моделі RISC CPU
Львів – 2012р.
Мета роботи :
1. Навчитися здійснювати оцінку структури об’єкта (RISC CPU) на
існуючій програмній моделі .
2. Навчитись встановлювати структуру інтерфейсів об’єкта .
3. Побудувати структурну схему блоку.
Порядок виконання роботи
1. Дослідити програмну модель блоку згідно варіанту, який входить до складу моделі процесора з архітектурою RISC;
2. На основі моделі, що досліджується, побудувати структурну схему блоку;
3. Дати пояснення функцій, що виконуються елементами схеми.
Лістинг програми
struct decode : sc_module {
sc_in<bool> resetin; // input reset
sc_in<unsigned> instruction; // fetched instruction
sc_in<unsigned> pred_instruction; // fetched instruction
sc_in<bool> instruction_valid; // input valid
sc_in<bool> pred_inst_valid; // input valid
sc_in<bool> destreg_write; // register write enable
sc_in<unsigned> destreg_write_src; // which register to write?
sc_in<signed> alu_dataout; // data from ALU
sc_in<signed> dram_dataout; // data from Dcache
sc_in<bool> dram_rd_valid; // Dcache read data valid
sc_in<unsigned> dram_write_src; // Dcache data write to which reg
sc_in<signed> fpu_dout; // data from FPU
sc_in<bool> fpu_valid; // FPU data valid
sc_in<unsigned> fpu_destout; // write to which register
sc_in<bool> clear_branch; // clear outstanding branch
sc_in<bool> display_done; // display to monitor done
sc_in<unsigned > pc; // program counter from IFU
sc_in<bool> pred_on; // branch prediction is on
sc_out<unsigned > br_instruction_address; // branch invoke instruction
sc_out<bool> next_pc; // next pc ++ ?
sc_out<bool> branch_valid; // branch valid signal
sc_out<unsigned > branch_target_address; // branch target address
sc_out<bool> mem_access; // memory access valid
sc_out<unsigned > mem_address; // memory physical address
sc_out<int> alu_op; // ALU/FPU/MMU Opcode
sc_out<bool> mem_write; // memory write enable
sc_out<unsigned> alu_src; // destination register number
sc_out<bool> reg_write; // not implemented
sc_out<signed int> src_A; // operand A
sc_out<signed int> src_B; // operand B
sc_out<bool> forward_A; // data forwarding to operand A
sc_out<bool> forward_B; // data forwarding to operand B
sc_out<bool> stall_fetch; // stall fetch due to branch
sc_out<bool> decode_valid; // decoder output valid
sc_out<bool> float_valid; // enable FPU
sc_out<bool> mmx_valid; // enable MMU
sc_out<bool> pid_valid; // load process ID
sc_out<signed> pid_data; // process ID value
sc_in_clk CLK;
signed int cpu_reg[32]; //CPU register
signed int vcpu_reg[32]; //virtual CPU register
bool cpu_reg_lock[32]; //lock architectural state register
unsigned int pc_reg; //pc register
unsigned int jalpc_reg; //jump back register
//Constructor
SC_CTOR(decode) {
SC_CTHREAD(entry, CLK.pos());
FILE *fp = fopen("register","r");
int size=0;
unsigned mem_word;
printf("** ALERT ** ID: initialize Architectural Registers\n");
while (fscanf(fp,"%x", &mem_word) != EOF) {
cpu_reg[size] = mem_word;
size++;
}
pc_reg = 0;
jalpc_reg = 0;
for (int j =0; j<32; j++) vcpu_reg[j] = 0;
for (int k =0; k<32; k++) cpu_reg_lock[k] = 0;
}
// Process functionality in member function below
void entry();
};
#include <iostream>
#include <climits> // for definition on value 's MAX
#include "systemc.h"
#include "decode.h"
#include "directive.h"
using namespace std;
void decode::entry()
{
unsigned int instr_tmp = 0;
unsigned int opcode_tmp = 0;
unsigned int regA_tmp = 0;
unsigned int regB_tmp = 0;
unsigned int regC_tmp = 0;
unsigned int imm_tmp = 0;
unsigned int offset_tmp = 0;
signed int label_tmp = 0;
unsigned int longlabel_tmp = 0;
unsigned int lastreg_tmp = 0;
signed int srcA_tmp = 0;
signed int srcB_tmp = 0;
signed int srcC_tmp = 0;
int i;
bool branch_direction_tmp = 0;
branch_valid.write(false);
decode_valid.write(false);
float_valid.write(false);
mmx_valid.write(false);
wait(2);
while (true) {
if (destreg_write.read() == true) {
cpu_reg[destreg_write_src.read()] = alu_dataout.read();
cout << "\t\t\t-------------------------------" << endl;
printf("\t\t\tID: R%d=0x%x(%d) fr ALU", destreg_write_src.read(), alu_dataout.read(),alu_dataout.read());
cout.setf(ios::dec,ios::basefield);
cout << " at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
}
if (dram_rd_valid.read() == true) {
cpu_reg[dram_write_src.read()] = dram_dataout.read();
cout << "\t\t\t-------------------------------" << endl;
printf("\t\t\tID: R%d=0x%x(%d) fr MemLd", dram_write_src.read(), dram_dataout.read(), dram_dataout.read());
cout.setf(ios::dec,ios::basefield);
cout << " at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
}
if (fpu_valid.read() == true) {
cpu_reg[fpu_destout.read()] = fpu_dout.read();
cout << "\t\t\t-------------------------------" << endl;
printf("\t\t\tID: R%d=0x%x fr MMX", fpu_destout.read(), fpu_dout.read());
cout.setf(ios::dec,ios::basefield);
cout << " at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
}
if ((instruction_valid.read() == true)) {
pc_reg = pc.read();
if (clear_branch.read() == true) {
cout << "\t\t\t-------------------------------" << endl;
printf("\t\t\tID: clear branch");
cout.setf(ios::dec,ios::basefield);
cout << " at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
branch_valid.write(false);
}
instr_tmp = instruction.read();
opcode_tmp = (instr_tmp & 0xff000000) >> 24;
regC_tmp = (instr_tmp & 0x00f00000) >> 20;
regA_tmp = (instr_tmp & 0x000f0000) >> 16;
regB_tmp = (instr_tmp & 0x0000f000) >> 12;
imm_tmp = (instr_tmp & 0x0000ffff);
offset_tmp = (instr_tmp & 0x00000fff);
label_tmp = (instr_tmp & 0x0000ffff);
longlabel_tmp = (instr_tmp & 0x00ffffff);
branch_direction_tmp = (instr_tmp & 0x00008000) >> 15;
if (branch_direction_tmp) { // handle backward branch
label_tmp = - (0xffff - label_tmp + 1) ;
}
//printf("opcode = %d regC = %d regA = %d regB = %d\n",opcode_tmp, regC_tmp, regA_tmp, regB_tmp);
srcA_tmp = cpu_reg[regA_tmp];
srcB_tmp = cpu_reg[regB_tmp];
srcC_tmp = cpu_reg[regC_tmp];
wait();
lastreg_tmp = regC_tmp;
cout << "\t\t\t-------------------------------" << endl;
/******************************************************************************
if (regA_tmp == lastreg_tmp){
forward_A.write(true);
forward_B.write(false);
} else if (regB_tmp == lastreg_tmp){
forward_A.write(false);
forward_B.write(true);
} else {
forward_A.write(false);
forward_B.write(false);
}
*********************************************************************************/
switch(opcode_tmp) {
case 0x0: // halt
printf("\n\n\t\t\t*******************************\n");
printf("\t\t\tID: REGISTERS DUMP");
cout << " at CSIM " << sc_time_stamp() << endl;
printf("\t\t\t*******************************\n");
printf("REG :==================================================================\n");
for(i =0; i<32; i++){
printf(" R%2d(%08x) ",i, cpu_reg[i]);
if ((i==3) || (i== 11) || (i==19) || (i== 27) ||(i==7) || (i==15) || (i==23) || (i==31)){
printf("\n");
}
}
printf("=======================================================================\n\n");
wait();
wait();
break;
case 0x01: // add R1, R2, R3
printf("\t\t\tID: R%d= R%d(=%d)+R%d(=%d)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(3);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x02: // addi R1, R2, #value
printf("\t\t\tID: R%d= R%d(=%d)+%d",
regC_tmp, regA_tmp, srcA_tmp, imm_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(imm_tmp);
alu_src.write(regC_tmp);
alu_op.write(3);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x03: // addc R1, R2, R3 + Carrybit
printf("\t\t\tID: R%d= R%d(=%d)+R%d(=%d)+C",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(1);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x04: // sub R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%d)-R%d(=%d)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(4);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x05: // subi R1, R2, #value
printf("\t\t\tID: R%d=R%d(=%d)-%d",
regC_tmp, regA_tmp, srcA_tmp, imm_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(imm_tmp);
alu_src.write(regC_tmp);
alu_op.write(4);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x06: // subc R1, R2, R3 - Carrybit
printf("\t\t\tID: R%d=R%d(=%d)-R%d(=%d)-C",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(2);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x07: // mul R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%d)*R%d(=%d)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(5);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x08: // div R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%d)/R%d(=%d)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(6);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x09: // nand R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%x) nand R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(7);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x0a: // and R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%x) and R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(8);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x0b: // or R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%x) or R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(9);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x0c: // xor R1, R2, R3
printf("\t\t\tID: R%d=R%d(=%x) xor R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(10);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x0d: // NOT R1, R2
printf("\t\t\tID: R%d= NOT R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(0);
alu_src.write(regC_tmp);
alu_op.write(11);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x0e: // modulo R1 = R2 mod R3
printf("\t\t\tID: R%d= R%d(=%x) mod R%d(=%x)",
regC_tmp, regA_tmp, srcA_tmp, regB_tmp, srcB_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(srcB_tmp);
alu_src.write(regC_tmp);
alu_op.write(14);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x4d: // lw R1, R2, offset
printf("\t\t\tID: R%d<=mem[R%d=(%d)+%d]",
regC_tmp, regA_tmp, srcA_tmp, offset_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
mem_access.write(true);
mem_write.write(false);
alu_src.write(regC_tmp);
offset_tmp = offset_tmp + srcA_tmp;
mem_address.write(offset_tmp);
wait();
mem_access.write(false);
wait();
break;
case 0x4e: // sw R1, R2, offset
printf("\t\t\tID: R%d=>mem[R%d(=%d) + %d]",
regC_tmp, regA_tmp, srcA_tmp, offset_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
mem_access.write(true);
mem_write.write(true);
offset_tmp = offset_tmp + srcA_tmp;
mem_address.write(offset_tmp);
wait();
mem_access.write(false);
mem_write.write(false);
wait();
break;
case 0x0f: // mov R1, R2
printf("\t\t\tID: R%d=R%d(=%d)",
regC_tmp, regA_tmp, srcA_tmp);
cout << " \n\t\t\t : at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
src_A.write(srcA_tmp);
src_B.write(0);
alu_src.write(regC_tmp);
alu_op.write(3);
decode_valid.write(true);
wait();
decode_valid.write(false);
wait();
break;
case 0x10: // beq R1, R2, label
src_A.write(0);
src_B.write(0);
alu_src.write(0);
alu_op.write(3);
decode_valid.write(true);
if (srcC_tmp == srcA_tmp) {
branch_target_address.write(pc_reg + label_tmp);
br_instruction_address.write(instr_tmp);
branch_valid.write(true);
printf("\t\t\tID: beq R%d(=%d), R%d(=%d), pc+=(%d).\n",
regC_tmp, srcC_tmp, regA_tmp, srcA_tmp, label_tmp);
} else {
printf("\t\t\tID: beq R%d(=%d) != R%d(=%d),pc++.\n",
regC_tmp, srcC_tmp, regA_tmp, srcA_tmp);
}
cout << "\t\t\tID: at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
wait();
branch_target_address.write(pc_reg + 1);
decode_valid.write(false);
wait();
break;
case 0x11: // bne R1, R2, label
src_A.write(0);
src_B.write(0);
alu_src.write(0);
alu_op.write(3);
decode_valid.write(true);
if (srcC_tmp != srcA_tmp) {
branch_target_address.write(pc_reg + label_tmp);
br_instruction_address.write(instr_tmp);
branch_valid.write(true);
printf("\t\t\tID: bne R%d(=%d), R%d(=%d), pc+=(%d).\n",
regC_tmp, srcC_tmp, regA_tmp, srcA_tmp, label_tmp);
} else {
printf("\t\t\tID: bne R%d(=%d) = R%d(=%d),pc++.\n",
regC_tmp, srcC_tmp, regA_tmp, srcA_tmp);
}
cout << "\t\t\tID: at CSIM " << sc_time_stamp() << endl;
cout << "\t\t\t-------------------------------" << endl;
wait();
branch_target_address.write(pc_reg + 1);
decode_valid.write(false);
wait();
break;
case 0x12: // bgt R1, R2, label
src_A.write(0);
src_B.write(0);
alu_src.write(0);
alu_op.write(3);
decode_valid.write(true);
if (srcC_tmp > srcA_tmp) {
branch_target_address.write(pc_reg + label_tmp);
br_instruction_address.write(instr_tmp);
branch_valid.write(true);
printf("\t\t\tID: bgt R%d(=%d)>