Пример #1
0
// this function will be activated on ID stage.
// it's mainly about recording forwarding data.
// But it will also help branch do their forwarding
//
// for some instructions that don't need to fwd,
// their reg_A, reg_B will be -1,
// so it's impossible to have hazard detect here
//
// if reg_A and reg_B be -1, 
// the only cnd they will have hazard is
// reg_EX = -1 or reg_EX = -1
// but it will fulfill the fwd cnd
int hazard_check(int reg_EX, int reg_ME, int reg_A, int reg_B) {
    int result = 0, branch = 0;
    struct ins* i = CPU.pipeline[0];
    int op_cur = i->opcode, func_cur = i->func;
    int op_ex = CPU.pipeline[1]->opcode;
    int op_me = CPU.pipeline[2]->opcode;
    int ex_cnd = ((reg_EX != -1) && (reg_EX != 0)) && (reg_EX == reg_A || reg_EX == reg_B); // make sure it is not access 0
    int me_cnd = ((reg_ME != -1) && (reg_ME != 0)) && !(reg_EX == reg_ME) && (reg_ME == reg_A || reg_ME == reg_B); // make sure it is not access 0
    int fwd_des = -1;
    //reg_A is rs, reg_B is rt
    //but for sll/srl/sra, reg_A is rt.

    //check if branch(jump) or not
    if(is_branch(_ID) || (op_cur == 0x00 && func_cur == _jr)) {
        branch = 1;
        fwd_des = _ID;
    } else fwd_des = _EX;

    //if they are not equals to -1, it means that it can forward now
    //this will happen only after stall, so the if(ex_cnd) and if(me_cnd) will not be trigger
    //branch/jump is ready to forward.
    if(branch && i->fwd_id) {
        //printf("do branch fowarding\n");
        return 0;
    }

    //clean forwarding message after stall
    if(i->fwd_id || i->fwd_ex) {
        i->fwd_id = 0;
        i->fwd_ex = 0;
        i->fwd_to_s = -1;
        i->fwd_to_t = -1;
    }


    if(ex_cnd && notNOP(1)) {
        int load = 0;
            //if it is load, need to stall. It's because the data cannot be access at EX stage
            if(is_load(op_ex)) result = 1;
            else {   
                fwd_signal(fwd_des, _EX, reg_EX, reg_A, reg_B);
                if(branch) result = 1;
            }
    }
    if(me_cnd && notNOP(2)) {
            // branch won't have chance to let ME-WB forward
            // when ID needs to compute, ME-WB might still not available
            // but when ME-WB is available
            // the data is already write back to register(first half cycle)
            if(!branch) fwd_signal(fwd_des, _ME, reg_ME, reg_A, reg_B);
            else {
                if(is_load(op_me)) result = 1;
                else if(!result) {
                    fwd_signal(_ID, _EX, reg_ME, reg_A, reg_B);
                } 
            }
    }

    return result;
}
Пример #2
0
void alu_unit(int s, int t) {
    struct ins* i = CPU.pipeline[1];
    int opc = i->opcode;
    short c = i->c;
    if(opc) {

        if(opc == _addi) addi(s, c);
        else if(opc == _halt) printf("encounter halt\n");
        else if(is_load(opc) || is_store(opc)) load_store(s, c);
        else if(opc == _lui) lui(c); 
        else if(opc == _andi) andi(s, c);
        else if(opc == _ori) ori(s, c);
        else if(opc == _nori) nori(s, c);
        else if(opc == _slti) slti(s, c);

    } else {
        int func = i->func;
        int shamt = i->shamt;
        
        if(func == _add) add(0, s, t);
        else if(func == _sub) add(1, s, t);
        else if(func == _and) and(0, s, t);
        else if(func == _or) or(0, s, t);
        else if(func == _xor) or(1, s, t);
        else if(func == _nor) or(2, s, t);
        else if(func == _nand) and(1, s, t);
        else if(func == _slt) slt(s, t);
        else if(func == _sll) sll(t, shamt);
        else if(func == _srl) sr(0, t, shamt);
        else if(func == _sra) sr(1, t, shamt);
    }
}
Пример #3
0
// read a char from io buf
inline char a2_io_readchar(struct a2_io* io_p){
	assert(io_p);
	if(is_end(io_p)) 
		return '\0';
	if(is_load(io_p, 0)) 
		_a2_io_load(io_p);
	
	return io_p->buf[io_p->seek++];
}
Пример #4
0
// match n char
inline char a2_io_matchchar(struct a2_io* io_p, int n){
	assert(io_p);
	if(_is_end(io_p, n))
		return '\0';
	else if (n<=0 && ((-n)<=io_p->seek) )
		return io_p->buf[io_p->seek+n];
	else if( n>0 && n<io_p->size){
		if(is_load(io_p, n))
			_a2_io_load(io_p);
		return io_p->buf[io_p->seek+n];
	}

	return '\0';
}