五級經典流水線執行 時間統計
阿新 • • 發佈:2019-01-05
五級經典流水線執行
時間統計
forwarding策略:來自EX/MEM 和 MEM/EX 流水線暫存器的ALU結果總是被反饋回ALU的輸入端
也就是,下一條指令,直接可以從上一條指令的EX中獲得資料
但是,forwarding演算法並不是完美的
它需要停頓的資料冒險:
LD/LW 的資料要在MEM結束以後才能將資料傳給下一個指令的ALU(即EX環節)
所以載入指令需要增加一種稱為流水線互鎖 , 以保持正確的執行模式
流水線互鎖檢測冒險 , 並在該冒險被清除之前使流水線停頓
每個時鐘週期只能新增一條指令
關於指令型別:
本實驗提供的指令序列檔案,不包含跳轉指令,只涉及到ALU指令和load/store指令,Trace中會出現的指令型別主要是如下的幾種:
ALU型別:DADD, DSUB, AND, OR, XOR
Load/store型別:LD, SD, LW, SW
模擬器正確性的驗證:
trace4.txt:
DADD R2, R3, R1
DSUB R4,, R2, R1
LW R7, 0(R1)
DADD R6, R5,, R7
XOR R5, R6, R4
AND R3, R5, R2
AND R3, R5, R2
注意點:
1、只有當LD/LW 的 目的運算元 , 作為下一條指令的元運算元時 , 才會發生停頓!!!!
2、每個始終週期只能執行一條指令
這也是為什麼,最後一條指令要往後再退一格
程式碼:
#include #include #include #include #include #include using namespace std; int main() { string buffer; string str[4]; string temp = "normal"; int index = 0;//判斷是否 int num = 0; ifstream in("trace4.txt"); if (! in.is_open()) { cout << "Error opening file"; exit (1); } //初始 num = 4; while (!in.eof() ) { //每執行一條指令至少多一個cycle num++; //cout << buffer << endl; getline空格也算一個字元 getline(in, buffer);/*要用#include*/ int s = 0, i; istringstream stream(buffer); stream >> str[0] >> str[1] >> str[2] >> str[3]; //一個字串一個字串地取出 //去掉逗號 size_t found; for(i=1 ; i<4 ; i++){ found = str[i].find(','); while(found != string::npos){ str[i] = str[i].erase(found,1); found = str[i].find(','); } } //去掉括號,去掉多餘的數字 if(str[0] == "LD" || str[0] == "LW" || str[0] == "SD" || str[0] == "SW") str[2] = str[2].substr(str[2].find("(")+1 ,str[2].find(")")-str[2].find("(")-1); //輸出檢驗 //cout << str[0] << str[1] << str[2] << str[3] << endl; //如果是Load的時候,做標記,因為只有在lod的時候會導致 , 整個流水線出現停頓的情況 if(str[0] == "LD" || str[0] == "LW"){ temp = str[1]; } else{ if(temp == "normal") continue; else{ //只有當上一個是LD / LW ,且LD / LW 的下一條命令中 , 有上一條命令的目的運算元時 //會對下一條命令產生影響,否則不會 if(str[0] == "SD" || str[0] == "SW"){ if(str[1] == temp || str[2] == temp ) num++; temp = "normal"; }else{ if(str[1] == temp || str[2] == temp || str[3] == temp) num++; temp = "normal"; } } } } cout << "num of cycles =" << num << endl; return 0; }