#ifndef __pipeline_fs #define __pipeline_fs /****************************************************************************** ** FILE: pipeline.fs ** In-order pipeline simulation using reservation tables. */ extern cache_load(ulong) : ulong; extern cache_store(ulong) : ulong; extern instructions : ullong; val instructions = 0?cvt(ullong); extern cycles : ullong; val cycles = 0?cvt(ullong); #define NONE 0x00 #define ALU1 0x04 #define ALU2 0x08 #define FPU 0x10 #define LOAD 0x20 #define STORE 0x40 type Pipe = struct { resources : uchar queue, instructions : struct { ready : uchar, dest : ushort } queue }; val pipe : Pipe = struct { resources = queue{}, instructions = queue{} }; type InstInfo1 = struct { reserve : uchar array[2], ready : uchar }; val _alu1_1 = struct { reserve = array { ALU1, NONE }, ready = 1?cvt(uchar) }; val _alu1_2 = struct { reserve = array { NONE, ALU1 }, ready = 2?cvt(uchar) }; val _alu2_1 = struct { reserve = array { ALU2, NONE }, ready = 1?cvt(uchar) }; val _alu2_2 = struct { reserve = array { NONE, ALU2 }, ready = 2?cvt(uchar) }; val _fpu = struct { reserve = array { FPU, FPU }, ready = 2?cvt(uchar) }; val _load1 = struct { reserve = array { ALU1, LOAD }, ready = 2?cvt(uchar) }; val _load2 = struct { reserve = array { ALU2, LOAD }, ready = 2?cvt(uchar) }; val _store1 = struct { reserve = array { ALU1, STORE }, ready = 0?cvt(uchar) }; val _store2 = struct { reserve = array { ALU2, STORE }, ready = 0?cvt(uchar) }; type InstInfo = InstInfo1 queue; const val alu : InstInfo = queue { _alu1_1, _alu1_2, _alu2_1, _alu2_2 }; const val fpu : InstInfo = queue { _fpu }; const val load : InstInfo = queue { _load1, _load2 }; const val store :InstInfo = queue { _store1, _store2 }; val srcQ : ushort queue = queue {}; val storeQ : ushort queue = queue {}; val destQ : ushort queue = queue {}; val address = 0; fun ready(var reserve : uchar array[2]) { val ii = 0; while(ii < 2) { val funit = reserve[ii]; if(ii < pipe.resources?length) if((funit & pipe.resources[+ii]) != 0?cvt(uchar)) return false; if(funit & (ALU1|ALU2|FPU) != 0?cvt(uchar)) { val jj = 0; while(jj < pipe.instructions?length) { var old = pipe.instructions[+jj]; val kk = 0; while(kk < srcQ?length) { if(srcQ[+kk] == old.dest) if(old.ready > 0?cvt(uchar)) return false; kk = kk + 1; } jj = jj + 1; } } else if(funit == STORE) { val jj = 0; while(jj < pipe.instructions?length) { var old = pipe.instructions[+jj]; val kk = 0; while(kk < storeQ?length) { if(storeQ[+kk] == old.dest) if(old.ready > 0?cvt(uchar)) return false; kk = kk + 1; } jj = jj + 1; } } ii = ii + 1; } return true; } fun update_pipe(var inst1 : InstInfo1) { val ready = inst1.ready?cvt(ulong); val ii = 0; while(ii < 2) { val funit = inst1.reserve[ii]; if(ii < pipe.resources?length) { var funits = pipe.resources[+ii]; funits = funits | funit; } else pipe.resources?push_back(funit); val delay = 0; if(funit == LOAD) delay = cache_load(address)?static(); else if(funit == STORE) delay = cache_store(address)?static(); val jj = 0; while(jj < delay) { ii = ii + 1; if(ready > 0) ready = ready + 1; if(ii < pipe.resources?length) { var funits = pipe.resources[+ii]; funits = funits | funit; } else pipe.resources?push_back(funit); jj = jj + 1; } ii = ii + 1; } if(ready > 0) { ii = 0; while(ii < destQ?length) { pipe.instructions?push_back(struct { ready = ready?cvt(uchar), dest = destQ[+ii] }); ii = ii + 1; } } } fun delay_pipe() { pipe.resources?pop_front(); val ii = 0; val new_first = 0; while(ii < pipe.instructions?length) { var inst = pipe.instructions[+ii]; if(inst.ready > 0?cvt(uchar)) inst.ready = inst.ready - 1?cvt(uchar); if(inst.ready > 0?cvt(uchar) && new_first <= 0) new_first = ii; ii = ii + 1; } pipe.instructions?pop_front(new_first?cvt(uchar)); cycles = cycles + 1?cvt(ullong); } fun schedule(var inst : InstInfo) { while(true) { val ii = 0; while(ii < inst?length) { if(ready(inst[+ii].reserve)) { update_pipe(inst[+ii]); return; } ii = ii + 1; } delay_pipe(); } } #endif