📄 dlxdoc.cpp
字号:
// DlxDoc.cpp : implementation of the CDlxDoc class
//
#include "stdafx.h"
#include "Architecture.h"
#include "Globals.h"
#include "PeriodDlg.h"
#include "RegDlg.h"
#include "MemDlg.h"
#include "CodeMemDlg.h"
#include "DlxDoc.h"
#include "mybar.h"
#include "MemBar.h"
#include "RegBar.h"
#include "codemem.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CDlxApp theApp;
extern CMyBar * MyBar;
extern CMemBar * MemBar;
extern CRegBar * RegBar;
extern CCodeMemBar * CodeMemBar;
CDlxDoc* MyDoc;
Operation OpCode[MAXOPERATION] =
{{"LW",LW},{"SW",SW},{"ADD",ADD},{"SUB",SUB},{"MUT",MUT},
{"DIV",DIV},{"AND",AND},{"OR",OR},{"XOR",XOR},{"ADDI",ADDI},
{"SUBI",SUBI},{"MUTI",MUTI},{"DIVI",DIVI},{"ANDI",ANDI},{"ORI",ORI},
{"XORI",XORI},{"BEQZ",BEQZ},{"BNEZ",BNEZ},{"J",J},{"JR",JR},
{"TRAP",TRAP}};
const CString OpMachineCode[MAXOPERATION] =
{
"010001","010010","100001","100010","100011",
"100100","100101","100110","101111","010011",
"010100","010101","010110","010111","011000",
"011001","011010","011011","110001","011100",
"111111"
} ;
Tokentype Lookout(const char * mcode)
{
for(int i=0;i<MAXOPERATION;i++)
if(!strcmp(OpMachineCode[i],mcode))
return OpCode[i].tok;
return UNKNOWN;
}
Tokentype Lookup(const char * name)
{
for(int i=0; i < MAXOPERATION; i++)
if(!strcmp(OpCode[i].name,name))
return OpCode[i].tok;
return UNKNOWN;
}
/////////////////////////////////////////////////////////////////////////////
// CDlxDoc
IMPLEMENT_DYNCREATE(CDlxDoc, CDocument)
BEGIN_MESSAGE_MAP(CDlxDoc, CDocument)
//{{AFX_MSG_MAP(CDlxDoc)
ON_COMMAND(ID_SET_PERIOD, OnSetPeriod)
ON_COMMAND(ID_EXE_RUN, OnExeRunStep)
ON_COMMAND_RANGE(ID_SET_FWD,ID_SET_NFWD,OnSetFwd)
ON_COMMAND_RANGE(ID_SET_FLUSH,ID_SET_DELAY,OnSetBranch)
ON_UPDATE_COMMAND_UI_RANGE(ID_SET_FWD, ID_SET_NFWD, OnUpdateFwd)
ON_UPDATE_COMMAND_UI_RANGE(ID_SET_FLUSH, ID_SET_DELAY, OnUpdateBranch)
ON_COMMAND(ID_EXE_RESET, OnExeReset)
ON_COMMAND(ID_SET_MEM, OnSetMem)
ON_COMMAND(ID_SET_REG, OnSetReg)
ON_COMMAND(ID_SAVE, OnSave)
ON_COMMAND(MY_ID_RESET, OnIdReset)
ON_COMMAND(MY_ID_COMPLE, OnIdComple)
ON_COMMAND(MY_ID_RUN, OnIdRun)
ON_COMMAND(ID_SET_CODEMEM, OnSetCodemem)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlxDoc construction/destruction
CDlxDoc::CDlxDoc() :m_Forwarding(ID_SET_NFWD),m_Branch(ID_SET_FLUSH),
m_MulPeriod(4),m_DivPeriod(4),m_InstructionNum(4),
m_CurInstr(0),m_Clock(0),m_Pc(0)
{
for(int i=0; i<MAXREGS; i++)
this->m_Register[i] = 0; //对所有寄存器置初值
for(i=0; i<MAXMEM; i++){
this->m_Memory[i] = 0; //对所有DATA内存置初值
this->m_CodeMemory[i] = "00000000000000000000000000000000";
}
for(i=0; i<MAXPC; i++)
{
this->m_Instruction[i].cmdString = "TRAP";
this->m_Instruction[i].outstate = _S_STALL;
this->m_Instruction[i].period = 1;
this->m_Instruction[i].state = _S_STALL;
for(int j = 0; j < 5; j++)
this->m_Instruction[j].forward[j][0] =
this->m_Instruction[j].forward[j][1] =
CSize(0,0);
}
}
CDlxDoc::~CDlxDoc()
{
}
BOOL CDlxDoc::OnNewDocument()
{
MyDoc = this;
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//函数名:Serialize() 功能:从外部文件读入程序指令 存放到m_CmdString
//参数:文件流 返回值: 无
/////////////////////////////////////////////////////////////////////////////
void CDlxDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
int i=0;
do
{
ar.ReadString(this->m_CmdString[i]);
this->m_CmdString[i].MakeUpper();
} while(this->m_CmdString[i++] != "TRAP");
i--;
this->SetInstructionNum(i);
this->OnExeReset();
this->UpdateAllViews(NULL);
}
}
/////////////////////////////////////////////////////////////////////////////
// CDlxDoc diagnostics
#ifdef _DEBUG
void CDlxDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CDlxDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDlxDoc commands
void CDlxDoc::OnSetPeriod()
{
// TODO: Add your command handler code here
CPeriodDlg dlg;
dlg.m_Mul = this->GetMulPeriod();
dlg.m_Div = this->GetDivPeriod();
if(dlg.DoModal() == IDOK)
{
this->SetMulPeriod(dlg.m_Mul);
this->SetDivPeriod(dlg.m_Div);
}
}
//////////////////////////////////////////
//函数名: OnExeRunStep() 功能:执行当前指令
//参数: 无 返回参数:无
/////////////////////////////////////////
void CDlxDoc::OnExeRunStep()
{
// OnSave();
UINT forward = GetForwarding();
UINT branch = GetBranch();
int instrNum = GetInstructionNum();
if(m_Clock >= MAXCLOCK)
return;
//遍历当前正在流水线上执行的所有指令
for(int i=0,j=0,stall=0; i < m_CurInstr; i++)
{
Tokentype t = ::Lookup(LPCSTR(m_Instruction[i].op));
//如果上一条指令在此时钟周期上stall则该条指令也stall
if(i && m_Instruction[i-1].states[ m_Clock] == _S_STALL)
m_Instruction[i].states[ m_Clock] = _S_STALL;
else
switch( m_Instruction[i].state)
{
case _S_IF:
//采用预测转移不成功策略
if(i && branch == ID_SET_UNTAKEN && this->m_Pc != m_Instruction[i].pc+1)
{
m_Instruction[i].state = _S_IDLE;
m_Instruction[i].states[ m_Clock] = _S_IDLE;
this->m_Instruction[i].exetimes = 1;
break;
}
//Forwarding
if(m_Instruction[i].src1.GetLength())
//从该指令开始往前遍历该指令前的所有指令
for(j=i-1; j>=0; j--)
{
Instruction * pInstr = & m_Instruction[j];
if(pInstr->states[ m_Clock] < _S_HALT&&
pInstr->dest == m_Instruction[i].src1&&
pInstr->dest.GetAt(0) == 'R')
{
if(forward == ID_SET_FWD && pInstr->state == _S_WB)
m_Instruction[i].forward[_S_IF][0] =
CSize( m_Clock,j);
else if(t == BEQZ || t == BNEZ || t == J || t == JR)
{
if(forward == ID_SET_FWD && pInstr->state > _S_EXE
&& pInstr->state > pInstr->outstate)
m_Instruction[i].forward[_S_IF][0] =
CSize( m_Clock,j);
else
stall = 1;
}
break;
}
}
//Forwarding
if(!stall&&m_Instruction[i].src2.GetLength())
//从该指令开始往前遍历该指令前的所有指令
for(j=i-1; j>=0; j--)
{
Instruction * pInstr = & m_Instruction[j];
if(pInstr->states[ m_Clock] < _S_HALT&&
pInstr->dest == m_Instruction[i].src2&&
pInstr->dest.GetAt(0) == 'R')
{
if(forward == ID_SET_FWD && pInstr->state == _S_WB)
m_Instruction[i].forward[_S_IF][1] =
CSize( m_Clock,j);
else if(t == BEQZ || t == BNEZ || t == J || t == JR)
{
if(forward == ID_SET_FWD && pInstr->state > _S_EXE
&& pInstr->state > pInstr->outstate)
m_Instruction[i].forward[_S_IF][1] =
CSize( m_Clock,j);
else
{
m_Instruction[i].forward[_S_IF][0] = CSize(0,0);
stall = 1;
}
}
break;
}
}
if(!stall)
{
m_Instruction[i].state++;
m_Instruction[i].states[ m_Clock] = _S_ID;
}
else
m_Instruction[i].states[ m_Clock] = _S_STALL;
break;
case _S_ID:
//ALU 唯一
if (i && m_Instruction[i-1].states[ m_Clock] == _S_EXE)
{
m_Instruction[i].states[ m_Clock] = _S_STALL;
break;
}
if(m_Instruction[i].src1.GetLength()&&t != BEQZ&&t != BNEZ&&t != J&&t != JR)
for(j=i-1; j>=0; j--)
{
Instruction * pInstr = & m_Instruction[j];
if(pInstr->states[ m_Clock] < _S_HALT&&
pInstr->dest == m_Instruction[i].src1&&
pInstr->dest.GetAt(0) == 'R')
{
if(forward == ID_SET_FWD && pInstr->state > _S_EXE
&& pInstr->state > pInstr->outstate)
m_Instruction[i].forward[_S_ID][0] =
CSize( m_Clock,j);
else
stall = 1;
break;
}
}
if(!stall && m_Instruction[i].src2.GetLength()&&t != BEQZ&&t != BNEZ&&t != J&&t != JR)
for(j=i-1; j>=0; j--)
{
Instruction * pInstr = & m_Instruction[j];
if(pInstr->states[ m_Clock] < _S_HALT&&
pInstr->dest == m_Instruction[i].src2)
{
if(forward == ID_SET_FWD && pInstr->state > _S_EXE
&& pInstr->state > pInstr->outstate)
m_Instruction[i].forward[_S_ID][1] =
CSize( m_Clock,j);
else
{
m_Instruction[i].forward[_S_ID][0] =
CSize(0,0);
stall = 1;
}
break;
}
}
if(!stall)
{
m_Instruction[i].state++;
m_Instruction[i].states[ m_Clock] = _S_EXE;
m_Instruction[i].exetimes++;
CString temp;
temp = this->m_Instruction[i].src1;
if(temp.GetLength())
if(temp.GetAt(0) == 'R')
{
temp.Delete(0);
m_Instruction[i].val1 = ::atoi(LPCSTR(temp));
m_Instruction[i].val1 = this->m_Register[m_Instruction[i].val1];
}
else
m_Instruction[i].val1 = ::atoi(LPCSTR(temp));
temp = this->m_Instruction[i].src2;
if(temp.GetLength())
if(temp.GetAt(0) == 'R')
{
temp.Delete(0);
m_Instruction[i].val2 = ::atoi(LPCSTR(temp));
m_Instruction[i].val2 = this->m_Register[m_Instruction[i].val2];
}
else
m_Instruction[i].val2 = ::atoi(LPCSTR(temp));
//Forwarding
CSize size;
if((size=m_Instruction[i].forward[_S_ID-1][0]) != CSize(0,0))
{
m_Instruction[i].val1 = m_Instruction[size.cy].val0;
}
if((size=m_Instruction[i].forward[_S_ID-1][1]) != CSize(0,0))
{
m_Instruction[i].val2 = m_Instruction[size.cy].val0;
}
//Branch
switch(t)
{
case BEQZ:
if(m_Instruction[i].val1 == 0)
this->m_Pc = this->m_Instruction[i].pc+::atoi(LPCSTR(this->m_Instruction[i].dest))/4;
break;
case BNEZ:
if(m_Instruction[i].val1 != 0)
this->m_Pc = this->m_Instruction[i].pc+::atoi(LPCSTR(this->m_Instruction[i].dest))/4;
break;
case J:
this->m_Pc = ::atoi(LPCSTR(this->m_Instruction[i].dest))/4;
break;
case JR:
temp = this->m_Instruction[i].src1;
temp.Delete(0);
this->m_Pc = this->m_Register[::atoi(LPCSTR(temp))]/4;
break;
default:
break;
}
//Forwarding
if((size=m_Instruction[i].forward[_S_ID][0]) != CSize(0,0))
{
m_Instruction[i].val1 = m_Instruction[size.cy].val0;
}
if((size=m_Instruction[i].forward[_S_ID][1]) != CSize(0,0))
{
m_Instruction[i].val2 = m_Instruction[size.cy].val0;
}
}
else
{
m_Instruction[i].states[ m_Clock] = _S_STALL;
}
break;
case _S_EXE:
if( m_Instruction[i].exetimes < m_Instruction[i].period)
{
m_Instruction[i].states[ m_Clock] = _S_EXE;
m_Instruction[i].exetimes++;
}
else
{
if( m_Instruction[i].outstate == _S_EXE)
this->InstructionExe(i,m_Instruction[i].val1,m_Instruction[i].val2,1);
m_Instruction[i].state++;
m_Instruction[i].states[ m_Clock] = _S_MEM;
}
break;
case _S_MEM:
if( m_Instruction[i].outstate == _S_MEM)
this->InstructionExe(i,m_Instruction[i].val1,m_Instruction[i].val2,1);
m_Instruction[i].state++;
m_Instruction[i].states[ m_Clock] = _S_WB;
break;
case _S_WB:
m_Instruction[i].state++;
m_Instruction[i].states[ m_Clock] = _S_HALT;
this->InstructionExe(i,m_Instruction[i].val1,m_Instruction[i].val2,0);
break;
case _S_HALT:
m_Instruction[i].states[ m_Clock] = _S_HALT;
break;
case _S_IDLE:
if( m_Instruction[i].exetimes < 4)
{
m_Instruction[i].states[ m_Clock] = _S_IDLE;
m_Instruction[i].exetimes++;
}
else
{
m_Instruction[i].state = _S_HALT;
m_Instruction[i].states[ m_Clock] = _S_HALT;
}
break;
default:
::AfxMessageBox("Unexpected fatat error during OnExeRunStep!\n");
}// switch end
}// for end
//取新指令执行,初始化指令(配置指令)
if (this->m_Pc < instrNum) //指令还没有全部执行
if (i==0)
{
this->m_Instruction[i].pc = this->m_Pc;
m_CmdString[m_Pc] = DisCompileInstruction(m_Pc);
this->m_Instruction[i].cmdString = this->m_CmdString[m_Pc++]; //取当前指令
this->SetInstruction(i); //设置指令
m_CurInstr++;
}
else if(m_Instruction[i-1].states[ m_Clock] != _S_STALL)
switch(::Lookup(LPCSTR(m_Instruction[i-1].op)))
{
case BEQZ:
case BNEZ:
case J:
case JR:
if((branch != ID_SET_FLUSH && branch != ID_SET_TAKEN)
|| m_Instruction[i-1].state != _S_ID)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -