From 015bc11b40cb68997ea42ea61303d0d1a87efa5c Mon Sep 17 00:00:00 2001 From: cag-uconn Date: Mon, 22 Nov 2021 14:12:03 -0500 Subject: [PATCH] . --- pa4/Makefile | 17 +++ pa4/README.md | 24 +++ pa4/src/instruction_map.c | 40 +++++ pa4/src/instruction_map.h | 43 ++++++ pa4/src/register_map.c | 49 ++++++ pa4/src/register_map.h | 16 ++ pa4/src/sim_core.c | 257 ++++++++++++++++++++++++++++++++ pa4/src/sim_core.h | 136 +++++++++++++++++ pa4/src/sim_stages.c | 70 +++++++++ pa4/src/sim_stages.h | 25 ++++ pa4/src/util.c | 305 ++++++++++++++++++++++++++++++++++++++ pa4/src/util.h | 24 +++ 12 files changed, 1006 insertions(+) create mode 100644 pa4/Makefile create mode 100644 pa4/README.md create mode 100644 pa4/src/instruction_map.c create mode 100644 pa4/src/instruction_map.h create mode 100644 pa4/src/register_map.c create mode 100644 pa4/src/register_map.h create mode 100644 pa4/src/sim_core.c create mode 100644 pa4/src/sim_core.h create mode 100644 pa4/src/sim_stages.c create mode 100644 pa4/src/sim_stages.h create mode 100644 pa4/src/util.c create mode 100644 pa4/src/util.h diff --git a/pa4/Makefile b/pa4/Makefile new file mode 100644 index 0000000..b17f6b5 --- /dev/null +++ b/pa4/Makefile @@ -0,0 +1,17 @@ +SRCS = $(wildcard src/*.c) +HEADERS = $(wildcard src/*.h) +CC = gcc +CFLAGS = -g -std=c99 +LDFLAGS = -lm + +default: simulator + +simulator: $(SRCS) $(HEADERS) + @echo "Building $@..." + @echo "Sources: $(SRCS)" + @echo "Headers: $(HEADERS)" + $(CC) $(CFLAGS) -o $@ $(SRCS) $(LDFLAGS) + +clean: + -rm -f simulator + -rm -f pipe_trace.txt *.out mdump.txt cdump.txt diff --git a/pa4/README.md b/pa4/README.md new file mode 100644 index 0000000..e7fdfca --- /dev/null +++ b/pa4/README.md @@ -0,0 +1,24 @@ +# Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard Algorithm +A pipelined CPU simulator for the MIPS-like riscy-uconn instruction set architecture implementing a +scoreboard algorithm. The simulator translates machine code created by the riscy-uconn assembler, and executes +instructions one at a time. + +## Build Instructions + $ make + +## Usage + $ ./simulator assembled_program_file.out + +where `assembled_program_file.out` may be any assembled program file generated by the riscy-uconn +assembler. + +## Unit Tests +Several unit tests are provided in the `unittests` directory. These unit tests must be assembled +before use with the simulator by executing the following command: + + $ ../assembler/assembler unittests/unit_test_file.asm unittests/unit_test_file.out + +where `unit_test_file` is any of the unit test files (written in riscy-uconn assembly) in the +`unittests` directory. + + diff --git a/pa4/src/instruction_map.c b/pa4/src/instruction_map.c new file mode 100644 index 0000000..b2f97d7 --- /dev/null +++ b/pa4/src/instruction_map.c @@ -0,0 +1,40 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: instruction_map.c + * + * DO NOT MODIFY THIS FILE + * + */ + +#include "instruction_map.h" + +char* opcode_map[] = { + [RTYPEOP] = "RTYPEOP", + [LW] = "lw", + [SW] = "sw", + [ANDI] = "andi", + [ADDI] = "addi", + [ORI] = "ori", + [SLTI] = "slti", + [LUI] = "lui", + [BEQ] = "beq", + [BNE] = "bne", + [J] = "j", + [JAL] = "jal" +}; + +char* func_map[] = { + [ADD] = "add", + [SUB] = "sub", + [AND] = "and", + [OR] = "or", + [SLL] = "sll", + [SRL] = "srl", + [SLT] = "slt", + [JR] = "jr" +}; \ No newline at end of file diff --git a/pa4/src/instruction_map.h b/pa4/src/instruction_map.h new file mode 100644 index 0000000..ba0e6c7 --- /dev/null +++ b/pa4/src/instruction_map.h @@ -0,0 +1,43 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: instruction_map.h + * + * DO NOT MODIFY THIS FILE + * + */ + +#pragma once + +extern char* opcode_map[]; +extern char* func_map[]; + +/* R-Type Instructions */ +#define RTYPEOP 0x0 +#define ADD 0x20 +#define SUB 0x21 +#define AND 0x24 +#define OR 0x25 +#define SLL 0x0 +#define SLT 0x2A +#define SRL 0x2 +#define JR 0x8 + +/* I-Type Instructions */ +#define LW 0x23 +#define SW 0x2B +#define ANDI 0xC +#define ORI 0xD +#define LUI 0xF +#define BEQ 0x4 +#define BNE 0x5 +#define SLTI 0xA +#define ADDI 0x8 + +/* J-Type Instructions */ +#define J 0x2 +#define JAL 0x3 \ No newline at end of file diff --git a/pa4/src/register_map.c b/pa4/src/register_map.c new file mode 100644 index 0000000..75cca0b --- /dev/null +++ b/pa4/src/register_map.c @@ -0,0 +1,49 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: register_map.c + * + * DO NOT MODIFY THIS FILE + * + */ + +#include "register_map.h" + +const char* register_map[] = { + [0] = "zero", + [1] = "at", + [2] = "v0", + [3] = "v1", + [4] = "a0", + [5] = "a1", + [6] = "a2", + [7] = "a3", + [8] = "t0", + [9] = "t1", + [10] = "t2", + [11] = "t3", + [12] = "t4", + [13] = "t5", + [14] = "t6", + [15] = "t7", + [16] = "s0", + [17] = "s1", + [18] = "s2", + [19] = "s3", + [20] = "s4", + [21] = "s5", + [22] = "s6", + [23] = "s7", + [24] = "t8", + [25] = "t9", + [26] = "k0", + [27] = "k1", + [28] = "gp", + [29] = "sp", + [30] = "fp", + [31] = "ra", +}; \ No newline at end of file diff --git a/pa4/src/register_map.h b/pa4/src/register_map.h new file mode 100644 index 0000000..617fd52 --- /dev/null +++ b/pa4/src/register_map.h @@ -0,0 +1,16 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: register_map.h + * + * DO NOT MODIFY THIS FILE + * + */ + +#pragma once + +extern const char* register_map[]; \ No newline at end of file diff --git a/pa4/src/sim_core.c b/pa4/src/sim_core.c new file mode 100644 index 0000000..f7dcc0a --- /dev/null +++ b/pa4/src/sim_core.c @@ -0,0 +1,257 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: sim_core.c + * + * DO NOT MODIFY THIS FILE + * + */ + +#include +#include +#include + +#include "instruction_map.h" +#include "register_map.h" +#include "sim_core.h" +#include "sim_stages.h" +#include "util.h" + +/** + * Initial CPU state + */ +int cycle = 0; // CPU cycle +int registers[MAX_LENGTH] = {0}; // Registers +unsigned int pc = 0; // Program Counter (PC) register +int committed_instructions = 0; // Committed instructions +int *memory = NULL; // Data & instruction memory + +/* Pipeline related initialization */ +int br_taken = 0; + +/* Scoreboard related initialization */ +int register_result[MAX_LENGTH] = { [0 ... (MAX_LENGTH - 1)] = -1 }; // Scoreboard register results +int br_taken_instruction_number = 0; + +/* Instruction latencies */ +const int LATENCY_MEMORY = 3; +const int LATENCY_BRANCH = 1; +const int LATENCY_OTHER = 5; + +/** + * Utility + */ +FILE *fptr_pt; + +/** + * Simulator entry point + */ +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "[ERROR] incorrect number of arguments.\n"); + printf("usage: simulator PROGRAM_FILE\n"); + exit(1); + } else { + /* Open input program file */ + FILE *fp; + fp = fopen(argv[1], "r"); + + /* Open pipe trace */ + if (pipe_trace) { + fptr_pt = fopen("pipe_trace.txt", "w"); + } + + /* Initialize registers and instruction/data memory */ + initialize(fp); + + puts("\n"); + printf("Simulating...\n"); + + /* Process instructions one at a time */ + process_instructions(); + + puts(""); + + /* Output state after termination */ + rdump(); // Register dump + mdump(); // Memory dump + + /* Cleanup */ + free(memory); + free(scoreboard); + fclose(fp); + if (pipe_trace) { + fclose(fptr_pt); + } + + return 0; + } +} + +void process_instructions() { + int terminate = 0; + int instruction_counter = 0; //committed instruction count + + while (terminate != 1) { + /* Print information at cycle start */ + if (pipe_trace == 1) { + fprintf(fptr_pt, "Cycle: %d (Start)\n", cycle); + fprintf(fptr_pt, "PC: %d\n", pc); + fprintf(fptr_pt, "Committed Instructions: %d\n", committed_instructions); + fprintf(fptr_pt, "\n"); + + print_scoreboard(); + + fprintf(fptr_pt, "\n"); + rdump_pt(); + fprintf(fptr_pt, "\n"); + fprintf(fptr_pt, "=================================================================================================================================\n"); + fprintf(fptr_pt, "\n"); + + fflush(fptr_pt); + } + + /* Update state */ + write_result(); + execute(); + read_operands(); + issue(); + + /* Print information at cycle end */ + if (pipe_trace == 1) { + fprintf(fptr_pt, "Cycle: %d (End)\n", cycle); + fprintf(fptr_pt, "PC: %d\n", pc); + fprintf(fptr_pt, "Committed Instructions: %d\n", committed_instructions); + fprintf(fptr_pt, "\n"); + + print_scoreboard(); + + fprintf(fptr_pt, "\n"); + rdump_pt(); + fprintf(fptr_pt, "\n"); + fprintf(fptr_pt, "=================================================================================================================================\n"); + fprintf(fptr_pt, "\n"); + + fflush(fptr_pt); + } + + if (registers[0] != 0) { + terminate = 1; // set terminate flag when $zero is updated + } + + cycle++; // Increment cycle count + + /* Potential infinite loop detected */ + if (cycle == 10000) { + fprintf(stderr, "\n[WARNING] Simulation has simulated 10,000 cycles without terminating. Something might be wrong. Press CTRL + C to force termination.\n"); + } + } + printf("\nFinished simulation!\n"); + printf("\nTOTAL INSTRUCTIONS COMMITTED: %d\n", committed_instructions); + printf("TOTAL CYCLES SIMULATED: %d\n", cycle); +} + +void initialize(FILE *fp) { + printf("======================================\n"); + printf("=== BEGIN SIMULATOR INITIALIZATION ===\n"); + printf("======================================\n"); + if (fp == NULL) { + fprintf(stderr, "[ERROR] opening input file. Aborting.\n"); + exit(1); + } + + /* Zero initialize registers */ + memset(registers, 0, sizeof(registers)); + printf("Initialized Registers\n"); + + /* Allocate and zero-initialize scoreboard */ + scoreboard = (struct ScoreboardEntry*) calloc(SCOREBOARD_ENTRIES, sizeof(struct ScoreboardEntry)); + if (scoreboard == NULL) { + fprintf(stderr, "[ERROR] not enough memory. Aborting.\n"); + exit(1); + } + printf("Initialized Scoreboard\n"); + + /* Allocate instruction and data memory */ + memory = (int*) malloc(16384 * sizeof(int)); + if (memory == NULL) { + fprintf(stderr, "[ERROR] not enough memory. Aborting.\n"); + exit(1); + } + + /* Initialize memory to -1 */ + for (int i = 0; i < 16384; i++) { + memory[i] = -1; + } + printf("Initialized Memory\n"); + puts(""); + + printf("----------------------\n"); + printf("--- Section: .text ---\n"); + printf("----------------------\n"); + + /* Initialize parsing variables */ + char line[MAX_LENGTH + 2]; + char *p; + int i = 0, line_num = 0; + + /* Copy .text section to memory, break at nop */ + while (fgets(line, MAX_LENGTH + 2, fp) != NULL) { + line_num++; + + /* Remove '\n' from 'line' */ + p = strchr(line, '\n'); + if (p != NULL) { + *p = '\0'; + } + + memory[i] = getDec(line); + + /* If 'nop' found, move to 0x800 / 2048 in memory and break */ + if (strcmp(line, "11111111111111111111111111111111") == 0) { + memory[i] = 0; + i = 0x800; + break; + } else { + printf("memory[%d] = 0x%08x\n", i, memory[i]); + i++; + } + } + + int j = 2048; //Data Memory Starts at 2048 + for (j = i; j < 16384; j++) { + memory[j] = 0; + } + + puts(""); + + printf("----------------------\n"); + printf("--- Section: .data ---\n"); + printf("----------------------\n"); + + /* Seek fp to first instruction in .data */ + char data[MAX_LENGTH + 2]; + int bytes = 33 * line_num; + fseek(fp, bytes, SEEK_SET); + + /* Copy .data section to memory */ + while (fgets(line, MAX_LENGTH + 2, fp) != NULL) { + /* Remove '\n' from 'line' */ + p = strchr(line, '\n'); + if (p != NULL) { + *p = '\0'; + } + + memory[i] = getDec(line); + printf("memory[%d] = 0x%08x\n", i, memory[i]); + i++; + } + + printf("====================================\n"); + printf("=== END SIMULATOR INITIALIZATION ===\n"); + printf("===================================="); +} diff --git a/pa4/src/sim_core.h b/pa4/src/sim_core.h new file mode 100644 index 0000000..ab14923 --- /dev/null +++ b/pa4/src/sim_core.h @@ -0,0 +1,136 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: sim_core.h + * + * DO NOT MODIFY THIS FILE + * + */ + +#pragma once + +#include + +extern FILE *fptr_pt; + +/* Max number of registers, and instruction length in bits */ +#define MAX_LENGTH 32 + +/* Array of registers (register file) */ +extern int registers[MAX_LENGTH]; + +/* Clock cycle */ +extern int cycle; + +/* Program Counter (PC) register */ +extern unsigned int pc; // Current PC + +/* Instruction and data memory */ +extern int *memory; + +/* Committed instructions */ +extern int committed_instructions; + +/* CPU state */ +struct State { + /* Fetched instruction */ + unsigned int inst; + + /* Decoded instruction fields */ + unsigned int opcode; + unsigned int func; + unsigned int rs; + unsigned int rt; + unsigned int rd; + unsigned int sa; + unsigned short imm; + + /* Memoryrelated */ + unsigned int mem_flag; + unsigned int mem_addr; + unsigned int mem_out; + + /* JAL related */ + unsigned int jmp_out_31; + + /* ALU */ + unsigned int alu_in1; + unsigned int alu_in2; + unsigned int alu_out; + + /* Scoreboard related */ + unsigned int pc_updated; +}; + +/* Pipeline related */ +extern int br_taken; + +/* Scoreboard related */ +#define SCOREBOARD_ENTRIES 100 + +extern int register_result[MAX_LENGTH]; +extern int br_taken_instruction_number; + +enum Stage {STAGE_INVALID, STAGE_ISSUE, STAGE_READ_OPERANDS, STAGE_EXECUTE, STAGE_WRITE_RESULT}; +enum Hazard {HAZARD_NONE, HAZARD_RAW, HAZARD_WAW, HAZARD_WAR, HAZARD_STRUCTURAL}; + +struct ScoreboardEntry { + /* Flag indicating if entry is valid */ + int valid; + + /* Instruction number of instruction corresponding to entry */ + int instruction_number; + + /* Pipeline stage of entry */ + enum Stage stage; + + /* Operation and sub-operation (for R-Type) instructions of entry */ + int operation; + int sub_operation; + + /* Hazard of entry (if any) */ + enum Hazard hazard; + + /* Source and destination register indices */ + int src_reg_1; + int src_reg_2; + int dest_reg; + + /* Source operand data */ + int src_reg_1_data; + int src_reg_2_data; + + /* Scoreboard entry that produces source operand data */ + int scb_1; + int scb_2; + + /* Flags indicating if source operands are available */ + int scb_1_ready; + int scb_2_ready; + + /* Immediate and shift amount for relevant instructions */ + int imm; + int sa; + + /* Branch/jump destination address */ + int br_address; + + /* Number of cycles spent in operation and operation latency */ + int cycles; + int latency; + + /* Operation result */ + int result; +} *scoreboard; + +/* Instruction latencies */ +extern const int LATENCY_MEMORY; +extern const int LATENCY_BRANCH; +extern const int LATENCY_OTHER; + +void initialize(FILE *fp); +void process_instructions(); \ No newline at end of file diff --git a/pa4/src/sim_stages.c b/pa4/src/sim_stages.c new file mode 100644 index 0000000..4ff0e8b --- /dev/null +++ b/pa4/src/sim_stages.c @@ -0,0 +1,70 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * YOUR NAME HERE + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: sim_stages.c + * + */ + +#include +#include +#include +#include + +#include "instruction_map.h" +#include "sim_core.h" +#include "sim_stages.h" + +/** + * Debug flags + */ +int debug = 0; // Set to 1 for additional debugging information. +int pipe_trace = 1; // Set to 1 for pipe trace. + +/** + * Issue stage implementation. + */ +void issue(void) { + + /* Your code for the issue stage goes here. */ + +} + +/** + * Read Operands stage implementation. + */ +void read_operands(void) { + + /* Your code for the read operands stage goes here. */ + +} + +/** + * Execute stage implementation + */ +void execute(void) { + + /* Your code for the execute stage goes here. */ + +} + +/** + * Write Result stage implementation + */ +void write_result(void) { + + /* Your code for the write result stage goes here. */ + +} + +/** + * Advance PC. + * DO NOT MODIFY. + */ +void advance_pc(int step) { + pc += step; +} \ No newline at end of file diff --git a/pa4/src/sim_stages.h b/pa4/src/sim_stages.h new file mode 100644 index 0000000..ce1dbfb --- /dev/null +++ b/pa4/src/sim_stages.h @@ -0,0 +1,25 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: sim_stages.h + * + * DO NOT MODIFY THIS FILE + * + */ + +#pragma once + +#include "sim_core.h" + +extern int debug; +extern int pipe_trace; + +void issue(void); +void read_operands(void); +void execute(void); +void write_result(void); +void advance_pc(int step); \ No newline at end of file diff --git a/pa4/src/util.c b/pa4/src/util.c new file mode 100644 index 0000000..88bd87b --- /dev/null +++ b/pa4/src/util.c @@ -0,0 +1,305 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: util.c + * + * DO NOT MODIFY THIS FILE + * + */ + +#include +#include +#include +#include +#include + +#include "instruction_map.h" +#include "register_map.h" +#include "sim_core.h" + +static const char* stage_map[] = { + [STAGE_INVALID] = "Invalid", + [STAGE_ISSUE] = "Issue", + [STAGE_READ_OPERANDS] = "Read Operands", + [STAGE_EXECUTE] = "Execute", + [STAGE_WRITE_RESULT] = "Write Result" +}; + +/** + * Dump register contents. + * Will format for desired number of columns and output in specified file. + */ +void rdump_file_columns(FILE* file, unsigned columns) { + static const unsigned int index_col_width = 4; + static const unsigned int name_col_width = 5; + static const unsigned int value_col_width = 8; + static const unsigned int tab_spaces = 4; + static const unsigned int col_sep = 2; + + assert(columns > 0); + + /* Calculate number of rows and total row length*/ + const unsigned int rows = (int)ceil((double) MAX_LENGTH / columns); + const unsigned int row_length = columns * (index_col_width + name_col_width + value_col_width + 2 + 2 * tab_spaces) + (columns - 1) * (col_sep * tab_spaces); + + /* Print header */ + fprintf(file, "---------------------\n"); + fprintf(file, "--- Register Dump ---\n"); + fprintf(file, "---------------------\n"); + for (int col = 0; col < columns; col++) { + fprintf(file, "%-*s%-*s%-*s", index_col_width + tab_spaces, "Index", name_col_width + tab_spaces, "Name", value_col_width + 2, "Value"); + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + for (int col = 0; col < columns; col++) { + fprintf(file, "%-*s%-*s%-*s", index_col_width + tab_spaces, "-----", name_col_width + tab_spaces, "----", value_col_width + 2, "-----"); + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + + /* Print rows */ + for (int row = 0; row < rows; row++) { + for (int col = 0; col < columns; col++) { + unsigned int i = row + col * rows; + + if (i < MAX_LENGTH) { + fprintf(file, "$%-*i%*s$%-*s%*s0x%0*x", index_col_width, i, tab_spaces - 1, "", name_col_width, register_map[i], tab_spaces - 1, "", value_col_width, registers[i]); + } else { + fprintf(file, "\n"); + break; + } + + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + } + fprintf(file, "%-*s%*s%-*s%*s0x%08x\n", index_col_width, "N/A", tab_spaces, "", name_col_width, "pc", tab_spaces, "", pc); +} + +void rdump_pt() { + rdump_file_columns(fptr_pt, 4); +} + +void rdump() { + rdump_file_columns(stdout, 4); +} + +/** + * Dump memory contents. + */ +void mdump() { + FILE* fptr; + fptr = fopen("mdump.txt", "w"); + int i = 0; + for (i = 0; i < 16384; i++) { + fprintf(fptr, "Memory[%d] = 0x%08x\n", i, memory[i]); + } + fclose(fptr); +} + +/** + * Print instruction information + */ +void inst_dump(const char stage[], const unsigned int inst) { + int opcode = inst >> 26; + + unsigned int func = inst << 26; + func = func >> 26; + + int rs = (inst >> 21) & 0x1F; + int rt = (inst >> 16) & 0x1F; + int rd = (inst >> 11) & 0x1F; + int sa = (inst >> 6) & 0x1F; + int imm = inst & 0xFFFF; + short shortImm = (short)imm; + int target = inst & 0x03ffffff; + + fprintf(fptr_pt, "%-12s ", stage); + + if (inst == 0xffffffff) { + fprintf(fptr_pt, "INVALID INSTRUCTION\n"); + return; + } + + switch (opcode) { + case RTYPEOP: + switch (func) { + case JR: + fprintf(fptr_pt, "%-4s $%d\n", func_map[func], rs); + break; + + case SLL: + case SRL: + fprintf(fptr_pt, "%-4s $%d, $%d, %d\n", func_map[func], rd, rt, sa); + break; + + case ADD: + case SUB: + case AND: + case OR: + case SLT: + fprintf(fptr_pt, "%-4s $%d, $%d, $%d\n", func_map[func], rd, rs, rt); + break; + + default: + fprintf(fptr_pt, "INVALID INSTRUCTION\n"); + return; + break; + } + break; + + case LW: + case SW: + fprintf(fptr_pt, "%-4s $%d %d($%d)\n", opcode_map[opcode], rt, imm, rs); + break; + + case ANDI: + case ADDI: + case ORI: + case SLTI: + fprintf(fptr_pt, "%-4s $%d, $%d, %d\n", opcode_map[opcode], rt, rs, imm); + break; + + case LUI: + fprintf(fptr_pt, "%-4s $%d, %d\n", opcode_map[opcode], rt, imm); + break; + + case BEQ: + case BNE: + fprintf(fptr_pt, "%-4s $%d, $%d, %d\n", opcode_map[opcode], rs, rt, shortImm); + break; + + case J: + case JAL: + fprintf(fptr_pt, "%-4s %d\n", opcode_map[opcode], target); + break; + + default: + fprintf(fptr_pt, "INVALID INSTRUCTION\n"); + return; + break; + } +} + +void rresult_file_columns(FILE* file, unsigned columns) { + static const unsigned int index_col_width = 4; + static const unsigned int name_col_width = 5; + static const unsigned int value_col_width = 8; + static const unsigned int tab_spaces = 4; + static const unsigned int col_sep = 2; + + assert(columns > 0); + + /* Calculate number of rows and total row length*/ + const unsigned int rows = (int)ceil((double) MAX_LENGTH / columns); + const unsigned int row_length = columns * (index_col_width + name_col_width + value_col_width + 2 + 2 * tab_spaces) + (columns - 1) * (col_sep * tab_spaces); + + /* Print header */ + fprintf(file, "------------------------\n"); + fprintf(file, "--- Register Results ---\n"); + fprintf(file, "------------------------\n"); + for (int col = 0; col < columns; col++) { + fprintf(file, "%-*s%-*s%-*s", index_col_width + tab_spaces, "Index", name_col_width + tab_spaces, "Name", value_col_width, "Entry"); + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + for (int col = 0; col < columns; col++) { + fprintf(file, "%-*s%-*s%-*s", index_col_width + tab_spaces, "-----", name_col_width + tab_spaces, "----", value_col_width, "-----"); + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + + /* Print rows */ + for (int row = 0; row < rows; row++) { + for (int col = 0; col < columns; col++) { + unsigned int i = row + col * rows; + + if (i < MAX_LENGTH) { + fprintf(file, "$%-*i%*s$%-*s%*s%-*i", index_col_width, i, tab_spaces - 1, "", name_col_width, register_map[i], tab_spaces - 1, "", value_col_width, register_result[i]); + } else { + fprintf(file, "\n"); + break; + } + + if (col == columns - 1) { + fprintf(file, "\n"); + } else { + fprintf(file, "%*s", col_sep * tab_spaces, ""); + } + } + } +} + +/** + * Print scoreboard + */ +void print_scoreboard() { + fprintf(fptr_pt, "--------------------------\n"); + fprintf(fptr_pt, "--- Instruction Status ---\n"); + fprintf(fptr_pt, "--------------------------\n"); + fprintf(fptr_pt, "Instruction Number Stage Operation Sub-operation dest_reg src_reg_1 src_reg_2 scb_1 scb_2 scb_1_ready scb_2_ready\n"); + fprintf(fptr_pt, "------------------ ----- --------- ------------- -------- --------- --------- ----- ----- ----------- -----------\n"); + for (int i = 0; i < SCOREBOARD_ENTRIES; i++) { + struct ScoreboardEntry *entry = &scoreboard[i]; + + if (!entry->valid) { + continue; + } + + char const *ins = (entry->operation == RTYPEOP) ? func_map[entry->sub_operation] : opcode_map[entry->operation]; + char const *op = opcode_map[entry->operation]; + char const *subop = (entry->operation == RTYPEOP) ? func_map[entry->sub_operation] : "N/A"; + + fprintf(fptr_pt, "%-18i %-13s %-9s %-13s %-8i %-9i %-9i %-5i %-5i %-11s %-11s\n", + entry->instruction_number, stage_map[entry->stage], op, subop, entry->dest_reg, entry->src_reg_1, entry->src_reg_2, entry->scb_1, entry->scb_2, (entry->scb_1_ready) ? "yes" : "no", (entry->scb_2_ready) ? "yes" : "no"); + } + fprintf(fptr_pt, "\n"); + rresult_file_columns(fptr_pt, 3); +} + +/** + * Convert a binary string to an integer + */ +int getDec(char *bin) { + int b, k, m, n; + int len, sum = 0; + + len = strlen(bin) - 1; + + /* Iterate over the string */ + for (k = 0; k <= len; k++) { + // Convert char to numeric value + n = (bin[k] - '0'); + + // Check the character is binary + if ((n > 1) || (n < 0)) { + return 0; + } + + for (b = 1, m = len; m > k; m--) + b *= 2; + + // sum it up + sum = sum + n * b; + } + return sum; +} \ No newline at end of file diff --git a/pa4/src/util.h b/pa4/src/util.h new file mode 100644 index 0000000..7788a9e --- /dev/null +++ b/pa4/src/util.h @@ -0,0 +1,24 @@ +/** + * University of Connecticut + * CSE 5302 / ECE 5402: Computer Architecture + * Fall 2021 + * + * Programming Assignment 4: Pipelined riscy-uconn Simulator With Scoreboard + * + * riscy-uconn: util.h + * + * DO NOT MODIFY THIS FILE + * + */ + +#pragma once + +#include + +void rdump_file_columns(FILE* file, unsigned columns); +void rdump(); +void rdump_pt(); +void mdump(); +void inst_dump(const char stage[], const unsigned int inst); +void print_scoreboard(); +int getDec(char *bin); \ No newline at end of file