⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 execinstctrl.cpp

📁 一个牛人做的MIPS模拟器
💻 CPP
字号:
// ExecInstCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "pipeline.h"
#include "ExecInstCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CExecInstCtrl

CExecInstCtrl::CExecInstCtrl()
{
	Reset();
}

CExecInstCtrl::~CExecInstCtrl()
{
	if(memDC.GetSafeHdc() != NULL)
	{
		memDC.SelectObject( m_pOldBitmap );
		if( m_pBitmap != NULL )
			delete m_pBitmap;

		memDC.SelectObject( m_pOldFont );
	}
	if( !m_rowList.IsEmpty() ) {
		ITEM_ROW* row = m_rowList.RemoveHead();
		delete row;
	}
}

BEGIN_MESSAGE_MAP(CExecInstCtrl, CWnd)
	//{{AFX_MSG_MAP(CExecInstCtrl)
	ON_WM_PAINT()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExecInstCtrl message handlers

BOOL CExecInstCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd)
{
	m_pParentWnd = pParentWnd;
	scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);

	// create window
	static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,AfxGetApp()->LoadStandardCursor(IDC_ARROW));
	BOOL ret = CWnd::CreateEx( 0/*WS_EX_CLIENTEDGE*/, className, NULL, dwStyle, 
		rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), 0);
	// init virtual screen
	GetClientRect( rcClient );
	CClientDC dc( this );
	if( memDC.GetSafeHdc() == NULL ) {
		memDC.CreateCompatibleDC( &dc );

		if( (m_pBitmap = new CBitmap()) == NULL ) return FALSE;
		m_pBitmap->CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );	
		m_pOldBitmap = memDC.SelectObject( m_pBitmap );

		CFont NewFont;
		NewFont.CreateFont( -13, 0, 0, 0, FW_MEDIUM, 0, 0,
			0, 134, 3, 2, 1, 2, "Courier New" );
		m_pOldFont = memDC.SelectObject( &NewFont );
		memDC.SetBkMode( TRANSPARENT );
	}
	memDC.FillSolidRect( &rcClient, m_BkColor );

	return ret;
}

void CExecInstCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	if( memDC.GetSafeHdc() != NULL )
		dc.BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY );
}

void CExecInstCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	if(pScrollBar == GetScrollBarCtrl(SB_HORZ))
	{
		if(nSBCode == SB_LEFT || nSBCode == SB_LINELEFT || nSBCode == SB_PAGELEFT)
			x_offset -= m_nColWidth;
		if(nSBCode == SB_RIGHT || nSBCode == SB_LINERIGHT || nSBCode == SB_PAGERIGHT)
			x_offset += m_nColWidth;
		if(nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK)
			x_offset = nPos * m_nColWidth;
		if(x_offset < 0)
			x_offset = 0;
		if(x_offset / m_nColWidth > m_nMaxCol - 2)
			x_offset = (m_nMaxCol - 2) * m_nColWidth;
		SetScrollPos(SB_HORZ, x_offset / m_nColWidth, TRUE);
		DrawAll();
	}
}

void CExecInstCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	if(pScrollBar == GetScrollBarCtrl(SB_VERT))
	{
		if(nSBCode == SB_TOP || nSBCode == SB_LINEUP || nSBCode == SB_PAGEUP) {
			y_offset -= m_nRowHeight;
		} else if(nSBCode == SB_BOTTOM || nSBCode == SB_LINEDOWN ||	nSBCode == SB_PAGEDOWN) {
			y_offset += m_nRowHeight;
		} else if(nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK) {
			y_offset = nPos * m_nRowHeight;
		}
		if( y_offset < 0 ) y_offset = 0;
		if( y_offset / m_nRowHeight > m_nMaxRow - 2 )
			y_offset = (m_nMaxRow - 2) * m_nRowHeight;
		SetScrollPos(SB_VERT, y_offset / m_nRowHeight, TRUE);
		DrawAll();
	}
}

void CExecInstCtrl::NextCycle( BOOL bRedraw )
{
	if( m_nState == kComplete || simulator.m_nState == CMIPSSimulator::kComplete )
		return;

	// add new instructions
	if( m_nState == kNone || simulator.HasNewStep() ) {
		m_nState = kRun;
		CExecInst* pExecInst = simulator.GetNewExecInst();
		ASSERT( pExecInst );
		int address = pExecInst->pInst->m_nAddress;
		COLORREF textColor = pExecInst->color;
		CString instString = pExecInst->pInst->InstString();
		int StartCycle = simulator.GetCurCycle();
		UINT_ARRAY StageArray;
		simulator.GetStageArray(pExecInst, StageArray);
		AddExecInst( address, textColor, instString, StartCycle, StageArray );
	}
	m_nCurCycle++;

	// remove completed instructions
	if( m_bInstComplete )
		for( int i = 0; i < addressArray.GetSize(); i++ )
			RemoveExecInst( addressArray[i] );
	if( m_bIdleInstComplete )
		RemoveExecInst( -1 );
	m_bInstComplete = simulator.HasInstComplete( addressArray );
	m_bIdleInstComplete = simulator.HasIdleInstComplete();

	if( simulator.IsExecComplete() ) m_nState = kComplete;

	if( bRedraw ) DrawAll();
}

void CExecInstCtrl::Reset()
{
	image_size = CSize(0,0);
	x_offset = 0;
	y_offset = 0;

	m_BkColor = RGB(230,230,250);
	defaultTextBkColor = RGB(230,230,250);
	defaultTextFgColor = RGB(0,0,0);

	while( !m_rowList.IsEmpty() ) {
		ITEM_ROW* row = m_rowList.RemoveHead();
		delete row;
	}
	m_nMaxRow = 0;
	m_nMaxCol = 0;
	m_nStartCycle = 0;
	m_nCurCycle = -1;
	m_bInstComplete = FALSE;
	m_bIdleInstComplete = FALSE;

	m_nState = kNone;
}

void CExecInstCtrl::ResetAndUpdate()
{
	Reset();
//	UpdateAll();
}

BOOL CExecInstCtrl::SetBackColor(COLORREF color)
{
	m_BkColor = color;
	return TRUE;
}

BOOL CExecInstCtrl::SetFont(CFont* pFont, BOOL bRedraw/*= TRUE*/)
{
	memDC.SelectObject( pFont );
	if( bRedraw ) Invalidate();
	return TRUE;
}

void CExecInstCtrl::AddExecInst( int address, COLORREF textColor,
	CString& instString, int StartCycle, UINT_ARRAY& StageArray )
{
	if( m_nMaxRow == 0 ) {
		m_nMaxRow = 1;
		m_nStartCycle = StartCycle;
		m_nCurCycle = StartCycle - 1;
		// add fixed row
		ITEM_ROW* row = new ITEM_ROW;
		row->m_nAddress = -1;
		m_rowList.AddHead( row );
	}
	m_nMaxRow += 1;
	UINT offset = StartCycle - m_nStartCycle + 1;
	UINT num = offset + StageArray.GetSize();
	if( m_nMaxCol < num ) {
		m_nMaxCol = num;
		AdjustFixRow();
	}
	// add row
	ITEM_ROW* row = new ITEM_ROW;
	row->m_nAddress = address;
	row->m_nStartCycle = StartCycle;
	// adjust this row
	ITEM item;
	item.row = m_nMaxRow - 1;
	item.m_TextBkColor = defaultTextBkColor;
	for( UINT col = 0; col < num; col++ ) {
		item.col = col;
		item.m_TextFgColor = defaultTextFgColor;
		if( col == 0 ) {
			item.szText = CString(_T(" ")) + instString;
			item.m_TextFgColor = textColor;
		} else if( col < offset )
			item.szText = _T("");
		else
			item.szText = MIPSStage[ StageArray[col-offset] ];
		row->m_itemList.AddTail( item );
	}
	m_rowList.AddTail( row );

	AdjustClientArea();
}

void CExecInstCtrl::RemoveExecInst( int address )
{
	int  index = 1;
	BOOL found = FALSE;
	ITEM_ROW* remove = NULL;
	POSITION pos = m_rowList.GetHeadPosition();
	m_rowList.GetNext( pos );// fix row
	while( pos ) {
		remove = m_rowList.GetNext( pos );
		if( remove->m_nAddress == address ) {
			found = TRUE; break;
		}
		index++;
	}
	// This inst should be existed
	if( !found ) {
#ifdef _DEBUG
		AfxMessageBox( "CExecInstCtrl::RemoveExecInst() error." );
#endif //_DEBUG
		return;
	}
	if( index == 1 && pos ) {
		// need to adjust following rows
		ITEM_ROW* next = m_rowList.GetNext( pos );
		UINT offset = next->m_nStartCycle - remove->m_nStartCycle;
		m_nMaxCol -= offset;
		m_nStartCycle += offset;
		AdjustFixRow();
		for( int i = offset; i > 0; i-- )
			next->m_itemList.RemoveAt( next->m_itemList.FindIndex(i) );
		while( pos ) {
			next = m_rowList.GetNext( pos );
			for( int i = offset; i > 0; i-- )
				next->m_itemList.RemoveAt( next->m_itemList.FindIndex(i) );
		}
	}
	m_rowList.RemoveAt( m_rowList.FindIndex(index) );
	m_nMaxRow--;
	delete remove;

	AdjustClientArea();
}

// When m_nStartCycle or m_nMaxCol changed, call this function
void CExecInstCtrl::AdjustFixRow()
{
	ITEM_ROW* row = m_rowList.GetHead();
	row->m_itemList.RemoveAll();
	UINT cycle = m_nStartCycle;
	ITEM item;
	item.row = 0;
	item.m_TextBkColor = defaultTextBkColor;
	item.m_TextFgColor = defaultTextFgColor;
	for( UINT col = 0; col < m_nMaxCol; col++ ) {
		item.col = col;
		if( col == 0 )
			item.szText = _T("");
		else
			item.szText.Format( "%u", cycle++ );
		row->m_itemList.AddTail( item );
	}
}

// call this function when contents of the control
// or the client rect is changed
void CExecInstCtrl::AdjustClientArea()
{
	//reset scrollbar
	SCROLLINFO si;
	si.fMask = SIF_PAGE | SIF_RANGE;
	si.nMin = 0;
	si.nMax = 0;
	si.nPage = 0;
	SetScrollInfo(SB_HORZ, &si, TRUE);
	SetScrollInfo(SB_VERT, &si, TRUE);
	
	//redraw background
	GetClientRect(&rcClient);
	memDC.FillSolidRect(&rcClient, m_BkColor);

	// calculate image size
	CSize nMargin = memDC.GetTextExtent( _T(" "), 1 );
	m_nFixColWidth = 22 * nMargin.cx;
	m_nColWidth = 7 * nMargin.cx;
	m_nFixRowHeight = m_nRowHeight = nMargin.cy + 4;

	image_size.cy = m_nRowHeight * m_nMaxRow;
	image_size.cx = m_nFixColWidth + (m_nMaxCol - 1) * m_nColWidth;
	
	// check if image size fits the client rect
	rcClient.bottom -= scrollbar_width;
	// VScrollBar
	ShowScrollBar(SB_HORZ);
	si.nMax = m_nMaxCol - 2;
	SetScrollInfo(SB_HORZ, &si, TRUE);

	BOOL y_fit;
	y_fit = (image_size.cy <= rcClient.Height());
	if( !y_fit )
		rcClient.right -= scrollbar_width;
	if( !y_fit ) {
		// show HScrollBar
		ShowScrollBar(SB_VERT);
		si.nMax = m_nMaxRow - 2;
		SetScrollInfo(SB_VERT, &si, TRUE);
	}
}

BOOL CExecInstCtrl::GetItem( int row, int col, ITEM& outItem )
{
	if( row < -1 || row >= m_rowList.GetCount() )
		return FALSE;
	ITEM_ROW* _row = m_rowList.GetAt( m_rowList.FindIndex(row) );
	if( col < -1 || col >= _row->m_itemList.GetCount() )
		return FALSE;
	outItem = _row->m_itemList.GetAt( _row->m_itemList.FindIndex(col) );
	return TRUE;
}

void CExecInstCtrl::DrawItem( int row, int col, BOOL TextOnly, BOOL invalid )
{
	CRect rect;
	if( row == 0 ) rect.top = 0;
	else rect.top = m_nFixRowHeight + (row-1)*m_nRowHeight;
	rect.bottom = m_nFixRowHeight + row*m_nRowHeight - 1;
	if( col == 0 ) rect.left = 0;
	else rect.left = m_nFixColWidth + (col-1)*m_nColWidth;
	rect.right = m_nFixColWidth + col*m_nColWidth - 1;

	if( row == 0 && col == 0 ) ;// do nothing
	else if( row == 0 ) {// fixed row
		rect.OffsetRect( -x_offset, 0 );
		if( rect.left < (int)m_nFixColWidth ) return;
	} else if( col == 0 ) {// fixed col
		rect.OffsetRect( 0, -y_offset );
		if( rect.top < (int)m_nFixRowHeight ) return;
	} else {
		// normal item
		rect.OffsetRect( -x_offset, -y_offset );
		if( rect.right < (int)m_nFixColWidth ||
			rect.bottom < (int)m_nFixRowHeight )
			// can't see, just return
			return;
	}

	ITEM item;
	if( GetItem(row, col, item) ) {
		if( !TextOnly )
			memDC.FillSolidRect( &rect, item.m_TextBkColor );
		memDC.SetTextColor( item.m_TextFgColor );
		if( col == 0 )
			memDC.DrawText( item.szText, &rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE );
		else
			memDC.DrawText( item.szText, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
	} else if( !TextOnly )
		memDC.FillSolidRect( &rect, defaultTextBkColor );
	if( invalid )
		InvalidateRect( &rect );
}

void CExecInstCtrl::DrawRow( int row, BOOL TextOnly, BOOL invalid )
{
	for( UINT col = 0; col < m_nMaxCol; col++ )
		DrawItem( row, col, TextOnly, invalid );
}

void CExecInstCtrl::DrawCol( int col, BOOL TextOnly, BOOL invalid )
{
	for( UINT row = 0; row < m_nMaxRow; row++ )
		DrawItem( row, col, TextOnly, invalid );
}

void CExecInstCtrl::DrawAll( BOOL invalid )
{
	memDC.FillSolidRect(&rcClient, m_BkColor);
	ShadeCol();
	for( int row = 0; row < m_rowList.GetCount(); row++ )
		DrawRow( row, TRUE/*text only*/, FALSE );
	if( invalid )
		Invalidate();
}

void CExecInstCtrl::ShadeCol()
{
	CRect rect;
	rect.left = m_nFixColWidth + (m_nCurCycle - m_nStartCycle) * m_nColWidth;
	rect.top = 0;
	rect.right = rect.left + m_nColWidth - 1;
	rect.bottom = rcClient.bottom;

	rect.OffsetRect( -x_offset, 0 );
	if( rect.right < (int)m_nFixColWidth ) return;
	memDC.FillSolidRect( &rect, RGB(200,200,200) );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -