#ifndef _funits_fs #define _funits_fs /****************************************************************************** ** FILE: funits.fs ** Manage function units in the OOO processor model. */ #include "param.h" #include "instq.fs" #include "funits.h" #include "cache.fs" /////////////////////////////////////////////////////////////////////////////// // Limit the number of each type of functional units. // fu_alloc() -- try to allocate one of the functional units // fu_clear() -- free all allocated units // const val fu_pool = array(FU_END1) { 0, // FU_NONE 2, // FU_ALU: 2 dyintegers ALUs 2, // FU_FPU: 2 floating-point units 1 // FU_ADDR: 1 address adder }; val fu_num_allocated = array(FU_END1) { 0 }; fun fu_alloc(ftype) { assert(ftype?cvt(ulong) < FU_END); if(ftype?cvt(ulong) >= FU_END1) return true; if(fu_num_allocated[ftype] >= fu_pool[ftype]) return false; fu_num_allocated[ftype] = fu_num_allocated[ftype] + 1; return true; } fun fu_clear() { fu_num_allocated = array(FU_END1) { 0 }; } /////////////////////////////////////////////////////////////////////////////// // fu_finish() -- called when the timer runs out on an instruction that has // been assigned a function unit. This means that the instruction is finished // with the function unit and is ready to move on. // Returns true if the instruction is ready to execute (in the execute() // function). Otherwise returns false. // fun fu_finish(ftype, var inst : InstOp, inum) { switch(ftype?cvt(ulong)) { case FU_ALU: return true; case FU_FPU: return true; case FU_ADDR: val op = inst.op?cvt(ulong); val va = (rmap_read(inst.srcq[+0],inum) + rmap_read(inst.srcq[+1],inum))?cvt(ulong); val delay : short; assert(inst.align <= 3?cvt(uchar)); if((va & ((1<<inst.align?cvt(ulong))-1)) != 0) { if(inum > 0) { inst.ftime = 1?cvt(uchar); return false; } } // Unknown store address => no more loads or stores if(unk_store_addr) { inst.ftime = 1?cvt(uchar); return false; } if(OP_LOAD_BEGIN <= op && op <= OP_LOAD_END) { if(cache_load_start(inum,va,no_loads,delay)) return true; // HIT delay?static; if(delay >= 0?cvt(short)) { inst.ftype = FU_LOAD?cvt(uchar); // MISS inst.ftime = delay?cvt(uchar); } else { // cache access aborted inst.ftime = (-delay)?cvt(uchar); unk_load_addr = true; } } else if(OP_STORE_BEGIN <= op && op <= OP_STORE_END) { // Unknown load address => store must issue speculatively if(cache_store_start(inum,va,is_spec||unk_load_addr,delay)) { // Successful hand-off to cache delay?static; assert(delay >= 0?cvt(short)); if(!is_spec && !unk_load_addr && delay == 0?cvt(short)) { // This store committed inst.ftype = FU_NONE?cvt(uchar); return true; } else { // This store still needs to be committed inst.ftype = FU_STORE?cvt(uchar); if(delay == 0?cvt(short)) inst.ftime = 1?cvt(uchar); else { assert(delay > 0?cvt(short)); inst.ftime = delay?cvt(uchar); } } } else { // cache access aborted delay?static; assert(delay < 0?cvt(short)); inst.ftime = (-delay)?cvt(uchar); unk_store_addr = true; } } else { assert(OP_SWAP_BEGIN <= op && op <= OP_SWAP_END); // Unknown load address => store must issue speculatively if(cache_store_start(inum,va,is_spec||unk_load_addr,delay)) { // Successful hand-off to cache delay?static; assert(delay >= 0?cvt(short)); if(!is_spec && !unk_load_addr && delay == 0?cvt(short)) { // This store committed inst.ftype = FU_NONE?cvt(uchar); return true; } else { // This store still needs to be committed inst.ftype = FU_STORE?cvt(uchar); if(delay == 0?cvt(short)) inst.ftime = 1?cvt(uchar); else { assert(delay > 0?cvt(short)); inst.ftime = delay?cvt(uchar); } } } else { // Cache access aborted delay?static; assert(delay < 0?cvt(short)); inst.ftime = (-delay)?cvt(uchar); unk_store_addr = true; } } case FU_LOAD: val delay : short; if(cache_load_continue(inum, delay)) return true; inst.ftime = delay?static?cvt(uchar); case FU_STORE: if(!is_spec && !unk_load_addr) { val delay : short; if(cache_store_commit(inum,delay)) { // This store committed inst.ftype = FU_NONE?cvt(uchar); return true; } else { // Conflicts still exist => try again later delay?static; assert(delay > 0?cvt(short)); inst.ftime = delay?cvt(uchar); } } else inst.ftime = 1?cvt(uchar); default: // Unexpected ftype assert(false); } return false; } #endif