1. 程式人生 > >深入理解計算機系統家庭作業第四章(4.43-4.54)

深入理解計算機系統家庭作業第四章(4.43-4.54)

/*

*****4.43 

*/

A.   根據4.6可知,push %esp 是將%esp的舊值壓入棧中;而這段程式碼壓入的新值,兩者不一致。

B.   將%esp的舊值先放入另一個暫存器中再進行操作

       movl   REG   %eax

       subl   $4   %esp

       movl   %eax   (%esp) 

/*

*****4.44

*/

A.   和4.7中描述的情況相比,第二條指令將%esp的值多加了4。

B.   同樣是引入另一個暫存器存放臨時值

       movl   (%esp)   ,%eax

       addl   $4   ,%esp

       movl   %eax   ,REG

/*

*****4.45

*/

A.   

void bubble_a(int *data, int count){
	int i,next;
	for(next = 1; next < count; next++){
		for(i = next - 1; i >= 0; i--)
			if(*(data + i + 1) < *(data + i)){
				int t = *(data + i + 1);
				*(data + i + 1) = *(data + i);
				*(data + i) = t;
			}
	}
}

B.

IA32程式碼:

bubble_b:
.LFB22:
	.cfi_startproc
	pushl	%edi
	.cfi_def_cfa_offset 8
	.cfi_offset 7, -8
	pushl	%esi
	.cfi_def_cfa_offset 12
	.cfi_offset 6, -12
	pushl	%ebx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	movl	16(%esp), %edx
	movl	20(%esp), %edi
	cmpl	$1, %edi
	jle	.L1
	subl	$1, %edi
	movl	$0, %esi
.L6:
	movl	%esi, %eax
	testl	%esi, %esi
	js	.L3
.L7:
	movl	4(%edx,%eax,4), %ecx
	movl	(%edx,%eax,4), %ebx
	cmpl	%ebx, %ecx
	jge	.L4
	movl	%ebx, 4(%edx,%eax,4)
	movl	%ecx, (%edx,%eax,4)
.L4:
	subl	$1, %eax
	cmpl	$-1, %eax
	jne	.L7
.L3:
	addl	$1, %esi
	cmpl	%edi, %esi
	jne	.L6
.L1:
	popl	%ebx
	.cfi_def_cfa_offset 12
	.cfi_restore 3
	popl	%esi
	.cfi_def_cfa_offset 8
	.cfi_restore 6
	popl	%edi
	.cfi_def_cfa_offset 4
	.cfi_restore 7
	ret
	.cfi_endproc
.LFE22:
	.size	bubble_b, .-bubble_b
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"%d "
	.text
	.globl	main
	.type	main, @function

Y86程式碼:
bubble_b:
.LFB22:
	.cfi_startproc
	pushl   %edi
	.cfi_def_cfa_offset 8
	.cfi_offset 7, -8
	pushl   %esi
	.cfi_def_cfa_offset 12
	.cfi_offset 6, -12
	pushl	%ebx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	mrmovl   16(%esp), %edx
	mrmovl   20(%esp), %edi
	irmovl   $1, %eax
	subl     %eax, %edi
	jle      .L1
	subl     $1, %edi
	irmovl   $0, %esi
.L6:
	rrmovl	 %esi, %eax
	irmovl   $0 , ebx 
	subl	 %ebx, %esi
	jl       .L3
.L7:
	rrmovl   %eax, %ecx
	addl     %ecx, %ecx
	addl     %ecx, %ecx
	addl     %edx, %ecx
	mrmovl   4(%ecx), %ecx
	rrmovl   %eax, %ebx
	addl     %ecx, %ebx
	addl     %ecx, %ebx
	addl     %edx, %ebx
	mrmovl   (%ebx), %ebx
	subl     %ebx, %ecx
	jge     .L4
	addl     %eax, %eax
	addl     %eax, %eax
	addl     %edx, %eax
	rmmovl   %ebx, 4(%eax)
	addl     %eax, %eax
	addl     %eax, %eax
	addl     %edx, %eax
	rmmovl   %ecx, 4(%eax)
.L4:
	subl	$1, %eax
	irmovl	$-1, %edx
	subl    %edx, %eax
	jne	.L7
.L3:
	addl	$1, %esi
	subl	%edi, %esi
	jne	.L6
.L1:
	popl	%ebx
	.cfi_def_cfa_offset 12
	.cfi_restore 3
	popl	%esi
	.cfi_def_cfa_offset 8
	.cfi_restore 6
	popl	%edi

	.cfi_def_cfa_offset 4
	.cfi_restore 7
	ret
	.cfi_endproc
.LFE22:
	.size	bubble_b, .-bubble_b
	.section	.rodata.str1.1,"aMS",@progbits,1	


/*

***4.46

*/

採用條件傳送的迴圈程式碼如下:

原始碼:

void bubble_c(int *data,int count)
{
	int i , next;
	int pre_ele,next_ele;
	for(next = 1;next < count;next++)
	{
		for(i = next -1;i >= 0;i--)
		{
			pre_ele = *(data + i);
			next_ele = *(data + i + 1);
			*(data + i) = next_ele < pre_ele ? next_ele : pre_ele;
			*(data + i + 1) = next_ele < pre_ele ? pre_ele : next_ele; 
		}
	}
}


Y86程式碼:

.L6:
	movl	(%ebx,%eax,4), %edx
	movl	4(%ebx,%eax,4), %ecx
	cmpl	%edx, %ecx
	movl	%edx, %ebp
	cmovle	%ecx, %ebp
	movl	%ebp, (%ebx,%eax,4)
	cmovge	%ecx, %edx
	movl	%edx, 4(%ebx,%eax,4)
	subl	$1, %eax
	cmpl	$-1, %eax
	jne	.L6


/*

*****4.47

*/

取值:     icode:ifun   <----   M1[PC]

                 ValP    <-----  PC + 1

譯碼:     ValA   <------  R[%ebp]

                 ValB   <------  R[%ebp]

執行:     ValE   <-----   ValB + 4

訪存:     ValM   <-----  M4[ValA]

寫回:     R[%esp]   <-----   ValE

                 R[%ebp]   <-----   ValM

更新PC:     PC   <-----   ValP

/*

*****4.48

*/

取值:     icode:ifun   <----   M1[PC]

                 rA : rB   <-----   M1[PC + 1]

                 ValC   <-----   M4[PC + 2]

                 ValP    <-----  PC + 6

譯碼:     ValB   <------  R[rB]

執行:     ValE   <-----   ValB + ValC

                 Set     CC

訪存:     

寫回:     R[rB]   <-----   ValE

更新PC:     PC   <-----   ValP


/*

*****4.49,4.50

*/

#/* $begin seq-all-hcl */
####################################################################
#  HCL Description of Control for Single Cycle Y86 Processor SEQ   #
#  Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010       #
####################################################################

## Your task is to implement the iaddl and leave instructions
## The file contains a declaration of the icodes
## for iaddl (IIADDL) and leave (ILEAVE).
## Your job is to add the rest of the logic to make it work

####################################################################
#    C Include's.  Don't alter these                               #
####################################################################

quote '#include <stdio.h>'
quote '#include "isa.h"'
quote '#include "sim.h"'
quote 'int sim_main(int argc, char *argv[]);'
quote 'int gen_pc(){return 0;}'
quote 'int main(int argc, char *argv[])'
quote '  {plusmode=0;return sim_main(argc,argv);}'

####################################################################
#    Declarations.  Do not change/remove/delete any of these       #
####################################################################

##### Symbolic representation of Y86 Instruction Codes #############
intsig INOP 	'I_NOP'
intsig IHALT	'I_HALT'
intsig IRRMOVL	'I_RRMOVL'
intsig IIRMOVL	'I_IRMOVL'
intsig IRMMOVL	'I_RMMOVL'
intsig IMRMOVL	'I_MRMOVL'
intsig IOPL	'I_ALU'
intsig IJXX	'I_JMP'
intsig ICALL	'I_CALL'
intsig IRET	'I_RET'
intsig IPUSHL	'I_PUSHL'
intsig IPOPL	'I_POPL'
# Instruction code for iaddl instruction
intsig IIADDL	'I_IADDL'
# Instruction code for leave instruction
intsig ILEAVE	'I_LEAVE'

##### Symbolic represenations of Y86 function codes                  #####
intsig FNONE    'F_NONE'        # Default function code

##### Symbolic representation of Y86 Registers referenced explicitly #####
intsig RESP     'REG_ESP'    	# Stack Pointer
intsig REBP     'REG_EBP'    	# Frame Pointer
intsig RNONE    'REG_NONE'   	# Special value indicating "no register"

##### ALU Functions referenced explicitly                            #####
intsig ALUADD	'A_ADD'		# ALU should add its arguments

##### Possible instruction status values                             #####
intsig SAOK	'STAT_AOK'		# Normal execution
intsig SADR	'STAT_ADR'	# Invalid memory address
intsig SINS	'STAT_INS'	# Invalid instruction
intsig SHLT	'STAT_HLT'	# Halt instruction encountered

##### Signals that can be referenced by control logic ####################

##### Fetch stage inputs		#####
intsig pc 'pc'				# Program counter
##### Fetch stage computations		#####
intsig imem_icode 'imem_icode'		# icode field from instruction memory
intsig imem_ifun  'imem_ifun' 		# ifun field from instruction memory
intsig icode	  'icode'		# Instruction control code
intsig ifun	  'ifun'		# Instruction function
intsig rA	  'ra'			# rA field from instruction
intsig rB	  'rb'			# rB field from instruction
intsig valC	  'valc'		# Constant from instruction
intsig valP	  'valp'		# Address of following instruction
boolsig imem_error 'imem_error'		# Error signal from instruction memory
boolsig instr_valid 'instr_valid'	# Is fetched instruction valid?

##### Decode stage computations		#####
intsig valA	'vala'			# Value from register A port
intsig valB	'valb'			# Value from register B port

##### Execute stage computations	#####
intsig valE	'vale'			# Value computed by ALU
boolsig Cnd	'cond'			# Branch test

##### Memory stage computations		#####
intsig valM	'valm'			# Value read from memory
boolsig dmem_error 'dmem_error'		# Error signal from data memory


####################################################################
#    Control Signal Definitions.                                   #
####################################################################

################ Fetch Stage     ###################################

# Determine instruction code
int icode = [
	imem_error: INOP;
	1: imem_icode;		# Default: get from instruction memory
];

# Determine instruction function
int ifun = [
	imem_error: FNONE;
	1: imem_ifun;		# Default: get from instruction memory
];

bool instr_valid = icode in 
	{ INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL,
	       IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL,ILEAVE,IIADDL};

# Does fetched instruction require a regid byte?
bool need_regids =
	icode in { IRRMOVL, IOPL, IPUSHL, IPOPL, 
		     IIRMOVL, IRMMOVL, IMRMOVL ,IIADDL};

# Does fetched instruction require a constant word?
bool need_valC =
	icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL ,IIADDL};

################ Decode Stage    ###################################

## What register should be used as the A source?
int srcA = [
	icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL  } : rA;
	icode in { IPOPL, IRET } : RESP;
	icode in {ILEAVE} : REBP;
	1 : RNONE; # Don't need register
];

## What register should be used as the B source?
int srcB = [
	icode in { IOPL, IRMMOVL, IMRMOVL ,IIADDL } : rB;
	icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
	icode in {ILEAVE} : REBP;
	1 : RNONE;  # Don't need register
];

## What register should be used as the E destination?
int dstE = [
	icode in { IRRMOVL } && Cnd : rB;
	icode in { IIRMOVL, IOPL,IIADDL} : rB;
	icode in { IPUSHL, IPOPL, ICALL, IRET, ILEAVE } : RESP;
	1 : RNONE;  # Don't write any register
];

## What register should be used as the M destination?
int dstM = [
	icode in { IMRMOVL, IPOPL } : rA;
	icode in {ILEAVE} : REBP;
	1 : RNONE;  # Don't write any register
];

################ Execute Stage   ###################################

## Select input A to ALU
int aluA = [
	icode in { IRRMOVL, IOPL } : valA;
	icode in { IIRMOVL, IRMMOVL, IMRMOVL,IIADDL } : valC;
	icode in { ICALL, IPUSHL } : -4;
	icode in { IRET, IPOPL , ILEAVE} : 4;
	# Other instructions don't need ALU
];

## Select input B to ALU
int aluB = [
	icode in { IRMMOVL, IMRMOVL, IOPL, ICALL, 
		      IPUSHL, IRET, IPOPL ,IIADDL,ILEAVE} : valB;
	icode in { IRRMOVL, IIRMOVL } : 0;
	# Other instructions don't need ALU
];

## Set the ALU function
int alufun = [
	icode == IOPL : ifun;
	1 : ALUADD;
];

## Should the condition codes be updated?
bool set_cc = icode in { IOPL , IIADDL};

################ Memory Stage    ###################################

## Set read control signal
bool mem_read = icode in { IMRMOVL, IPOPL, IRET ,ILEAVE};

## Set write control signal
bool mem_write = icode in { IRMMOVL, IPUSHL, ICALL };

## Select memory address
int mem_addr = [
	icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : valE;
	icode in { IPOPL, IRET ,ILEAVE } : valA;
	# Other instructions don't need address
];

## Select memory input data
int mem_data = [
	# Value from register
	icode in { IRMMOVL, IPUSHL } : valA;
	# Return PC
	icode == ICALL : valP;
	# Default: Don't write anything
];

## Determine instruction status
int Stat = [
	imem_error || dmem_error : SADR;
	!instr_valid: SINS;
	icode == IHALT : SHLT;
	1 : SAOK;
];

################ Program Counter Update ############################

## What address should instruction be fetched at

int new_pc = [
	# Call.  Use instruction constant
	icode == ICALL : valC;
	# Taken branch.  Use instruction constant
	icode == IJXX && Cnd : valC;
	# Completion of RET instruction.  Use value from stack
	icode == IRET : valM;
	# Default: Use incremented PC
	1 : valP;
];
#/* $end seq-all-hcl */

/*

***4.51-4.53

*/

#/* $begin pipe-all-hcl */  
####################################################################  
#    HCL Description of Control for Pipelined Y86 Processor        #  
#    Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010     #  
####################################################################  
  
## Your task is to implement the iaddl and leave instructions  
## The file contains a declaration of the icodes  
## for iaddl (IIADDL) and leave (ILEAVE).  
## Your job is to add the rest of the logic to make it work  
  
####################################################################  
#    C Include's.  Don't alter these                               #  
####################################################################  
  
quote '#include <stdio.h>'  
quote '#include "isa.h"'  
quote '#include "pipeline.h"'  
quote '#include "stages.h"'  
quote '#include "sim.h"'  
quote 'int sim_main(int argc, char *argv[]);'  
quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}'  
  
####################################################################  
#    Declarations.  Do not change/remove/delete any of these       #  
####################################################################  
  
##### Symbolic representation of Y86 Instruction Codes #############  
intsig INOP     'I_NOP'  
intsig IHALT    'I_HALT'  
intsig IRRMOVL  'I_RRMOVL'  
intsig IIRMOVL  'I_IRMOVL'  
intsig IRMMOVL  'I_RMMOVL'  
intsig IMRMOVL  'I_MRMOVL'  
intsig IOPL 'I_ALU'  
intsig IJXX 'I_JMP'  
intsig ICALL    'I_CALL'  
intsig IRET 'I_RET'  
intsig IPUSHL   'I_PUSHL'  
intsig IPOPL    'I_POPL'  
# Instruction code for iaddl instruction  
intsig IIADDL   'I_IADDL'  
# Instruction code for leave instruction  
intsig ILEAVE   'I_LEAVE'  
  
##### Symbolic represenations of Y86 function codes            #####  
intsig FNONE    'F_NONE'        # Default function code  
  
##### Symbolic representation of Y86 Registers referenced      #####  
intsig RESP     'REG_ESP'            # Stack Pointer  
intsig REBP     'REG_EBP'            # Frame Pointer  
intsig RNONE    'REG_NONE'           # Special value indicating "no register"  
  
##### ALU Functions referenced explicitly ##########################  
intsig ALUADD   'A_ADD'          # ALU should add its arguments  
  
##### Possible instruction status values                       #####  
intsig SBUB 'STAT_BUB'  # Bubble in stage  
intsig SAOK 'STAT_AOK'  # Normal execution  
intsig SADR 'STAT_ADR'  # Invalid memory address  
intsig SINS 'STAT_INS'  # Invalid instruction  
intsig SHLT 'STAT_HLT'  # Halt instruction encountered  
  
##### Signals that can be referenced by control logic ##############  
  
##### Pipeline Register F ##########################################  
  
intsig F_predPC 'pc_curr->pc'         # Predicted value of PC  
  
##### Intermediate Values in Fetch Stage ###########################  
  
intsig imem_icode  'imem_icode'      # icode field from instruction memory  
intsig imem_ifun   'imem_ifun'       # ifun  field from instruction memory  
intsig f_icode  'if_id_next->icode'  # (Possibly modified) instruction code  
intsig f_ifun   'if_id_next->ifun'   # Fetched instruction function  
intsig f_valC   'if_id_next->valc'   # Constant data of fetched instruction  
intsig f_valP   'if_id_next->valp'   # Address of following instruction  
boolsig imem_error 'imem_error'      # Error signal from instruction memory  
boolsig instr_valid 'instr_valid'    # Is fetched instruction valid?  
  
##### Pipeline Register D ##########################################  
intsig D_icode 'if_id_curr->icode'   # Instruction code  
intsig D_rA 'if_id_curr->ra'      # rA field from instruction  
intsig D_rB 'if_id_curr->rb'      # rB field from instruction  
intsig D_valP 'if_id_curr->valp'     # Incremented PC  
  
##### Intermediate Values in Decode Stage  #########################  
  
intsig d_srcA    'id_ex_next->srca'  # srcA from decoded instruction  
intsig d_srcB    'id_ex_next->srcb'  # srcB from decoded instruction  
intsig d_rvalA 'd_regvala'       # valA read from register file  
intsig d_rvalB 'd_regvalb'       # valB read from register file  
  
##### Pipeline Register E ##########################################  
intsig E_icode 'id_ex_curr->icode'   # Instruction code  
intsig E_ifun  'id_ex_curr->ifun'    # Instruction function  
intsig E_valC  'id_ex_curr->valc'    # Constant data  
intsig E_srcA  'id_ex_curr->srca'    # Source A register ID  
intsig E_valA  'id_ex_curr->vala'    # Source A value  
intsig E_srcB  'id_ex_curr->srcb'    # Source B register ID  
intsig E_valB  'id_ex_curr->valb'    # Source B value  
intsig E_dstE 'id_ex_curr->deste'    # Destination E register ID  
intsig E_dstM 'id_ex_curr->destm'    # Destination M register ID  
  
##### Intermediate Values in Execute Stage #########################  
intsig e_valE 'ex_mem_next->vale'    # valE generated by ALU  
boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold?  
intsig e_dstE 'ex_mem_next->deste'      # dstE (possibly modified to be RNONE)  
  
##### Pipeline Register M                  #########################  
intsig M_stat 'ex_mem_curr->status'     # Instruction status  
intsig M_icode 'ex_mem_curr->icode'  # Instruction code  
intsig M_ifun  'ex_mem_curr->ifun'   # Instruction function  
intsig M_valA  'ex_mem_curr->vala'      # Source A value  
intsig M_dstE 'ex_mem_curr->deste'   # Destination E register ID  
intsig M_valE  'ex_mem_curr->vale'      # ALU E value  
intsig M_dstM 'ex_mem_curr->destm'   # Destination M register ID  
boolsig M_Cnd 'ex_mem_curr->takebranch'  # Condition flag  
boolsig dmem_error 'dmem_error'         # Error signal from instruction memory  
  
##### Intermediate Values in Memory Stage ##########################  
intsig m_valM 'mem_wb_next->valm'    # valM generated by memory  
intsig m_stat 'mem_wb_next->status'  # stat (possibly modified to be SADR)  
  
##### Pipeline Register W ##########################################  
intsig W_stat 'mem_wb_curr->status'     # Instruction status  
intsig W_icode 'mem_wb_curr->icode'  # Instruction code  
intsig W_dstE 'mem_wb_curr->deste'   # Destination E register ID  
intsig W_valE  'mem_wb_curr->vale'      # ALU E value  
intsig W_dstM 'mem_wb_curr->destm'   # Destination M register ID  
intsig W_valM  'mem_wb_curr->valm'   # Memory M value  
  
####################################################################  
#    Control Signal Definitions.                                   #  
####################################################################  
  
################ Fetch Stage     ###################################  
  
## What address should instruction be fetched at  
int f_pc = [  
    # Mispredicted branch.  Fetch at incremented PC  
    M_icode == IJXX && !M_Cnd : M_valA;  
    # Completion of RET instruction.  
    W_icode == IRET : W_valM;  
    # Default: Use predicted value of PC  
    1 : F_predPC;  
];  
  
## Determine icode of fetched instruction  
int f_icode = [  
    imem_error : INOP;  
    1: imem_icode;  
];  
  
# Determine ifun  
int f_ifun = [  
    imem_error : FNONE;  
    1: imem_ifun;  
];  
  
# Is instruction valid?  
bool instr_valid = f_icode in   
    { INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL,  
      IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL,ILEAVE,IIADDL };  
  
# Determine status code for fetched instruction  
int f_stat = [  
    imem_error: SADR;  
    !instr_valid : SINS;  
    f_icode == IHALT : SHLT;  
    1 : SAOK;  
];  
  
# Does fetched instruction require a regid byte?  
bool need_regids =  
    f_icode in { IRRMOVL, IOPL, IPUSHL, IPOPL,   
             IIRMOVL, IRMMOVL, IMRMOVL,IIADDL };  
  
# Does fetched instruction require a constant word?  
bool need_valC =  
    f_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL ,IIADDL};  
  
# Predict next value of PC  
int f_predPC = [  
    f_icode in { IJXX, ICALL } : f_valC;  
    1 : f_valP;  
];  
  
################ Decode Stage ######################################  
  
  
## What register should be used as the A source?  
int d_srcA = [  
    D_icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL  } : D_rA;  
    D_icode in { IPOPL, IRET } : RESP;  
    D_icode in {ILEAVE} :REBP;  
    1 : RNONE; # Don't need register  
];  
  
## What register should be used as the B source?  
int d_srcB = [  
    D_icode in { IOPL, IRMMOVL, IMRMOVL,IIADDL  } : D_rB;  
    D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;  
    D_icode in {ILEAVE} : REBP;  
    1 : RNONE;  # Don't need register  
];  
  
## What register should be used as the E destination?  
int d_dstE = [  
    D_icode in { IRRMOVL, IIRMOVL, IOPL,IIADDL} : D_rB;  
    D_icode in { IPUSHL, IPOPL, ICALL, IRET,ILEAVE } : RESP;  
    1 : RNONE;  # Don't write any register  
];  
  
## What register should be used as the M destination?  
int d_dstM = [  
    D_icode in { IMRMOVL, IPOPL } : D_rA;  
    D_icode in {ILEAVE} :REBP;  
    1 : RNONE;  # Don't write any register  
];  
  
## What should be the A value?  
## Forward into decode stage for valA  
int d_valA = [  
    D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC  
    d_srcA == e_dstE : e_valE;    # Forward valE from execute  
    d_srcA == M_dstM : m_valM;    # Forward valM from memory  
    d_srcA == M_dstE : M_valE;    # Forward valE from memory  
    d_srcA == W_dstM : W_valM;    # Forward valM from write back  
    d_srcA == W_dstE : W_valE;    # Forward valE from write back  
    1 : d_rvalA;  # Use value read from register file  
];  
  
int d_valB = [  
    d_srcB == e_dstE : e_valE;    # Forward valE from execute  
    d_srcB == M_dstM : m_valM;    # Forward valM from memory  
    d_srcB == M_dstE : M_valE;    # Forward valE from memory  
    d_srcB == W_dstM : W_valM;    # Forward valM from write back  
    d_srcB == W_dstE : W_valE;    # Forward valE from write back  
    1 : d_rvalB;  # Use value read from register file  
];  
  
################ Execute Stage #####################################  
  
## Select input A to ALU  
int aluA = [  
    E_icode in { IRRMOVL, IOPL } : E_valA;  
    E_icode in { IIRMOVL, IRMMOVL, IMRMOVL,IIADDL } : E_valC;  
    E_icode in { ICALL, IPUSHL } : -4;  
    E_icode in { IRET, IPOPL,ILEAVE } : 4;  
    # Other instructions don't need ALU  
];  
  
## Select input B to ALU  
int aluB = [  
    E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL,   
             IPUSHL, IRET, IPOPL,ILEAVE,IIADDL } : E_valB;  
    E_icode in { IRRMOVL, IIRMOVL } : 0;  
    # Other instructions don't need ALU  
];  
  
## Set the ALU function  
int alufun = [  
    E_icode == IOPL : E_ifun;  
    1 : ALUADD;  
];  
  
## Should the condition codes be updated?  
bool set_cc = (E_icode in { IOPL,IIADDL}) &&  
    # State changes only during normal operation  
    !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT };  
  
## Generate valA in execute stage  
int e_valA = E_valA;    # Pass valA through stage  
  
## Set dstE to RNONE in event of not-taken conditional move  
int e_dstE = [  
    E_icode == IRRMOVL && !e_Cnd : RNONE;  
    1 : E_dstE;  
];  
  
################ Memory Stage ######################################  
  
## Select memory address  
int mem_addr = [  
    M_icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : M_valE;  
    M_icode in { IPOPL, IRET,ILEAVE } : M_valA;  
    # Other instructions don't need address  
];  
  
## Set read control signal  
bool mem_read = M_icode in { IMRMOVL, IPOPL, IRET,ILEAVE };  
  
## Set write control signal  
bool mem_write = M_icode in { IRMMOVL, IPUSHL, ICALL };  
  
#/* $begin pipe-m_stat-hcl */  
## Update the status  
int m_stat = [  
    dmem_error : SADR;  
    1 : M_stat;  
];  
#/* $end pipe-m_stat-hcl */  
  
## Set E port register ID  
int w_dstE = W_dstE;  
  
## Set E port value  
int w_valE = W_valE;  
  
## Set M port register ID  
int w_dstM = W_dstM;  
  
## Set M port value  
int w_valM = W_valM;  
  
## Update processor status  
int Stat = [  
    W_stat == SBUB : SAOK;  
    1 : W_stat;  
]; 

################ Pipeline Register Control #########################

# Should I stall or inject a bubble into Pipeline Register F?
# At most one of these can be true.
bool F_bubble = 0;
bool F_stall =
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL ,ILEAVE} &&
	 E_dstM in { d_srcA, d_srcB } ||
	# Stalling at fetch while ret passes through pipeline
	IRET in { D_icode, E_icode, M_icode };

# Should I stall or inject a bubble into Pipeline Register D?
# At most one of these can be true.
bool D_stall = 
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL, ILEAVE } &&
	 E_dstM in { d_srcA, d_srcB };

bool D_bubble =
	# Mispredicted branch
	(E_icode == IJXX && !e_Cnd) ||
	# Stalling at fetch while ret passes through pipeline
	# but not condition for a load/use hazard
	!(E_icode in { IMRMOVL, IPOPL, ILEAVE } && E_dstM in { d_srcA, d_srcB }) &&
	  IRET in { D_icode, E_icode, M_icode };

# Should I stall or inject a bubble into Pipeline Register E?
# At most one of these can be true.
bool E_stall = 0;
bool E_bubble =
	# Mispredicted branch
	(E_icode == IJXX && !e_Cnd) ||
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL, ILEAVE } &&
	 E_dstM in { d_srcA, d_srcB};

# Should I stall or inject a bubble into Pipeline Register M?
# At most one of these can be true.
bool M_stall = 0;
# Start injecting bubbles as soon as exception passes through memory stage
bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT };

# Should I stall or inject a bubble into Pipeline Register W?
bool W_stall = W_stat in { SADR, SINS, SHLT };
bool W_bubble = 0;
#/* $end pipe-all-hcl */


/*

***4.54

*/

#/* $begin pipe-all-hcl */
####################################################################
#    HCL Description of Control for Pipelined Y86 Processor        #
#    Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010     #
####################################################################

## Your task is to modify the design so that conditional branches are
## predicted as being not-taken.  The code here is nearly identical
## to that for the normal pipeline.  
## Comments starting with keyword "BNT" have been added at places
## relevant to the exercise.

####################################################################
#    C Include's.  Don't alter these                               #
####################################################################

quote '#include <stdio.h>'
quote '#include "isa.h"'
quote '#include "pipeline.h"'
quote '#include "stages.h"'
quote '#include "sim.h"'
quote 'int sim_main(int argc, char *argv[]);'
quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}'

####################################################################
#    Declarations.  Do not change/remove/delete any of these       #
####################################################################

##### Symbolic representation of Y86 Instruction Codes #############
intsig INOP 	'I_NOP'
intsig IHALT	'I_HALT'
intsig IRRMOVL	'I_RRMOVL'
intsig IIRMOVL	'I_IRMOVL'
intsig IRMMOVL	'I_RMMOVL'
intsig IMRMOVL	'I_MRMOVL'
intsig IOPL	'I_ALU'
intsig IJXX	'I_JMP'
intsig ICALL	'I_CALL'
intsig IRET	'I_RET'
intsig IPUSHL	'I_PUSHL'
intsig IPOPL	'I_POPL'

##### Symbolic represenations of Y86 function codes            #####
intsig FNONE    'F_NONE'        # Default function code

##### Symbolic representation of Y86 Registers referenced      #####
intsig RESP     'REG_ESP'    	     # Stack Pointer
intsig RNONE    'REG_NONE'   	     # Special value indicating "no register"

##### ALU Functions referenced explicitly ##########################
intsig ALUADD	'A_ADD'		     # ALU should add its arguments
## BNT: For modified branch prediction, need to distinguish
## conditional vs. unconditional branches
##### Jump conditions referenced explicitly
intsig UNCOND 'C_YES'       	     # Unconditional transfer

##### Possible instruction status values                       #####
intsig SBUB	'STAT_BUB'	# Bubble in stage
intsig SAOK	'STAT_AOK'	# Normal execution
intsig SADR	'STAT_ADR'	# Invalid memory address
intsig SINS	'STAT_INS'	# Invalid instruction
intsig SHLT	'STAT_HLT'	# Halt instruction encountered

##### Signals that can be referenced by control logic ##############

##### Pipeline Register F ##########################################

intsig F_predPC 'pc_curr->pc'	     # Predicted value of PC

##### Intermediate Values in Fetch Stage ###########################

intsig imem_icode  'imem_icode'      # icode field from instruction memory
intsig imem_ifun   'imem_ifun'       # ifun  field from instruction memory
intsig f_icode	'if_id_next->icode'  # (Possibly modified) instruction code
intsig f_ifun	'if_id_next->ifun'   # Fetched instruction function
intsig f_valC	'if_id_next->valc'   # Constant data of fetched instruction
intsig f_valP	'if_id_next->valp'   # Address of following instruction
boolsig imem_error 'imem_error'	     # Error signal from instruction memory
boolsig instr_valid 'instr_valid'    # Is fetched instruction valid?

##### Pipeline Register D ##########################################
intsig D_icode 'if_id_curr->icode'   # Instruction code
intsig D_rA 'if_id_curr->ra'	     # rA field from instruction
intsig D_rB 'if_id_curr->rb'	     # rB field from instruction
intsig D_valP 'if_id_curr->valp'     # Incremented PC
intsig D_valC 'if_id_curr->valc'
##### Intermediate Values in Decode Stage  #########################

intsig d_srcA	 'id_ex_next->srca'  # srcA from decoded instruction
intsig d_srcB	 'id_ex_next->srcb'  # srcB from decoded instruction
intsig d_rvalA 'd_regvala'	     # valA read from register file
intsig d_rvalB 'd_regvalb'	     # valB read from register file

##### Pipeline Register E ##########################################
intsig E_icode 'id_ex_curr->icode'   # Instruction code
intsig E_ifun  'id_ex_curr->ifun'    # Instruction function
intsig E_valC  'id_ex_curr->valc'    # Constant data
intsig E_srcA  'id_ex_curr->srca'    # Source A register ID
intsig E_valA  'id_ex_curr->vala'    # Source A value
intsig E_srcB  'id_ex_curr->srcb'    # Source B register ID
intsig E_valB  'id_ex_curr->valb'    # Source B value
intsig E_dstE 'id_ex_curr->deste'    # Destination E register ID
intsig E_dstM 'id_ex_curr->destm'    # Destination M register ID

##### Intermediate Values in Execute Stage #########################
intsig e_valE 'ex_mem_next->vale'	# valE generated by ALU
boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold?
intsig e_dstE 'ex_mem_next->deste'      # dstE (possibly modified to be RNONE)

##### Pipeline Register M                  #########################
intsig M_stat 'ex_mem_curr->status'     # Instruction status
intsig M_icode 'ex_mem_curr->icode'	# Instruction code
intsig M_ifun  'ex_mem_curr->ifun'	# Instruction function
intsig M_valA  'ex_mem_curr->vala'      # Source A value
intsig M_dstE 'ex_mem_curr->deste'	# Destination E register ID
intsig M_valE  'ex_mem_curr->vale'      # ALU E value
intsig M_dstM 'ex_mem_curr->destm'	# Destination M register ID
boolsig M_Cnd 'ex_mem_curr->takebranch'	# Condition flag
boolsig dmem_error 'dmem_error'	        # Error signal from instruction memory

##### Intermediate Values in Memory Stage ##########################
intsig m_valM 'mem_wb_next->valm'	# valM generated by memory
intsig m_stat 'mem_wb_next->status'	# stat (possibly modified to be SADR)

##### Pipeline Register W ##########################################
intsig W_stat 'mem_wb_curr->status'     # Instruction status
intsig W_icode 'mem_wb_curr->icode'	# Instruction code
intsig W_dstE 'mem_wb_curr->deste'	# Destination E register ID
intsig W_valE  'mem_wb_curr->vale'      # ALU E value
intsig W_dstM 'mem_wb_curr->destm'	# Destination M register ID
intsig W_valM  'mem_wb_curr->valm'	# Memory M value

####################################################################
#    Control Signal Definitions.                                   #
####################################################################

################ Fetch Stage     ###################################

## What address should instruction be fetched at
int f_pc = [
	# Mispredicted branch.  Fetch at incremented PC
	M_icode == IJXX && M_Cnd : M_valA;
	# Completion of RET instruction.
	W_icode == IRET : W_valM;
	# Default: Use predicted value of PC
	1 : F_predPC;
];

## Determine icode of fetched instruction
int f_icode = [
	imem_error : INOP;
	1: imem_icode;
];

# Determine ifun
int f_ifun = [
	imem_error : FNONE;
	1: imem_ifun;
];

# Is instruction valid?
bool instr_valid = f_icode in 
	{ INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL,
	  IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL };

# Determine status code for fetched instruction
int f_stat = [
	imem_error: SADR;
	!instr_valid : SINS;
	f_icode == IHALT : SHLT;
	1 : SAOK;
];

# Does fetched instruction require a regid byte?
bool need_regids =
	f_icode in { IRRMOVL, IOPL, IPUSHL, IPOPL, 
		     IIRMOVL, IRMMOVL, IMRMOVL };

# Does fetched instruction require a constant word?
bool need_valC =
	f_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL };

# Predict next value of PC
int f_predPC = [
	# BNT: This is where you'll change the branch prediction rule
	f_icode == ICALL : f_valC;
	(f_icode == IJXX) && (f_ifun == 0) : f_valC;
	1 : f_valP;
];

################ Decode Stage ######################################


## What register should be used as the A source?
int d_srcA = [
	D_icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL  } : D_rA;
	D_icode in { IPOPL, IRET } : RESP;
	1 : RNONE; # Don't need register
];

## What register should be used as the B source?
int d_srcB = [
	D_icode in { IOPL, IRMMOVL, IMRMOVL  } : D_rB;
	D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
	1 : RNONE;  # Don't need register
];

## What register should be used as the E destination?
int d_dstE = [
	D_icode in { IRRMOVL, IIRMOVL, IOPL} : D_rB;
	D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
	1 : RNONE;  # Don't write any register
];

## What register should be used as the M destination?
int d_dstM = [
	D_icode in { IMRMOVL, IPOPL } : D_rA;
	1 : RNONE;  # Don't write any register
];

## What should be the A value?
## Forward into decode stage for valA
int d_valA = [
	D_icode in { ICALL } : D_valP; # Use incremented PC
	D_icode in {IJXX} : D_valC;
	d_srcA == e_dstE : e_valE;    # Forward valE from execute
	d_srcA == M_dstM : m_valM;    # Forward valM from memory
	d_srcA == M_dstE : M_valE;    # Forward valE from memory
	d_srcA == W_dstM : W_valM;    # Forward valM from write back
	d_srcA == W_dstE : W_valE;    # Forward valE from write back
	1 : d_rvalA;  # Use value read from register file
];

int d_valB = [
	d_srcB == e_dstE : e_valE;    # Forward valE from execute
	d_srcB == M_dstM : m_valM;    # Forward valM from memory
	d_srcB == M_dstE : M_valE;    # Forward valE from memory
	d_srcB == W_dstM : W_valM;    # Forward valM from write back
	d_srcB == W_dstE : W_valE;    # Forward valE from write back
	1 : d_rvalB;  # Use value read from register file
];

################ Execute Stage #####################################

# BNT: When some branches are predicted as not-taken, you need some
# way to get valC into pipeline register M, so that
# you can correct for a mispredicted branch.

## Select input A to ALU
int aluA = [
	E_icode in { IRRMOVL, IOPL } : E_valA;
	E_icode in { IIRMOVL, IRMMOVL, IMRMOVL } : E_valC;
	E_icode in { ICALL, IPUSHL } : -4;
	E_icode in { IRET, IPOPL } : 4;
	# Other instructions don't need ALU
];

## Select input B to ALU
int aluB = [
	E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL, 
		     IPUSHL, IRET, IPOPL } : E_valB;
	E_icode in { IRRMOVL, IIRMOVL } : 0;
	# Other instructions don't need ALU
];

## Set the ALU function
int alufun = [
	E_icode == IOPL : E_ifun;
	1 : ALUADD;
];

## Should the condition codes be updated?
bool set_cc = E_icode == IOPL &&
	# State changes only during normal operation
	!m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT };

## Generate valA in execute stage
int e_valA = E_valA;    # Pass valA through stage

## Set dstE to RNONE in event of not-taken conditional move
int e_dstE = [
	E_icode == IRRMOVL && !e_Cnd : RNONE;
	1 : E_dstE;
];

################ Memory Stage ######################################

## Select memory address
int mem_addr = [
	M_icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : M_valE;
	M_icode in { IPOPL, IRET } : M_valA;
	# Other instructions don't need address
];

## Set read control signal
bool mem_read = M_icode in { IMRMOVL, IPOPL, IRET };

## Set write control signal
bool mem_write = M_icode in { IRMMOVL, IPUSHL, ICALL };

#/* $begin pipe-m_stat-hcl */
## Update the status
int m_stat = [
	dmem_error : SADR;
	1 : M_stat;
];
#/* $end pipe-m_stat-hcl */

## Set E port register ID
int w_dstE = W_dstE;

## Set E port value
int w_valE = W_valE;

## Set M port register ID
int w_dstM = W_dstM;

## Set M port value
int w_valM = W_valM;

## Update processor status
int Stat = [
	W_stat == SBUB : SAOK;
	1 : W_stat;
];

################ Pipeline Register Control #########################

# Should I stall or inject a bubble into Pipeline Register F?
# At most one of these can be true.
bool F_bubble = 0;
bool F_stall =
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL } &&
	 E_dstM in { d_srcA, d_srcB } ||
	# Stalling at fetch while ret passes through pipeline
	IRET in { D_icode, E_icode, M_icode };

# Should I stall or inject a bubble into Pipeline Register D?
# At most one of these can be true.
bool D_stall = 
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL } &&
	 E_dstM in { d_srcA, d_srcB };

bool D_bubble =
	# Mispredicted branch
	(E_icode == IJXX && e_Cnd) ||
	# Stalling at fetch while ret passes through pipeline
	# but not condition for a load/use hazard
	!(E_icode in { IMRMOVL, IPOPL } && E_dstM in { d_srcA, d_srcB }) &&
	  IRET in { D_icode, E_icode, M_icode };

# Should I stall or inject a bubble into Pipeline Register E?
# At most one of these can be true.
bool E_stall = 0;
bool E_bubble =
	# Mispredicted branch
	(E_icode == IJXX && e_Cnd) ||
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL } &&
	 E_dstM in { d_srcA, d_srcB};

# Should I stall or inject a bubble into Pipeline Register M?
# At most one of these can be true.
bool M_stall = 0;
# Start injecting bubbles as soon as exception passes through memory stage
bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT };

# Should I stall or inject a bubble into Pipeline Register W?
bool W_stall = W_stat in { SADR, SINS, SHLT };
bool W_bubble = 0;
#/* $end pipe-all-hcl */