├── .gitignore ├── Makefile ├── README ├── misc ├── Makefile ├── README ├── copy_block.ys ├── examples.c ├── hcl.lex ├── hcl.y ├── isa.c ├── isa.h ├── mux4.hcl ├── node.c ├── node.h ├── outgen.c ├── outgen.h ├── rsum.ys ├── sum.ys ├── yas-grammar.lex ├── yas.c ├── yas.h └── yis.c ├── pipe ├── 4ncopy.ys ├── 8ncopy.ys ├── Makefile ├── README ├── benchmark.pl ├── check-len.pl ├── correctness.pl ├── gen-driver.pl ├── mncopy.ys ├── ncopy.c ├── ncopy.ys ├── pipe-1w.hcl ├── pipe-broken.hcl ├── pipe-btfnt.hcl ├── pipe-full.hcl ├── pipe-lf.hcl ├── pipe-nobypass.hcl ├── pipe-nt.hcl ├── pipe-std.hcl ├── pipe.tcl ├── pipeline.h ├── psim.c ├── sim.h └── stages.h ├── ptest ├── Makefile ├── README ├── ctest.pl ├── etest.pl ├── htest.pl ├── jtest.pl ├── optest.pl └── tester.pm ├── seq ├── Makefile ├── README ├── seq+-std.hcl ├── seq+.tcl ├── seq-full.hcl ├── seq-std.hcl ├── seq.tcl ├── sim.h └── ssim.c └── y86-code ├── Makefile ├── README ├── abs-asum-cmov.ys ├── abs-asum-jmp.ys ├── asum.ys ├── asumi.ys ├── asumr.ys ├── cjr.ys ├── j-cc.ys ├── poptest.ys ├── prog1.ys ├── prog10.ys ├── prog2.ys ├── prog3.ys ├── prog4.ys ├── prog5.ys ├── prog6.ys ├── prog7.ys ├── prog8.ys ├── prog9.ys ├── pushquestion.ys ├── pushtest.ys └── ret-hazard.ys /.gitignore: -------------------------------------------------------------------------------- 1 | pipe/ldriver.ys 2 | pipe/sdriver.ys 3 | *.yo 4 | *.o 5 | misc/hcl.tab.c 6 | misc/hcl.tab.h 7 | misc/hcl2c 8 | misc/lex.yy.c 9 | misc/yas 10 | misc/yas-grammar.c 11 | misc/yis 12 | pipe/pipe-std.c 13 | pipe/psim 14 | seq/seq-std.c 15 | seq/ssim 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Comment this out if you don't have Tcl/Tk on your system 2 | 3 | #GUIMODE=-DHAS_GUI 4 | 5 | # Modify the following line so that gcc can find the libtcl.so and 6 | # libtk.so libraries on your system. You may need to use the -L option 7 | # to tell gcc which directory to look in. Comment this out if you 8 | # don't have Tcl/Tk. 9 | 10 | #TKLIBS=-L/usr/lib -ltk -ltcl 11 | 12 | # Modify the following line so that gcc can find the tcl.h and tk.h 13 | # header files on your system. Comment this out if you don't have 14 | # Tcl/Tk. 15 | 16 | #TKINC=-isystem /usr/include/tcl8.5 17 | 18 | ################################################## 19 | # You shouldn't need to modify anything below here 20 | ################################################## 21 | 22 | # Use this rule (make all) to build the Y86-64 tools. The variables you've 23 | # assigned to GUIMODE, TKLIBS, and TKINC will override the values that 24 | # are currently assigned in seq/Makefile and pipe/Makefile. 25 | all: 26 | (cd misc; make all) 27 | (cd pipe; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)") 28 | (cd seq; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)") 29 | (cd y86-code; make all) 30 | 31 | clean: 32 | rm -f *~ core 33 | (cd misc; make clean) 34 | (cd pipe; make clean) 35 | (cd seq; make clean) 36 | (cd y86-code; make clean) 37 | (cd ptest; make clean) 38 | 39 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Y86-64 Tools (Student Distribution) 3 | * 4 | * Copyright (c) 2002, 2010, 2015, R. Bryant and D. O'Hallaron, 5 | * All rights reserved. May not be used, modified, or copied 6 | * without permission. 7 | ***********************************************************************/ 8 | 9 | This directory contains the student distribution of the Y86-64 tools. It 10 | is a proper subset of the master distribution, minus the solution 11 | files found in the master distribution. 12 | 13 | yas Y86-64 assembler 14 | yis Y86-64 instruction (ISA) simulator 15 | hcl2c HCL to C translator 16 | hcl2v HCL to Verilog translator 17 | ssim SEQ simulator 18 | ssim+ SEQ+ simulator 19 | psim PIPE simulator 20 | 21 | ************************* 22 | 1. Building the Y86-64 tools 23 | ************************* 24 | 25 | The Y86-64 simulators can be configured to support TTY and GUI 26 | interfaces. A simulator running in TTY mode prints all information 27 | about its run-time behavior on the terminal. It's harder to understand what's 28 | going on, but useful for automated testing, and doesn't require any 29 | special installation features. A simulator running in GUI mode uses a 30 | fancy graphical user interface. Nice for visualizing and debugging, 31 | but requires installation of Tcl/Tk on your system. 32 | 33 | To build the Y86-64 tools, perform the following steps: 34 | 35 | NOTE: If your instructor prepared this distribution for you, then you 36 | can skip Step 1 and proceed directly to Step 2. The Makefile will 37 | already have the proper values for GUIMODE, TKLIBS, and TKINC for your 38 | system. 39 | 40 | Step 1. Decide whether you want the TTY or GUI form of the simulators, 41 | and then modify ./Makefile in this directory accordingly. (The changes 42 | you make to the variables in this Makefile will override the values 43 | already assigned in the Makefiles in the seq and pipe directories.) 44 | 45 | Building the GUI simulators: If you have Tcl/Tk installed on your 46 | system, then you can build the GUI form by initializing the GUIMODE, 47 | TKLIBS, and TKINC variables, as appropriate for your system. (The 48 | default values work for Linux systems.) 49 | 50 | Assigning GUIMODE=-DHAS_GUI causes the necessary GUI support code in 51 | the simulator sources to be included. The TKLIBS variable tells gcc 52 | where to look for the libtcl.so and libtk.so libraries. And the TKINC 53 | variable tells gcc where to find the tcl.h and tk.h header files. 54 | 55 | Building the TTY simulators: If you don't have Tcl/Tk installed on 56 | your system, then build the TTY form by commenting out all three of 57 | these variables (GUIMODE, TKLIBS, and TKINC) in the Makefile. 58 | 59 | Step 2: Once you've modified the Makefile to build either the GUI or 60 | TTY form, then you can construct the entire set of Y86-64 tools by typing 61 | 62 | unix> make clean; make 63 | 64 | ******** 65 | 2. Files 66 | ******** 67 | 68 | Makefile 69 | Builds the Y86-64 tools 70 | 71 | README 72 | This file 73 | 74 | misc/ 75 | Source files for the Y86-64 assembler yas, the Y86-64 instruction 76 | simulator yis, and the isa.c file that is used by the -t option 77 | of the processor simulators to check the results against the 78 | ISA simulation. Also contains files for the programs 79 | hcl2c and hcl2v 80 | 81 | seq/ 82 | Code for the SEQ and SEQ+ simulators. Contains HCL files for 83 | labs and homework problems that involve modifying SEQ. 84 | 85 | pipe/ 86 | Code for the PIPE simulator. Contains HCL files for labs and 87 | homework problems that involve modifying PIPE. 88 | 89 | y86-code/ 90 | Example .ys files from CS:APP and scripts for conducting 91 | automated benchmark teseting of the new processor designs. 92 | 93 | ptest/ 94 | Automated regression testing scripts for testing processor designs. 95 | 96 | verilog/ 97 | System for producing Verilog designs from HCL code 98 | -------------------------------------------------------------------------------- /misc/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -O1 -g 3 | LCFLAGS=-O1 4 | LEX = flex 5 | YACC=bison 6 | LEXLIB = -lfl 7 | YAS=./yas 8 | 9 | all: yis yas hcl2c 10 | 11 | # These are implicit rules for making .yo files from .ys files. 12 | # E.g., make sum.yo 13 | .SUFFIXES: .ys .yo 14 | .ys.yo: 15 | $(YAS) $*.ys 16 | 17 | # These are the explicit rules for making yis yas and hcl2c and hcl2v 18 | yas-grammar.o: yas-grammar.c 19 | $(CC) $(LCFLAGS) -c yas-grammar.c 20 | 21 | yas-grammar.c: yas-grammar.lex 22 | $(LEX) yas-grammar.lex 23 | mv lex.yy.c yas-grammar.c 24 | 25 | isa.o: isa.c isa.h 26 | $(CC) $(CFLAGS) -c isa.c 27 | 28 | yas.o: yas.c yas.h isa.h 29 | $(CC) $(CFLAGS) -c yas.c 30 | 31 | yas: yas.o yas-grammar.o isa.o 32 | $(CC) $(CFLAGS) yas-grammar.o yas.o isa.o ${LEXLIB} -o yas 33 | 34 | yis.o: yis.c isa.h 35 | $(CC) $(CFLAGS) -c yis.c 36 | 37 | yis: yis.o isa.o 38 | $(CC) $(CFLAGS) yis.o isa.o -o yis 39 | 40 | hcl2c: hcl.tab.c lex.yy.c node.c outgen.c 41 | $(CC) $(LCFLAGS) node.c lex.yy.c hcl.tab.c outgen.c -o hcl2c 42 | 43 | hcl2v: hcl.tab.c lex.yy.c node.c outgen.c 44 | $(CC) $(LCFLAGS) -DVLOG node.c lex.yy.c hcl.tab.c outgen.c -o hcl2v 45 | 46 | hcl2u: hcl.tab.c lex.yy.c node.c outgen.c 47 | $(CC) $(LCFLAGS) -DUCLID node.c lex.yy.c hcl.tab.c outgen.c -o hcl2u 48 | 49 | lex.yy.c: hcl.lex 50 | $(LEX) hcl.lex 51 | 52 | hcl.tab.c: hcl.y 53 | $(YACC) -d hcl.y 54 | 55 | clean: 56 | rm -f *.o *.yo *.exe yis yas hcl2c mux4 *~ core.* 57 | rm -f hcl.tab.c hcl.tab.h lex.yy.c yas-grammar.c 58 | 59 | 60 | -------------------------------------------------------------------------------- /misc/README: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Y86-64 Assembler, Instruction Simulator, and HCL translator 3 | * 4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 5 | * May not be used, modified, or copied without permission. 6 | ***********************************************************************/ 7 | 8 | This directory contains all of the source files for the following: 9 | 10 | YAS Y86-64 assembler 11 | YIS Y86-64 instruction level simulator 12 | HCL2C HCL to C translator 13 | HCL2V HCL to Verilog translator 14 | 15 | ********************* 16 | 1. Building the tools 17 | ********************* 18 | 19 | unix> make clean 20 | unix> make 21 | 22 | ******** 23 | 2. Files 24 | ******** 25 | 26 | Makefile Builds yas, yis, hcl2c, hcl2v 27 | README This file 28 | 29 | * Versions of Makefile in the student's distribution 30 | * (Instructor distribution only) 31 | Makefile-sim 32 | 33 | * Example programs for Part A of the CS:APP Architecture Lab 34 | examples.c C versions of three Y86-64 functions 35 | ans-copy.ys Solution copy function (instructor distribution only) 36 | ans-sum.ys Solution sum function (instructor distribution only) 37 | ans-rsum.ys Solution rsum function (instructor distribution only) 38 | 39 | 40 | * Instruction simulator code shared by yas, yis, ssim, ssim+, and psim 41 | isa.c 42 | isa.h 43 | 44 | * Files used to build the yas assembler 45 | yas The YAS binary 46 | yas.c yas source file and header file 47 | yas.h 48 | yas-grammar.lex Y86-64 lexical scanner spec 49 | yas-grammar.c Lexical scanner generated from yas-grammar.lex 50 | 51 | * Files used to build the yis instruction simulator 52 | yis The YIS binary 53 | yis.c yis source file 54 | 55 | * Files used to build the hcl2c translator 56 | hcl2c The HCL2C binary 57 | node.c auxiliary routines and header file 58 | node.h 59 | hcl.lex HCL lexical scanner spec 60 | lex.yy.c HCL lexical scanner generated from hcl.lex 61 | hcl.y HCL grammar 62 | hcl.tab.c HCL parser generated from hcl.y 63 | hcl.tab.h Token definitions 64 | 65 | * Example HCL programs used during the writing of the CS:APP book 66 | * (Instructor distribution only) 67 | frag.{hcl,c} 68 | mux4.{hcl,c} 69 | reg-file.{hcl,c} 70 | 71 | 72 | -------------------------------------------------------------------------------- /misc/copy_block.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp 4 | # Set up stack pointer 5 | call main 6 | # Execute main program 7 | halt 8 | # Terminate program 9 | # Sample linked list 10 | .align 8 11 | # Source block 12 | src: 13 | .quad 0x00a 14 | .quad 0x0b0 15 | .quad 0xc00 16 | # Destination block 17 | dest: 18 | .quad 0x111 19 | .quad 0x222 20 | .quad 0x333 21 | main: 22 | irmovq src , %rdi 23 | irmovq dest , %rsi 24 | irmovq $3 , %rdx 25 | call copyblock 26 | ret 27 | # sum_list - Recursive version of sum_list 28 | # start in %rdi 29 | copyblock: 30 | xorq %rax , %rax 31 | loop: 32 | andq %rdx , %rdx 33 | jle end 34 | mrmovq (%rdi) , %rcx 35 | irmovq $8 , %rbx 36 | addq %rbx , %rdi 37 | rmmovq %rcx , (%rsi) 38 | addq %rbx , %rsi 39 | xorq %rcx , %rax 40 | irmovq $1 , %rbx 41 | subq %rbx , %rdx 42 | jmp loop 43 | end: 44 | ret 45 | # Stack starts here and grows to lower addresses 46 | .pos 0x200 47 | stack: 48 | -------------------------------------------------------------------------------- /misc/examples.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Architecture Lab: Part A 3 | * 4 | * High level specs for the functions that the students will rewrite 5 | * in Y86-64 assembly language 6 | */ 7 | 8 | /* $begin examples */ 9 | /* linked list element */ 10 | typedef struct ELE { 11 | long val; 12 | struct ELE *next; 13 | } *list_ptr; 14 | 15 | /* sum_list - Sum the elements of a linked list */ 16 | long sum_list(list_ptr ls) 17 | { 18 | long val = 0; 19 | while (ls) { 20 | val += ls->val; 21 | ls = ls->next; 22 | } 23 | return val; 24 | } 25 | 26 | /* rsum_list - Recursive version of sum_list */ 27 | long rsum_list(list_ptr ls) 28 | { 29 | if (!ls) 30 | return 0; 31 | else { 32 | long val = ls->val; 33 | long rest = rsum_list(ls->next); 34 | return val + rest; 35 | } 36 | } 37 | 38 | /* copy_block - Copy src to dest and return xor checksum of src */ 39 | long copy_block(long *src, long *dest, long len) 40 | { 41 | long result = 0; 42 | while (len > 0) { 43 | long val = *src++; 44 | *dest++ = val; 45 | result ^= val; 46 | len--; 47 | } 48 | return result; 49 | } 50 | /* $end examples */ 51 | -------------------------------------------------------------------------------- /misc/hcl.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "node.h" 4 | #define YYSTYPE node_ptr 5 | #include "hcl.tab.h" 6 | 7 | 8 | extern YYSTYPE yylval; 9 | extern int lineno; 10 | %} 11 | %% 12 | [ \r\t\f] ; 13 | [\n] lineno++; 14 | "#".*\n lineno++ ; 15 | quote return(QUOTE); 16 | boolsig return(BOOLARG); 17 | bool return(BOOL); 18 | wordsig return(WORDARG); 19 | word return(WORD); 20 | in return(IN); 21 | '[^']*' yylval = make_quote(yytext); return(QSTRING); 22 | [a-zA-Z][a-zA-Z0-9_]* yylval = make_var(yytext); return(VAR); 23 | [0-9][0-9]* yylval = make_num(yytext); return(NUM); 24 | -[0-9][0-9]* yylval = make_num(yytext); return(NUM); 25 | "=" return(ASSIGN); 26 | ";" return(SEMI); 27 | ":" return(COLON); 28 | "," return(COMMA); 29 | "(" return(LPAREN); 30 | ")" return(RPAREN); 31 | "{" return(LBRACE); 32 | "}" return(RBRACE); 33 | "[" return(LBRACK); 34 | "]" return(RBRACK); 35 | "&&" return(AND); 36 | "||" return(OR); 37 | "!=" yylval = make_var(yytext); return(COMP); 38 | "==" yylval = make_var(yytext); return(COMP); 39 | "<" yylval = make_var(yytext); return(COMP); 40 | "<=" yylval = make_var(yytext); return(COMP); 41 | ">" yylval = make_var(yytext); return(COMP); 42 | ">=" yylval = make_var(yytext); return(COMP); 43 | "!" return(NOT); 44 | %% 45 | 46 | -------------------------------------------------------------------------------- /misc/hcl.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include "node.h" 6 | #define YYSTYPE node_ptr 7 | 8 | /* Current line number. Maintained by lex */ 9 | int lineno = 1; 10 | #define ERRLIM 5 11 | int errcnt = 0; 12 | 13 | 14 | 15 | FILE *outfile; 16 | 17 | int yyparse(void); 18 | int yylex(void); 19 | 20 | void yyerror(const char *str) 21 | { 22 | fprintf(stderr, "Error, near line %d: %s\n", lineno, str); 23 | if (++errcnt > ERRLIM) { 24 | fprintf(stderr, "Too many errors, aborting\n"); 25 | exit(1); 26 | } 27 | } 28 | 29 | static char errmsg[1024]; 30 | void yyserror(const char *str, char *other) 31 | { 32 | sprintf(errmsg, str, other); 33 | yyerror(errmsg); 34 | } 35 | 36 | int yywrap() 37 | { 38 | return 1; 39 | } 40 | 41 | int main(int argc, char **argv) 42 | { 43 | init_node(argc, argv); 44 | outfile = stdout; 45 | yyparse(); 46 | finish_node(0); 47 | return errcnt != 0; 48 | } 49 | 50 | %} 51 | 52 | %token QUOTE BOOLARG BOOL WORDARG WORD QSTRING 53 | VAR NUM ASSIGN SEMI COLON COMMA LPAREN RPAREN LBRACE 54 | RBRACE LBRACK RBRACK AND OR NOT COMP IN 55 | 56 | /* All operators are left associative. Listed from lowest to highest */ 57 | %left OR 58 | %left AND 59 | %left NOT 60 | %left COMP 61 | %left IN 62 | 63 | %% 64 | 65 | statements: /* empty */ 66 | | statements statement 67 | ; 68 | 69 | statement: 70 | QUOTE QSTRING { insert_code($2); } 71 | | BOOLARG VAR QSTRING { add_arg($2, $3, 1); } 72 | | WORDARG VAR QSTRING { add_arg($2, $3, 0); } 73 | | BOOL VAR ASSIGN expr SEMI { gen_funct($2, $4, 1); } 74 | | WORD VAR ASSIGN expr SEMI { gen_funct($2, $4, 0); } 75 | ; 76 | 77 | expr: 78 | VAR { $$=$1; } 79 | | NUM { $$=$1; } 80 | | LPAREN expr RPAREN { $$=$2; } 81 | | NOT expr { $$=make_not($2); } 82 | | expr AND expr { $$=make_and($1, $3); } 83 | | expr OR expr { $$=make_or($1, $3); } 84 | | expr COMP expr { $$=make_comp($2,$1,$3); } 85 | | expr IN LBRACE exprlist RBRACE { $$=make_ele($1, $4);} 86 | | LBRACK caselist RBRACK { $$=$2; } 87 | ; 88 | 89 | exprlist: 90 | expr { $$=$1; } 91 | | exprlist COMMA expr { $$=concat($1, $3); } 92 | 93 | caselist: 94 | /* Empty */ { $$=NULL; } 95 | | caselist expr COLON expr SEMI { $$=concat($1, make_case($2, $4));} 96 | 97 | -------------------------------------------------------------------------------- /misc/isa.h: -------------------------------------------------------------------------------- 1 | /* Instruction Set definition for Y86-64 Architecture */ 2 | /* Revisions: 3 | 2013-10-25: 4 | Extended all data widths and addresses to 64 bits 5 | Changed all 'l' instructions to 'q' 6 | Changed registers name from e-form to r-form 7 | Added registers %r8 to %r14 8 | 2009-03-11: 9 | Changed RNONE to be 0xF 10 | Changed J_XX and jump_t to C_XX and cond_t; take_branch to cond_holds 11 | Expanded RRMOVL to include conditional moves 12 | */ 13 | 14 | /**************** Registers *************************/ 15 | 16 | /* REG_NONE is a special one to indicate no register */ 17 | typedef enum { REG_RAX, REG_RCX, REG_RDX, REG_RBX, 18 | REG_RSP, REG_RBP, REG_RSI, REG_RDI, 19 | REG_R8, REG_R9, REG_R10, REG_R11, 20 | REG_R12, REG_R13, REG_R14, REG_NONE=0xF, REG_ERR } reg_id_t; 21 | 22 | /* Find register ID given its name */ 23 | reg_id_t find_register(char *name); 24 | /* Return name of register given its ID */ 25 | char *reg_name(reg_id_t id); 26 | 27 | /**************** Instruction Encoding **************/ 28 | 29 | /* Different argument types */ 30 | typedef enum { R_ARG, M_ARG, I_ARG, NO_ARG } arg_t; 31 | 32 | /* Different instruction types */ 33 | typedef enum { I_HALT, I_NOP, I_RRMOVQ, I_IRMOVQ, I_RMMOVQ, I_MRMOVQ, 34 | I_ALU, I_JMP, I_CALL, I_RET, I_PUSHQ, I_POPQ, 35 | I_IADDQ, I_POP2 } itype_t; 36 | 37 | /* Different ALU operations */ 38 | typedef enum { A_ADD, A_SUB, A_AND, A_XOR, A_NONE } alu_t; 39 | 40 | /* Default function code */ 41 | typedef enum { F_NONE } fun_t; 42 | 43 | /* Return name of operation given its ID */ 44 | char op_name(alu_t op); 45 | 46 | /* Different Jump conditions */ 47 | typedef enum { C_YES, C_LE, C_L, C_E, C_NE, C_GE, C_G } cond_t; 48 | 49 | /* Pack itype and function into single byte */ 50 | #define HPACK(hi,lo) ((((hi)&0xF)<<4)|((lo)&0xF)) 51 | 52 | /* Unpack byte */ 53 | #define HI4(byte) (((byte)>>4)&0xF) 54 | #define LO4(byte) ((byte)&0xF) 55 | 56 | /* Get the opcode out of one byte instruction field */ 57 | #define GET_ICODE(instr) HI4(instr) 58 | 59 | /* Get the ALU/JMP function out of one byte instruction field */ 60 | #define GET_FUN(instr) LO4(instr) 61 | 62 | /* Return name of instruction given it's byte encoding */ 63 | char *iname(int instr); 64 | 65 | /**************** Truth Values **************/ 66 | typedef enum { FALSE, TRUE } bool_t; 67 | 68 | /* Table used to encode information about instructions */ 69 | typedef struct { 70 | char *name; 71 | unsigned char code; /* Byte code for instruction+op */ 72 | int bytes; 73 | arg_t arg1; 74 | int arg1pos; 75 | int arg1hi; /* 0/1 for register argument, # bytes for allocation */ 76 | arg_t arg2; 77 | int arg2pos; 78 | int arg2hi; /* 0/1 */ 79 | } instr_t, *instr_ptr; 80 | 81 | instr_ptr find_instr(char *name); 82 | 83 | /* Return invalid instruction for error handling purposes */ 84 | instr_ptr bad_instr(); 85 | 86 | /*********** Implementation of Memory *****************/ 87 | typedef unsigned char byte_t; 88 | typedef long long int word_t; 89 | typedef long long unsigned uword_t; 90 | 91 | /* Represent a memory as an array of bytes */ 92 | typedef struct { 93 | int len; 94 | word_t maxaddr; 95 | byte_t *contents; 96 | } mem_rec, *mem_t; 97 | 98 | /* Create a memory with len bytes */ 99 | mem_t init_mem(int len); 100 | void free_mem(mem_t m); 101 | 102 | /* Set contents of memory to 0 */ 103 | void clear_mem(mem_t m); 104 | 105 | /* Make a copy of a memory */ 106 | mem_t copy_mem(mem_t oldm); 107 | /* Print the differences between two memories */ 108 | bool_t diff_mem(mem_t oldm, mem_t newm, FILE *outfile); 109 | 110 | /* How big should the memory be? */ 111 | #ifdef BIG_MEM 112 | #define MEM_SIZE (1<<16) 113 | #else 114 | #define MEM_SIZE (1<<13) 115 | #endif 116 | 117 | /*** In the following functions, a return value of 1 means success ***/ 118 | 119 | /* Load memory from .yo file. Return number of bytes read */ 120 | int load_mem(mem_t m, FILE *infile, int report_error); 121 | 122 | /* Get byte from memory */ 123 | bool_t get_byte_val(mem_t m, word_t pos, byte_t *dest); 124 | 125 | /* Get 8 bytes from memory */ 126 | bool_t get_word_val(mem_t m, word_t pos, word_t *dest); 127 | 128 | /* Set byte in memory */ 129 | bool_t set_byte_val(mem_t m, word_t pos, byte_t val); 130 | 131 | /* Set 8 bytes in memory */ 132 | bool_t set_word_val(mem_t m, word_t pos, word_t val); 133 | 134 | /* Print contents of memory */ 135 | void dump_memory(FILE *outfile, mem_t m, word_t pos, int cnt); 136 | 137 | /********** Implementation of Register File *************/ 138 | 139 | mem_t init_reg(); 140 | void free_reg(); 141 | 142 | /* Make a copy of a register file */ 143 | mem_t copy_reg(mem_t oldr); 144 | /* Print the differences between two register files */ 145 | bool_t diff_reg(mem_t oldr, mem_t newr, FILE *outfile); 146 | 147 | 148 | word_t get_reg_val(mem_t r, reg_id_t id); 149 | void set_reg_val(mem_t r, reg_id_t id, word_t val); 150 | void dump_reg(FILE *outfile, mem_t r); 151 | 152 | 153 | 154 | /* **************** ALU Function **********************/ 155 | 156 | /* Compute ALU operation */ 157 | word_t compute_alu(alu_t op, word_t arg1, word_t arg2); 158 | 159 | typedef unsigned char cc_t; 160 | 161 | #define GET_ZF(cc) (((cc) >> 2)&0x1) 162 | #define GET_SF(cc) (((cc) >> 1)&0x1) 163 | #define GET_OF(cc) (((cc) >> 0)&0x1) 164 | 165 | #define PACK_CC(z,s,o) (((z)<<2)|((s)<<1)|((o)<<0)) 166 | 167 | #define DEFAULT_CC PACK_CC(1,0,0) 168 | 169 | /* Compute condition code. */ 170 | cc_t compute_cc(alu_t op, word_t arg1, word_t arg2); 171 | 172 | /* Generated printed form of condition code */ 173 | char *cc_name(cc_t c); 174 | 175 | /* **************** Status types *******************/ 176 | 177 | typedef enum 178 | {STAT_BUB, STAT_AOK, STAT_HLT, STAT_ADR, STAT_INS, STAT_PIP } stat_t; 179 | 180 | /* Describe Status */ 181 | char *stat_name(stat_t e); 182 | 183 | /* **************** ISA level implementation *********/ 184 | 185 | typedef struct { 186 | word_t pc; 187 | mem_t r; 188 | mem_t m; 189 | cc_t cc; 190 | } state_rec, *state_ptr; 191 | 192 | state_ptr new_state(int memlen); 193 | void free_state(state_ptr s); 194 | 195 | state_ptr copy_state(state_ptr s); 196 | bool_t diff_state(state_ptr olds, state_ptr news, FILE *outfile); 197 | 198 | /* Determine if condition satisified */ 199 | bool_t cond_holds(cc_t cc, cond_t bcond); 200 | 201 | /* Execute single instruction. Return status. */ 202 | stat_t step_state(state_ptr s, FILE *error_file); 203 | 204 | /************************ Interface Functions *************/ 205 | 206 | #ifdef HAS_GUI 207 | void report_line(word_t line_no, word_t addr, char *hexcode, char *line); 208 | void signal_register_update(reg_id_t r, word_t val); 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /misc/mux4.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin sim-mux4-raw-hcl */ 2 | ## Simple example of an HCL file. 3 | ## This file can be converted to C using hcl2c, and then compiled. 4 | 5 | ## In this example, we will generate the MUX4 circuit shown in 6 | ## Section SLASHrefLBRACKsect:arch:hclsetRBRACK. It consists of a control block that generates 7 | ## bit-level signals s1 and s0 from the input signal code, 8 | ## and then uses these signals to control a 4-way multiplexor 9 | ## with data inputs A, B, C, and D. 10 | 11 | ## This code is embedded in a C program that reads 12 | ## the values of code, A, B, C, and D from the command line 13 | ## and then prints the circuit output 14 | 15 | ## Information that is inserted verbatim into the C file 16 | quote '#include ' 17 | quote '#include ' 18 | quote 'long long code_val, s0_val, s1_val;' 19 | quote 'char **data_names;' 20 | 21 | ## Declarations of signals used in the HCL description and 22 | ## the corresponding C expressions. 23 | boolsig s0 's0_val' 24 | boolsig s1 's1_val' 25 | wordsig code 'code_val' 26 | wordsig A 'atoll(data_names[0])' 27 | wordsig B 'atoll(data_names[1])' 28 | wordsig C 'atoll(data_names[2])' 29 | wordsig D 'atoll(data_names[3])' 30 | 31 | ## HCL descriptions of the logic blocks 32 | quote '/* $begin sim-mux4-s1-c */' 33 | bool s1 = code in { 2, 3 }; 34 | quote '/* $end sim-mux4-s1-c */' 35 | 36 | bool s0 = code in { 1, 3 }; 37 | 38 | word Out4 = [ 39 | !s1 && !s0 : A; # 00 40 | !s1 : B; # 01 41 | !s0 : C; # 10 42 | 1 : D; # 11 43 | ]; 44 | 45 | ## More information inserted verbatim into the C code to 46 | ## compute the values and print the output 47 | quote '/* $begin sim-mux4-main-c */' 48 | quote 'int main(int argc, char *argv[]) {' 49 | quote ' data_names = argv+2;' 50 | quote ' code_val = atoll(argv[1]);' 51 | quote ' s1_val = gen_s1();' 52 | quote ' s0_val = gen_s0();' 53 | quote ' printf("Out = %lld\n", gen_Out4());' 54 | quote ' return 0;' 55 | quote '}' 56 | quote '/* $end sim-mux4-main-c */' 57 | #/* $end sim-mux4-raw-hcl */ 58 | -------------------------------------------------------------------------------- /misc/node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | typedef enum { N_QUOTE, N_VAR, N_NUM, N_AND, N_OR, N_NOT, N_COMP, N_ELE, N_CASE } node_type_t; 3 | 4 | typedef struct NODE { 5 | node_type_t type; 6 | int isbool; /* Is this node a Boolean expression? */ 7 | char *sval; 8 | struct NODE *arg1; 9 | struct NODE *arg2; 10 | int ref; /* For var, how many times has it been referenced? */ 11 | struct NODE *next; 12 | } node_rec, *node_ptr; 13 | 14 | void init_node(int argc, char **argv); 15 | void finish_node(int check_ref); 16 | 17 | node_ptr make_quote(char *qstring); 18 | node_ptr make_var(char *name); 19 | node_ptr make_num(char *name); 20 | void set_bool(node_ptr varnode); 21 | node_ptr make_not(node_ptr arg); 22 | node_ptr make_and(node_ptr arg1, node_ptr arg2); 23 | node_ptr make_or(node_ptr arg1, node_ptr arg2); 24 | node_ptr make_comp(node_ptr op, node_ptr arg1, node_ptr arg2); 25 | node_ptr make_ele(node_ptr arg1, node_ptr arg2); 26 | node_ptr make_case(node_ptr arg1, node_ptr arg2); 27 | 28 | node_ptr concat(node_ptr n1, node_ptr n2); 29 | 30 | void insert_code(node_ptr qstring); 31 | void add_arg(node_ptr var, node_ptr qstring, int isbool); 32 | void gen_funct(node_ptr var, node_ptr expr, int isbool); 33 | #define NODE_H 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /misc/outgen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "outgen.h" 7 | /* Output generator that ensures no line exceeds specified number of columns */ 8 | 9 | #define STRING_LENGTH 1024 10 | 11 | FILE *outfile = NULL; 12 | int max_column = 80; 13 | int first_indent = 4; 14 | int other_indents = 2; 15 | int cur_pos = 0; 16 | int indent = 0; 17 | 18 | 19 | /* Controlling parameters */ 20 | void outgen_init(FILE *arg_outfile, int arg_max_column, int arg_first_indent, int arg_other_indents) { 21 | outfile = arg_outfile; 22 | max_column = arg_max_column; 23 | first_indent = arg_first_indent; 24 | other_indents = arg_other_indents; 25 | cur_pos = 0; 26 | indent = first_indent; 27 | } 28 | 29 | static void print_token(char *string) { 30 | if (outfile == NULL) 31 | outfile = stdout; 32 | int len = strlen(string); 33 | int i; 34 | if (len+cur_pos > max_column) { 35 | fprintf(outfile, "\n"); 36 | for (i = 0; i < indent; i++) 37 | fprintf(outfile, " "); 38 | cur_pos = indent; 39 | } 40 | fprintf(outfile, "%s", string); 41 | cur_pos += len; 42 | } 43 | 44 | 45 | /* Terminate statement and reset indentations */ 46 | void outgen_terminate() { 47 | printf("\n"); 48 | cur_pos = 0; 49 | indent = first_indent; 50 | } 51 | 52 | /* Output generator printing */ 53 | void outgen_print(char *fmt, ...) { 54 | char buf[STRING_LENGTH]; 55 | va_list argp; 56 | va_start(argp, fmt); 57 | vsprintf(buf, fmt, argp); 58 | va_end(argp); 59 | print_token(buf); 60 | } 61 | 62 | /* Increase indentation level */ 63 | void outgen_upindent() { 64 | indent += other_indents; 65 | } 66 | /* Decrease indentation level */ 67 | void outgen_downindent() { 68 | indent -= other_indents; 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /misc/outgen.h: -------------------------------------------------------------------------------- 1 | /* Output generator that ensures no line exceeds specified number of columns */ 2 | 3 | /* Controlling parameters */ 4 | void outgen_init(FILE *outfile, int max_column, int first_indent, int other_indents); 5 | 6 | /* Terminate statement and reset indentations */ 7 | void outgen_terminate(); 8 | 9 | /* Output generator printing */ 10 | void outgen_print(char *fmt, ...); 11 | 12 | /* Increase indentation level */ 13 | void outgen_upindent(); 14 | /* Decrease indentation level */ 15 | void outgen_downindent(); 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /misc/rsum.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp 4 | # Set up stack pointer 5 | call main 6 | # Execute main program 7 | halt 8 | # Terminate program 9 | # Sample linked list 10 | .align 8 11 | ele1: 12 | .quad 0x00a 13 | .quad ele2 14 | ele2: 15 | .quad 0x0b0 16 | .quad ele3 17 | ele3: 18 | .quad 0xc00 19 | .quad 0 20 | main: 21 | irmovq ele1,%rdi 22 | xorq %rax,%rax 23 | call rsumlist 24 | ret 25 | # sum_list - Recursive version of sum_list 26 | # start in %rdi 27 | rsumlist: 28 | pushq %rcx 29 | andq %rdi , %rdi 30 | je end 31 | mrmovq (%rdi) , %rcx 32 | irmovq $8 , %rbx 33 | addq %rbx , %rdi 34 | mrmovq (%rdi), %rdi 35 | call rsumlist 36 | addq %rcx , %rax 37 | end: 38 | popq %rcx 39 | ret 40 | # Stack starts here and grows to lower addresses 41 | .pos 0x200 42 | stack: 43 | -------------------------------------------------------------------------------- /misc/sum.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp 4 | # Set up stack pointer 5 | call main 6 | # Execute main program 7 | halt 8 | # Terminate program 9 | # Sample linked list 10 | .align 8 11 | ele1: 12 | .quad 0x00a 13 | .quad ele2 14 | ele2: 15 | .quad 0x0b0 16 | .quad ele3 17 | ele3: 18 | .quad 0xc00 19 | .quad 0 20 | main: 21 | irmovq ele1,%rdi 22 | call sumlist 23 | ret 24 | # sum_list - Sum the elements of a linked list 25 | # start in %rdi 26 | sumlist: 27 | xorq %rax,%rax 28 | # sum = 0 29 | andq %rdi , %rdi 30 | je end 31 | loop: mrmovq (%rdi) , %rcx 32 | addq %rcx , %rax 33 | irmovq $8 , %rbx 34 | addq %rbx , %rdi 35 | mrmovq (%rdi), %rdi 36 | andq %rdi , %rdi 37 | jne loop 38 | end: 39 | ret 40 | # Stack starts here and grows to lower addresses 41 | .pos 0x200 42 | stack: 43 | -------------------------------------------------------------------------------- /misc/yas-grammar.lex: -------------------------------------------------------------------------------- 1 | /* Grammar for Y86-64 Assembler */ 2 | #include "yas.h" 3 | 4 | Instr rrmovq|cmovle|cmovl|cmove|cmovne|cmovge|cmovg|rmmovq|mrmovq|irmovq|addq|subq|andq|xorq|jmp|jle|jl|je|jne|jge|jg|call|ret|pushq|popq|"."byte|"."word|"."long|"."quad|"."pos|"."align|halt|nop|iaddq 5 | Letter [a-zA-Z] 6 | Digit [0-9] 7 | Ident {Letter}({Letter}|{Digit}|_)* 8 | Hex [0-9a-fA-F] 9 | Blank [ \t] 10 | Newline [\n\r] 11 | Return [\r] 12 | Char [^\n\r] 13 | Reg %rax|%rcx|%rdx|%rbx|%rsi|%rdi|%rsp|%rbp|%r8|%r9|%r10|%r11|%r12|%r13|%r14 14 | 15 | %x ERR COM 16 | %% 17 | 18 | ^{Char}*{Return}*{Newline} { save_line(yytext); REJECT;} /* Snarf input line */ 19 | #{Char}*{Return}*{Newline} {finish_line(); lineno++;} 20 | "//"{Char}*{Return}*{Newline} {finish_line(); lineno++;} 21 | "/*"{Char}*{Return}*{Newline} {finish_line(); lineno++;} 22 | {Blank}*{Return}*{Newline} {finish_line(); lineno++;} 23 | 24 | {Blank}+ ; 25 | "$"+ ; 26 | {Instr} add_instr(yytext); 27 | {Reg} add_reg(yytext); 28 | [-]?{Digit}+ add_num(atoll(yytext)); 29 | "0"[xX]{Hex}+ add_num(atollh(yytext)); 30 | [():,] add_punct(*yytext); 31 | {Ident} add_ident(yytext); 32 | {Char} {; BEGIN ERR;} 33 | {Char}*{Newline} {fail("Invalid line"); lineno++; BEGIN 0;} 34 | %% 35 | 36 | unsigned int atoh(const char *s) 37 | { 38 | return(strtoul(s, NULL, 16)); 39 | } 40 | -------------------------------------------------------------------------------- /misc/yas.h: -------------------------------------------------------------------------------- 1 | void save_line(char *); 2 | void finish_line(); 3 | void add_reg(char *); 4 | void add_ident(char *); 5 | void add_instr(char *); 6 | void add_punct(char); 7 | void add_num(long long); 8 | void fail(char *msg); 9 | unsigned long long atollh(const char *); 10 | 11 | 12 | /* Current line number */ 13 | int lineno; 14 | -------------------------------------------------------------------------------- /misc/yis.c: -------------------------------------------------------------------------------- 1 | /* Instruction set simulator for Y86-64 Architecture */ 2 | 3 | #include 4 | #include 5 | 6 | #include "isa.h" 7 | 8 | /* YIS never runs in GUI mode */ 9 | int gui_mode = 0; 10 | 11 | void usage(char *pname) 12 | { 13 | printf("Usage: %s code_file [max_steps]\n", pname); 14 | exit(0); 15 | } 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | FILE *code_file; 20 | int max_steps = 10000; 21 | 22 | state_ptr s = new_state(MEM_SIZE); 23 | mem_t saver = copy_reg(s->r); 24 | mem_t savem; 25 | int step = 0; 26 | 27 | stat_t e = STAT_AOK; 28 | 29 | if (argc < 2 || argc > 3) 30 | usage(argv[0]); 31 | code_file = fopen(argv[1], "r"); 32 | if (!code_file) { 33 | fprintf(stderr, "Can't open code file '%s'\n", argv[1]); 34 | exit(1); 35 | } 36 | 37 | if (!load_mem(s->m, code_file, 1)) { 38 | printf("Exiting\n"); 39 | return 1; 40 | } 41 | 42 | savem = copy_mem(s->m); 43 | 44 | if (argc > 2) 45 | max_steps = atoi(argv[2]); 46 | 47 | for (step = 0; step < max_steps && e == STAT_AOK; step++) 48 | e = step_state(s, stdout); 49 | 50 | printf("Stopped in %d steps at PC = 0x%llx. Status '%s', CC %s\n", 51 | step, s->pc, stat_name(e), cc_name(s->cc)); 52 | 53 | printf("Changes to registers:\n"); 54 | diff_reg(saver, s->r, stdout); 55 | 56 | printf("\nChanges to memory:\n"); 57 | diff_mem(savem, s->m, stdout); 58 | 59 | free_state(s); 60 | free_reg(saver); 61 | free_mem(savem); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /pipe/4ncopy.ys: -------------------------------------------------------------------------------- 1 | #/* $begin ncopy-ys */ 2 | ################################################################## 3 | # ncopy.ys - Copy a src block of len words to dst. 4 | # Return the number of positive words (>0) contained in src. 5 | # 6 | # Include your name and ID here. 7 | # 8 | # Describe how and why you modified the baseline code. 9 | # 1. use iaddq. 10 | # 2. unroll loop. 11 | ################################################################## 12 | # Do not modify this portion 13 | # Function prologue. 14 | # %rdi = src, %rsi = dst, %rdx = len 15 | ncopy: 16 | 17 | ################################################################## 18 | # You can modify this portion 19 | # Loop header 20 | xorq %rax,%rax # count = 0; 21 | rrmovq %rdx, %rcx 22 | iaddq $-8, %rcx 23 | #andq %rdx,%rdx # len <= 0? 24 | jle Next 25 | Next: rrmovq %rdx, %rcx 26 | iaddq $-4, %rcx 27 | jle Next2 28 | Loop2: 29 | mrmovq (%rdi), %r8 30 | mrmovq 8(%rdi), %r9 31 | mrmovq 16(%rdi), %r10 32 | mrmovq 24(%rdi), %r11 33 | rmmovq %r8, (%rsi) 34 | rmmovq %r9, 8(%rsi) 35 | rmmovq %r10, 16(%rsi) 36 | rmmovq %r11, 24(%rsi) 37 | ele1: andq %r8, %r8 # val <= 0? 38 | jle ele2: # if so, goto ele1: 39 | iaddq $1, %rax # count++, %rax 40 | ele2: andq %r9, %r9 41 | jle ele3: 42 | iaddq $1, %rax 43 | ele3: andq %r10, %r10 44 | jle ele4: 45 | iaddq $1, %rax 46 | ele4: andq %r11, %r11 47 | jle Npos2: 48 | iaddq $1, %rax 49 | Npos2: iaddq $32,%rdi 50 | iaddq $32, %rsi 51 | iaddq $-4, %rdx 52 | iaddq $-4, %rcx 53 | jg Loop2 54 | Next2: andq %rdx,%rdx # len <= 0? 55 | jle Done # if so, goto Done: 56 | Loop3: mrmovq (%rdi), %rbx # read val from src... 57 | rmmovq %rbx, (%rsi) # ...and store it to dst 58 | andq %rbx, %rbx # val <= 0? 59 | jle Npos3 # if so, goto Npos3: 60 | iaddq $1, %rax # count++ 61 | Npos3: iaddq $8, %rdi # src++ 62 | iaddq $8, %rsi # dst++ 63 | iaddq $-1, %rdx # len-- 64 | jg Loop3 # if so, goto Loop3: 65 | ################################################################## 66 | # Do not modify the following section of code 67 | # Function epilogue. 68 | Done: 69 | ret 70 | ################################################################## 71 | # Keep the following label at the end of your function 72 | End: 73 | #/* $end ncopy-ys */ 74 | -------------------------------------------------------------------------------- /pipe/8ncopy.ys: -------------------------------------------------------------------------------- 1 | #/* $begin ncopy-ys */ 2 | ################################################################## 3 | # ncopy.ys - Copy a src block of len words to dst. 4 | # Return the number of positive words (>0) contained in src. 5 | # 6 | # Include your name and ID here. 7 | # 8 | # Describe how and why you modified the baseline code. 9 | # 1. use iaddq. 10 | # 2. unroll loop. 11 | ################################################################## 12 | # Do not modify this portion 13 | # Function prologue. 14 | # %rdi = src, %rsi = dst, %rdx = len 15 | ncopy: 16 | 17 | ################################################################## 18 | # You can modify this portion 19 | # Loop header 20 | xorq %rax,%rax # count = 0; 21 | rrmovq %rdx, %rcx 22 | iaddq $-8, %rcx 23 | #andq %rdx,%rdx # len <= 0? 24 | jle Next2 25 | Loop1: 26 | mrmovq (%rdi), %r8 27 | mrmovq 8(%rdi), %r9 28 | mrmovq 16(%rdi), %r10 29 | mrmovq 24(%rdi), %r11 30 | mrmovq 32(%rdi), %r12 31 | mrmovq 40(%rdi), %r13 32 | mrmovq 48(%rdi), %r14 33 | mrmovq 56(%rdi), %rbx 34 | rmmovq %r8, (%rsi) 35 | rmmovq %r9, 8(%rsi) 36 | rmmovq %r10, 16(%rsi) 37 | rmmovq %r11, 24(%rsi) 38 | rmmovq %r12, 32(%rsi) 39 | rmmovq %r13, 40(%rsi) 40 | rmmovq %r14, 48(%rsi) 41 | rmmovq %rbx, 56(%rsi) 42 | ele1: andq %r8, %r8 # val <= 0? 43 | jle ele2: # if so, goto ele1: 44 | iaddq $1, %rax # count++, %rax 45 | ele2: andq %r9, %r9 46 | jle ele3: 47 | iaddq $1, %rax 48 | ele3: andq %r10, %r10 49 | jle ele4: 50 | iaddq $1, %rax 51 | ele4: andq %r11, %r11 52 | jle ele5: 53 | iaddq $1, %rax 54 | ele5: andq %r12, %r12 55 | jle ele6: 56 | iaddq $1, %rax 57 | ele6: andq %r13, %r13 58 | jle ele7: 59 | iaddq $1, %rax 60 | ele7: andq %r14, %r14 61 | jle ele8: 62 | iaddq $1, %rax 63 | ele8: andq %rbx, %rbx 64 | jle Npos1: 65 | iaddq $1, %rax 66 | Npos1: iaddq $64, %rdi # src++ 67 | iaddq $64, %rsi # dst++ 68 | iaddq $-8, %rdx # len-- 69 | iaddq $-8, %rcx # (len-8)-- 70 | jg Loop1 # if so, goto Loop1: 71 | Next2: andq %rdx,%rdx # len <= 0? 72 | jle Done # if so, goto Done: 73 | Loop3: mrmovq (%rdi), %rbx # read val from src... 74 | rmmovq %rbx, (%rsi) # ...and store it to dst 75 | andq %rbx, %rbx # val <= 0? 76 | jle Npos3 # if so, goto Npos3: 77 | iaddq $1, %rax # count++ 78 | Npos3: iaddq $8, %rdi # src++ 79 | iaddq $8, %rsi # dst++ 80 | iaddq $-1, %rdx # len-- 81 | jg Loop3 # if so, goto Loop3: 82 | ################################################################## 83 | # Do not modify the following section of code 84 | # Function epilogue. 85 | Done: 86 | ret 87 | ################################################################## 88 | # Keep the following label at the end of your function 89 | End: 90 | #/* $end ncopy-ys */ 91 | -------------------------------------------------------------------------------- /pipe/Makefile: -------------------------------------------------------------------------------- 1 | # Modify this line to indicate the default version to build 2 | 3 | VERSION=std 4 | 5 | # Comment this out if you don't have Tcl/Tk on your system 6 | 7 | #GUIMODE=-DHAS_GUI 8 | 9 | # Modify the following line so that gcc can find the libtcl.so and 10 | # libtk.so libraries on your system. You may need to use the -L option 11 | # to tell gcc which directory to look in. Comment this out if you 12 | # don't have Tcl/Tk. 13 | 14 | #TKLIBS=-L/usr/lib -ltk -ltcl 15 | 16 | # Modify the following line so that gcc can find the tcl.h and tk.h 17 | # header files on your system. Comment this out if you don't have 18 | # Tcl/Tk. 19 | 20 | #TKINC=-isystem /usr/include/tcl8.5 21 | 22 | # Modify these two lines to choose your compiler and compile time 23 | # flags. 24 | 25 | CC=gcc 26 | CFLAGS=-Wall -O2 27 | 28 | ################################################## 29 | # You shouldn't need to modify anything below here 30 | ################################################## 31 | 32 | MISCDIR=../misc 33 | HCL2C=$(MISCDIR)/hcl2c 34 | INC=$(TKINC) -I$(MISCDIR) $(GUIMODE) 35 | LIBS=$(TKLIBS) -lm 36 | YAS = ../misc/yas 37 | 38 | all: psim drivers 39 | 40 | # This rule builds the PIPE simulator 41 | psim: psim.c sim.h pipe-$(VERSION).hcl $(MISCDIR)/isa.c $(MISCDIR)/isa.h 42 | # Building the pipe-$(VERSION).hcl version of PIPE 43 | $(HCL2C) -n pipe-$(VERSION).hcl < pipe-$(VERSION).hcl > pipe-$(VERSION).c 44 | $(CC) $(CFLAGS) $(INC) -o psim psim.c pipe-$(VERSION).c \ 45 | $(MISCDIR)/isa.c $(LIBS) 46 | 47 | # This rule builds driver programs for Part C of the Architecture Lab 48 | drivers: 49 | ./gen-driver.pl -n 4 -f ncopy.ys > sdriver.ys 50 | ../misc/yas sdriver.ys 51 | ./gen-driver.pl -n 63 -f ncopy.ys > ldriver.ys 52 | ../misc/yas ldriver.ys 53 | 54 | # These are implicit rules for assembling .yo files from .ys files. 55 | .SUFFIXES: .ys .yo 56 | .ys.yo: 57 | $(YAS) $*.ys 58 | 59 | 60 | clean: 61 | rm -f psim pipe-*.c *.o *.exe *~ 62 | 63 | 64 | -------------------------------------------------------------------------------- /pipe/README: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Pipelined Y86-64 Simulator 3 | * 4 | * Copyright (c) 2002, 2010, 2015 R. Bryant and D. O'Hallaron, 5 | * All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | ***********************************************************************/ 8 | 9 | This directory contains the code to construct simulators for PIPE and 10 | the variants of it described in the homework exercises. 11 | 12 | ************************* 13 | 1. Building the simulator 14 | ************************* 15 | 16 | Different versions of the PIPE simulator can be constructed to use 17 | different HCL files when working on the different homework problems. 18 | 19 | 20 | Binary VERSION HCL File Description 21 | psim std pipe-std.hcl Standard simulator (default) 22 | psim broken pipe-broken.hcl Does not handle any hazards 23 | psim full pipe-full.hcl For adding iaddq 24 | psim nobypass pipe-nobypass.hcl For implementing PIPE- 25 | (called pipe-stall.hcl in text) 26 | psim lf pipe-lf.hcl For implementing load forwarding 27 | psim nt pipe-nt.hcl For implementing NT branch prediction 28 | psim btfnt pipe-btfnt.hcl For implementing BTFNT branch pred. 29 | psim 1w pipe-1w.hcl For implementing single write port 30 | psim super pipe-super.hcl Implements iaddq & load forwarding 31 | 32 | The Makefile can be configured to build simulators that support GUI 33 | and/or TTY interfaces. A simulator running in TTY mode prints all 34 | information about its runtime behavior on the terminal. It's hard to 35 | understand what's going on, but useful for automated testing, and 36 | doesn't require any special installation features. A simulator 37 | running in GUI mode uses a fancy graphical user interface. Nice for 38 | visualizing and debugging, but requires installation of Tcl/Tk on your 39 | system. 40 | 41 | The Makefile has simple instructions for building the TTY and GUI 42 | forms. In either case, once you've configured the Makefile, you can 43 | build different versions of the simulators with different HCL files 44 | with commands of the form: 45 | 46 | unix> make clean; make psim VERSION=xxx 47 | 48 | where "xxx" is one of the versions listed above. To save typing, you 49 | can set the Makefile's VERSION variable. For example, if you are working 50 | on Problems 4.52 and 4.53, which require to modify pipe-full.hcl, then 51 | you could set VERSION=full in the Makefile. Typing 52 | 53 | unix> make clean; make psim 54 | 55 | would then make the pipe-full.hcl version of PIPE. 56 | 57 | *********************** 58 | 2. Using the simulators 59 | *********************** 60 | 61 | The simulator recognizes the following command line arguments: 62 | 63 | Usage: psim [-htg] [-l m] [-v n] file.yo 64 | 65 | file.yo required in GUI mode, optional in TTY mode (default stdin) 66 | 67 | -h Print this message 68 | -g Run in GUI mode instead of TTY mode (default TTY mode) 69 | -l m Set instruction limit to m [TTY mode only] (default 10000) 70 | -v n Set verbosity level to 0 <= n <= 2 [TTY mode only] (default 2) 71 | -t Test result against the ISA simulator (yis) [TTY model only] 72 | 73 | ******** 74 | 3. Files 75 | ******** 76 | 77 | Makefile Build the simulator 78 | Makefile-sim Makefile for the student distribution 79 | README This file 80 | 81 | ********************************************** 82 | * Files related to the CS:APP Architecture Lab 83 | ********************************************** 84 | 85 | * Sample programs 86 | ncopy.ys The default version of ncopy that the students optimize 87 | ncopy.c C version of ncopy that defines its semantics 88 | 89 | * Preconstructed driver programs (by gen-driver.pl) 90 | sdriver.ys Driver that calls ncopy.ys on a short (4-word) array 91 | ldriver.ys Driver that calls ncopy.ys on a longer (63-word) array 92 | Both drivers are generated automatically by the 93 | Makefile by typing "make drivers". 94 | 95 | * Solution files (Instructors only) 96 | gen-ncopy.pl Generates versions of benchmark program with various 97 | optimizations. See comments in file for explanation. 98 | 99 | * Testing scripts 100 | gen-driver.pl Generate a driver program for an arbitrary ncopy 101 | implementation (default ncopy.ys). Type "make drivers" 102 | to construct sdriver.ys and ldriver.ys. 103 | benchmark.pl Runs an implementation of ncopy on array sizes 104 | 1 to 64 (default ncopy.ys) and computes its performance 105 | in units of CPE (cycles per element). 106 | correctness.pl Runs an implementation of ncopy on array sizes 107 | 0 to 64, and several longer ones and checks each for 108 | correctness. 109 | check-len.pl Determines number of bytes in .yo representation of 110 | ncopy function. 111 | 112 | 113 | **************************************************** 114 | * HCL files for different versions of the simulators 115 | **************************************************** 116 | 117 | pipe-std.hcl The standard PIPE processor described in the text 118 | pipe-broken.hcl A simulator that does not detect or handle hazards 119 | (useful when explaining hazards in lectures) 120 | 121 | * HCL files for various CS:APP Homework Problems 122 | pipe-nobypass.hcl 4.51: Build version of PIPE without bypassing 123 | (called pipe-stall.hcl in the text) 124 | pipe-full.hcl 4.52-53: Add iaddq instruction to PIPE 125 | pipe-nt.hcl 4.54: Implement branch not taken strategy 126 | pipe-btfnt.hcl 4.55: Implement back-taken forward-not-taken strategy 127 | pipe-lf.hcl 4.56: Implement load forwarding logic 128 | pipe-1w.hcl 4.57: Implement single ported register file 129 | 130 | * HCL solution files for the CS:APP Homework Problems (Instructors only) 131 | pipe-nobypass-ans.hcl 4.51 solution 132 | pipe-full-ans.hcl 4.52-53 solutions 133 | pipe-nt-ans.hcl 4.54 solution 134 | pipe-btfnt-ans.hcl 4.55 solution 135 | pipe-lf-ans.hcl 4.56 solutions 136 | pipe-1w-ans.hcl 4.57 solutions 137 | pipe-super.hcl Gives best performance for lab 138 | 139 | ***************************** 140 | * PIPE simulator source files 141 | ***************************** 142 | 143 | psim.c Base simulator code 144 | sim.h PIPE header files 145 | pipeline.h 146 | stages.h 147 | pipe.tcl TCL script for the GUI version of PIPE 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /pipe/benchmark.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | # 5 | # benchmark.pl - Run test of pipeline on ncopy for different block sizes 6 | # and determine CPE (cycles per element) 7 | # 8 | use Getopt::Std; 9 | 10 | # 11 | # Configuration 12 | # 13 | $blocklen = 64; 14 | $yas = "../misc/yas"; 15 | $pipe = "./psim"; 16 | $gendriver = "./gen-driver.pl"; 17 | $fname = "bdriver"; 18 | $verbose = 1; 19 | 20 | ## Grading criteria 21 | $totalpoints = 60; 22 | # What CPE is required to get full credit? 23 | $fullcpe = 7.5; 24 | # What CPE is required to get nonzero credit: 25 | $threshcpe = 10.5; 26 | 27 | 28 | 29 | # 30 | # usage - Print the help message and terminate 31 | # 32 | sub usage { 33 | print STDERR "Usage: $0 [-hq] [-n N] -f FILE\n"; 34 | print STDERR " -h Print help message\n"; 35 | print STDERR " -q Quiet mode (default verbose)\n"; 36 | print STDERR " -n N Set max number of elements up to 64 (default $blocklen)\n"; 37 | print STDERR " -f FILE Input .ys file is FILE\n"; 38 | die "\n"; 39 | } 40 | 41 | getopts('hqn:f:'); 42 | 43 | if ($opt_h) { 44 | usage(); 45 | } 46 | 47 | if ($opt_q) { 48 | $verbose = 0; 49 | } 50 | 51 | if ($opt_n) { 52 | $blocklen = $opt_n; 53 | if ($blocklen < 0 || $blocklen > 64) { 54 | print STDERR "n must be between 0 and 64\n"; 55 | die "\n"; 56 | } 57 | } 58 | 59 | # Filename is required 60 | if (!$opt_f) { 61 | $ncopy = "ncopy"; 62 | } else { 63 | $ncopy = $opt_f; 64 | # Strip off .ys 65 | $ncopy =~ s/\.ys//; 66 | } 67 | 68 | if ($verbose) { 69 | print "\t$ncopy\n"; 70 | } 71 | 72 | $tcpe = 0; 73 | for ($i = 0; $i <= $blocklen; $i++) { 74 | !(system "$gendriver -n $i -f $ncopy.ys > $fname$i.ys") || 75 | die "Couldn't generate driver file $fname$i.ys\n"; 76 | !(system "$yas $fname$i.ys") || 77 | die "Couldn't assemble file $fname$i.ys\n"; 78 | $stat = `$pipe -v 0 $fname$i.yo` || 79 | die "Couldn't simulate file $fname$i.yo\n"; 80 | !(system "rm $fname$i.ys $fname$i.yo") || 81 | die "Couldn't remove files $fname$i.ys and/or $fname$i.yo\n"; 82 | chomp $stat; 83 | $stat =~ s/[ ]*CPI:[ ]*//; 84 | $stat =~ s/ cycles.*//; 85 | if ($i > 0) { 86 | $cpe = $stat/$i; 87 | if ($verbose) { 88 | printf "%d\t%d\t%.2f\n", $i, $stat, $cpe; 89 | } 90 | $tcpe += $cpe; 91 | } else { 92 | if ($verbose) { 93 | printf "%d\t%d\n", $i, $stat; 94 | } 95 | } 96 | 97 | } 98 | 99 | $acpe = $tcpe/$blocklen; 100 | printf "Average CPE\t%.2f\n", $acpe; 101 | 102 | ## Compute Score 103 | $score = 0; 104 | if ($acpe <= $fullcpe) { 105 | $score = $totalpoints; 106 | } elsif ($acpe <= $threshcpe) { 107 | $score = $totalpoints * ($threshcpe - $acpe)/($threshcpe - $fullcpe); 108 | } 109 | printf "Score\t%.1f/%.1f\n", $score, $totalpoints; 110 | 111 | -------------------------------------------------------------------------------- /pipe/check-len.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Check length of ncopy function in .yo file 4 | # Assumes that function starts with label "ncopy:" 5 | # and finishes with label "End:" 6 | 7 | $startpos = -1; 8 | $endpos = -1; 9 | 10 | while (<>) { 11 | $line = $_; 12 | if ($line =~ /(0x[0-9a-fA-F]+):.* ncopy:/) { 13 | $startpos = hex($1); 14 | } 15 | if ($line =~ /(0x[0-9a-fA-F]+):.* End:/) { 16 | $endpos = hex($1); 17 | } 18 | } 19 | 20 | if ($startpos >= 0 && $endpos > $startpos) { 21 | $len = $endpos - $startpos; 22 | print "ncopy length = $len bytes\n"; 23 | } else { 24 | print "Couldn't determine ncopy length\n"; 25 | } 26 | -------------------------------------------------------------------------------- /pipe/correctness.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | # 5 | # correctness.pl - Test ncopy assembly code for correctness 6 | # 7 | use Getopt::Std; 8 | 9 | # 10 | # Configuration 11 | # 12 | $blocklen = 64; 13 | $over = 3; 14 | $yas = "../misc/yas"; 15 | $yis = "../misc/yis"; 16 | $pipe = "./psim"; 17 | $gendriver = "./gen-driver.pl"; 18 | $fname = "cdriver"; 19 | $verbose = 1; 20 | # Maximum allowable code length 21 | $bytelim = 1000; 22 | 23 | # 24 | # usage - Print the help message and terminate 25 | # 26 | sub usage { 27 | print STDERR "Usage: $0 [-hqp] [-n N] -f FILE\n"; 28 | print STDERR " -h Print help message\n"; 29 | print STDERR " -q Quiet mode (default verbose)\n"; 30 | print STDERR " -p Run program on pipeline simulator (default ISA sim)\n"; 31 | print STDERR " -n N Set max number of elements up to 64 (default $blocklen)\n"; 32 | print STDERR " -f FILE Input .ys file is FILE\n"; 33 | print STDERR " -b blim set byte limit for function\n"; 34 | die "\n"; 35 | } 36 | 37 | getopts('hqpn:f:b:'); 38 | 39 | if ($opt_h) { 40 | usage(); 41 | } 42 | 43 | if ($opt_q) { 44 | $verbose = 0; 45 | } 46 | 47 | if ($opt_b) { 48 | $bytelim = $opt_b; 49 | } 50 | 51 | $usepipe = 0; 52 | if ($opt_p) { 53 | $usepipe = 1; 54 | print "Simulating with pipeline simulator psim\n"; 55 | } else { 56 | print "Simulating with instruction set simulator yis\n"; 57 | } 58 | 59 | 60 | if ($opt_n) { 61 | $blocklen = $opt_n; 62 | if ($blocklen < 0) { 63 | print STDERR "n must be >= 0\n"; 64 | die "\n"; 65 | } 66 | } 67 | 68 | # Filename is required 69 | if (!$opt_f) { 70 | $ncopy = "ncopy"; 71 | } else { 72 | $ncopy = $opt_f; 73 | # Strip off .ys 74 | $ncopy =~ s/\.ys//; 75 | } 76 | 77 | if ($verbose) { 78 | print "\t$ncopy\n"; 79 | } 80 | 81 | $goodcnt = 0; 82 | 83 | for ($i = 0; $i <= $blocklen+$over; $i++) { 84 | $len = $i; 85 | if ($i > $blocklen) { 86 | # Try some larger values 87 | $len = $blocklen * ($i - $blocklen + 1); 88 | } 89 | !(system "$gendriver -rc -n $len -f $ncopy.ys -b $bytelim > $fname$len.ys") || 90 | die "Couldn't generate driver file $fname$len.ys\n"; 91 | !(system "$yas $fname$len.ys") || 92 | die "Couldn't assemble file $fname$len.ys\n"; 93 | if ($usepipe) { 94 | !(system "$pipe -v 1 $fname$len.yo > $fname$len.pipe") || 95 | die "Couldn't simulate file $fname$len.yo with pipeline simulator\n"; 96 | $stat = `grep "rax:" $fname$len.pipe`; 97 | !(system "rm $fname$len.ys $fname$len.yo $fname$len.pipe") || 98 | die "Couldn't remove files $fname$len.ys and/or $fname$len.yo and/or $fname$len.pipe\n"; 99 | chomp $stat; 100 | } else { 101 | !(system "$yis $fname$len.yo > $fname$len.yis") || 102 | die "Couldn't simulate file $fname$len.yo with instruction set simulator\n"; 103 | $stat = `grep rax $fname$len.yis`; 104 | !(system "rm $fname$len.ys $fname$len.yo $fname$len.yis") || 105 | die "Couldn't remove files $fname$len.ys and/or $fname$len.yo and/or $fname$len.yis\n"; 106 | chomp $stat; 107 | } 108 | $result = "failed"; 109 | if ($stat =~ "zzzz") { 110 | $result = "Couldn't run checking code"; 111 | } 112 | if ($stat =~ "aaaa") { 113 | $result = "OK"; 114 | $goodcnt ++; 115 | } 116 | if ($stat =~ "bbbb") { 117 | $result = "Bad count"; 118 | } 119 | if ($stat =~ "cccc") { 120 | $result = "Program too long"; 121 | printf "%d\t%s\n", $len, $result; 122 | last; 123 | } 124 | if ($stat =~ "dddd") { 125 | $result = "Incorrect copying"; 126 | } 127 | if ($stat =~ "eeee") { 128 | $result = "Corruption before or after destination"; 129 | } 130 | if ($verbose) { 131 | printf "%d\t%s\n", $len, $result; 132 | } 133 | } 134 | 135 | $bp1 = $blocklen+$over+1; 136 | printf "$goodcnt/$bp1 pass correctness test\n"; 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /pipe/gen-driver.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | # 5 | # gen-driver - Generate driver file for any ncopy function 6 | # 7 | use Getopt::Std; 8 | 9 | $n = 0; 10 | 11 | getopts('hcrn:f:b:'); 12 | 13 | if ($opt_h) { 14 | print STDERR "Usage $argv[0] [-h] [-c] [-n N] [-f FILE]\n"; 15 | print STDERR " -h print help message\n"; 16 | print STDERR " -c include correctness checking code\n"; 17 | print STDERR " -n N set number of elements\n"; 18 | print STDERR " -f FILE set input file (default stdin)\n"; 19 | print STDERR " -b blim set byte limit for function\n"; 20 | print STDERR " -r Allow random result\n"; 21 | die "\n"; 22 | } 23 | 24 | $check = 0; 25 | if ($opt_c) { 26 | $check = 1; 27 | } 28 | 29 | $bytelim = 1000; 30 | if ($opt_b) { 31 | $bytelim = $opt_b; 32 | } 33 | 34 | if ($opt_n) { 35 | $n = $opt_n; 36 | if ($n < 0) { 37 | print STDERR "n must be at least 0\n"; 38 | die "\n"; 39 | } 40 | } 41 | 42 | $randomval = 0; 43 | # Accumulated count 44 | $rval = 0; 45 | 46 | if ($opt_r) { 47 | $randomval = 1; 48 | } else { 49 | # Value that should be returned by function 50 | $tval = int($n/2); 51 | } 52 | 53 | 54 | # The data to be stored. 55 | @data = (); 56 | 57 | for ($i = 0; $i < $n; $i++) { 58 | $data[$i] = -($i+1); 59 | if ($randomval) { 60 | if (int(rand(2)) == 1) { 61 | $data[$i] = -$data[$i]; 62 | $rval++; 63 | } 64 | } else { 65 | if ($rval < $tval && int(rand(2)) % 2 == 1 || 66 | $tval - $rval >= $n - $i) { 67 | $data[$i] = -$data[$i]; 68 | $rval++; 69 | } 70 | } 71 | } 72 | 73 | 74 | # Values to put at beginning and end of destination 75 | $Preval = "0xbcdefa"; 76 | $Postval = "0xdefabc"; 77 | 78 | 79 | print <) { 108 | printf "%s", $_; 109 | } 110 | } else { 111 | while (<>) { 112 | printf "%s", $_; 113 | } 114 | } 115 | print "EndFun:\n"; 116 | 117 | if ($check) { 118 | print <0) contained in src. 5 | # 6 | # Include your name and ID here. 7 | # 8 | # Describe how and why you modified the baseline code. 9 | # 1. use iaddq. 10 | # 2. unroll loop. 11 | ################################################################## 12 | # Do not modify this portion 13 | # Function prologue. 14 | # %rdi = src, %rsi = dst, %rdx = len 15 | ncopy: 16 | 17 | ################################################################## 18 | # You can modify this portion 19 | # Loop header 20 | xorq %rax,%rax # count = 0; 21 | rrmovq %rdx, %rcx 22 | iaddq $-8, %rcx 23 | #andq %rdx,%rdx # len <= 0? 24 | jle Next 25 | Loop1: 26 | mrmovq (%rdi), %r8 27 | mrmovq 8(%rdi), %r9 28 | mrmovq 16(%rdi), %r10 29 | mrmovq 24(%rdi), %r11 30 | mrmovq 32(%rdi), %r12 31 | mrmovq 40(%rdi), %r13 32 | mrmovq 48(%rdi), %r14 33 | mrmovq 56(%rdi), %rbx 34 | rmmovq %r8, (%rsi) 35 | rmmovq %r9, 8(%rsi) 36 | rmmovq %r10, 16(%rsi) 37 | rmmovq %r11, 24(%rsi) 38 | rmmovq %r12, 32(%rsi) 39 | rmmovq %r13, 40(%rsi) 40 | rmmovq %r14, 48(%rsi) 41 | rmmovq %rbx, 56(%rsi) 42 | ele1: andq %r8, %r8 # val <= 0? 43 | jle ele2: # if so, goto ele1: 44 | iaddq $1, %rax # count++, %rax 45 | ele2: andq %r9, %r9 46 | jle ele3: 47 | iaddq $1, %rax 48 | ele3: andq %r10, %r10 49 | jle ele4: 50 | iaddq $1, %rax 51 | ele4: andq %r11, %r11 52 | jle ele5: 53 | iaddq $1, %rax 54 | ele5: andq %r12, %r12 55 | jle ele6: 56 | iaddq $1, %rax 57 | ele6: andq %r13, %r13 58 | jle ele7: 59 | iaddq $1, %rax 60 | ele7: andq %r14, %r14 61 | jle ele8: 62 | iaddq $1, %rax 63 | ele8: andq %rbx, %rbx 64 | jle Npos1: 65 | iaddq $1, %rax 66 | Npos1: iaddq $64, %rdi # src++ 67 | iaddq $64, %rsi # dst++ 68 | iaddq $-8, %rdx # len-- 69 | iaddq $-8, %rcx # (len-8)-- 70 | jg Loop1 # if so, goto Loop1: 71 | Next: rrmovq %rdx, %rcx 72 | iaddq $-4, %rcx 73 | jl Next2 74 | Loop2: 75 | mrmovq (%rdi), %r8 76 | mrmovq 8(%rdi), %r9 77 | mrmovq 16(%rdi), %r10 78 | mrmovq 24(%rdi), %r11 79 | rmmovq %r8, (%rsi) 80 | rmmovq %r9, 8(%rsi) 81 | rmmovq %r10, 16(%rsi) 82 | rmmovq %r11, 24(%rsi) 83 | ele1: andq %r8, %r8 # val <= 0? 84 | jle ele2: # if so, goto ele1: 85 | iaddq $1, %rax # count++, %rax 86 | ele2: andq %r9, %r9 87 | jle ele3: 88 | iaddq $1, %rax 89 | ele3: andq %r10, %r10 90 | jle ele4: 91 | iaddq $1, %rax 92 | ele4: andq %r11, %r11 93 | jle Npos2: 94 | iaddq $1, %rax 95 | Npos2: iaddq $32,%rdi 96 | iaddq $32, %rsi 97 | iaddq $-4, %rdx 98 | iaddq $-4, %rcx 99 | jg Loop2 100 | Next2: andq %rdx,%rdx # len <= 0? 101 | jle Done # if so, goto Done: 102 | Loop3: mrmovq (%rdi), %rbx # read val from src... 103 | rmmovq %rbx, (%rsi) # ...and store it to dst 104 | andq %rbx, %rbx # val <= 0? 105 | jle Npos3 # if so, goto Npos3: 106 | iaddq $1, %rax # count++ 107 | Npos3: iaddq $8, %rdi # src++ 108 | iaddq $8, %rsi # dst++ 109 | iaddq $-1, %rdx # len-- 110 | jg Loop3 # if so, goto Loop3: 111 | ################################################################## 112 | # Do not modify the following section of code 113 | # Function epilogue. 114 | Done: 115 | ret 116 | ################################################################## 117 | # Keep the following label at the end of your function 118 | End: 119 | #/* $end ncopy-ys */ 120 | -------------------------------------------------------------------------------- /pipe/ncopy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef word_t word_t; 4 | 5 | word_t src[8], dst[8]; 6 | 7 | /* $begin ncopy */ 8 | /* 9 | * ncopy - copy src to dst, returning number of positive ints 10 | * contained in src array. 11 | */ 12 | word_t ncopy(word_t *src, word_t *dst, word_t len) 13 | { 14 | word_t count = 0; 15 | word_t val; 16 | 17 | while (len > 0) { 18 | val = *src++; 19 | *dst++ = val; 20 | if (val > 0) 21 | count++; 22 | len--; 23 | } 24 | return count; 25 | } 26 | /* $end ncopy */ 27 | 28 | int main() 29 | { 30 | word_t i, count; 31 | 32 | for (i=0; i<8; i++) 33 | src[i]= i+1; 34 | count = ncopy(src, dst, 8); 35 | printf ("count=%d\n", count); 36 | exit(0); 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /pipe/ncopy.ys: -------------------------------------------------------------------------------- 1 | #/* $begin ncopy-ys */ 2 | ################################################################## 3 | # ncopy.ys - Copy a src block of len words to dst. 4 | # Return the number of positive words (>0) contained in src. 5 | # 6 | # Include your name and ID here. 7 | # 8 | # Describe how and why you modified the baseline code. 9 | # 1. use iaddq. 10 | # 2. unroll loop. 11 | ################################################################## 12 | # Do not modify this portion 13 | # Function prologue. 14 | # %rdi = src, %rsi = dst, %rdx = len 15 | ncopy: 16 | 17 | ################################################################## 18 | # You can modify this portion 19 | # Loop header 20 | xorq %rax,%rax # count = 0; 21 | rrmovq %rdx, %rcx 22 | iaddq $-8, %rcx 23 | #andq %rdx,%rdx # len <= 0? 24 | jle Next2 25 | Loop1: 26 | mrmovq (%rdi), %r8 27 | mrmovq 8(%rdi), %r9 28 | mrmovq 16(%rdi), %r10 29 | mrmovq 24(%rdi), %r11 30 | mrmovq 32(%rdi), %r12 31 | mrmovq 40(%rdi), %r13 32 | mrmovq 48(%rdi), %r14 33 | mrmovq 56(%rdi), %rbx 34 | rmmovq %r8, (%rsi) 35 | rmmovq %r9, 8(%rsi) 36 | rmmovq %r10, 16(%rsi) 37 | rmmovq %r11, 24(%rsi) 38 | rmmovq %r12, 32(%rsi) 39 | rmmovq %r13, 40(%rsi) 40 | rmmovq %r14, 48(%rsi) 41 | rmmovq %rbx, 56(%rsi) 42 | ele1: andq %r8, %r8 # val <= 0? 43 | jle ele2: # if so, goto ele1: 44 | iaddq $1, %rax # count++, %rax 45 | ele2: andq %r9, %r9 46 | jle ele3: 47 | iaddq $1, %rax 48 | ele3: andq %r10, %r10 49 | jle ele4: 50 | iaddq $1, %rax 51 | ele4: andq %r11, %r11 52 | jle ele5: 53 | iaddq $1, %rax 54 | ele5: andq %r12, %r12 55 | jle ele6: 56 | iaddq $1, %rax 57 | ele6: andq %r13, %r13 58 | jle ele7: 59 | iaddq $1, %rax 60 | ele7: andq %r14, %r14 61 | jle ele8: 62 | iaddq $1, %rax 63 | ele8: andq %rbx, %rbx 64 | jle Npos1: 65 | iaddq $1, %rax 66 | Npos1: iaddq $64, %rdi # src++ 67 | iaddq $64, %rsi # dst++ 68 | iaddq $-8, %rdx # len-- 69 | iaddq $-8, %rcx # (len-8)-- 70 | jg Loop1 # if so, goto Loop1: 71 | Next2: andq %rdx,%rdx # len <= 0? 72 | jle Done # if so, goto Done: 73 | Loop3: mrmovq (%rdi), %rbx # read val from src... 74 | rmmovq %rbx, (%rsi) # ...and store it to dst 75 | andq %rbx, %rbx # val <= 0? 76 | jle Npos3 # if so, goto Npos3: 77 | iaddq $1, %rax # count++ 78 | Npos3: iaddq $8, %rdi # src++ 79 | iaddq $8, %rsi # dst++ 80 | iaddq $-1, %rdx # len-- 81 | jg Loop3 # if so, goto Loop3: 82 | ################################################################## 83 | # Do not modify the following section of code 84 | # Function epilogue. 85 | Done: 86 | ret 87 | ################################################################## 88 | # Keep the following label at the end of your function 89 | End: 90 | #/* $end ncopy-ys */ 91 | -------------------------------------------------------------------------------- /pipe/pipe-broken.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin pipe-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Pipelined Y86-64 Processor # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2014 # 5 | #################################################################### 6 | ## This version does not detect or handle any hazards 7 | 8 | #################################################################### 9 | # C Include's. Don't alter these # 10 | #################################################################### 11 | 12 | quote '#include ' 13 | quote '#include "isa.h"' 14 | quote '#include "pipeline.h"' 15 | quote '#include "stages.h"' 16 | quote '#include "sim.h"' 17 | quote 'int sim_main(int argc, char *argv[]);' 18 | quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' 19 | 20 | #################################################################### 21 | # Declarations. Do not change/remove/delete any of these # 22 | #################################################################### 23 | 24 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 25 | wordsig INOP 'I_NOP' 26 | wordsig IHALT 'I_HALT' 27 | wordsig IRRMOVQ 'I_RRMOVQ' 28 | wordsig IIRMOVQ 'I_IRMOVQ' 29 | wordsig IRMMOVQ 'I_RMMOVQ' 30 | wordsig IMRMOVQ 'I_MRMOVQ' 31 | wordsig IOPQ 'I_ALU' 32 | wordsig IJXX 'I_JMP' 33 | wordsig ICALL 'I_CALL' 34 | wordsig IRET 'I_RET' 35 | wordsig IPUSHQ 'I_PUSHQ' 36 | wordsig IPOPQ 'I_POPQ' 37 | 38 | ##### Symbolic represenations of Y86-64 function codes ##### 39 | wordsig FNONE 'F_NONE' # Default function code 40 | 41 | ##### Symbolic representation of Y86-64 Registers referenced ##### 42 | wordsig RRSP 'REG_RSP' # Stack Pointer 43 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 44 | 45 | ##### ALU Functions referenced explicitly ########################## 46 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 47 | 48 | ##### Possible instruction status values ##### 49 | wordsig SBUB 'STAT_BUB' # Bubble in stage 50 | wordsig SAOK 'STAT_AOK' # Normal execution 51 | wordsig SADR 'STAT_ADR' # Invalid memory address 52 | wordsig SINS 'STAT_INS' # Invalid instruction 53 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 54 | 55 | ##### Signals that can be referenced by control logic ############## 56 | 57 | ##### Pipeline Register F ########################################## 58 | 59 | wordsig F_predPC 'pc_curr->pc' # Predicted value of PC 60 | 61 | ##### Intermediate Values in Fetch Stage ########################### 62 | 63 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 64 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 65 | wordsig f_icode 'if_id_next->icode' # (Possibly modified) instruction code 66 | wordsig f_ifun 'if_id_next->ifun' # Fetched instruction function 67 | wordsig f_valC 'if_id_next->valc' # Constant data of fetched instruction 68 | wordsig f_valP 'if_id_next->valp' # Address of following instruction 69 | boolsig imem_error 'imem_error' # Error signal from instruction memory 70 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 71 | 72 | ##### Pipeline Register D ########################################## 73 | wordsig D_icode 'if_id_curr->icode' # Instruction code 74 | wordsig D_rA 'if_id_curr->ra' # rA field from instruction 75 | wordsig D_rB 'if_id_curr->rb' # rB field from instruction 76 | wordsig D_valP 'if_id_curr->valp' # Incremented PC 77 | 78 | ##### Intermediate Values in Decode Stage ######################### 79 | 80 | wordsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction 81 | wordsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction 82 | wordsig d_rvalA 'd_regvala' # valA read from register file 83 | wordsig d_rvalB 'd_regvalb' # valB read from register file 84 | 85 | ##### Pipeline Register E ########################################## 86 | wordsig E_icode 'id_ex_curr->icode' # Instruction code 87 | wordsig E_ifun 'id_ex_curr->ifun' # Instruction function 88 | wordsig E_valC 'id_ex_curr->valc' # Constant data 89 | wordsig E_srcA 'id_ex_curr->srca' # Source A register ID 90 | wordsig E_valA 'id_ex_curr->vala' # Source A value 91 | wordsig E_srcB 'id_ex_curr->srcb' # Source B register ID 92 | wordsig E_valB 'id_ex_curr->valb' # Source B value 93 | wordsig E_dstE 'id_ex_curr->deste' # Destination E register ID 94 | wordsig E_dstM 'id_ex_curr->destm' # Destination M register ID 95 | 96 | ##### Intermediate Values in Execute Stage ######################### 97 | wordsig e_valE 'ex_mem_next->vale' # valE generated by ALU 98 | boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold? 99 | wordsig e_dstE 'ex_mem_next->deste' # dstE (possibly modified to be RNONE) 100 | 101 | ##### Pipeline Register M ######################### 102 | wordsig M_stat 'ex_mem_curr->status' # Instruction status 103 | wordsig M_icode 'ex_mem_curr->icode' # Instruction code 104 | wordsig M_ifun 'ex_mem_curr->ifun' # Instruction function 105 | wordsig M_valA 'ex_mem_curr->vala' # Source A value 106 | wordsig M_dstE 'ex_mem_curr->deste' # Destination E register ID 107 | wordsig M_valE 'ex_mem_curr->vale' # ALU E value 108 | wordsig M_dstM 'ex_mem_curr->destm' # Destination M register ID 109 | boolsig M_Cnd 'ex_mem_curr->takebranch' # Condition flag 110 | boolsig dmem_error 'dmem_error' # Error signal from instruction memory 111 | 112 | ##### Intermediate Values in Memory Stage ########################## 113 | wordsig m_valM 'mem_wb_next->valm' # valM generated by memory 114 | wordsig m_stat 'mem_wb_next->status' # stat (possibly modified to be SADR) 115 | 116 | ##### Pipeline Register W ########################################## 117 | wordsig W_stat 'mem_wb_curr->status' # Instruction status 118 | wordsig W_icode 'mem_wb_curr->icode' # Instruction code 119 | wordsig W_dstE 'mem_wb_curr->deste' # Destination E register ID 120 | wordsig W_valE 'mem_wb_curr->vale' # ALU E value 121 | wordsig W_dstM 'mem_wb_curr->destm' # Destination M register ID 122 | wordsig W_valM 'mem_wb_curr->valm' # Memory M value 123 | 124 | #################################################################### 125 | # Control Signal Definitions. # 126 | #################################################################### 127 | 128 | ################ Fetch Stage ################################### 129 | 130 | ## What address should instruction be fetched at 131 | word f_pc = [ 132 | # Mispredicted branch. Fetch at incremented PC 133 | M_icode == IJXX && !M_Cnd : M_valA; 134 | # Completion of RET instruction 135 | W_icode == IRET : W_valM; 136 | # Default: Use predicted value of PC 137 | 1 : F_predPC; 138 | ]; 139 | 140 | ## Determine icode of fetched instruction 141 | word f_icode = [ 142 | imem_error : INOP; 143 | 1: imem_icode; 144 | ]; 145 | 146 | # Determine ifun 147 | word f_ifun = [ 148 | imem_error : FNONE; 149 | 1: imem_ifun; 150 | ]; 151 | 152 | # Is instruction valid? 153 | bool instr_valid = f_icode in 154 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 155 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 156 | 157 | # Determine status code for fetched instruction 158 | word f_stat = [ 159 | imem_error: SADR; 160 | !instr_valid : SINS; 161 | f_icode == IHALT : SHLT; 162 | 1 : SAOK; 163 | ]; 164 | 165 | # Does fetched instruction require a regid byte? 166 | bool need_regids = 167 | f_icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 168 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 169 | 170 | # Does fetched instruction require a constant word? 171 | bool need_valC = 172 | f_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 173 | 174 | # Predict next value of PC 175 | word f_predPC = [ 176 | f_icode in { IJXX, ICALL } : f_valC; 177 | 1 : f_valP; 178 | ]; 179 | 180 | ################ Decode Stage ###################################### 181 | 182 | 183 | ## What register should be used as the A source? 184 | word d_srcA = [ 185 | D_icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : D_rA; 186 | D_icode in { IPOPQ, IRET } : RRSP; 187 | 1 : RNONE; # Don't need register 188 | ]; 189 | 190 | ## What register should be used as the B source? 191 | word d_srcB = [ 192 | D_icode in { IOPQ, IRMMOVQ, IMRMOVQ } : D_rB; 193 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 194 | 1 : RNONE; # Don't need register 195 | ]; 196 | 197 | ## What register should be used as the E destination? 198 | word d_dstE = [ 199 | D_icode in { IRRMOVQ, IIRMOVQ, IOPQ} : D_rB; 200 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 201 | 1 : RNONE; # Don't write any register 202 | ]; 203 | 204 | ## What register should be used as the M destination? 205 | word d_dstM = [ 206 | D_icode in { IMRMOVQ, IPOPQ } : D_rA; 207 | 1 : RNONE; # Don't write any register 208 | ]; 209 | 210 | ## What should be the A value? 211 | ## No forwarding. valA is either valP or value from register file 212 | word d_valA = [ 213 | D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC 214 | 1 : d_rvalA; # Use value read from register file 215 | ]; 216 | 217 | ## No forwarding. valB is value from register file 218 | word d_valB = d_rvalB; 219 | 220 | ################ Execute Stage ##################################### 221 | 222 | ## Select input A to ALU 223 | word aluA = [ 224 | E_icode in { IRRMOVQ, IOPQ } : E_valA; 225 | E_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : E_valC; 226 | E_icode in { ICALL, IPUSHQ } : -8; 227 | E_icode in { IRET, IPOPQ } : 8; 228 | # Other instructions don't need ALU 229 | ]; 230 | 231 | ## Select input B to ALU 232 | word aluB = [ 233 | E_icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 234 | IPUSHQ, IRET, IPOPQ } : E_valB; 235 | E_icode in { IRRMOVQ, IIRMOVQ } : 0; 236 | # Other instructions don't need ALU 237 | ]; 238 | 239 | ## Set the ALU function 240 | word alufun = [ 241 | E_icode == IOPQ : E_ifun; 242 | 1 : ALUADD; 243 | ]; 244 | 245 | ## Should the condition codes be updated? 246 | bool set_cc = E_icode == IOPQ && 247 | # State changes only during normal operation 248 | !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT }; 249 | 250 | ## Generate valA in execute stage 251 | word e_valA = E_valA; # Pass valA through stage 252 | 253 | ## Set dstE to RNONE in event of not-taken conditional move 254 | word e_dstE = [ 255 | E_icode == IRRMOVQ && !e_Cnd : RNONE; 256 | 1 : E_dstE; 257 | ]; 258 | 259 | ################ Memory Stage ###################################### 260 | 261 | ## Select memory address 262 | word mem_addr = [ 263 | M_icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : M_valE; 264 | M_icode in { IPOPQ, IRET } : M_valA; 265 | # Other instructions don't need address 266 | ]; 267 | 268 | ## Set read control signal 269 | bool mem_read = M_icode in { IMRMOVQ, IPOPQ, IRET }; 270 | 271 | ## Set write control signal 272 | bool mem_write = M_icode in { IRMMOVQ, IPUSHQ, ICALL }; 273 | 274 | #/* $begin pipe-m_stat-hcl */ 275 | ## Update the status 276 | word m_stat = [ 277 | dmem_error : SADR; 278 | 1 : M_stat; 279 | ]; 280 | #/* $end pipe-m_stat-hcl */ 281 | 282 | ## Set E port register ID 283 | word w_dstE = W_dstE; 284 | 285 | ## Set E port value 286 | word w_valE = W_valE; 287 | 288 | ## Set M port register ID 289 | word w_dstM = W_dstM; 290 | 291 | ## Set M port value 292 | word w_valM = W_valM; 293 | 294 | ## Update processor status 295 | word Stat = [ 296 | W_stat == SBUB : SAOK; 297 | 1 : W_stat; 298 | ]; 299 | 300 | ################ Pipeline Register Control ######################### 301 | 302 | # Should I stall or inject a bubble into Pipeline Register F? 303 | # At most one of these can be true. 304 | bool F_bubble = 0; 305 | bool F_stall = 306 | 0; 307 | 308 | # Should I stall or inject a bubble into Pipeline Register D? 309 | # At most one of these can be true. 310 | bool D_stall = 311 | 0; 312 | 313 | bool D_bubble = 314 | 0; 315 | 316 | # Should I stall or inject a bubble into Pipeline Register E? 317 | # At most one of these can be true. 318 | bool E_stall = 0; 319 | bool E_bubble = 320 | 0; 321 | 322 | # Should I stall or inject a bubble into Pipeline Register M? 323 | # At most one of these can be true. 324 | bool M_stall = 0; 325 | # Start injecting bubbles as soon as exception passes through memory stage 326 | bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT }; 327 | 328 | # Should I stall or inject a bubble into Pipeline Register W? 329 | bool W_stall = W_stat in { SADR, SINS, SHLT }; 330 | bool W_bubble = 0; 331 | #/* $end pipe-all-hcl */ 332 | -------------------------------------------------------------------------------- /pipe/pipe-full.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin pipe-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Pipelined Y86-64 Processor # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2014 # 5 | #################################################################### 6 | 7 | ## Your task is to implement the iaddq instruction 8 | ## The file contains a declaration of the icodes 9 | ## for iaddq (IIADDQ) 10 | ## Your job is to add the rest of the logic to make it work 11 | 12 | #################################################################### 13 | # C Include's. Don't alter these # 14 | #################################################################### 15 | 16 | quote '#include ' 17 | quote '#include "isa.h"' 18 | quote '#include "pipeline.h"' 19 | quote '#include "stages.h"' 20 | quote '#include "sim.h"' 21 | quote 'int sim_main(int argc, char *argv[]);' 22 | quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' 23 | 24 | #################################################################### 25 | # Declarations. Do not change/remove/delete any of these # 26 | #################################################################### 27 | 28 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 29 | wordsig INOP 'I_NOP' 30 | wordsig IHALT 'I_HALT' 31 | wordsig IRRMOVQ 'I_RRMOVQ' 32 | wordsig IIRMOVQ 'I_IRMOVQ' 33 | wordsig IRMMOVQ 'I_RMMOVQ' 34 | wordsig IMRMOVQ 'I_MRMOVQ' 35 | wordsig IOPQ 'I_ALU' 36 | wordsig IJXX 'I_JMP' 37 | wordsig ICALL 'I_CALL' 38 | wordsig IRET 'I_RET' 39 | wordsig IPUSHQ 'I_PUSHQ' 40 | wordsig IPOPQ 'I_POPQ' 41 | # Instruction code for iaddq instruction 42 | wordsig IIADDQ 'I_IADDQ' 43 | 44 | ##### Symbolic represenations of Y86-64 function codes ##### 45 | wordsig FNONE 'F_NONE' # Default function code 46 | 47 | ##### Symbolic representation of Y86-64 Registers referenced ##### 48 | wordsig RRSP 'REG_RSP' # Stack Pointer 49 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 50 | 51 | ##### ALU Functions referenced explicitly ########################## 52 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 53 | 54 | ##### Possible instruction status values ##### 55 | wordsig SBUB 'STAT_BUB' # Bubble in stage 56 | wordsig SAOK 'STAT_AOK' # Normal execution 57 | wordsig SADR 'STAT_ADR' # Invalid memory address 58 | wordsig SINS 'STAT_INS' # Invalid instruction 59 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 60 | 61 | ##### Signals that can be referenced by control logic ############## 62 | 63 | ##### Pipeline Register F ########################################## 64 | 65 | wordsig F_predPC 'pc_curr->pc' # Predicted value of PC 66 | 67 | ##### Intermediate Values in Fetch Stage ########################### 68 | 69 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 70 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 71 | wordsig f_icode 'if_id_next->icode' # (Possibly modified) instruction code 72 | wordsig f_ifun 'if_id_next->ifun' # Fetched instruction function 73 | wordsig f_valC 'if_id_next->valc' # Constant data of fetched instruction 74 | wordsig f_valP 'if_id_next->valp' # Address of following instruction 75 | boolsig imem_error 'imem_error' # Error signal from instruction memory 76 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 77 | 78 | ##### Pipeline Register D ########################################## 79 | wordsig D_icode 'if_id_curr->icode' # Instruction code 80 | wordsig D_rA 'if_id_curr->ra' # rA field from instruction 81 | wordsig D_rB 'if_id_curr->rb' # rB field from instruction 82 | wordsig D_valP 'if_id_curr->valp' # Incremented PC 83 | 84 | ##### Intermediate Values in Decode Stage ######################### 85 | 86 | wordsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction 87 | wordsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction 88 | wordsig d_rvalA 'd_regvala' # valA read from register file 89 | wordsig d_rvalB 'd_regvalb' # valB read from register file 90 | 91 | ##### Pipeline Register E ########################################## 92 | wordsig E_icode 'id_ex_curr->icode' # Instruction code 93 | wordsig E_ifun 'id_ex_curr->ifun' # Instruction function 94 | wordsig E_valC 'id_ex_curr->valc' # Constant data 95 | wordsig E_srcA 'id_ex_curr->srca' # Source A register ID 96 | wordsig E_valA 'id_ex_curr->vala' # Source A value 97 | wordsig E_srcB 'id_ex_curr->srcb' # Source B register ID 98 | wordsig E_valB 'id_ex_curr->valb' # Source B value 99 | wordsig E_dstE 'id_ex_curr->deste' # Destination E register ID 100 | wordsig E_dstM 'id_ex_curr->destm' # Destination M register ID 101 | 102 | ##### Intermediate Values in Execute Stage ######################### 103 | wordsig e_valE 'ex_mem_next->vale' # valE generated by ALU 104 | boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold? 105 | wordsig e_dstE 'ex_mem_next->deste' # dstE (possibly modified to be RNONE) 106 | 107 | ##### Pipeline Register M ######################### 108 | wordsig M_stat 'ex_mem_curr->status' # Instruction status 109 | wordsig M_icode 'ex_mem_curr->icode' # Instruction code 110 | wordsig M_ifun 'ex_mem_curr->ifun' # Instruction function 111 | wordsig M_valA 'ex_mem_curr->vala' # Source A value 112 | wordsig M_dstE 'ex_mem_curr->deste' # Destination E register ID 113 | wordsig M_valE 'ex_mem_curr->vale' # ALU E value 114 | wordsig M_dstM 'ex_mem_curr->destm' # Destination M register ID 115 | boolsig M_Cnd 'ex_mem_curr->takebranch' # Condition flag 116 | boolsig dmem_error 'dmem_error' # Error signal from instruction memory 117 | 118 | ##### Intermediate Values in Memory Stage ########################## 119 | wordsig m_valM 'mem_wb_next->valm' # valM generated by memory 120 | wordsig m_stat 'mem_wb_next->status' # stat (possibly modified to be SADR) 121 | 122 | ##### Pipeline Register W ########################################## 123 | wordsig W_stat 'mem_wb_curr->status' # Instruction status 124 | wordsig W_icode 'mem_wb_curr->icode' # Instruction code 125 | wordsig W_dstE 'mem_wb_curr->deste' # Destination E register ID 126 | wordsig W_valE 'mem_wb_curr->vale' # ALU E value 127 | wordsig W_dstM 'mem_wb_curr->destm' # Destination M register ID 128 | wordsig W_valM 'mem_wb_curr->valm' # Memory M value 129 | 130 | #################################################################### 131 | # Control Signal Definitions. # 132 | #################################################################### 133 | 134 | ################ Fetch Stage ################################### 135 | 136 | ## What address should instruction be fetched at 137 | word f_pc = [ 138 | # Mispredicted branch. Fetch at incremented PC 139 | M_icode == IJXX && !M_Cnd : M_valA; 140 | # Completion of RET instruction 141 | W_icode == IRET : W_valM; 142 | # Default: Use predicted value of PC 143 | 1 : F_predPC; 144 | ]; 145 | 146 | ## Determine icode of fetched instruction 147 | word f_icode = [ 148 | imem_error : INOP; 149 | 1: imem_icode; 150 | ]; 151 | 152 | # Determine ifun 153 | word f_ifun = [ 154 | imem_error : FNONE; 155 | 1: imem_ifun; 156 | ]; 157 | 158 | # Is instruction valid? 159 | bool instr_valid = f_icode in 160 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 161 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ, IIADDQ }; 162 | 163 | # Determine status code for fetched instruction 164 | word f_stat = [ 165 | imem_error: SADR; 166 | !instr_valid : SINS; 167 | f_icode == IHALT : SHLT; 168 | 1 : SAOK; 169 | ]; 170 | 171 | # Does fetched instruction require a regid byte? 172 | bool need_regids = 173 | f_icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 174 | IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ }; 175 | 176 | # Does fetched instruction require a constant word? 177 | bool need_valC = 178 | f_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL, IIADDQ }; 179 | 180 | # Predict next value of PC 181 | word f_predPC = [ 182 | f_icode in { IJXX, ICALL } : f_valC; 183 | 1 : f_valP; 184 | ]; 185 | 186 | ################ Decode Stage ###################################### 187 | 188 | 189 | ## What register should be used as the A source? 190 | word d_srcA = [ 191 | D_icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : D_rA; 192 | D_icode in { IPOPQ, IRET } : RRSP; 193 | 1 : RNONE; # Don't need register 194 | ]; 195 | 196 | ## What register should be used as the B source? 197 | word d_srcB = [ 198 | D_icode in { IOPQ, IRMMOVQ, IMRMOVQ, IIADDQ } : D_rB; 199 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 200 | 1 : RNONE; # Don't need register 201 | ]; 202 | 203 | ## What register should be used as the E destination? 204 | word d_dstE = [ 205 | D_icode in { IRRMOVQ, IIRMOVQ, IOPQ, IIADDQ } : D_rB; 206 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 207 | 1 : RNONE; # Don't write any register 208 | ]; 209 | 210 | ## What register should be used as the M destination? 211 | word d_dstM = [ 212 | D_icode in { IMRMOVQ, IPOPQ } : D_rA; 213 | 1 : RNONE; # Don't write any register 214 | ]; 215 | 216 | ## What should be the A value? 217 | ## Forward into decode stage for valA 218 | word d_valA = [ 219 | D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC 220 | d_srcA == e_dstE : e_valE; # Forward valE from execute 221 | d_srcA == M_dstM : m_valM; # Forward valM from memory 222 | d_srcA == M_dstE : M_valE; # Forward valE from memory 223 | d_srcA == W_dstM : W_valM; # Forward valM from write back 224 | d_srcA == W_dstE : W_valE; # Forward valE from write back 225 | 1 : d_rvalA; # Use value read from register file 226 | ]; 227 | 228 | word d_valB = [ 229 | d_srcB == e_dstE : e_valE; # Forward valE from execute 230 | d_srcB == M_dstM : m_valM; # Forward valM from memory 231 | d_srcB == M_dstE : M_valE; # Forward valE from memory 232 | d_srcB == W_dstM : W_valM; # Forward valM from write back 233 | d_srcB == W_dstE : W_valE; # Forward valE from write back 234 | 1 : d_rvalB; # Use value read from register file 235 | ]; 236 | 237 | ################ Execute Stage ##################################### 238 | 239 | ## Select input A to ALU 240 | word aluA = [ 241 | E_icode in { IRRMOVQ, IOPQ } : E_valA; 242 | E_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ } : E_valC; 243 | E_icode in { ICALL, IPUSHQ } : -8; 244 | E_icode in { IRET, IPOPQ } : 8; 245 | # Other instructions don't need ALU 246 | ]; 247 | 248 | ## Select input B to ALU 249 | word aluB = [ 250 | E_icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 251 | IPUSHQ, IRET, IPOPQ, IIADDQ } : E_valB; 252 | E_icode in { IRRMOVQ, IIRMOVQ } : 0; 253 | # Other instructions don't need ALU 254 | ]; 255 | 256 | ## Set the ALU function 257 | word alufun = [ 258 | E_icode == IOPQ : E_ifun; 259 | 1 : ALUADD; 260 | ]; 261 | 262 | ## Should the condition codes be updated? 263 | bool set_cc = E_icode in {IOPQ, IIADDQ }&& 264 | # State changes only during normal operation 265 | !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT }; 266 | 267 | ## Generate valA in execute stage 268 | word e_valA = E_valA; # Pass valA through stage 269 | 270 | ## Set dstE to RNONE in event of not-taken conditional move 271 | word e_dstE = [ 272 | E_icode == IRRMOVQ && !e_Cnd : RNONE; 273 | 1 : E_dstE; 274 | ]; 275 | 276 | ################ Memory Stage ###################################### 277 | 278 | ## Select memory address 279 | word mem_addr = [ 280 | M_icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : M_valE; 281 | M_icode in { IPOPQ, IRET } : M_valA; 282 | # Other instructions don't need address 283 | ]; 284 | 285 | ## Set read control signal 286 | bool mem_read = M_icode in { IMRMOVQ, IPOPQ, IRET }; 287 | 288 | ## Set write control signal 289 | bool mem_write = M_icode in { IRMMOVQ, IPUSHQ, ICALL }; 290 | 291 | #/* $begin pipe-m_stat-hcl */ 292 | ## Update the status 293 | word m_stat = [ 294 | dmem_error : SADR; 295 | 1 : M_stat; 296 | ]; 297 | #/* $end pipe-m_stat-hcl */ 298 | 299 | ## Set E port register ID 300 | word w_dstE = W_dstE; 301 | 302 | ## Set E port value 303 | word w_valE = W_valE; 304 | 305 | ## Set M port register ID 306 | word w_dstM = W_dstM; 307 | 308 | ## Set M port value 309 | word w_valM = W_valM; 310 | 311 | ## Update processor status 312 | word Stat = [ 313 | W_stat == SBUB : SAOK; 314 | 1 : W_stat; 315 | ]; 316 | 317 | ################ Pipeline Register Control ######################### 318 | 319 | # Should I stall or inject a bubble into Pipeline Register F? 320 | # At most one of these can be true. 321 | bool F_bubble = 0; 322 | bool F_stall = 323 | # Conditions for a load/use hazard 324 | E_icode in { IMRMOVQ, IPOPQ } && 325 | E_dstM in { d_srcA, d_srcB } || 326 | # Stalling at fetch while ret passes through pipeline 327 | IRET in { D_icode, E_icode, M_icode }; 328 | 329 | # Should I stall or inject a bubble into Pipeline Register D? 330 | # At most one of these can be true. 331 | bool D_stall = 332 | # Conditions for a load/use hazard 333 | E_icode in { IMRMOVQ, IPOPQ } && 334 | E_dstM in { d_srcA, d_srcB }; 335 | 336 | bool D_bubble = 337 | # Mispredicted branch 338 | (E_icode == IJXX && !e_Cnd) || 339 | # Stalling at fetch while ret passes through pipeline 340 | # but not condition for a load/use hazard 341 | !(E_icode in { IMRMOVQ, IPOPQ } && E_dstM in { d_srcA, d_srcB }) && 342 | IRET in { D_icode, E_icode, M_icode }; 343 | 344 | # Should I stall or inject a bubble into Pipeline Register E? 345 | # At most one of these can be true. 346 | bool E_stall = 0; 347 | bool E_bubble = 348 | # Mispredicted branch 349 | (E_icode == IJXX && !e_Cnd) || 350 | # Conditions for a load/use hazard 351 | E_icode in { IMRMOVQ, IPOPQ } && 352 | E_dstM in { d_srcA, d_srcB}; 353 | 354 | # Should I stall or inject a bubble into Pipeline Register M? 355 | # At most one of these can be true. 356 | bool M_stall = 0; 357 | # Start injecting bubbles as soon as exception passes through memory stage 358 | bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT }; 359 | 360 | # Should I stall or inject a bubble into Pipeline Register W? 361 | bool W_stall = W_stat in { SADR, SINS, SHLT }; 362 | bool W_bubble = 0; 363 | #/* $end pipe-all-hcl */ 364 | -------------------------------------------------------------------------------- /pipe/pipe-lf.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin pipe-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Pipelined Y86-64 Processor # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2014 # 5 | #################################################################### 6 | 7 | ## Your task is to implement load-forwarding, where a value 8 | ## read from memory can be stored to memory by the immediately 9 | ## following instruction without stalling 10 | ## This requires modifying the definition of e_valA 11 | ## and relaxing the stall conditions. Relevant sections to change 12 | ## are shown in comments containing the keyword "LB" 13 | 14 | #################################################################### 15 | # C Include's. Don't alter these # 16 | #################################################################### 17 | 18 | quote '#include ' 19 | quote '#include "isa.h"' 20 | quote '#include "pipeline.h"' 21 | quote '#include "stages.h"' 22 | quote '#include "sim.h"' 23 | quote 'int sim_main(int argc, char *argv[]);' 24 | quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' 25 | 26 | #################################################################### 27 | # Declarations. Do not change/remove/delete any of these # 28 | #################################################################### 29 | 30 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 31 | wordsig INOP 'I_NOP' 32 | wordsig IHALT 'I_HALT' 33 | wordsig IRRMOVQ 'I_RRMOVQ' 34 | wordsig IIRMOVQ 'I_IRMOVQ' 35 | wordsig IRMMOVQ 'I_RMMOVQ' 36 | wordsig IMRMOVQ 'I_MRMOVQ' 37 | wordsig IOPQ 'I_ALU' 38 | wordsig IJXX 'I_JMP' 39 | wordsig ICALL 'I_CALL' 40 | wordsig IRET 'I_RET' 41 | wordsig IPUSHQ 'I_PUSHQ' 42 | wordsig IPOPQ 'I_POPQ' 43 | 44 | ##### Symbolic represenations of Y86-64 function codes ##### 45 | wordsig FNONE 'F_NONE' # Default function code 46 | 47 | ##### Symbolic representation of Y86-64 Registers referenced ##### 48 | wordsig RRSP 'REG_RSP' # Stack Pointer 49 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 50 | 51 | ##### ALU Functions referenced explicitly ########################## 52 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 53 | 54 | ##### Possible instruction status values ##### 55 | wordsig SBUB 'STAT_BUB' # Bubble in stage 56 | wordsig SAOK 'STAT_AOK' # Normal execution 57 | wordsig SADR 'STAT_ADR' # Invalid memory address 58 | wordsig SINS 'STAT_INS' # Invalid instruction 59 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 60 | 61 | ##### Signals that can be referenced by control logic ############## 62 | 63 | ##### Pipeline Register F ########################################## 64 | 65 | wordsig F_predPC 'pc_curr->pc' # Predicted value of PC 66 | 67 | ##### Intermediate Values in Fetch Stage ########################### 68 | 69 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 70 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 71 | wordsig f_icode 'if_id_next->icode' # (Possibly modified) instruction code 72 | wordsig f_ifun 'if_id_next->ifun' # Fetched instruction function 73 | wordsig f_valC 'if_id_next->valc' # Constant data of fetched instruction 74 | wordsig f_valP 'if_id_next->valp' # Address of following instruction 75 | boolsig imem_error 'imem_error' # Error signal from instruction memory 76 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 77 | 78 | ##### Pipeline Register D ########################################## 79 | wordsig D_icode 'if_id_curr->icode' # Instruction code 80 | wordsig D_rA 'if_id_curr->ra' # rA field from instruction 81 | wordsig D_rB 'if_id_curr->rb' # rB field from instruction 82 | wordsig D_valP 'if_id_curr->valp' # Incremented PC 83 | 84 | ##### Intermediate Values in Decode Stage ######################### 85 | 86 | wordsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction 87 | wordsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction 88 | wordsig d_rvalA 'd_regvala' # valA read from register file 89 | wordsig d_rvalB 'd_regvalb' # valB read from register file 90 | 91 | ##### Pipeline Register E ########################################## 92 | wordsig E_icode 'id_ex_curr->icode' # Instruction code 93 | wordsig E_ifun 'id_ex_curr->ifun' # Instruction function 94 | wordsig E_valC 'id_ex_curr->valc' # Constant data 95 | wordsig E_srcA 'id_ex_curr->srca' # Source A register ID 96 | wordsig E_valA 'id_ex_curr->vala' # Source A value 97 | wordsig E_srcB 'id_ex_curr->srcb' # Source B register ID 98 | wordsig E_valB 'id_ex_curr->valb' # Source B value 99 | wordsig E_dstE 'id_ex_curr->deste' # Destination E register ID 100 | wordsig E_dstM 'id_ex_curr->destm' # Destination M register ID 101 | 102 | ##### Intermediate Values in Execute Stage ######################### 103 | wordsig e_valE 'ex_mem_next->vale' # valE generated by ALU 104 | boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold? 105 | wordsig e_dstE 'ex_mem_next->deste' # dstE (possibly modified to be RNONE) 106 | 107 | ##### Pipeline Register M ######################### 108 | wordsig M_stat 'ex_mem_curr->status' # Instruction status 109 | wordsig M_icode 'ex_mem_curr->icode' # Instruction code 110 | wordsig M_ifun 'ex_mem_curr->ifun' # Instruction function 111 | wordsig M_valA 'ex_mem_curr->vala' # Source A value 112 | wordsig M_dstE 'ex_mem_curr->deste' # Destination E register ID 113 | wordsig M_valE 'ex_mem_curr->vale' # ALU E value 114 | wordsig M_dstM 'ex_mem_curr->destm' # Destination M register ID 115 | boolsig M_Cnd 'ex_mem_curr->takebranch' # Condition flag 116 | boolsig dmem_error 'dmem_error' # Error signal from instruction memory 117 | ## LF: Carry srcA up to pipeline register M 118 | wordsig M_srcA 'ex_mem_curr->srca' # Source A register ID 119 | 120 | ##### Intermediate Values in Memory Stage ########################## 121 | wordsig m_valM 'mem_wb_next->valm' # valM generated by memory 122 | wordsig m_stat 'mem_wb_next->status' # stat (possibly modified to be SADR) 123 | 124 | ##### Pipeline Register W ########################################## 125 | wordsig W_stat 'mem_wb_curr->status' # Instruction status 126 | wordsig W_icode 'mem_wb_curr->icode' # Instruction code 127 | wordsig W_dstE 'mem_wb_curr->deste' # Destination E register ID 128 | wordsig W_valE 'mem_wb_curr->vale' # ALU E value 129 | wordsig W_dstM 'mem_wb_curr->destm' # Destination M register ID 130 | wordsig W_valM 'mem_wb_curr->valm' # Memory M value 131 | 132 | #################################################################### 133 | # Control Signal Definitions. # 134 | #################################################################### 135 | 136 | ################ Fetch Stage ################################### 137 | 138 | ## What address should instruction be fetched at 139 | word f_pc = [ 140 | # Mispredicted branch. Fetch at incremented PC 141 | M_icode == IJXX && !M_Cnd : M_valA; 142 | # Completion of RET instruction 143 | W_icode == IRET : W_valM; 144 | # Default: Use predicted value of PC 145 | 1 : F_predPC; 146 | ]; 147 | 148 | ## Determine icode of fetched instruction 149 | word f_icode = [ 150 | imem_error : INOP; 151 | 1: imem_icode; 152 | ]; 153 | 154 | # Determine ifun 155 | word f_ifun = [ 156 | imem_error : FNONE; 157 | 1: imem_ifun; 158 | ]; 159 | 160 | # Is instruction valid? 161 | bool instr_valid = f_icode in 162 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 163 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 164 | 165 | # Determine status code for fetched instruction 166 | word f_stat = [ 167 | imem_error: SADR; 168 | !instr_valid : SINS; 169 | f_icode == IHALT : SHLT; 170 | 1 : SAOK; 171 | ]; 172 | 173 | # Does fetched instruction require a regid byte? 174 | bool need_regids = 175 | f_icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 176 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 177 | 178 | # Does fetched instruction require a constant word? 179 | bool need_valC = 180 | f_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 181 | 182 | # Predict next value of PC 183 | word f_predPC = [ 184 | f_icode in { IJXX, ICALL } : f_valC; 185 | 1 : f_valP; 186 | ]; 187 | 188 | ################ Decode Stage ###################################### 189 | 190 | 191 | ## What register should be used as the A source? 192 | word d_srcA = [ 193 | D_icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : D_rA; 194 | D_icode in { IPOPQ, IRET } : RRSP; 195 | 1 : RNONE; # Don't need register 196 | ]; 197 | 198 | ## What register should be used as the B source? 199 | word d_srcB = [ 200 | D_icode in { IOPQ, IRMMOVQ, IMRMOVQ } : D_rB; 201 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 202 | 1 : RNONE; # Don't need register 203 | ]; 204 | 205 | ## What register should be used as the E destination? 206 | word d_dstE = [ 207 | D_icode in { IRRMOVQ, IIRMOVQ, IOPQ} : D_rB; 208 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 209 | 1 : RNONE; # Don't write any register 210 | ]; 211 | 212 | ## What register should be used as the M destination? 213 | word d_dstM = [ 214 | D_icode in { IMRMOVQ, IPOPQ } : D_rA; 215 | 1 : RNONE; # Don't write any register 216 | ]; 217 | 218 | ## What should be the A value? 219 | ## Forward into decode stage for valA 220 | word d_valA = [ 221 | D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC 222 | d_srcA == e_dstE : e_valE; # Forward valE from execute 223 | d_srcA == M_dstM : m_valM; # Forward valM from memory 224 | d_srcA == M_dstE : M_valE; # Forward valE from memory 225 | d_srcA == W_dstM : W_valM; # Forward valM from write back 226 | d_srcA == W_dstE : W_valE; # Forward valE from write back 227 | 1 : d_rvalA; # Use value read from register file 228 | ]; 229 | 230 | word d_valB = [ 231 | d_srcB == e_dstE : e_valE; # Forward valE from execute 232 | d_srcB == M_dstM : m_valM; # Forward valM from memory 233 | d_srcB == M_dstE : M_valE; # Forward valE from memory 234 | d_srcB == W_dstM : W_valM; # Forward valM from write back 235 | d_srcB == W_dstE : W_valE; # Forward valE from write back 236 | 1 : d_rvalB; # Use value read from register file 237 | ]; 238 | 239 | ################ Execute Stage ##################################### 240 | 241 | ## Select input A to ALU 242 | word aluA = [ 243 | E_icode in { IRRMOVQ, IOPQ } : E_valA; 244 | E_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : E_valC; 245 | E_icode in { ICALL, IPUSHQ } : -8; 246 | E_icode in { IRET, IPOPQ } : 8; 247 | # Other instructions don't need ALU 248 | ]; 249 | 250 | ## Select input B to ALU 251 | word aluB = [ 252 | E_icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 253 | IPUSHQ, IRET, IPOPQ } : E_valB; 254 | E_icode in { IRRMOVQ, IIRMOVQ } : 0; 255 | # Other instructions don't need ALU 256 | ]; 257 | 258 | ## Set the ALU function 259 | word alufun = [ 260 | E_icode == IOPQ : E_ifun; 261 | 1 : ALUADD; 262 | ]; 263 | 264 | ## Should the condition codes be updated? 265 | bool set_cc = E_icode == IOPQ && 266 | # State changes only during normal operation 267 | !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT }; 268 | 269 | ## Generate valA in execute stage 270 | ## LB: With load forwarding, want to insert valM 271 | ## from memory stage when appropriate 272 | ## Here it is set to the default used in the normal pipeline 273 | word e_valA = [ 274 | 1 : E_valA; # Use valA from stage pipe register 275 | ]; 276 | 277 | ## Set dstE to RNONE in event of not-taken conditional move 278 | word e_dstE = [ 279 | E_icode == IRRMOVQ && !e_Cnd : RNONE; 280 | 1 : E_dstE; 281 | ]; 282 | 283 | ################ Memory Stage ###################################### 284 | 285 | ## Select memory address 286 | word mem_addr = [ 287 | M_icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : M_valE; 288 | M_icode in { IPOPQ, IRET } : M_valA; 289 | # Other instructions don't need address 290 | ]; 291 | 292 | ## Set read control signal 293 | bool mem_read = M_icode in { IMRMOVQ, IPOPQ, IRET }; 294 | 295 | ## Set write control signal 296 | bool mem_write = M_icode in { IRMMOVQ, IPUSHQ, ICALL }; 297 | 298 | #/* $begin pipe-m_stat-hcl */ 299 | ## Update the status 300 | word m_stat = [ 301 | dmem_error : SADR; 302 | 1 : M_stat; 303 | ]; 304 | #/* $end pipe-m_stat-hcl */ 305 | 306 | ## Set E port register ID 307 | word w_dstE = W_dstE; 308 | 309 | ## Set E port value 310 | word w_valE = W_valE; 311 | 312 | ## Set M port register ID 313 | word w_dstM = W_dstM; 314 | 315 | ## Set M port value 316 | word w_valM = W_valM; 317 | 318 | ## Update processor status 319 | word Stat = [ 320 | W_stat == SBUB : SAOK; 321 | 1 : W_stat; 322 | ]; 323 | 324 | ################ Pipeline Register Control ######################### 325 | 326 | # Should I stall or inject a bubble into Pipeline Register F? 327 | # At most one of these can be true. 328 | bool F_bubble = 0; 329 | bool F_stall = 330 | # Conditions for a load/use hazard 331 | ## Set this to the new load/use condition 332 | 0 || 333 | # Stalling at fetch while ret passes through pipeline 334 | IRET in { D_icode, E_icode, M_icode }; 335 | 336 | # Should I stall or inject a bubble into Pipeline Register D? 337 | # At most one of these can be true. 338 | bool D_stall = 339 | # Conditions for a load/use hazard 340 | ## Set this to the new load/use condition 341 | 0; 342 | 343 | bool D_bubble = 344 | # Mispredicted branch 345 | (E_icode == IJXX && !e_Cnd) || 346 | # Stalling at fetch while ret passes through pipeline 347 | # but not condition for a load/use hazard 348 | !(E_icode in { IMRMOVQ, IPOPQ } && E_dstM in { d_srcA, d_srcB }) && 349 | IRET in { D_icode, E_icode, M_icode }; 350 | 351 | # Should I stall or inject a bubble into Pipeline Register E? 352 | # At most one of these can be true. 353 | bool E_stall = 0; 354 | bool E_bubble = 355 | # Mispredicted branch 356 | (E_icode == IJXX && !e_Cnd) || 357 | # Conditions for a load/use hazard 358 | ## Set this to the new load/use condition 359 | 0; 360 | 361 | # Should I stall or inject a bubble into Pipeline Register M? 362 | # At most one of these can be true. 363 | bool M_stall = 0; 364 | # Start injecting bubbles as soon as exception passes through memory stage 365 | bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT }; 366 | 367 | # Should I stall or inject a bubble into Pipeline Register W? 368 | bool W_stall = W_stat in { SADR, SINS, SHLT }; 369 | bool W_bubble = 0; 370 | #/* $end pipe-all-hcl */ 371 | -------------------------------------------------------------------------------- /pipe/pipe-nobypass.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin pipe-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Pipelined Y86-64 Processor # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2014 # 5 | #################################################################### 6 | 7 | ## Your task is to make the pipeline work without using any forwarding 8 | ## The normal bypassing logic in the file is disabled. 9 | ## You can only change the pipeline control logic at the end of this file. 10 | ## The trick is to make the pipeline stall whenever there is a data hazard. 11 | 12 | #################################################################### 13 | # C Include's. Don't alter these # 14 | #################################################################### 15 | 16 | quote '#include ' 17 | quote '#include "isa.h"' 18 | quote '#include "pipeline.h"' 19 | quote '#include "stages.h"' 20 | quote '#include "sim.h"' 21 | quote 'int sim_main(int argc, char *argv[]);' 22 | quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' 23 | 24 | #################################################################### 25 | # Declarations. Do not change/remove/delete any of these # 26 | #################################################################### 27 | 28 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 29 | wordsig INOP 'I_NOP' 30 | wordsig IHALT 'I_HALT' 31 | wordsig IRRMOVQ 'I_RRMOVQ' 32 | wordsig IIRMOVQ 'I_IRMOVQ' 33 | wordsig IRMMOVQ 'I_RMMOVQ' 34 | wordsig IMRMOVQ 'I_MRMOVQ' 35 | wordsig IOPQ 'I_ALU' 36 | wordsig IJXX 'I_JMP' 37 | wordsig ICALL 'I_CALL' 38 | wordsig IRET 'I_RET' 39 | wordsig IPUSHQ 'I_PUSHQ' 40 | wordsig IPOPQ 'I_POPQ' 41 | 42 | ##### Symbolic represenations of Y86-64 function codes ##### 43 | wordsig FNONE 'F_NONE' # Default function code 44 | 45 | ##### Symbolic representation of Y86-64 Registers referenced ##### 46 | wordsig RRSP 'REG_RSP' # Stack Pointer 47 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 48 | 49 | ##### ALU Functions referenced explicitly ########################## 50 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 51 | 52 | ##### Possible instruction status values ##### 53 | wordsig SBUB 'STAT_BUB' # Bubble in stage 54 | wordsig SAOK 'STAT_AOK' # Normal execution 55 | wordsig SADR 'STAT_ADR' # Invalid memory address 56 | wordsig SINS 'STAT_INS' # Invalid instruction 57 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 58 | 59 | ##### Signals that can be referenced by control logic ############## 60 | 61 | ##### Pipeline Register F ########################################## 62 | 63 | wordsig F_predPC 'pc_curr->pc' # Predicted value of PC 64 | 65 | ##### Intermediate Values in Fetch Stage ########################### 66 | 67 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 68 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 69 | wordsig f_icode 'if_id_next->icode' # (Possibly modified) instruction code 70 | wordsig f_ifun 'if_id_next->ifun' # Fetched instruction function 71 | wordsig f_valC 'if_id_next->valc' # Constant data of fetched instruction 72 | wordsig f_valP 'if_id_next->valp' # Address of following instruction 73 | boolsig imem_error 'imem_error' # Error signal from instruction memory 74 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 75 | 76 | ##### Pipeline Register D ########################################## 77 | wordsig D_icode 'if_id_curr->icode' # Instruction code 78 | wordsig D_rA 'if_id_curr->ra' # rA field from instruction 79 | wordsig D_rB 'if_id_curr->rb' # rB field from instruction 80 | wordsig D_valP 'if_id_curr->valp' # Incremented PC 81 | 82 | ##### Intermediate Values in Decode Stage ######################### 83 | 84 | wordsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction 85 | wordsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction 86 | wordsig d_rvalA 'd_regvala' # valA read from register file 87 | wordsig d_rvalB 'd_regvalb' # valB read from register file 88 | 89 | ##### Pipeline Register E ########################################## 90 | wordsig E_icode 'id_ex_curr->icode' # Instruction code 91 | wordsig E_ifun 'id_ex_curr->ifun' # Instruction function 92 | wordsig E_valC 'id_ex_curr->valc' # Constant data 93 | wordsig E_srcA 'id_ex_curr->srca' # Source A register ID 94 | wordsig E_valA 'id_ex_curr->vala' # Source A value 95 | wordsig E_srcB 'id_ex_curr->srcb' # Source B register ID 96 | wordsig E_valB 'id_ex_curr->valb' # Source B value 97 | wordsig E_dstE 'id_ex_curr->deste' # Destination E register ID 98 | wordsig E_dstM 'id_ex_curr->destm' # Destination M register ID 99 | 100 | ##### Intermediate Values in Execute Stage ######################### 101 | wordsig e_valE 'ex_mem_next->vale' # valE generated by ALU 102 | boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold? 103 | wordsig e_dstE 'ex_mem_next->deste' # dstE (possibly modified to be RNONE) 104 | 105 | ##### Pipeline Register M ######################### 106 | wordsig M_stat 'ex_mem_curr->status' # Instruction status 107 | wordsig M_icode 'ex_mem_curr->icode' # Instruction code 108 | wordsig M_ifun 'ex_mem_curr->ifun' # Instruction function 109 | wordsig M_valA 'ex_mem_curr->vala' # Source A value 110 | wordsig M_dstE 'ex_mem_curr->deste' # Destination E register ID 111 | wordsig M_valE 'ex_mem_curr->vale' # ALU E value 112 | wordsig M_dstM 'ex_mem_curr->destm' # Destination M register ID 113 | boolsig M_Cnd 'ex_mem_curr->takebranch' # Condition flag 114 | boolsig dmem_error 'dmem_error' # Error signal from instruction memory 115 | 116 | ##### Intermediate Values in Memory Stage ########################## 117 | wordsig m_valM 'mem_wb_next->valm' # valM generated by memory 118 | wordsig m_stat 'mem_wb_next->status' # stat (possibly modified to be SADR) 119 | 120 | ##### Pipeline Register W ########################################## 121 | wordsig W_stat 'mem_wb_curr->status' # Instruction status 122 | wordsig W_icode 'mem_wb_curr->icode' # Instruction code 123 | wordsig W_dstE 'mem_wb_curr->deste' # Destination E register ID 124 | wordsig W_valE 'mem_wb_curr->vale' # ALU E value 125 | wordsig W_dstM 'mem_wb_curr->destm' # Destination M register ID 126 | wordsig W_valM 'mem_wb_curr->valm' # Memory M value 127 | 128 | #################################################################### 129 | # Control Signal Definitions. # 130 | #################################################################### 131 | 132 | ################ Fetch Stage ################################### 133 | 134 | ## What address should instruction be fetched at 135 | word f_pc = [ 136 | # Mispredicted branch. Fetch at incremented PC 137 | M_icode == IJXX && !M_Cnd : M_valA; 138 | # Completion of RET instruction 139 | W_icode == IRET : W_valM; 140 | # Default: Use predicted value of PC 141 | 1 : F_predPC; 142 | ]; 143 | 144 | ## Determine icode of fetched instruction 145 | word f_icode = [ 146 | imem_error : INOP; 147 | 1: imem_icode; 148 | ]; 149 | 150 | # Determine ifun 151 | word f_ifun = [ 152 | imem_error : FNONE; 153 | 1: imem_ifun; 154 | ]; 155 | 156 | # Is instruction valid? 157 | bool instr_valid = f_icode in 158 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 159 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 160 | 161 | # Determine status code for fetched instruction 162 | word f_stat = [ 163 | imem_error: SADR; 164 | !instr_valid : SINS; 165 | f_icode == IHALT : SHLT; 166 | 1 : SAOK; 167 | ]; 168 | 169 | # Does fetched instruction require a regid byte? 170 | bool need_regids = 171 | f_icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 172 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 173 | 174 | # Does fetched instruction require a constant word? 175 | bool need_valC = 176 | f_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 177 | 178 | # Predict next value of PC 179 | word f_predPC = [ 180 | f_icode in { IJXX, ICALL } : f_valC; 181 | 1 : f_valP; 182 | ]; 183 | 184 | ################ Decode Stage ###################################### 185 | 186 | 187 | ## What register should be used as the A source? 188 | word d_srcA = [ 189 | D_icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : D_rA; 190 | D_icode in { IPOPQ, IRET } : RRSP; 191 | 1 : RNONE; # Don't need register 192 | ]; 193 | 194 | ## What register should be used as the B source? 195 | word d_srcB = [ 196 | D_icode in { IOPQ, IRMMOVQ, IMRMOVQ } : D_rB; 197 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 198 | 1 : RNONE; # Don't need register 199 | ]; 200 | 201 | ## What register should be used as the E destination? 202 | word d_dstE = [ 203 | D_icode in { IRRMOVQ, IIRMOVQ, IOPQ} : D_rB; 204 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 205 | 1 : RNONE; # Don't write any register 206 | ]; 207 | 208 | ## What register should be used as the M destination? 209 | word d_dstM = [ 210 | D_icode in { IMRMOVQ, IPOPQ } : D_rA; 211 | 1 : RNONE; # Don't write any register 212 | ]; 213 | 214 | ## What should be the A value? 215 | ## DO NOT MODIFY THE FOLLOWING CODE. 216 | ## No forwarding. valA is either valP or value from register file 217 | word d_valA = [ 218 | D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC 219 | 1 : d_rvalA; # Use value read from register file 220 | ]; 221 | 222 | ## No forwarding. valB is value from register file 223 | word d_valB = d_rvalB; 224 | 225 | ################ Execute Stage ##################################### 226 | 227 | ## Select input A to ALU 228 | word aluA = [ 229 | E_icode in { IRRMOVQ, IOPQ } : E_valA; 230 | E_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : E_valC; 231 | E_icode in { ICALL, IPUSHQ } : -8; 232 | E_icode in { IRET, IPOPQ } : 8; 233 | # Other instructions don't need ALU 234 | ]; 235 | 236 | ## Select input B to ALU 237 | word aluB = [ 238 | E_icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 239 | IPUSHQ, IRET, IPOPQ } : E_valB; 240 | E_icode in { IRRMOVQ, IIRMOVQ } : 0; 241 | # Other instructions don't need ALU 242 | ]; 243 | 244 | ## Set the ALU function 245 | word alufun = [ 246 | E_icode == IOPQ : E_ifun; 247 | 1 : ALUADD; 248 | ]; 249 | 250 | ## Should the condition codes be updated? 251 | bool set_cc = E_icode == IOPQ && 252 | # State changes only during normal operation 253 | !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT }; 254 | 255 | ## Generate valA in execute stage 256 | word e_valA = E_valA; # Pass valA through stage 257 | 258 | ## Set dstE to RNONE in event of not-taken conditional move 259 | word e_dstE = [ 260 | E_icode == IRRMOVQ && !e_Cnd : RNONE; 261 | 1 : E_dstE; 262 | ]; 263 | 264 | ################ Memory Stage ###################################### 265 | 266 | ## Select memory address 267 | word mem_addr = [ 268 | M_icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : M_valE; 269 | M_icode in { IPOPQ, IRET } : M_valA; 270 | # Other instructions don't need address 271 | ]; 272 | 273 | ## Set read control signal 274 | bool mem_read = M_icode in { IMRMOVQ, IPOPQ, IRET }; 275 | 276 | ## Set write control signal 277 | bool mem_write = M_icode in { IRMMOVQ, IPUSHQ, ICALL }; 278 | 279 | #/* $begin pipe-m_stat-hcl */ 280 | ## Update the status 281 | word m_stat = [ 282 | dmem_error : SADR; 283 | 1 : M_stat; 284 | ]; 285 | #/* $end pipe-m_stat-hcl */ 286 | 287 | ## Set E port register ID 288 | word w_dstE = W_dstE; 289 | 290 | ## Set E port value 291 | word w_valE = W_valE; 292 | 293 | ## Set M port register ID 294 | word w_dstM = W_dstM; 295 | 296 | ## Set M port value 297 | word w_valM = W_valM; 298 | 299 | ## Update processor status 300 | word Stat = [ 301 | W_stat == SBUB : SAOK; 302 | 1 : W_stat; 303 | ]; 304 | 305 | ################ Pipeline Register Control ######################### 306 | 307 | # Should I stall or inject a bubble into Pipeline Register F? 308 | # At most one of these can be true. 309 | bool F_bubble = 0; 310 | bool F_stall = 311 | # Modify the following to stall the update of pipeline register F 312 | 0 || 313 | # Stalling at fetch while ret passes through pipeline 314 | IRET in { D_icode, E_icode, M_icode }; 315 | 316 | # Should I stall or inject a bubble into Pipeline Register D? 317 | # At most one of these can be true. 318 | bool D_stall = 319 | # Modify the following to stall the instruction in decode 320 | 0; 321 | 322 | bool D_bubble = 323 | # Mispredicted branch 324 | (E_icode == IJXX && !e_Cnd) || 325 | # Stalling at fetch while ret passes through pipeline 326 | !(E_icode in { IMRMOVQ, IPOPQ } && E_dstM in { d_srcA, d_srcB }) && 327 | # but not condition for a generate/use hazard 328 | !0 && 329 | IRET in { D_icode, E_icode, M_icode }; 330 | 331 | # Should I stall or inject a bubble into Pipeline Register E? 332 | # At most one of these can be true. 333 | bool E_stall = 0; 334 | bool E_bubble = 335 | # Mispredicted branch 336 | (E_icode == IJXX && !e_Cnd) || 337 | # Modify the following to inject bubble into the execute stage 338 | 0; 339 | 340 | # Should I stall or inject a bubble into Pipeline Register M? 341 | # At most one of these can be true. 342 | bool M_stall = 0; 343 | # Start injecting bubbles as soon as exception passes through memory stage 344 | bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT }; 345 | 346 | # Should I stall or inject a bubble into Pipeline Register W? 347 | bool W_stall = W_stat in { SADR, SINS, SHLT }; 348 | bool W_bubble = 0; 349 | #/* $end pipe-all-hcl */ 350 | -------------------------------------------------------------------------------- /pipe/pipe-std.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin pipe-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Pipelined Y86-64 Processor # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2014 # 5 | #################################################################### 6 | 7 | #################################################################### 8 | # C Include's. Don't alter these # 9 | #################################################################### 10 | 11 | quote '#include ' 12 | quote '#include "isa.h"' 13 | quote '#include "pipeline.h"' 14 | quote '#include "stages.h"' 15 | quote '#include "sim.h"' 16 | quote 'int sim_main(int argc, char *argv[]);' 17 | quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' 18 | 19 | #################################################################### 20 | # Declarations. Do not change/remove/delete any of these # 21 | #################################################################### 22 | 23 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 24 | wordsig INOP 'I_NOP' 25 | wordsig IHALT 'I_HALT' 26 | wordsig IRRMOVQ 'I_RRMOVQ' 27 | wordsig IIRMOVQ 'I_IRMOVQ' 28 | wordsig IRMMOVQ 'I_RMMOVQ' 29 | wordsig IMRMOVQ 'I_MRMOVQ' 30 | wordsig IOPQ 'I_ALU' 31 | wordsig IJXX 'I_JMP' 32 | wordsig ICALL 'I_CALL' 33 | wordsig IRET 'I_RET' 34 | wordsig IPUSHQ 'I_PUSHQ' 35 | wordsig IPOPQ 'I_POPQ' 36 | 37 | ##### Symbolic represenations of Y86-64 function codes ##### 38 | wordsig FNONE 'F_NONE' # Default function code 39 | 40 | ##### Symbolic representation of Y86-64 Registers referenced ##### 41 | wordsig RRSP 'REG_RSP' # Stack Pointer 42 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 43 | 44 | ##### ALU Functions referenced explicitly ########################## 45 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 46 | 47 | ##### Possible instruction status values ##### 48 | wordsig SBUB 'STAT_BUB' # Bubble in stage 49 | wordsig SAOK 'STAT_AOK' # Normal execution 50 | wordsig SADR 'STAT_ADR' # Invalid memory address 51 | wordsig SINS 'STAT_INS' # Invalid instruction 52 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 53 | 54 | ##### Signals that can be referenced by control logic ############## 55 | 56 | ##### Pipeline Register F ########################################## 57 | 58 | wordsig F_predPC 'pc_curr->pc' # Predicted value of PC 59 | 60 | ##### Intermediate Values in Fetch Stage ########################### 61 | 62 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 63 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 64 | wordsig f_icode 'if_id_next->icode' # (Possibly modified) instruction code 65 | wordsig f_ifun 'if_id_next->ifun' # Fetched instruction function 66 | wordsig f_valC 'if_id_next->valc' # Constant data of fetched instruction 67 | wordsig f_valP 'if_id_next->valp' # Address of following instruction 68 | boolsig imem_error 'imem_error' # Error signal from instruction memory 69 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 70 | 71 | ##### Pipeline Register D ########################################## 72 | wordsig D_icode 'if_id_curr->icode' # Instruction code 73 | wordsig D_rA 'if_id_curr->ra' # rA field from instruction 74 | wordsig D_rB 'if_id_curr->rb' # rB field from instruction 75 | wordsig D_valP 'if_id_curr->valp' # Incremented PC 76 | 77 | ##### Intermediate Values in Decode Stage ######################### 78 | 79 | wordsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction 80 | wordsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction 81 | wordsig d_rvalA 'd_regvala' # valA read from register file 82 | wordsig d_rvalB 'd_regvalb' # valB read from register file 83 | 84 | ##### Pipeline Register E ########################################## 85 | wordsig E_icode 'id_ex_curr->icode' # Instruction code 86 | wordsig E_ifun 'id_ex_curr->ifun' # Instruction function 87 | wordsig E_valC 'id_ex_curr->valc' # Constant data 88 | wordsig E_srcA 'id_ex_curr->srca' # Source A register ID 89 | wordsig E_valA 'id_ex_curr->vala' # Source A value 90 | wordsig E_srcB 'id_ex_curr->srcb' # Source B register ID 91 | wordsig E_valB 'id_ex_curr->valb' # Source B value 92 | wordsig E_dstE 'id_ex_curr->deste' # Destination E register ID 93 | wordsig E_dstM 'id_ex_curr->destm' # Destination M register ID 94 | 95 | ##### Intermediate Values in Execute Stage ######################### 96 | wordsig e_valE 'ex_mem_next->vale' # valE generated by ALU 97 | boolsig e_Cnd 'ex_mem_next->takebranch' # Does condition hold? 98 | wordsig e_dstE 'ex_mem_next->deste' # dstE (possibly modified to be RNONE) 99 | 100 | ##### Pipeline Register M ######################### 101 | wordsig M_stat 'ex_mem_curr->status' # Instruction status 102 | wordsig M_icode 'ex_mem_curr->icode' # Instruction code 103 | wordsig M_ifun 'ex_mem_curr->ifun' # Instruction function 104 | wordsig M_valA 'ex_mem_curr->vala' # Source A value 105 | wordsig M_dstE 'ex_mem_curr->deste' # Destination E register ID 106 | wordsig M_valE 'ex_mem_curr->vale' # ALU E value 107 | wordsig M_dstM 'ex_mem_curr->destm' # Destination M register ID 108 | boolsig M_Cnd 'ex_mem_curr->takebranch' # Condition flag 109 | boolsig dmem_error 'dmem_error' # Error signal from instruction memory 110 | 111 | ##### Intermediate Values in Memory Stage ########################## 112 | wordsig m_valM 'mem_wb_next->valm' # valM generated by memory 113 | wordsig m_stat 'mem_wb_next->status' # stat (possibly modified to be SADR) 114 | 115 | ##### Pipeline Register W ########################################## 116 | wordsig W_stat 'mem_wb_curr->status' # Instruction status 117 | wordsig W_icode 'mem_wb_curr->icode' # Instruction code 118 | wordsig W_dstE 'mem_wb_curr->deste' # Destination E register ID 119 | wordsig W_valE 'mem_wb_curr->vale' # ALU E value 120 | wordsig W_dstM 'mem_wb_curr->destm' # Destination M register ID 121 | wordsig W_valM 'mem_wb_curr->valm' # Memory M value 122 | 123 | #################################################################### 124 | # Control Signal Definitions. # 125 | #################################################################### 126 | 127 | ################ Fetch Stage ################################### 128 | 129 | ## What address should instruction be fetched at 130 | word f_pc = [ 131 | # Mispredicted branch. Fetch at incremented PC 132 | M_icode == IJXX && !M_Cnd : M_valA; 133 | # Completion of RET instruction 134 | W_icode == IRET : W_valM; 135 | # Default: Use predicted value of PC 136 | 1 : F_predPC; 137 | ]; 138 | 139 | ## Determine icode of fetched instruction 140 | word f_icode = [ 141 | imem_error : INOP; 142 | 1: imem_icode; 143 | ]; 144 | 145 | # Determine ifun 146 | word f_ifun = [ 147 | imem_error : FNONE; 148 | 1: imem_ifun; 149 | ]; 150 | 151 | # Is instruction valid? 152 | bool instr_valid = f_icode in 153 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 154 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 155 | 156 | # Determine status code for fetched instruction 157 | word f_stat = [ 158 | imem_error: SADR; 159 | !instr_valid : SINS; 160 | f_icode == IHALT : SHLT; 161 | 1 : SAOK; 162 | ]; 163 | 164 | # Does fetched instruction require a regid byte? 165 | bool need_regids = 166 | f_icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 167 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 168 | 169 | # Does fetched instruction require a constant word? 170 | bool need_valC = 171 | f_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 172 | 173 | # Predict next value of PC 174 | word f_predPC = [ 175 | f_icode in { IJXX, ICALL } : f_valC; 176 | 1 : f_valP; 177 | ]; 178 | 179 | ################ Decode Stage ###################################### 180 | 181 | 182 | ## What register should be used as the A source? 183 | word d_srcA = [ 184 | D_icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : D_rA; 185 | D_icode in { IPOPQ, IRET } : RRSP; 186 | 1 : RNONE; # Don't need register 187 | ]; 188 | 189 | ## What register should be used as the B source? 190 | word d_srcB = [ 191 | D_icode in { IOPQ, IRMMOVQ, IMRMOVQ } : D_rB; 192 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 193 | 1 : RNONE; # Don't need register 194 | ]; 195 | 196 | ## What register should be used as the E destination? 197 | word d_dstE = [ 198 | D_icode in { IRRMOVQ, IIRMOVQ, IOPQ} : D_rB; 199 | D_icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 200 | 1 : RNONE; # Don't write any register 201 | ]; 202 | 203 | ## What register should be used as the M destination? 204 | word d_dstM = [ 205 | D_icode in { IMRMOVQ, IPOPQ } : D_rA; 206 | 1 : RNONE; # Don't write any register 207 | ]; 208 | 209 | ## What should be the A value? 210 | ## Forward into decode stage for valA 211 | word d_valA = [ 212 | D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC 213 | d_srcA == e_dstE : e_valE; # Forward valE from execute 214 | d_srcA == M_dstM : m_valM; # Forward valM from memory 215 | d_srcA == M_dstE : M_valE; # Forward valE from memory 216 | d_srcA == W_dstM : W_valM; # Forward valM from write back 217 | d_srcA == W_dstE : W_valE; # Forward valE from write back 218 | 1 : d_rvalA; # Use value read from register file 219 | ]; 220 | 221 | word d_valB = [ 222 | d_srcB == e_dstE : e_valE; # Forward valE from execute 223 | d_srcB == M_dstM : m_valM; # Forward valM from memory 224 | d_srcB == M_dstE : M_valE; # Forward valE from memory 225 | d_srcB == W_dstM : W_valM; # Forward valM from write back 226 | d_srcB == W_dstE : W_valE; # Forward valE from write back 227 | 1 : d_rvalB; # Use value read from register file 228 | ]; 229 | 230 | ################ Execute Stage ##################################### 231 | 232 | ## Select input A to ALU 233 | word aluA = [ 234 | E_icode in { IRRMOVQ, IOPQ } : E_valA; 235 | E_icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : E_valC; 236 | E_icode in { ICALL, IPUSHQ } : -8; 237 | E_icode in { IRET, IPOPQ } : 8; 238 | # Other instructions don't need ALU 239 | ]; 240 | 241 | ## Select input B to ALU 242 | word aluB = [ 243 | E_icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 244 | IPUSHQ, IRET, IPOPQ } : E_valB; 245 | E_icode in { IRRMOVQ, IIRMOVQ } : 0; 246 | # Other instructions don't need ALU 247 | ]; 248 | 249 | ## Set the ALU function 250 | word alufun = [ 251 | E_icode == IOPQ : E_ifun; 252 | 1 : ALUADD; 253 | ]; 254 | 255 | ## Should the condition codes be updated? 256 | bool set_cc = E_icode == IOPQ && 257 | # State changes only during normal operation 258 | !m_stat in { SADR, SINS, SHLT } && !W_stat in { SADR, SINS, SHLT }; 259 | 260 | ## Generate valA in execute stage 261 | word e_valA = E_valA; # Pass valA through stage 262 | 263 | ## Set dstE to RNONE in event of not-taken conditional move 264 | word e_dstE = [ 265 | E_icode == IRRMOVQ && !e_Cnd : RNONE; 266 | 1 : E_dstE; 267 | ]; 268 | 269 | ################ Memory Stage ###################################### 270 | 271 | ## Select memory address 272 | word mem_addr = [ 273 | M_icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : M_valE; 274 | M_icode in { IPOPQ, IRET } : M_valA; 275 | # Other instructions don't need address 276 | ]; 277 | 278 | ## Set read control signal 279 | bool mem_read = M_icode in { IMRMOVQ, IPOPQ, IRET }; 280 | 281 | ## Set write control signal 282 | bool mem_write = M_icode in { IRMMOVQ, IPUSHQ, ICALL }; 283 | 284 | #/* $begin pipe-m_stat-hcl */ 285 | ## Update the status 286 | word m_stat = [ 287 | dmem_error : SADR; 288 | 1 : M_stat; 289 | ]; 290 | #/* $end pipe-m_stat-hcl */ 291 | 292 | ## Set E port register ID 293 | word w_dstE = W_dstE; 294 | 295 | ## Set E port value 296 | word w_valE = W_valE; 297 | 298 | ## Set M port register ID 299 | word w_dstM = W_dstM; 300 | 301 | ## Set M port value 302 | word w_valM = W_valM; 303 | 304 | ## Update processor status 305 | word Stat = [ 306 | W_stat == SBUB : SAOK; 307 | 1 : W_stat; 308 | ]; 309 | 310 | ################ Pipeline Register Control ######################### 311 | 312 | # Should I stall or inject a bubble into Pipeline Register F? 313 | # At most one of these can be true. 314 | bool F_bubble = 0; 315 | bool F_stall = 316 | # Conditions for a load/use hazard 317 | E_icode in { IMRMOVQ, IPOPQ } && 318 | E_dstM in { d_srcA, d_srcB } || 319 | # Stalling at fetch while ret passes through pipeline 320 | IRET in { D_icode, E_icode, M_icode }; 321 | 322 | # Should I stall or inject a bubble into Pipeline Register D? 323 | # At most one of these can be true. 324 | bool D_stall = 325 | # Conditions for a load/use hazard 326 | E_icode in { IMRMOVQ, IPOPQ } && 327 | E_dstM in { d_srcA, d_srcB }; 328 | 329 | bool D_bubble = 330 | # Mispredicted branch 331 | (E_icode == IJXX && !e_Cnd) || 332 | # Stalling at fetch while ret passes through pipeline 333 | # but not condition for a load/use hazard 334 | !(E_icode in { IMRMOVQ, IPOPQ } && E_dstM in { d_srcA, d_srcB }) && 335 | IRET in { D_icode, E_icode, M_icode }; 336 | 337 | # Should I stall or inject a bubble into Pipeline Register E? 338 | # At most one of these can be true. 339 | bool E_stall = 0; 340 | bool E_bubble = 341 | # Mispredicted branch 342 | (E_icode == IJXX && !e_Cnd) || 343 | # Conditions for a load/use hazard 344 | E_icode in { IMRMOVQ, IPOPQ } && 345 | E_dstM in { d_srcA, d_srcB}; 346 | 347 | # Should I stall or inject a bubble into Pipeline Register M? 348 | # At most one of these can be true. 349 | bool M_stall = 0; 350 | # Start injecting bubbles as soon as exception passes through memory stage 351 | bool M_bubble = m_stat in { SADR, SINS, SHLT } || W_stat in { SADR, SINS, SHLT }; 352 | 353 | # Should I stall or inject a bubble into Pipeline Register W? 354 | bool W_stall = W_stat in { SADR, SINS, SHLT }; 355 | bool W_bubble = 0; 356 | #/* $end pipe-all-hcl */ 357 | -------------------------------------------------------------------------------- /pipe/pipeline.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * pipe.h 3 | * 4 | * Code for implementing pipelined processor simulators 5 | ******************************************************************************/ 6 | 7 | #ifndef PIPE_H 8 | #define PIPE_H 9 | 10 | /****************************************************************************** 11 | * #includes 12 | ******************************************************************************/ 13 | 14 | #include 15 | 16 | /****************************************************************************** 17 | * typedefs 18 | ******************************************************************************/ 19 | 20 | /* Different control operations for pipeline register */ 21 | /* LOAD: Copy next state to current */ 22 | /* STALL: Keep current state unchanged */ 23 | /* BUBBLE: Set current state to nop */ 24 | /* ERROR: Occurs when both stall & load signals set */ 25 | 26 | typedef enum { P_LOAD, P_STALL, P_BUBBLE, P_ERROR } p_stat_t; 27 | 28 | typedef struct { 29 | /* Current and next register state */ 30 | void *current; 31 | void *next; 32 | /* Contents of register when bubble occurs */ 33 | void *bubble_val; 34 | /* Number of state bytes */ 35 | int count; 36 | /* How should state be updated next time? */ 37 | p_stat_t op; 38 | } pipe_ele, *pipe_ptr; 39 | 40 | /****************************************************************************** 41 | * function declarations 42 | ******************************************************************************/ 43 | 44 | /* Create new pipe with count bytes of state */ 45 | /* bubble_val indicates state corresponding to pipeline bubble */ 46 | pipe_ptr new_pipe(int count, void *bubble_val); 47 | 48 | /* Update all pipes */ 49 | void update_pipes(); 50 | 51 | /* Set all pipes to bubble values */ 52 | void clear_pipes(); 53 | 54 | /* Utility code */ 55 | 56 | /* Print hex/oct/binary format with leading zeros */ 57 | /* bpd denotes bits per digit Should be in range 1-4, 58 | bpw denotes bits per word.*/ 59 | void wprint(uword_t x, int bpd, int bpw, FILE *fp); 60 | void wstring(uword_t x, int bpd, int bpw, char *s); 61 | 62 | /******************************************************************************/ 63 | 64 | #endif /* PIPE_H */ 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /pipe/sim.h: -------------------------------------------------------------------------------- 1 | 2 | /********** Typedefs ************/ 3 | 4 | /* EX stage mux settings */ 5 | typedef enum { MUX_NONE, MUX_EX_A, MUX_EX_B, MUX_MEM_E, 6 | MUX_WB_M, MUX_WB_E } mux_source_t; 7 | 8 | /* Simulator operating modes */ 9 | typedef enum { S_WEDGED, S_STALL, S_FORWARD } sim_mode_t; 10 | 11 | /* Pipeline stage identifiers for stage operation control */ 12 | typedef enum { IF_STAGE, ID_STAGE, EX_STAGE, MEM_STAGE, WB_STAGE } stage_id_t; 13 | 14 | /********** Defines **************/ 15 | 16 | /* Get ra out of one byte regid field */ 17 | #define GET_RA(r) HI4(r) 18 | 19 | /* Get rb out of one byte regid field */ 20 | #define GET_RB(r) LO4(r) 21 | 22 | 23 | /************ Global state declaration ****************/ 24 | 25 | /* How many cycles have been simulated? */ 26 | extern word_t cycles; 27 | /* How many instructions have passed through the EX stage? */ 28 | extern word_t instructions; 29 | 30 | /* Both instruction and data memory */ 31 | extern mem_t mem; 32 | 33 | /* Keep track of range of addresses that have been written */ 34 | extern word_t minAddr; 35 | extern word_t memCnt; 36 | 37 | /* Register file */ 38 | extern mem_t reg; 39 | /* Condition code register */ 40 | extern cc_t cc; 41 | extern stat_t stat; 42 | 43 | /* Operand sources in EX (to show forwarding) */ 44 | extern mux_source_t amux, bmux; 45 | 46 | /* Provide global access to current states of all pipeline registers */ 47 | pipe_ptr pc_state, if_id_state, id_ex_state, ex_mem_state, mem_wb_state; 48 | 49 | /* Current States */ 50 | extern pc_ptr pc_curr; 51 | extern if_id_ptr if_id_curr; 52 | extern id_ex_ptr id_ex_curr; 53 | extern ex_mem_ptr ex_mem_curr; 54 | extern mem_wb_ptr mem_wb_curr; 55 | 56 | /* Next States */ 57 | extern pc_ptr pc_next; 58 | extern if_id_ptr if_id_next; 59 | extern id_ex_ptr id_ex_next; 60 | extern ex_mem_ptr ex_mem_next; 61 | extern mem_wb_ptr mem_wb_next; 62 | 63 | /* Pending updates to state */ 64 | extern word_t cc_in; 65 | extern word_t wb_destE; 66 | extern word_t wb_valE; 67 | extern word_t wb_destM; 68 | extern word_t wb_valM; 69 | extern word_t mem_addr; 70 | extern word_t mem_data; 71 | extern bool_t mem_write; 72 | 73 | 74 | /* Intermdiate stage values that must be used by control functions */ 75 | extern word_t f_pc; 76 | extern byte_t imem_icode; 77 | extern byte_t imem_ifun; 78 | extern bool_t imem_error; 79 | extern bool_t instr_valid; 80 | extern word_t d_regvala; 81 | extern word_t d_regvalb; 82 | extern word_t e_vala; 83 | extern word_t e_valb; 84 | extern bool_t e_bcond; 85 | extern bool_t dmem_error; 86 | 87 | /* Simulator operating mode */ 88 | extern sim_mode_t sim_mode; 89 | /* Log file */ 90 | extern FILE *dumpfile; 91 | 92 | /*************** Simulation Control Functions ***********/ 93 | 94 | /* Bubble next execution of specified stage */ 95 | void sim_bubble_stage(stage_id_t stage); 96 | 97 | /* Stall stage (has effect at next update) */ 98 | void sim_stall_stage(stage_id_t stage); 99 | 100 | /* Sets the simulator name (called from main routine in HCL file) */ 101 | void set_simname(char *name); 102 | 103 | /* Initialize simulator */ 104 | void sim_init(); 105 | 106 | /* Reset simulator state, including register, instruction, and data memories */ 107 | void sim_reset(); 108 | 109 | /* 110 | Run pipeline until one of following occurs: 111 | - A status error is encountered in WB. 112 | - max_instr instructions have completed through WB 113 | - max_cycle cycles have been simulated 114 | 115 | Return number of instructions executed. 116 | if statusp nonnull, then will be set to status of final instruction 117 | if ccp nonnull, then will be set to condition codes of final instruction 118 | */ 119 | word_t sim_run_pipe(word_t max_instr, word_t max_cycle, byte_t *statusp, cc_t *ccp); 120 | 121 | /* If dumpfile set nonNULL, lots of status info printed out */ 122 | void sim_set_dumpfile(FILE *file); 123 | 124 | /* 125 | * sim_log dumps a formatted string to the dumpfile, if it exists 126 | * accepts variable argument list 127 | */ 128 | void sim_log( const char *format, ... ); 129 | 130 | 131 | /******************* GUI Interface Functions **********************/ 132 | #ifdef HAS_GUI 133 | 134 | void signal_sources(); 135 | 136 | void signal_register_clear(); 137 | 138 | void report_pc(unsigned fpc, unsigned char fpcv, 139 | unsigned dpc, unsigned char dpcv, 140 | unsigned epc, unsigned char epcv, 141 | unsigned mpc, unsigned char mpcv, 142 | unsigned wpc, unsigned char wpcv); 143 | 144 | void report_state(char *id, word_t current, char *txt); 145 | 146 | void show_cc(cc_t cc); 147 | void show_cpi(); 148 | void show_stat(stat_t stat); 149 | 150 | void create_memory_display(); 151 | void set_memory(word_t addr, word_t val); 152 | #endif 153 | 154 | -------------------------------------------------------------------------------- /pipe/stages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stages.h - Defines the layout of the pipe registers 3 | * Declares the functions that implement the pipeline stages 4 | */ 5 | 6 | /********** Pipeline register contents **************/ 7 | 8 | /* Program Counter */ 9 | typedef struct { 10 | word_t pc; 11 | stat_t status; 12 | } pc_ele, *pc_ptr; 13 | 14 | /* IF/ID Pipe Register */ 15 | typedef struct { 16 | byte_t icode; /* Single byte instruction code */ 17 | byte_t ifun; /* ALU/JMP qualifier */ 18 | byte_t ra; /* Register ra ID */ 19 | byte_t rb; /* Register rb ID */ 20 | word_t valc; /* Instruction word encoding immediate data */ 21 | word_t valp; /* Incremented program counter */ 22 | stat_t status; 23 | /* The following is included for debugging */ 24 | word_t stage_pc; 25 | } if_id_ele, *if_id_ptr; 26 | 27 | /* ID/EX Pipe Register */ 28 | typedef struct { 29 | byte_t icode; /* Instruction code */ 30 | byte_t ifun; /* ALU/JMP qualifier */ 31 | word_t valc; /* Immediate data */ 32 | word_t vala; /* valA */ 33 | word_t valb; /* valB */ 34 | byte_t srca; /* Source Reg ID for valA */ 35 | byte_t srcb; /* Source Reg ID for valB */ 36 | byte_t deste; /* Destination register for valE */ 37 | byte_t destm; /* Destination register for valM */ 38 | stat_t status; 39 | /* The following is included for debugging */ 40 | word_t stage_pc; 41 | } id_ex_ele, *id_ex_ptr; 42 | 43 | /* EX/MEM Pipe Register */ 44 | typedef struct { 45 | byte_t icode; /* Instruction code */ 46 | byte_t ifun; /* ALU/JMP qualifier */ 47 | bool_t takebranch; /* Taken branch signal */ 48 | word_t vale; /* valE */ 49 | word_t vala; /* valA */ 50 | byte_t deste; /* Destination register for valE */ 51 | byte_t destm; /* Destination register for valM */ 52 | byte_t srca; /* Source register for valA */ 53 | stat_t status; 54 | /* The following is included for debugging */ 55 | word_t stage_pc; 56 | } ex_mem_ele, *ex_mem_ptr; 57 | 58 | /* Mem/WB Pipe Register */ 59 | typedef struct { 60 | byte_t icode; /* Instruction code */ 61 | byte_t ifun; /* ALU/JMP qualifier */ 62 | word_t vale; /* valE */ 63 | word_t valm; /* valM */ 64 | byte_t deste; /* Destination register for valE */ 65 | byte_t destm; /* Destination register for valM */ 66 | stat_t status; 67 | /* The following is included for debugging */ 68 | word_t stage_pc; 69 | } mem_wb_ele, *mem_wb_ptr; 70 | 71 | /************ Global Declarations ********************/ 72 | 73 | extern pc_ele bubble_pc; 74 | extern if_id_ele bubble_if_id; 75 | extern id_ex_ele bubble_id_ex; 76 | extern ex_mem_ele bubble_ex_mem; 77 | extern mem_wb_ele bubble_mem_wb; 78 | 79 | /************ Function declarations *******************/ 80 | 81 | /* Stage functions */ 82 | void do_if_stage(); 83 | void do_id_wb_stages(); /* Both ID and WB */ 84 | void do_ex_stage(); 85 | void do_mem_stage(); 86 | 87 | /* Set stalling conditions for different stages */ 88 | void do_stall_check(); 89 | 90 | 91 | -------------------------------------------------------------------------------- /ptest/Makefile: -------------------------------------------------------------------------------- 1 | SIM=../pipe/psim 2 | TFLAGS= 3 | 4 | ISADIR = ../misc 5 | YAS=$(ISADIR)/yas 6 | 7 | .SUFFIXES: .ys .yo 8 | 9 | .ys.yo: 10 | $(YAS) $*.ys 11 | 12 | test: 13 | ./optest.pl -s $(SIM) $(TFLAGS) 14 | ./jtest.pl -s $(SIM) $(TFLAGS) 15 | ./ctest.pl -s $(SIM) $(TFLAGS) 16 | ./htest.pl -s $(SIM) $(TFLAGS) 17 | 18 | clean: 19 | rm -f *.o *~ *.yo *.ys 20 | 21 | -------------------------------------------------------------------------------- /ptest/README: -------------------------------------------------------------------------------- 1 | This directory contains Perl scripts that provide comprehensive 2 | regression testing of the different Y86-64 simulators. There are four 3 | basic test types, implemented as four different scripts: 4 | 5 | optest.pl: Tests each individual instruction type 6 | jtest.pl: Tests all of the jump types under different conditions 7 | ctest.pl: Tests different pipeline control combinations 8 | htest.pl: Tests many different hazard possibilities 9 | This involves running 864+ tests, so it takes a while. 10 | 11 | Each of the tests has the following optional arguments: 12 | -s simfile Use simfile as simulator (default ../pipe/psim). 13 | -i Test the iaddq instruction 14 | 15 | You can use make to run all four test programs. Options to make include: 16 | 17 | SIM=simfile 18 | TFLAGS= 19 | 20 | For example, you could say: 21 | make SIM=../pipe/psim TFLAGS=-i 22 | to test the pipeline simulator including the iaddq instruction. (Note that 23 | this test will fail for the default implementation of pipe, since it does 24 | not implement the iaddq instruction.) 25 | 26 | When the test program detects an erroneous simulation, it leaves the 27 | .ys file in the directory (ordinarily it deletes the test code it 28 | generates). You can then run a simulator (the GUI version is 29 | especially helpful here) on one of these failing cases. Suppose the 30 | failing test is in file bad-test.ys. Then you can execute "make 31 | bad-test.yo" to create the object code, and simulate it with one of 32 | the simulators. 33 | 34 | Note that the standard test code only detects functional bugs, where the 35 | processor simulation produces different results than would be 36 | predicted by simulating at the ISA level. 37 | -------------------------------------------------------------------------------- /ptest/ctest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | # Test for pipeline hazard combinations 4 | 5 | use Getopt::Std; 6 | use lib "."; 7 | use tester; 8 | 9 | cmdline(); 10 | 11 | # Instruction templates 12 | $tcount = 8; 13 | 14 | @templates = 15 | ( 16 | "||jne target\n\thalt\ntarget:|", # M 17 | "|||ret", # R 18 | 19 | "||mrmovq (%rax),%rsp|ret", # G1a 20 | "|mrmovq (%rax),%rsp||ret", # G1b 21 | "mrmovq (%rax),%rsp|||ret", # G1c 22 | "||irmovq \$3,%rax|rrmovq %rax,%rdx", # G2a 23 | "|irmovq \$3,%rax||rrmovq %rax,%rdx", # G2b 24 | "irmovq \$3,%rax|||rrmovq %rax,%rdx", # G2c 25 | ); 26 | 27 | # Try combining two templates to generate test sequence 28 | sub make_test 29 | { 30 | local ($t1, $t2) = @_; 31 | $ok = 1; 32 | @test1 = split(/\|/, $t1); 33 | @test2 = split(/\|/, $t2); 34 | for ($i = 0; $i < 4; $i++) { 35 | if ($test1[$i] eq "") { 36 | if ($test2[$i] eq "") { 37 | $test[$i] = "nop"; 38 | } else { 39 | $test[$i] = $test2[$i]; 40 | } 41 | } else { 42 | if ($test2[$i] eq "") { 43 | $test[$i] = $test1[$i]; 44 | } else { 45 | if ($test1[$i] eq $test2[$i]) { 46 | # $ok = 0; 47 | $test[$i] = $test1[$i]; 48 | } else { 49 | $ok = 0; 50 | $test[$i] = "XXX"; 51 | } 52 | } 53 | } 54 | } 55 | if ($ok) { 56 | &gen_test($test[0], $test[1], $test[2], $test[3]); 57 | } 58 | 59 | } 60 | 61 | $testcnt = 0; 62 | 63 | # Generate test with 4 instructions inserted 64 | sub gen_test 65 | { 66 | local ($i1, $i2, $i3, $i4) = @_; 67 | $tname = "c-$testcnt"; 68 | $testcnt++; 69 | open(YFILE, ">$tname.ys") || die "Can't write to $tname.ys\n"; 70 | 71 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 59 | &gen_test($e, "nop", $s); 60 | close YFILE; 61 | &run_test($tname); 62 | 63 | # Two instructions in succession 64 | $tname = "e-$ei-$si"; 65 | open (YFILE, ">$tname.ys") || die "Can't write to $tname.ys\n"; 66 | &gen_test($e, "", $s); 67 | close YFILE; 68 | &run_test($tname); 69 | $si++; 70 | } 71 | $si = 0; 72 | $ei++; 73 | } 74 | 75 | &test_stat(); 76 | -------------------------------------------------------------------------------- /ptest/htest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | # Test for pipeline hazards 4 | 5 | use Getopt::Std; 6 | use lib "."; 7 | use tester; 8 | 9 | cmdline(); 10 | 11 | # Destination Instructions 12 | @dest = 13 | ( 14 | # Having %rax as destination 15 | "1:rrmovq %rcx,%rax", 16 | "1:irmovq \$0x101,%rax", 17 | "1:mrmovq 0(%rbp),%rax", 18 | "1:addq %rax,%rax", 19 | "1:popq %rax", 20 | "1:cmovne %rcx,%rax", # Not taken 21 | "1:cmove %rcx,%rax", # Taken 22 | # Instructions having %rbp as destination 23 | "2:rrmovq %rax,%rbp", 24 | "2:irmovq \$0x100,%rbp", 25 | "2:mrmovq 4(%rbp),%rbp", 26 | "2:addq %rax,%rbp", 27 | "2:popq %rbp", 28 | "2:cmovne %rax,%rbp", # Not taken 29 | "2:cmove %rax,%rbp", # Taken 30 | # Instructions having %rsp as destination 31 | "3:rrmovq %rbp,%rsp", 32 | "3:irmovq \$0x104,%rsp", 33 | "3:mrmovq 4(%rbp),%rsp", 34 | "3:addq %rax,%rsp", 35 | "3:popq %rbp", 36 | "3:pushq %rax", 37 | "3:pushq %rsp", 38 | "3:popq %rsp", 39 | "1:cmovne %rbp,%rsp", # Not taken 40 | "1:cmove %rbp,%rsp" # Taken 41 | ); 42 | 43 | if ($testiaddq) { 44 | @dest = (@dest, 45 | "1:iaddq \$0x201,%rax", 46 | "2:iaddq \$0x4,%rbp", 47 | "3:iaddq \$0x4,%rsp",); 48 | } 49 | 50 | if ($testleave) { 51 | @dest = (@dest, "2:leave", "3:leave"); 52 | } 53 | 54 | @src = 55 | ( 56 | # Instructions having %rax as source 57 | "1:rrmovq %rax,%rbp", 58 | "1:rmmovq %rax,0(%rbp)", 59 | "1:rmmovq %rbp,0(%rax)", 60 | "1:mrmovq 4(%rax),%rbp", 61 | "1:addq %rax,%rbp", 62 | "1:addq %rbp,%rax", 63 | "1:addq %rax,%rax", 64 | "1:pushq %rax", 65 | # Instructions having %rbp as source 66 | "2:rrmovq %rbp,%rbp", 67 | "2:rmmovq %rbp,4(%rbp)", 68 | "2:rmmovq %rax,0(%rbp)", 69 | "2:mrmovq 8(%rbp),%rax", 70 | "2:addq %rbp,%rax", 71 | "2:addq %rax,%rbp", 72 | "2:addq %rbp,%rbp", 73 | "2:pushq %rbp", 74 | # Instructions having %rsp as source 75 | "3:rrmovq %rsp,%rbp", 76 | "3:rmmovq %rsp,4(%rbp)", 77 | "3:rmmovq %rax,-4(%rsp)", 78 | "3:mrmovq 4(%rsp),%rax", 79 | "3:addq %rsp,%rax", 80 | "3:addq %rax,%rsp", 81 | "3:addq %rsp,%rsp", 82 | "3:pushq %rsp", 83 | "3:ret" 84 | ); 85 | 86 | if ($testiaddq) { 87 | @src = (@src, 88 | "1:iaddq \$0x301,%rax", 89 | "2:iaddq \$0x8,%rbp", 90 | "3:iaddq \$0x8,%rsp"); 91 | } 92 | 93 | # Generate test with 4 instructions inserted 94 | sub gen_test 95 | { 96 | local ($i1, $i2, $i3, $i4) = @_; 97 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 225 | &gen_test($d, "nop", "nop", $s); 226 | close YFILE; 227 | &run_test($tname); 228 | 229 | # Two instructions with nop between them 230 | $tname = "hn-$di-$si"; 231 | open (YFILE, ">$tname.ys") || die "Can't write to $tname.ys\n"; 232 | &gen_test($d, "nop", "", $s); 233 | close YFILE; 234 | &run_test($tname); 235 | 236 | # Two instructions in succession 237 | $tname = "h-$di-$si"; 238 | open (YFILE, ">$tname.ys") || die "Can't write to $tname.ys\n"; 239 | &gen_test($d, "", "", $s); 240 | close YFILE; 241 | &run_test($tname); 242 | } 243 | $si++; 244 | } 245 | $si = 0; 246 | $di++; 247 | } 248 | 249 | &test_stat(); 250 | -------------------------------------------------------------------------------- /ptest/jtest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | # Test jump instructions 4 | 5 | use Getopt::Std; 6 | use lib "."; 7 | use tester; 8 | 9 | cmdline(); 10 | 11 | @vals = (32, 64); 12 | 13 | @instr = ("jmp", "jle", "jl", "je", "jne", "jge", "jg", "call"); 14 | 15 | # Create set of forward tests 16 | foreach $t (@instr) { 17 | foreach $va (@vals) { 18 | foreach $vb (@vals) { 19 | $tname = "jf-$t-$va-$vb"; 20 | open (YFILE, ">$tname.ys") || die "Can't write to $tname.ys\n"; 21 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 56 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 96 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 21 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 43 | print YFILE <$tname.ys") || die "Can't write to $tname.ys\n"; 66 | print YFILE <] [-P] [-p ]\n"; 140 | print STDERR " -h print Help message\n"; 141 | print STDERR " -i test iaddq instruction\n"; 142 | print STDERR " -s Specify simulator\n"; 143 | print STDERR " -d Specify directory for counterexamples\n"; 144 | print STDERR " -P Generate performance data\n"; 145 | print STDERR " -p Check using performance file \n"; 146 | print STDERR " -V test Verilog implementation\n"; 147 | print STDERR " -m Model for Verilog\n"; 148 | die "\n"; 149 | } 150 | 151 | if ($opt_i) { 152 | $testiaddq = 1; 153 | } 154 | 155 | if ($opt_d) { 156 | $outputdir = $opt_d; 157 | } 158 | 159 | if ($opt_P) { 160 | $gen_perf = 1; 161 | } 162 | 163 | if ($opt_p) { 164 | $check_perf = 1; 165 | $perf_file = $opt_p; 166 | } 167 | 168 | if ($opt_s) { 169 | $sim = $opt_s; 170 | } 171 | if ($opt_V) { 172 | $test_vlog = 1; 173 | if ($opt_m) { 174 | $vmodel = $opt_m; 175 | } 176 | } else { 177 | print "Simulating with $sim\n"; 178 | } 179 | } 180 | 181 | # Perl gives error messages without the following line !?! 182 | $junk = 1; 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /seq/Makefile: -------------------------------------------------------------------------------- 1 | # Modify this line to indicate the default version 2 | 3 | VERSION=std 4 | 5 | # Comment this out if you don't have Tcl/Tk on your system 6 | 7 | #GUIMODE=-DHAS_GUI 8 | 9 | # Modify the following line so that gcc can find the libtcl.so and 10 | # libtk.so libraries on your system. You may need to use the -L option 11 | # to tell gcc which directory to look in. Comment this out if you 12 | # don't have Tcl/Tk. 13 | 14 | #TKLIBS=-L/usr/lib -ltk -ltcl 15 | 16 | # Modify the following line so that gcc can find the tcl.h and tk.h 17 | # header files on your system. Comment this out if you don't have 18 | # Tcl/Tk. 19 | 20 | #TKINC=-isystem /usr/include/tcl8.5 21 | 22 | # Modify these two lines to choose your compiler and compile time 23 | # flags. 24 | 25 | CC=gcc 26 | CFLAGS=-Wall -O2 27 | 28 | ################################################## 29 | # You shouldn't need to modify anything below here 30 | ################################################## 31 | 32 | MISCDIR=../misc 33 | HCL2C=$(MISCDIR)/hcl2c 34 | INC=$(TKINC) -I$(MISCDIR) $(GUIMODE) 35 | LIBS=$(TKLIBS) -lm 36 | YAS=../misc/yas 37 | 38 | all: ssim 39 | 40 | # This rule builds the SEQ simulator (ssim) 41 | ssim: seq-$(VERSION).hcl ssim.c sim.h $(MISCDIR)/isa.c $(MISCDIR)/isa.h 42 | # Building the seq-$(VERSION).hcl version of SEQ 43 | $(HCL2C) -n seq-$(VERSION).hcl seq-$(VERSION).c 44 | $(CC) $(CFLAGS) $(INC) -o ssim \ 45 | seq-$(VERSION).c ssim.c $(MISCDIR)/isa.c $(LIBS) 46 | 47 | # This rule builds the SEQ+ simulator (ssim+) 48 | ssim+: seq+-std.hcl ssim.c sim.h $(MISCDIR)/isa.c $(MISCDIR)/isa.h 49 | # Building the seq+-std.hcl version of SEQ+ 50 | $(HCL2C) -n seq+-std.hcl seq+-std.c 51 | $(CC) $(CFLAGS) $(INC) -o ssim+ \ 52 | seq+-std.c ssim.c $(MISCDIR)/isa.c $(LIBS) 53 | 54 | # These are implicit rules for assembling .yo files from .ys files. 55 | .SUFFIXES: .ys .yo 56 | .ys.yo: 57 | $(YAS) $*.ys 58 | 59 | 60 | clean: 61 | rm -f ssim ssim+ seq*-*.c *.o *~ *.exe *.yo *.ys 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /seq/README: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Sequential Y86-64 Simulators 3 | * 4 | * Copyright (c) 2002, 2010, 2013, 2015 R. Bryant and D. O'Hallaron, 5 | * All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | ***********************************************************************/ 8 | 9 | This directory contains the code to construct simulators for SEQ, 10 | SEQ+, and the variants of it described in the homework exercises. 11 | 12 | ************************** 13 | 1. Building the simulators 14 | ************************** 15 | 16 | Different versions of the SEQ and SEQ+ simulators can be constructed 17 | to use different HCL files when working on the different homework 18 | problems. 19 | 20 | Binary VERSION HCL File Description 21 | ssim std seq-std.hcl Standard SEQ simulator described in textbook. 22 | ssim full seq-full.hcl For adding iaddq to SEQ. 23 | ssim+ std seq+-std.hcl Standard SEQ+ simulator described in textbook. 24 | 25 | The simulators run in either TTY or GUI mode: 26 | 27 | o TTY mode: A simulator running in TTY mode prints all information 28 | about its runtime behavior on the terminal. It's hard to understand what's 29 | going on, but useful for automated testing, and doesn't require any 30 | special installation features. 31 | 32 | o GUI mode: A simulator running in GUI mode uses a fancy graphical 33 | user interface. Nice for visualizing and debugging, but requires 34 | installation of Tcl/Tk on your system. 35 | 36 | The Makefile has simple instructions for building TTY or GUI 37 | simulators. A TTY simulator runs in TTY mode only. A GUI 38 | simulator can run in either TTY mode or GUI mode, according to 39 | a command line argument. 40 | 41 | Once you've configured the Makefile, you can build the different 42 | simulators with commands of the form 43 | 44 | unix> make clean; make ssim VERSION=xxx 45 | 46 | where "xxx" is one of the versions listed above. For example, to build 47 | the version of SEQ described in the CS:APP text based on the control 48 | logic in seq-std.hcl, type 49 | 50 | unix> make clean; make ssim VERSION=std 51 | 52 | To save typing, you can also set the Makefile's VERSION variable. 53 | 54 | *********************** 55 | 2. Using the simulators 56 | *********************** 57 | 58 | The simulators take identical command line arguments: 59 | 60 | Usage: ssim [-htg] [-l m] [-v n] file.yo 61 | 62 | file.yo required in GUI mode, optional in TTY mode (default stdin) 63 | 64 | -h Print this message 65 | -g Run in GUI mode instead of TTY mode (default TTY mode) 66 | -l m Set instruction limit to m [TTY mode only] (default 10000) 67 | -v n Set verbosity level to 0 <= n <= 2 [TTY mode only] (default 2) 68 | -t Test result against the ISA simulator (yis) [TTY model only] 69 | 70 | ******** 71 | 3. Files 72 | ******** 73 | 74 | Makefile Builds the SEQ and SEQ+ simulators 75 | Makefile-sim Makefile for student distribution 76 | README This file 77 | 78 | seq+.tcl TCL script for GUI version of SEQ+ 79 | seq.tcl TCL script for GUI version of SEQ 80 | 81 | ssim.c Base sequential simulator code and header file 82 | sim.h 83 | 84 | seq-std.hcl Standard SEQ control logic 85 | seq+-std.hcl Standard SEQ+ control logic 86 | seq-full.hcl Template for the iaddq problem (4.34-35) 87 | 88 | seq-full-ans.hcl Solution for the iaddq problems (4.34-35) 89 | (Instructor distribution only) 90 | 91 | 92 | -------------------------------------------------------------------------------- /seq/seq+-std.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin seq-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Single Cycle Y86-64 Processor SEQ+ # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010 # 5 | #################################################################### 6 | 7 | #################################################################### 8 | # C Include's. Don't alter these # 9 | #################################################################### 10 | 11 | quote '#include ' 12 | quote '#include "isa.h"' 13 | quote '#include "sim.h"' 14 | quote 'int sim_main(int argc, char *argv[]);' 15 | quote 'word_t gen_new_pc(){return 0;}' 16 | quote 'int main(int argc, char *argv[])' 17 | quote ' {plusmode=1;return sim_main(argc,argv);}' 18 | 19 | #################################################################### 20 | # Declarations. Do not change/remove/delete any of these # 21 | #################################################################### 22 | 23 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 24 | wordsig INOP 'I_NOP' 25 | wordsig IHALT 'I_HALT' 26 | wordsig IRRMOVQ 'I_RRMOVQ' 27 | wordsig IIRMOVQ 'I_IRMOVQ' 28 | wordsig IRMMOVQ 'I_RMMOVQ' 29 | wordsig IMRMOVQ 'I_MRMOVQ' 30 | wordsig IOPQ 'I_ALU' 31 | wordsig IJXX 'I_JMP' 32 | wordsig ICALL 'I_CALL' 33 | wordsig IRET 'I_RET' 34 | wordsig IPUSHQ 'I_PUSHQ' 35 | wordsig IPOPQ 'I_POPQ' 36 | 37 | ##### Symbolic represenations of Y86-64 function codes ##### 38 | wordsig FNONE 'F_NONE' # Default function code 39 | 40 | ##### Symbolic representation of Y86-64 Registers referenced explicitly ##### 41 | wordsig RRSP 'REG_RSP' # Stack Pointer 42 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 43 | 44 | ##### ALU Functions referenced explicitly ##### 45 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 46 | 47 | ##### Possible instruction status values ##### 48 | wordsig SAOK 'STAT_AOK' # Normal execution 49 | wordsig SADR 'STAT_ADR' # Invalid memory address 50 | wordsig SINS 'STAT_INS' # Invalid instruction 51 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 52 | 53 | ##### Signals that can be referenced by control logic #################### 54 | 55 | ##### PC stage inputs ##### 56 | 57 | ## All of these values are based on those from previous instruction 58 | wordsig pIcode 'prev_icode' # Instr. control code 59 | wordsig pValC 'prev_valc' # Constant from instruction 60 | wordsig pValM 'prev_valm' # Value read from memory 61 | wordsig pValP 'prev_valp' # Incremented program counter 62 | boolsig pCnd 'prev_bcond' # Condition flag 63 | 64 | ##### Fetch stage computations ##### 65 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 66 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 67 | wordsig icode 'icode' # Instruction control code 68 | wordsig ifun 'ifun' # Instruction function 69 | wordsig rA 'ra' # rA field from instruction 70 | wordsig rB 'rb' # rB field from instruction 71 | wordsig valC 'valc' # Constant from instruction 72 | wordsig valP 'valp' # Address of following instruction 73 | boolsig imem_error 'imem_error' # Error signal from instruction memory 74 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 75 | 76 | ##### Decode stage computations ##### 77 | wordsig valA 'vala' # Value from register A port 78 | wordsig valB 'valb' # Value from register B port 79 | 80 | ##### Execute stage computations ##### 81 | wordsig valE 'vale' # Value computed by ALU 82 | boolsig Cnd 'cond' # Branch test 83 | 84 | ##### Memory stage computations ##### 85 | wordsig valM 'valm' # Value read from memory 86 | boolsig dmem_error 'dmem_error' # Error signal from data memory 87 | 88 | 89 | #################################################################### 90 | # Control Signal Definitions. # 91 | #################################################################### 92 | 93 | ################ Program Counter Computation ####################### 94 | 95 | # Compute fetch location for this instruction based on results from 96 | # previous instruction. 97 | 98 | word pc = [ 99 | # Call. Use instruction constant 100 | pIcode == ICALL : pValC; 101 | # Taken branch. Use instruction constant 102 | pIcode == IJXX && pCnd : pValC; 103 | # Completion of RET instruction. Use value from stack 104 | pIcode == IRET : pValM; 105 | # Default: Use incremented PC 106 | 1 : pValP; 107 | ]; 108 | #/* $end seq-plus-pc-hcl */ 109 | 110 | ################ Fetch Stage ################################### 111 | 112 | # Determine instruction code 113 | word icode = [ 114 | imem_error: INOP; 115 | 1: imem_icode; # Default: get from instruction memory 116 | ]; 117 | 118 | # Determine instruction function 119 | word ifun = [ 120 | imem_error: FNONE; 121 | 1: imem_ifun; # Default: get from instruction memory 122 | ]; 123 | 124 | bool instr_valid = icode in 125 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 126 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 127 | 128 | # Does fetched instruction require a regid byte? 129 | bool need_regids = 130 | icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 131 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 132 | 133 | # Does fetched instruction require a constant word? 134 | bool need_valC = 135 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 136 | 137 | ################ Decode Stage ################################### 138 | 139 | ## What register should be used as the A source? 140 | word srcA = [ 141 | icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : rA; 142 | icode in { IPOPQ, IRET } : RRSP; 143 | 1 : RNONE; # Don't need register 144 | ]; 145 | 146 | ## What register should be used as the B source? 147 | word srcB = [ 148 | icode in { IOPQ, IRMMOVQ, IMRMOVQ } : rB; 149 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 150 | 1 : RNONE; # Don't need register 151 | ]; 152 | 153 | ## What register should be used as the E destination? 154 | word dstE = [ 155 | icode in { IRRMOVQ } && Cnd : rB; 156 | icode in { IIRMOVQ, IOPQ} : rB; 157 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 158 | 1 : RNONE; # Don't write any register 159 | ]; 160 | 161 | ## What register should be used as the M destination? 162 | word dstM = [ 163 | icode in { IMRMOVQ, IPOPQ } : rA; 164 | 1 : RNONE; # Don't write any register 165 | ]; 166 | 167 | ################ Execute Stage ################################### 168 | 169 | ## Select input A to ALU 170 | word aluA = [ 171 | icode in { IRRMOVQ, IOPQ } : valA; 172 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : valC; 173 | icode in { ICALL, IPUSHQ } : -8; 174 | icode in { IRET, IPOPQ } : 8; 175 | # Other instructions don't need ALU 176 | ]; 177 | 178 | ## Select input B to ALU 179 | word aluB = [ 180 | icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 181 | IPUSHQ, IRET, IPOPQ } : valB; 182 | icode in { IRRMOVQ, IIRMOVQ } : 0; 183 | # Other instructions don't need ALU 184 | ]; 185 | 186 | ## Set the ALU function 187 | word alufun = [ 188 | icode == IOPQ : ifun; 189 | 1 : ALUADD; 190 | ]; 191 | 192 | ## Should the condition codes be updated? 193 | bool set_cc = icode in { IOPQ }; 194 | 195 | ################ Memory Stage ################################### 196 | 197 | ## Set read control signal 198 | bool mem_read = icode in { IMRMOVQ, IPOPQ, IRET }; 199 | 200 | ## Set write control signal 201 | bool mem_write = icode in { IRMMOVQ, IPUSHQ, ICALL }; 202 | 203 | ## Select memory address 204 | word mem_addr = [ 205 | icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : valE; 206 | icode in { IPOPQ, IRET } : valA; 207 | # Other instructions don't need address 208 | ]; 209 | 210 | ## Select memory input data 211 | word mem_data = [ 212 | # Value from register 213 | icode in { IRMMOVQ, IPUSHQ } : valA; 214 | # Return PC 215 | icode == ICALL : valP; 216 | # Default: Don't write anything 217 | ]; 218 | 219 | ## Determine instruction status 220 | word Stat = [ 221 | imem_error || dmem_error : SADR; 222 | !instr_valid: SINS; 223 | icode == IHALT : SHLT; 224 | 1 : SAOK; 225 | ]; 226 | #/* $end seq-all-hcl */ 227 | -------------------------------------------------------------------------------- /seq/seq-full.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin seq-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Single Cycle Y86-64 Processor SEQ # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010 # 5 | #################################################################### 6 | 7 | ## Your task is to implement the iaddq instruction 8 | ## The file contains a declaration of the icodes 9 | ## for iaddq (IIADDQ) 10 | ## Your job is to add the rest of the logic to make it work 11 | 12 | #################################################################### 13 | # C Include's. Don't alter these # 14 | #################################################################### 15 | 16 | quote '#include ' 17 | quote '#include "isa.h"' 18 | quote '#include "sim.h"' 19 | quote 'int sim_main(int argc, char *argv[]);' 20 | quote 'word_t gen_pc(){return 0;}' 21 | quote 'int main(int argc, char *argv[])' 22 | quote ' {plusmode=0;return sim_main(argc,argv);}' 23 | 24 | #################################################################### 25 | # Declarations. Do not change/remove/delete any of these # 26 | #################################################################### 27 | 28 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 29 | wordsig INOP 'I_NOP' 30 | wordsig IHALT 'I_HALT' 31 | wordsig IRRMOVQ 'I_RRMOVQ' 32 | wordsig IIRMOVQ 'I_IRMOVQ' 33 | wordsig IRMMOVQ 'I_RMMOVQ' 34 | wordsig IMRMOVQ 'I_MRMOVQ' 35 | wordsig IOPQ 'I_ALU' 36 | wordsig IJXX 'I_JMP' 37 | wordsig ICALL 'I_CALL' 38 | wordsig IRET 'I_RET' 39 | wordsig IPUSHQ 'I_PUSHQ' 40 | wordsig IPOPQ 'I_POPQ' 41 | # Instruction code for iaddq instruction 42 | wordsig IIADDQ 'I_IADDQ' 43 | 44 | ##### Symbolic represenations of Y86-64 function codes ##### 45 | wordsig FNONE 'F_NONE' # Default function code 46 | 47 | ##### Symbolic representation of Y86-64 Registers referenced explicitly ##### 48 | wordsig RRSP 'REG_RSP' # Stack Pointer 49 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 50 | 51 | ##### ALU Functions referenced explicitly ##### 52 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 53 | 54 | ##### Possible instruction status values ##### 55 | wordsig SAOK 'STAT_AOK' # Normal execution 56 | wordsig SADR 'STAT_ADR' # Invalid memory address 57 | wordsig SINS 'STAT_INS' # Invalid instruction 58 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 59 | 60 | ##### Signals that can be referenced by control logic #################### 61 | 62 | ##### Fetch stage inputs ##### 63 | wordsig pc 'pc' # Program counter 64 | ##### Fetch stage computations ##### 65 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 66 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 67 | wordsig icode 'icode' # Instruction control code 68 | wordsig ifun 'ifun' # Instruction function 69 | wordsig rA 'ra' # rA field from instruction 70 | wordsig rB 'rb' # rB field from instruction 71 | wordsig valC 'valc' # Constant from instruction 72 | wordsig valP 'valp' # Address of following instruction 73 | boolsig imem_error 'imem_error' # Error signal from instruction memory 74 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 75 | 76 | ##### Decode stage computations ##### 77 | wordsig valA 'vala' # Value from register A port 78 | wordsig valB 'valb' # Value from register B port 79 | 80 | ##### Execute stage computations ##### 81 | wordsig valE 'vale' # Value computed by ALU 82 | boolsig Cnd 'cond' # Branch test 83 | 84 | ##### Memory stage computations ##### 85 | wordsig valM 'valm' # Value read from memory 86 | boolsig dmem_error 'dmem_error' # Error signal from data memory 87 | 88 | 89 | #################################################################### 90 | # Control Signal Definitions. # 91 | #################################################################### 92 | 93 | ################ Fetch Stage ################################### 94 | 95 | # Determine instruction code 96 | word icode = [ 97 | imem_error: INOP; 98 | 1: imem_icode; # Default: get from instruction memory 99 | ]; 100 | 101 | # Determine instruction function 102 | word ifun = [ 103 | imem_error: FNONE; 104 | 1: imem_ifun; # Default: get from instruction memory 105 | ]; 106 | 107 | bool instr_valid = icode in 108 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 109 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ, IIADDQ }; 110 | 111 | # Does fetched instruction require a regid byte? 112 | bool need_regids = 113 | icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 114 | IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ }; 115 | 116 | # Does fetched instruction require a constant word? 117 | bool need_valC = 118 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL, IIADDQ }; 119 | 120 | ################ Decode Stage ################################### 121 | 122 | ## What register should be used as the A source? 123 | word srcA = [ 124 | icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : rA; 125 | icode in { IPOPQ, IRET } : RRSP; 126 | 1 : RNONE; # Don't need register 127 | ]; 128 | 129 | ## What register should be used as the B source? 130 | word srcB = [ 131 | icode in { IOPQ, IRMMOVQ, IMRMOVQ,IIADDQ } : rB; 132 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 133 | 1 : RNONE; # Don't need register 134 | ]; 135 | 136 | ## What register should be used as the E destination? 137 | word dstE = [ 138 | icode in { IRRMOVQ } && Cnd : rB; 139 | icode in { IIRMOVQ, IOPQ,IIADDQ } : rB; 140 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 141 | 1 : RNONE; # Don't write any register 142 | ]; 143 | 144 | ## What register should be used as the M destination? 145 | word dstM = [ 146 | icode in { IMRMOVQ, IPOPQ } : rA; 147 | 1 : RNONE; # Don't write any register 148 | ]; 149 | 150 | ################ Execute Stage ################################### 151 | 152 | ## Select input A to ALU 153 | word aluA = [ 154 | icode in { IRRMOVQ, IOPQ } : valA; 155 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ } : valC; 156 | icode in { ICALL, IPUSHQ } : -8; 157 | icode in { IRET, IPOPQ } : 8; 158 | # Other instructions don't need ALU 159 | ]; 160 | 161 | ## Select input B to ALU 162 | word aluB = [ 163 | icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 164 | IPUSHQ, IRET, IPOPQ, IIADDQ } : valB; 165 | icode in { IRRMOVQ, IIRMOVQ } : 0; 166 | # Other instructions don't need ALU 167 | ]; 168 | 169 | ## Set the ALU function 170 | word alufun = [ 171 | icode == IOPQ : ifun; 172 | 1 : ALUADD; 173 | ]; 174 | 175 | ## Should the condition codes be updated? 176 | bool set_cc = icode in { IOPQ, IIADDQ }; 177 | 178 | ################ Memory Stage ################################### 179 | 180 | ## Set read control signal 181 | bool mem_read = icode in { IMRMOVQ, IPOPQ, IRET }; 182 | 183 | ## Set write control signal 184 | bool mem_write = icode in { IRMMOVQ, IPUSHQ, ICALL }; 185 | 186 | ## Select memory address 187 | word mem_addr = [ 188 | icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : valE; 189 | icode in { IPOPQ, IRET } : valA; 190 | # Other instructions don't need address 191 | ]; 192 | 193 | ## Select memory input data 194 | word mem_data = [ 195 | # Value from register 196 | icode in { IRMMOVQ, IPUSHQ } : valA; 197 | # Return PC 198 | icode == ICALL : valP; 199 | # Default: Don't write anything 200 | ]; 201 | 202 | ## Determine instruction status 203 | word Stat = [ 204 | imem_error || dmem_error : SADR; 205 | !instr_valid: SINS; 206 | icode == IHALT : SHLT; 207 | 1 : SAOK; 208 | ]; 209 | 210 | ################ Program Counter Update ############################ 211 | 212 | ## What address should instruction be fetched at 213 | 214 | word new_pc = [ 215 | # Call. Use instruction constant 216 | icode == ICALL : valC; 217 | # Taken branch. Use instruction constant 218 | icode == IJXX && Cnd : valC; 219 | # Completion of RET instruction. Use value from stack 220 | icode == IRET : valM; 221 | # Default: Use incremented PC 222 | 1 : valP; 223 | ]; 224 | #/* $end seq-all-hcl */ 225 | -------------------------------------------------------------------------------- /seq/seq-std.hcl: -------------------------------------------------------------------------------- 1 | #/* $begin seq-all-hcl */ 2 | #################################################################### 3 | # HCL Description of Control for Single Cycle Y86-64 Processor SEQ # 4 | # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2010 # 5 | #################################################################### 6 | 7 | #################################################################### 8 | # C Include's. Don't alter these # 9 | #################################################################### 10 | 11 | quote '#include ' 12 | quote '#include "isa.h"' 13 | quote '#include "sim.h"' 14 | quote 'int sim_main(int argc, char *argv[]);' 15 | quote 'word_t gen_pc(){return 0;}' 16 | quote 'int main(int argc, char *argv[])' 17 | quote ' {plusmode=0;return sim_main(argc,argv);}' 18 | 19 | #################################################################### 20 | # Declarations. Do not change/remove/delete any of these # 21 | #################################################################### 22 | 23 | ##### Symbolic representation of Y86-64 Instruction Codes ############# 24 | wordsig INOP 'I_NOP' 25 | wordsig IHALT 'I_HALT' 26 | wordsig IRRMOVQ 'I_RRMOVQ' 27 | wordsig IIRMOVQ 'I_IRMOVQ' 28 | wordsig IRMMOVQ 'I_RMMOVQ' 29 | wordsig IMRMOVQ 'I_MRMOVQ' 30 | wordsig IOPQ 'I_ALU' 31 | wordsig IJXX 'I_JMP' 32 | wordsig ICALL 'I_CALL' 33 | wordsig IRET 'I_RET' 34 | wordsig IPUSHQ 'I_PUSHQ' 35 | wordsig IPOPQ 'I_POPQ' 36 | 37 | ##### Symbolic represenations of Y86-64 function codes ##### 38 | wordsig FNONE 'F_NONE' # Default function code 39 | 40 | ##### Symbolic representation of Y86-64 Registers referenced explicitly ##### 41 | wordsig RRSP 'REG_RSP' # Stack Pointer 42 | wordsig RNONE 'REG_NONE' # Special value indicating "no register" 43 | 44 | ##### ALU Functions referenced explicitly ##### 45 | wordsig ALUADD 'A_ADD' # ALU should add its arguments 46 | 47 | ##### Possible instruction status values ##### 48 | wordsig SAOK 'STAT_AOK' # Normal execution 49 | wordsig SADR 'STAT_ADR' # Invalid memory address 50 | wordsig SINS 'STAT_INS' # Invalid instruction 51 | wordsig SHLT 'STAT_HLT' # Halt instruction encountered 52 | 53 | ##### Signals that can be referenced by control logic #################### 54 | 55 | ##### Fetch stage inputs ##### 56 | wordsig pc 'pc' # Program counter 57 | ##### Fetch stage computations ##### 58 | wordsig imem_icode 'imem_icode' # icode field from instruction memory 59 | wordsig imem_ifun 'imem_ifun' # ifun field from instruction memory 60 | wordsig icode 'icode' # Instruction control code 61 | wordsig ifun 'ifun' # Instruction function 62 | wordsig rA 'ra' # rA field from instruction 63 | wordsig rB 'rb' # rB field from instruction 64 | wordsig valC 'valc' # Constant from instruction 65 | wordsig valP 'valp' # Address of following instruction 66 | boolsig imem_error 'imem_error' # Error signal from instruction memory 67 | boolsig instr_valid 'instr_valid' # Is fetched instruction valid? 68 | 69 | ##### Decode stage computations ##### 70 | wordsig valA 'vala' # Value from register A port 71 | wordsig valB 'valb' # Value from register B port 72 | 73 | ##### Execute stage computations ##### 74 | wordsig valE 'vale' # Value computed by ALU 75 | boolsig Cnd 'cond' # Branch test 76 | 77 | ##### Memory stage computations ##### 78 | wordsig valM 'valm' # Value read from memory 79 | boolsig dmem_error 'dmem_error' # Error signal from data memory 80 | 81 | 82 | #################################################################### 83 | # Control Signal Definitions. # 84 | #################################################################### 85 | 86 | ################ Fetch Stage ################################### 87 | 88 | # Determine instruction code 89 | word icode = [ 90 | imem_error: INOP; 91 | 1: imem_icode; # Default: get from instruction memory 92 | ]; 93 | 94 | # Determine instruction function 95 | word ifun = [ 96 | imem_error: FNONE; 97 | 1: imem_ifun; # Default: get from instruction memory 98 | ]; 99 | 100 | bool instr_valid = icode in 101 | { INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ, 102 | IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ }; 103 | 104 | # Does fetched instruction require a regid byte? 105 | bool need_regids = 106 | icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, 107 | IIRMOVQ, IRMMOVQ, IMRMOVQ }; 108 | 109 | # Does fetched instruction require a constant word? 110 | bool need_valC = 111 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL }; 112 | 113 | ################ Decode Stage ################################### 114 | 115 | ## What register should be used as the A source? 116 | word srcA = [ 117 | icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : rA; 118 | icode in { IPOPQ, IRET } : RRSP; 119 | 1 : RNONE; # Don't need register 120 | ]; 121 | 122 | ## What register should be used as the B source? 123 | word srcB = [ 124 | icode in { IOPQ, IRMMOVQ, IMRMOVQ } : rB; 125 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 126 | 1 : RNONE; # Don't need register 127 | ]; 128 | 129 | ## What register should be used as the E destination? 130 | word dstE = [ 131 | icode in { IRRMOVQ } && Cnd : rB; 132 | icode in { IIRMOVQ, IOPQ} : rB; 133 | icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP; 134 | 1 : RNONE; # Don't write any register 135 | ]; 136 | 137 | ## What register should be used as the M destination? 138 | word dstM = [ 139 | icode in { IMRMOVQ, IPOPQ } : rA; 140 | 1 : RNONE; # Don't write any register 141 | ]; 142 | 143 | ################ Execute Stage ################################### 144 | 145 | ## Select input A to ALU 146 | word aluA = [ 147 | icode in { IRRMOVQ, IOPQ } : valA; 148 | icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : valC; 149 | icode in { ICALL, IPUSHQ } : -8; 150 | icode in { IRET, IPOPQ } : 8; 151 | # Other instructions don't need ALU 152 | ]; 153 | 154 | ## Select input B to ALU 155 | word aluB = [ 156 | icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, 157 | IPUSHQ, IRET, IPOPQ } : valB; 158 | icode in { IRRMOVQ, IIRMOVQ } : 0; 159 | # Other instructions don't need ALU 160 | ]; 161 | 162 | ## Set the ALU function 163 | word alufun = [ 164 | icode == IOPQ : ifun; 165 | 1 : ALUADD; 166 | ]; 167 | 168 | ## Should the condition codes be updated? 169 | bool set_cc = icode in { IOPQ }; 170 | 171 | ################ Memory Stage ################################### 172 | 173 | ## Set read control signal 174 | bool mem_read = icode in { IMRMOVQ, IPOPQ, IRET }; 175 | 176 | ## Set write control signal 177 | bool mem_write = icode in { IRMMOVQ, IPUSHQ, ICALL }; 178 | 179 | ## Select memory address 180 | word mem_addr = [ 181 | icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : valE; 182 | icode in { IPOPQ, IRET } : valA; 183 | # Other instructions don't need address 184 | ]; 185 | 186 | ## Select memory input data 187 | word mem_data = [ 188 | # Value from register 189 | icode in { IRMMOVQ, IPUSHQ } : valA; 190 | # Return PC 191 | icode == ICALL : valP; 192 | # Default: Don't write anything 193 | ]; 194 | 195 | ## Determine instruction status 196 | word Stat = [ 197 | imem_error || dmem_error : SADR; 198 | !instr_valid: SINS; 199 | icode == IHALT : SHLT; 200 | 1 : SAOK; 201 | ]; 202 | 203 | ################ Program Counter Update ############################ 204 | 205 | ## What address should instruction be fetched at 206 | 207 | word new_pc = [ 208 | # Call. Use instruction constant 209 | icode == ICALL : valC; 210 | # Taken branch. Use instruction constant 211 | icode == IJXX && Cnd : valC; 212 | # Completion of RET instruction. Use value from stack 213 | icode == IRET : valM; 214 | # Default: Use incremented PC 215 | 1 : valP; 216 | ]; 217 | #/* $end seq-all-hcl */ 218 | -------------------------------------------------------------------------------- /seq/sim.h: -------------------------------------------------------------------------------- 1 | 2 | /********** Defines **************/ 3 | 4 | /* Get ra out of one byte regid field */ 5 | #define GET_RA(r) HI4(r) 6 | 7 | /* Get rb out of one byte regid field */ 8 | #define GET_RB(r) LO4(r) 9 | 10 | 11 | /************ Global state declaration ****************/ 12 | 13 | /* Determines whether running SEQ or SEQ+ */ 14 | extern int plusmode; 15 | 16 | /* Both instruction and data memory */ 17 | extern mem_t mem; 18 | 19 | /* Keep track of range of addresses that have been written */ 20 | extern word_t minAddr; 21 | extern word_t memCnt; 22 | 23 | /* Register file */ 24 | extern mem_t reg; 25 | /* Condition code register */ 26 | extern cc_t cc; 27 | /* Program counter */ 28 | extern word_t pc; 29 | 30 | /* For seq+ */ 31 | /* Results computed by previous instruction. 32 | Used to compute PC in current instruction */ 33 | extern byte_t prev_icode; 34 | extern byte_t prev_ifun; 35 | extern word_t prev_valc; 36 | extern word_t prev_valm; 37 | extern word_t prev_valp; 38 | extern bool_t prev_bcond; 39 | 40 | /* Intermdiate stage values that must be used by control functions */ 41 | extern byte_t imem_icode; 42 | extern byte_t imem_ifun; 43 | extern byte_t icode; 44 | extern word_t ifun; 45 | extern word_t ra; 46 | extern word_t rb; 47 | extern word_t valc; 48 | extern word_t valp; 49 | extern bool_t imem_error; 50 | extern bool_t instr_valid; 51 | extern word_t vala; 52 | extern word_t valb; 53 | extern word_t vale; 54 | extern bool_t bcond; 55 | extern bool_t cond; 56 | extern word_t valm; 57 | extern bool_t dmem_error; 58 | extern byte_t status; 59 | 60 | /* Log file */ 61 | extern FILE *dumpfile; 62 | 63 | 64 | /* Sets the simulator name (called from main routine in HCL file) */ 65 | void set_simname(char *name); 66 | 67 | /* Initialize simulator */ 68 | void sim_init(); 69 | 70 | /* Reset simulator state, including register, instruction, and data memories */ 71 | void sim_reset(); 72 | 73 | /* 74 | Run processor until one of following occurs: 75 | - An status error is encountered 76 | - max_instr instructions have completed 77 | 78 | Return number of instructions executed. 79 | if statusp nonnull, then will be set to status of final instruction 80 | if ccp nonnull, then will be set to condition codes of final instruction 81 | */ 82 | word_t sim_run(word_t max_instr, byte_t *statusp, cc_t *ccp); 83 | 84 | /* If dumpfile set nonNULL, lots of status info printed out */ 85 | void sim_set_dumpfile(FILE *file); 86 | 87 | /* 88 | * sim_log dumps a formatted string to the dumpfile, if it exists 89 | * accepts variable argument list 90 | */ 91 | void sim_log( const char *format, ... ); 92 | 93 | 94 | /******************* GUI Interface Functions **********************/ 95 | #ifdef HAS_GUI 96 | 97 | void signal_register_clear(); 98 | 99 | void report_pc(word_t pc); 100 | 101 | void report_state(char *id, char *txt); 102 | 103 | void show_cc(cc_t cc); 104 | 105 | void create_memory_display(); 106 | void set_memory(word_t addr, word_t val); 107 | #endif 108 | 109 | -------------------------------------------------------------------------------- /y86-code/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -O2 3 | 4 | ISADIR = ../misc 5 | YAS=$(ISADIR)/yas 6 | YIS=$(ISADIR)/yis 7 | PIPE=../pipe/psim 8 | SEQ=../seq/ssim 9 | SEQ+ =../seq/ssim+ 10 | 11 | YOFILES = abs-asum-cmov.yo abs-asum-jmp.yo asum.yo asumr.yo asumi.yo cjr.yo j-cc.yo poptest.yo pushquestion.yo pushtest.yo prog1.yo prog2.yo prog3.yo prog4.yo prog5.yo prog6.yo prog7.yo prog8.yo prog9.yo prog10.yo ret-hazard.yo 12 | 13 | PIPEFILES = asum.pipe asumr.pipe cjr.pipe j-cc.pipe poptest.pipe pushquestion.pipe pushtest.pipe prog1.pipe prog2.pipe prog3.pipe prog4.pipe prog5.pipe prog6.pipe prog7.pipe prog8.pipe ret-hazard.pipe 14 | 15 | SEQFILES = asum.seq asumr.seq cjr.seq j-cc.seq poptest.seq pushquestion.seq pushtest.seq prog1.seq prog2.seq prog3.seq prog4.seq prog5.seq prog6.seq prog7.seq prog8.seq ret-hazard.seq 16 | 17 | SEQ+FILES = asum.seq+ asumr.seq+ cjr.seq+ j-cc.seq+ poptest.seq+ pushquestion.seq+ pushtest.seq+ prog1.seq+ prog2.seq+ prog3.seq+ prog4.seq+ prog5.seq+ prog6.seq+ prog7.seq+ prog8.seq+ ret-hazard.seq+ 18 | 19 | .SUFFIXES: 20 | .SUFFIXES: .c .s .o .ys .yo .yis .pipe .seq .seq+ 21 | 22 | all: $(YOFILES) 23 | 24 | test: testpsim testssim testssim+ 25 | 26 | testpsim: $(PIPEFILES) 27 | grep "ISA Check" *.pipe 28 | rm $(PIPEFILES) 29 | 30 | testssim: $(SEQFILES) 31 | grep "ISA Check" *.seq 32 | rm $(SEQFILES) 33 | 34 | testssim+: $(SEQ+FILES) 35 | grep "ISA Check" *.seq+ 36 | rm $(SEQ+FILES) 37 | 38 | .ys.yo: 39 | $(YAS) $*.ys 40 | 41 | .yo.yis: $(YIS) 42 | $(YIS) $*.yo > $*.yis 43 | 44 | .yo.pipe: $(PIPE) 45 | $(PIPE) -t $*.yo > $*.pipe 46 | 47 | .yo.seq: $(SEQ) 48 | $(SEQ) -t $*.yo > $*.seq 49 | 50 | .yo.seq+: $(SEQ+) 51 | $(SEQ+) -t $*.yo > $*.seq+ 52 | 53 | clean: 54 | rm -f *.o *.yis *~ *.yo *.pipe *.seq *.seq+ core 55 | -------------------------------------------------------------------------------- /y86-code/README: -------------------------------------------------------------------------------- 1 | This directory contains examples of Y86-64 assembly code programs 2 | (extension `.ys') used in Chapter 4 of CS:APP3e. 3 | 4 | Given an assembly code file "file.ys", you can assemble it with the 5 | command "make file.yo". The resulting file is in the "object code" 6 | format described in the book. 7 | 8 | You can assemble and simulate all the test programs in this directory. 9 | First, you need to make the different simulators in the pipe (psim) 10 | and seq (ssim and ssim+) directories. Then use the following 11 | commands: 12 | 13 | PIPE: make testpsim 14 | SEQ: make testssim 15 | SEQ+: make testssim+ 16 | 17 | Each of these commands will cause a number of programs to be assembled 18 | and simulated. Lots of things will scroll by, but you should see the message 19 | "ISA Check Succeeds" for each of the programs tested. 20 | 21 | -------------------------------------------------------------------------------- /y86-code/abs-asum-cmov.ys: -------------------------------------------------------------------------------- 1 | # Modification of asum code to compute absolute values of entries. 2 | # This version uses a conditional move 3 | # Execution begins at address 0 4 | .pos 0 5 | irmovq stack, %rsp # Set up stack pointer 6 | call main # Execute main program 7 | halt # Terminate program 8 | 9 | # Array of 4 elements 10 | .align 8 11 | array: .quad 0x0000000d000d000d 12 | .quad 0xffffff3fff3fff40 # -0x000000c000c000c0 13 | .quad 0x00000b000b000b00 14 | .quad 0xffff5fff5fff6000 # -0x0000a000a000a000 15 | 16 | main: 17 | irmovq array,%rdi 18 | irmovq $4,%rsi 19 | call absSum # absSum(array, 4) 20 | ret 21 | 22 | # long absSum(long *start, long count) 23 | # start in %rdi, count in %rsi 24 | absSum: 25 | irmovq $8,%r8 # Constant 8 26 | irmovq $1,%r9 # Constant 1 27 | xorq %rax,%rax # sum = 0 28 | andq %rsi,%rsi # Set condition codes 29 | jmp test 30 | /* $begin abs-sum-cmov-ys */ 31 | loop: 32 | mrmovq (%rdi),%r10 # x = *start 33 | xorq %r11,%r11 # Constant 0 34 | subq %r10,%r11 # -x 35 | cmovg %r11,%r10 # If -x > 0 then x = -x 36 | addq %r10,%rax # Add to sum 37 | addq %r8,%rdi # start++ 38 | subq %r9,%rsi # count-- 39 | test: 40 | jne loop # Stop when 0 41 | /* $end abs-sum-cmov-ys */ 42 | ret 43 | 44 | # The stack starts here and grows to lower addresses 45 | .pos 0x200 46 | stack: 47 | -------------------------------------------------------------------------------- /y86-code/abs-asum-jmp.ys: -------------------------------------------------------------------------------- 1 | # Modification of asum code to compute absolute values of entries. 2 | # This version uses a conditional jump 3 | # Execution begins at address 0 4 | .pos 0 5 | irmovq stack, %rsp # Set up stack pointer 6 | call main # Execute main program 7 | halt # Terminate program 8 | 9 | # Array of 4 elements 10 | .align 8 11 | array: .quad 0x0000000d000d000d 12 | .quad 0xffffff3fff3fff40 # -0x000000c000c000c0 13 | .quad 0x00000b000b000b00 14 | .quad 0xffff5fff5fff6000 # -0x0000a000a000a000 15 | 16 | main: irmovq array,%rdi 17 | irmovq $4,%rsi 18 | call absSum # absSum(array, 4) 19 | ret 20 | /* $begin abs-sum-jmp-ys */ 21 | # long absSum(long *start, long count) 22 | # start in %rdi, count in %rsi 23 | absSum: 24 | irmovq $8,%r8 # Constant 8 25 | irmovq $1,%r9 # Constant 1 26 | xorq %rax,%rax # sum = 0 27 | andq %rsi,%rsi # Set condition codes 28 | jmp test 29 | loop: 30 | mrmovq (%rdi),%r10 # x = *start 31 | xorq %r11,%r11 # Constant 0 32 | subq %r10,%r11 # -x 33 | jle pos # Skip if -x <= 0 34 | rrmovq %r11,%r10 # x = -x 35 | pos: 36 | addq %r10,%rax # Add to sum 37 | addq %r8,%rdi # start++ 38 | subq %r9,%rsi # count-- 39 | test: 40 | jne loop # Stop when 0 41 | ret 42 | /* $end abs-sum-jmp-ys */ 43 | 44 | # The stack starts here and grows to lower addresses 45 | .pos 0x200 46 | stack: 47 | -------------------------------------------------------------------------------- /y86-code/asum.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp # Set up stack pointer 4 | call main # Execute main program 5 | halt # Terminate program 6 | 7 | # Array of 4 elements 8 | .align 8 9 | array: .quad 0x000d000d000d 10 | .quad 0x00c000c000c0 11 | .quad 0x0b000b000b00 12 | .quad 0xa000a000a000 13 | 14 | main: irmovq array,%rdi 15 | irmovq $4,%rsi 16 | call sum # sum(array, 4) 17 | ret 18 | 19 | # long sum(long *start, long count) 20 | # start in %rdi, count in %rsi 21 | sum: irmovq $8,%r8 # Constant 8 22 | irmovq $1,%r9 # Constant 1 23 | xorq %rax,%rax # sum = 0 24 | andq %rsi,%rsi # Set CC 25 | jmp test # Goto test 26 | loop: mrmovq (%rdi),%r10 # Get *start 27 | addq %r10,%rax # Add to sum 28 | addq %r8,%rdi # start++ 29 | subq %r9,%rsi # count--. Set CC 30 | test: jne loop # Stop when 0 31 | ret # Return 32 | 33 | # Stack starts here and grows to lower addresses 34 | .pos 0x200 35 | stack: 36 | -------------------------------------------------------------------------------- /y86-code/asumi.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp # Set up stack pointer 4 | call main # Execute main program 5 | halt # Terminate program 6 | 7 | # Array of 4 elements 8 | .align 8 9 | array: .quad 0x000d000d000d 10 | .quad 0x00c000c000c0 11 | .quad 0x0b000b000b00 12 | .quad 0xa000a000a000 13 | 14 | main: irmovq array,%rdi 15 | irmovq $4,%rsi 16 | call sum # sum(array, 4) 17 | ret 18 | 19 | /* $begin sumi-ys */ 20 | # long sum(long *start, long count) 21 | # start in %rdi, count in %rsi 22 | sum: 23 | xorq %rax,%rax # sum = 0 24 | andq %rsi,%rsi # Set condition codes 25 | jmp test 26 | loop: 27 | mrmovq (%rdi),%r10 # Get *start 28 | addq %r10,%rax # Add to sum 29 | iaddq $8,%rdi # start++ 30 | iaddq $-1,%rsi # count-- 31 | test: 32 | jne loop # Stop when 0 33 | ret 34 | /* $end sumi-ys */ 35 | 36 | # The stack starts here and grows to lower addresses 37 | .pos 0x100 38 | stack: 39 | -------------------------------------------------------------------------------- /y86-code/asumr.ys: -------------------------------------------------------------------------------- 1 | # Execution begins at address 0 2 | .pos 0 3 | irmovq stack, %rsp # Set up stack pointer 4 | call main # Execute main program 5 | halt # Terminate program 6 | 7 | # Array of 4 elements 8 | .align 8 9 | array: .quad 0x000d000d000d 10 | .quad 0x00c000c000c0 11 | .quad 0x0b000b000b00 12 | .quad 0xa000a000a000 13 | 14 | main: irmovq array,%rdi 15 | irmovq $4,%rsi 16 | call rsum # rsum(array, 4) 17 | ret 18 | 19 | /* $begin rsum-ys */ 20 | # long rsum(long *start, long count) 21 | # start in %rdi, count in %rsi 22 | rsum: 23 | xorq %rax,%rax # Set return value to 0 24 | andq %rsi,%rsi # Set condition codes 25 | jle return # If count <= 0, return 0 26 | pushq %rbx # Save callee-saved register 27 | mrmovq (%rdi),%rbx # Get *start 28 | irmovq $-1,%r10 29 | addq %r10,%rsi # count-- 30 | irmovq $8,%r10 31 | addq %r10,%rdi # start++ 32 | call rsum 33 | addq %rbx,%rax # Add *start to sum 34 | popq %rbx # Restore callee-saved register 35 | return: 36 | ret 37 | /* $end rsum-ys */ 38 | 39 | # The stack starts here and grows to lower addresses 40 | .pos 0x200 41 | stack: 42 | 43 | -------------------------------------------------------------------------------- /y86-code/cjr.ys: -------------------------------------------------------------------------------- 1 | # /* $begin cjr-ys */ 2 | # Code to generate a combination of not-taken branch and ret 3 | irmovq Stack, %rsp 4 | irmovq rtnp,%rax 5 | pushq %rax # Set up return pointer 6 | xorq %rax,%rax # Set Z condition code 7 | jne target # Not taken (First part of combination) 8 | irmovq $1,%rax # Should execute this 9 | halt 10 | target: ret # Second part of combination 11 | irmovq $2,%rbx # Should not execute this 12 | halt 13 | rtnp: irmovq $3,%rdx # Should not execute this 14 | halt 15 | .pos 0x40 16 | Stack: 17 | # /* $end cjr-ys */ 18 | -------------------------------------------------------------------------------- /y86-code/j-cc.ys: -------------------------------------------------------------------------------- 1 | irmovq $1, %rsi 2 | irmovq $2, %rdi 3 | irmovq $4, %rbp 4 | irmovq $-32, %rax 5 | irmovq $64, %rdx 6 | subq %rdx,%rax 7 | je target 8 | nop 9 | halt 10 | target: 11 | addq %rsi,%rdx 12 | nop 13 | nop 14 | nop 15 | halt 16 | -------------------------------------------------------------------------------- /y86-code/poptest.ys: -------------------------------------------------------------------------------- 1 | # Test of Pop semantics for Y86-64 2 | irmovq $0x100,%rsp # Initialize stack pointer 3 | irmovq $0xABCD,%rax 4 | pushq %rax # Put known value on stack 5 | popq %rsp # Either get 0xABCD, or 0xfc 6 | halt 7 | -------------------------------------------------------------------------------- /y86-code/prog1.ys: -------------------------------------------------------------------------------- 1 | # prog1: Pad with 3 nop's 2 | irmovq $10,%rdx 3 | irmovq $3,%rax 4 | nop 5 | nop 6 | nop 7 | addq %rdx,%rax 8 | halt 9 | -------------------------------------------------------------------------------- /y86-code/prog10.ys: -------------------------------------------------------------------------------- 1 | # prog10 2 | irmovq $1,%rax 3 | xorq %rsp,%rsp # Set stack pointer to 0 and CC to 100 4 | pushq %rax # Attempt to write to 0xfffffffffffffff8 5 | addq %rax,%rax # (Should not be executed) Would set CC to 000 6 | irmovq $2, %rax # Not executed 7 | irmovq $3, %rax # Not executed 8 | -------------------------------------------------------------------------------- /y86-code/prog2.ys: -------------------------------------------------------------------------------- 1 | # prog2: Pad with 2 nop's 2 | irmovq $10,%rdx 3 | irmovq $3,%rax 4 | nop 5 | nop 6 | addq %rdx,%rax 7 | halt 8 | -------------------------------------------------------------------------------- /y86-code/prog3.ys: -------------------------------------------------------------------------------- 1 | # prog3: Pad with 1 nop 2 | irmovq $10,%rdx 3 | irmovq $3,%rax 4 | nop 5 | addq %rdx,%rax 6 | halt 7 | -------------------------------------------------------------------------------- /y86-code/prog4.ys: -------------------------------------------------------------------------------- 1 | # prog4: No padding 2 | irmovq $10,%rdx 3 | irmovq $3,%rax 4 | addq %rdx,%rax 5 | halt 6 | -------------------------------------------------------------------------------- /y86-code/prog5.ys: -------------------------------------------------------------------------------- 1 | # prog5: Load/use hazard 2 | irmovq $128,%rdx 3 | irmovq $3,%rcx 4 | rmmovq %rcx, 0(%rdx) 5 | irmovq $10,%rbx 6 | mrmovq 0(%rdx), %rax # Load %rax 7 | addq %rbx,%rax # Use %rax 8 | halt 9 | -------------------------------------------------------------------------------- /y86-code/prog6.ys: -------------------------------------------------------------------------------- 1 | # Demonstration of return 2 | # /* $begin prog6-ys */ 3 | # prog6 4 | irmovq stack,%rsp # Initialize stack pointer 5 | call proc # Procedure call 6 | irmovq $10,%rdx # Return point 7 | halt 8 | .pos 0x20 9 | proc: # proc: 10 | ret # Return immediately 11 | rrmovq %rdx,%rbx # Not executed 12 | .pos 0x30 13 | stack: # stack: Stack pointer 14 | # /* $end prog6-ys */ 15 | -------------------------------------------------------------------------------- /y86-code/prog7.ys: -------------------------------------------------------------------------------- 1 | # Demonstrate branch cancellation 2 | # /* $begin prog7-ys */ 3 | # prog7 4 | xorq %rax,%rax 5 | jne target # Not taken 6 | irmovq $1, %rax # Fall through 7 | halt 8 | target: 9 | irmovq $2, %rdx # Target 10 | irmovq $3, %rbx # Target+1 11 | # /* $end prog7-ys */ 12 | halt 13 | 14 | -------------------------------------------------------------------------------- /y86-code/prog8.ys: -------------------------------------------------------------------------------- 1 | # prog8: Forwarding Priority 2 | irmovq $10,%rdx 3 | irmovq $3,%rdx 4 | rrmovq %rdx,%rax 5 | halt 6 | -------------------------------------------------------------------------------- /y86-code/prog9.ys: -------------------------------------------------------------------------------- 1 | # Exception handling 2 | # /* $begin prog9-yo */ 3 | xorq %rax,%rax 4 | jne target # Not taken 5 | irmovq $1, %rax # Fall through 6 | halt 7 | target: 8 | .byte 0xFF # Invalid instruction code 9 | # /* $end prog9-yo */ 10 | -------------------------------------------------------------------------------- /y86-code/pushquestion.ys: -------------------------------------------------------------------------------- 1 | # Assembly Code to test semantics of pushq 2 | irmovq 0x100, %rsp 3 | pushq %rsp # Ambiguous 4 | popq %rax 5 | halt 6 | -------------------------------------------------------------------------------- /y86-code/pushtest.ys: -------------------------------------------------------------------------------- 1 | # Test of Push semantics for Y86-64 2 | irmovq $0x100,%rsp # Initialize stack pointer 3 | rrmovq %rsp,%rax # Save stack pointer 4 | pushq %rsp # Push the stack pointer (old or new?) 5 | popq %rdx # Get it back 6 | subq %rdx,%rax # Compute difference. Either 0 (old) or 4 (new). 7 | halt 8 | -------------------------------------------------------------------------------- /y86-code/ret-hazard.ys: -------------------------------------------------------------------------------- 1 | /* $begin ret-hazard-ys */ 2 | # Test instruction that modifies %esp followed by ret 3 | irmovq mem,%rbx 4 | mrmovq 0(%rbx),%rsp # Sets %rsp to point to return point 5 | ret # Returns to return point 6 | halt # 7 | rtnpt: irmovq $5,%rsi # Return point 8 | halt 9 | .pos 0x40 10 | mem: .quad stack # Holds desired stack pointer 11 | .pos 0x50 12 | stack: .quad rtnpt # Top of stack: Holds return point 13 | /* $end ret-hazard-ys */ 14 | --------------------------------------------------------------------------------