You are on page 1of 11

/*

* um.c
*
* The main file for the um
*
* Created By: Gabe Terrell and Eli Boninger
* Assignment: HW6 - UM
* Last Edited On: 11/12/2014
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

<stdio.h>
"bitpack.h"
<sys/types.h>
<sys/stat.h>
<unistd.h>
<assert.h>
"memory_management.h"
<mem.h>
"decode_instructions.h"
"ALU.h"

void load_initial_program (const char *filename, Memory_T prog_memory);
void run_program (Memory_T prog_memory);
int main (int argc, char *argv[])
{
assert(argc == 2);
Memory_T prog_memory = initialize_memory();
load_initial_program(argv[1], prog_memory);
run_program(prog_memory);
free_memory(prog_memory);
return 0;
}
/* Load the program from the um file into $m[0] */
void load_initial_program (const char *filename, Memory_T prog_memory)
{
struct stat file_stats;
stat(filename, &file_stats);
/* The total number of instructions is the total number of bytes read
in divided by four, because each instruction is 4 bytes. */
int num_instructions = file_stats.st_size / 4;
FILE *fp = fopen(filename, "rb");
uint32_t index = initialize_segment(num_instructions, prog_memory);
assert(index == 0);
/* Pack each instruction into a 32-bit word */
for (int i = 0; i < num_instructions; i++) {
uint32_t instr = 0;
for (int byte = 3; byte >= 0; byte--) {
instr = Bitpack_newu(instr, 8, 8 * byte, getc(fp));
}
put_word(instr, index, i, prog_memory);
}

h> #include <stdio. isHalted = execute(di. } } /* * decode_instructions. uint32_t rB.c The implementation for decoding UM instructions Created By: Gabe Terrell and Eli Boninger Assignment: HW6 . uint32_t rA.UM .fclose(fp).h * * The interface for all UM instruction decoding * * Created By: Gabe Terrell and Eli Boninger * Assignment: HW6 .UM * Last Edited On: 11/12/2014 */ #ifndef DECODE_INSTRUCTIONS #define DECODE_INSTRUCTIONS #include <stdint. prog_memory). } /* Continue fetching and executing instructions until a halt is reached */ void run_program (Memory_T prog_memory) { bool isHalted = false. uint32_t value. uint32_t rC. while (!isHalted) { uint32_t instr = get_next_instruction(prog_memory). struct decoded_instr di = decode_instruction(instr). /* returns a struct which represents the decoded 32-bit integer */ extern struct decoded_instr decode_instruction (uint32_t instr). }.h> struct decoded_instr { uint32_t opcode. #endif /* * * * * * * decode_instructions.

} static inline uint32_t get_load_value (uint32_t instr) { return (uint32_t) Bitpack_getu(instr. } /* If the instruction is a load value.h" #include "bitpack. 3. 6).rB = get_rB(instr). */ struct decoded_instr decode_instruction (uint32_t instr) { struct decoded_instr di.opcode = get_opcode(instr). 25. 3. behave normally */ if (di. } /* Given the 32-bit integer.opcode != 13) { di. } static inline uint32_t get_rC (uint32_t instr) { return (uint32_t) Bitpack_getu(instr.* Last Edited On: 11/12/2014 */ #include "decode_instructions. 0).rA = get_rA(instr). 25). 3). find the instruction contents */ else { di. di.value = get_load_value(instr). di. unpack the bits into discrete values to represents an instruction. di. 28). 3. } static inline uint32_t get_load_rA (uint32_t instr) { return (uint32_t) Bitpack_getu(instr. di.rC = get_rC(instr). } static inline uint32_t get_rA (uint32_t instr) { return (uint32_t) Bitpack_getu(instr.h" static inline uint32_t get_opcode (uint32_t instr) { return (uint32_t) Bitpack_getu(instr. 3.rA = get_load_rA(instr). } return di. 0). 4. } static inline uint32_t get_rB (uint32_t instr) { return (uint32_t) Bitpack_getu(instr. } . /* If the instruction is a not a load value.

Memory_T mem).h" /* constants to represent each instruction */ #define COND_MOV 0 #define SEG_LOAD 1 #define SEG_STORE 2 #define ADD 3 #define MUL 4 #define DIV 5 #define NAND 6 #define HALT 7 #define MAP_SEG 8 #define UNMAP_SEG 9 #define OUT 10 #define IN 11 #define LOAD_PROG 12 #define LOAD_VAL 13 /* Given the decoded instruction di.h * * The interface for our arithmetic logic unit. Memory_T mem).UM * Last Edited On: 11/12/2014 */ #ifndef __ALU__ #define __ALU__ #include "memory_management.h" #include <stdint. execute the instruction using the contents * of the given Memory_T structure */ extern bool execute (struct decoded_instr di.UM * Last Edited On: 11/12/2014 */ #include "ALU. void seg_load (struct decoded_instr di.c * * The implementation for our arithmetic logic unit * * Created By: Gabe Terrell and Eli Boninger * Assignment: HW6 .h> void cond_mov (struct decoded_instr di.h> #include "decode_instructions. void seg_store (struct decoded_instr di. Memory_T mem). Memory_T mem)./* * ALU. #endif /* * ALU. This module is responsible for * performing all universal machine instructions * * Created By: Gabe Terrell and Eli Boninger * Assignment: HW6 .h" #include <stdbool. .

load_val(struct decoded_instr di. "In cond_mov\n"). break. mem). } } . /* based on the opcode in the di struct. default : return false. } return false. case LOAD_VAL : load_val(di. mem). case IN : in(di. mem). case SEG_LOAD : seg_load(di. mul (struct decoded_instr di. in(struct decoded_instr di. mem). break. break. map_seg (struct decoded_instr di. mem). mem). Memory_T mem) { // fprintf(stdout. Memory_T mem). break. case LOAD_PROG : load_prog(di. break. break. if (get_register(di. mem). break. case MUL : mul(di. break. case DIV : divide(di. case UNMAP_SEG : unmap_seg(di. mem) != 0) { set_register(di. Memory_T mem). Memory_T mem). mem). break. mem).rA. mem). get_register(di. case MAP_SEG : map_seg(di. load_prog(struct decoded_instr di. break. mem). nand (struct decoded_instr di. break.opcode) { case COND_MOV : cond_mov(di. Memory_T mem) { switch (di. case NAND : nand(di. case SEG_STORE : seg_store(di. } /************INSTRUCTION*EXECUTION*****************************************/ /* If rC is not 0. Memory_T mem). move the contents of rB into rA */ void cond_mov (struct decoded_instr di. unmap_seg (struct decoded_instr di.rB.void void void void void void void void void void add (struct decoded_instr di. mem). Memory_T mem).rC. case OUT : out(di. divide (struct decoded_instr di. Memory_T mem). case HALT : return true. Memory_T mem). case ADD : add(di. break. Memory_T mem). Memory_T mem). mem). break. execute the given instruction */ extern bool execute (struct decoded_instr di. mem). mem). out(struct decoded_instr di. Memory_T mem).

"In mul\n").rB. Memory_T mem) { // fprintf(stdout. mem)).rC. set_register(di.rA.rA. then place them in rA */ void add (struct decoded_instr di. uint32_t index = initialize_segment(get_register(di. mem).rA. } . } /* Peform the NAND logic operation on rB and rC. mem) * get_register(di. uint32_t ans = ~(get_register(di. } /* Multiply the contents of rB and rC. get_register(di. product = product % 4294967296. set_register(di.rB. mem). uint32_t answer = get_register(di.rA./* Load the contents at $m[rB][rC] into rA */ void seg_load (struct decoded_instr di. get_register(di. uint32_t word = get_word(get_register(di. "In seg_store\n"). mem). "In seg_load\n"). put_word(get_register(di. } /* Map a segment of length rC words.rC. mem) + get_register(di. set_register(di. mem). mem).rC. "In add\n"). "In divide\n"). } /* Add the contents of rB and rC. set_register(di. mem). sum.rC. mem). then put the returned index in rB */ void map_seg (struct decoded_instr di. mem). uint32_t sum = get_register(di.rB. mem) & get_register(di. get_register(di. uint32_t product = get_register(di. mem).rC.rB.rB. then place the product in rA */ void mul (struct decoded_instr di. Memory_T mem) { // fprintf(stdout. answer. "In map_seg\n"). ans. set_register(di.rC.rB. mem) / get_register(di. mem). "In cond_mov\n"). word. set_register(di. Memory_T mem) { // fprintf(stdout. Memory_T mem) { // fprintf(stdout. mem). product. mem).rC.rA. mem).rA. } /* Divide rB by rC and the put the answer in rA */ void divide (struct decoded_instr di. mem). index. Memory_T mem) { // fprintf(stdout. mem).rB. mem). Memory_T mem) { // fprintf(stdout. mem). mem). sum = sum % 4294967296. and put the result in rA */ void nand (struct decoded_instr di. } /* Store the contents of rC in $m[rA][rB] */ void seg_store (struct decoded_instr di. Memory_T mem) { // fprintf(stdout.

mem). stdout). mem). mem)./* Unmap the segment at rC */ void unmap_seg (struct decoded_instr di.rC. set_register(di.value. putc(get_register(di. di. load_program(get_register(di. Memory_T mem) { // fprintf(stdout.rB. } /* Load the given value into rA */ void load_val(struct decoded_instr di. Memory_T mem) { // fprintf(stdout. Memory_T mem) { // fprintf(stdout. mem).rC.h> . "In unmap_seg\n").rC. mem). free_segment(get_register(di. "In load_prog\n"). value. mem).h> #include <stdint. get_register(di. } /* * memory_management. } /* Load the program at $m[rB] into $m[0] and set the progam_counter to rC */ void load_prog (struct decoded_instr di. mem). } /* Read a singe byte from stdin into rC */ void in (struct decoded_instr di. "In load_val\n").h * * This module is used for handling all things related to memory. "In out\n").h> #include <stdbool.rC. set_register(di. including * the segmented memory data structure as well as the registers * * Created By: Gabe Terrell and Eli Boninger * Assignment: HW6 .rA. } /* Output the value of rC as a character to stdout */ void out (struct decoded_instr di. Memory_T mem) { // fprintf(stdout. "In in\n"). int value = getchar() % 256. Memory_T mem) { // fprintf(stdout. mem).UM * Last Edited On: 11/12/2014 */ #ifndef MEMORY_MANAGEMENT #define MEMORY_MANAGEMENT #include <stdlib.

return the segment ID */ extern uint32_t initialize_segment (uint32_t num_words. /* Set the contents of the given register to val */ extern void set_register (uint32_t reg.UM * Last Edited On: 11/12/2014 */ #include #include #include #include #include #include "memory_management. Memory_T memory).typedef struct Memory_T *Memory_T. uint32_t rC. uint32_t n.h> <stdio. /* Return the contents of the given register number */ extern uint32_t get_register (uint32_t reg.h" <assert. . * * Created By: Gabe Terrell and Eli Boninger * Assignment: HW6 . uint32_t next_unused_index. Memory_T memory). Memory_T memory). /* Frees the memory segment at the index passed in */ extern void free_segment (uint32_t i. /* Load the conents of $m[rB] into $m[0] and set program_counter to rC */ extern void load_program (uint32_t rB. Memory_T memory). /* Put the given word into $m[i][n] */ extern void put_word (uint32_t word. Memory_T memory). uint32_t n.h" "mem. #endif /* * memory_management. /* Retrieve the next instruction from $m[0] */ extern uint32_t get_next_instruction (Memory_T memory). /* Free all previously unfreed memory */ extern void free_memory(Memory_T memory).c * * The implementation for our memory managing interface.h" "uarray. uint32_t i.h> #define NUM_REGS 8 struct Memory_T { Seq_T unmapped_segments. /* initializes variables for memory management -. Memory_T memory). uint32_t val.should only be called ONCE */ extern Memory_T initialize_memory(). /* Returns word at $m[i][n] */ extern uint32_t get_word (uint32_t i. Memory_T memory). /* Initailize a new segment of length num_words.h" "seq.

uint32_t val.should only be called ONCE */ extern Memory_T initialize_memory() { Memory_T memory = malloc(sizeof(*memory)). memory->program_counter++. Memory_T memory) { return memory->regs[reg]. /* Set all registers to 0 */ for (int i = 0. memory->unmapped_segments = Seq_new(10). /* Returns the lowest available segment ID */ static inline uint32_t get_unused_index (Memory_T memory) { /* If the sequence isn't empty. }. i++) { memory->regs[i] = 0.UArray_T segments. uint32_t program_counter. memory). sizeof(UArray_T)). Memory_T memory) . } return memory. Memory_T memory) { memory->regs[reg] = val. memory->segments = UArray_new(10. } /* return word at $m[i][n] */ extern uint32_t get_word (uint32_t i. } /* Set the given register to the given value */ extern void set_register (uint32_t reg. memory->next_unused_index = 0. } /* Retrieve the next instruction from $m[0] and increment program_counter */ extern uint32_t get_next_instruction (Memory_T memory) { return get_word(0. i). Memory_T memory) { return * (UArray_T *) UArray_at(memory->segments. uint32_t regs[NUM_REGS]. } /* initializes variables for memory management -. i < NUM_REGS. memory->program_counter = 0. uint32_t n. return its first value */ if (Seq_length(memory->unmapped_segments) > 0) return (uint32_t) (uintptr_t) Seq_remlo(memory->unmapped_segments). } /* Return the value of the given register */ extern uint32_t get_register (uint32_t reg. return memory->next_unused_index++. } /* Return the segment at index i */ static inline UArray_T get_segment (uint32_t i.

} free_segment(0. uint32_t word = * (uint32_t *) UArray_at(segment. } /* Duplicate the segment at $m[rB] and place it at $m[0]. uint32_t i. Memory_T memory) { uint32_t index = get_unused_index(memory). memory). memory). return. * (uint32_t *) UArray_at(segment. } /* places the given word at segment $m[i][n] */ extern void put_word (uint32_t word. /* Create a new segment at $r[0] with the $[rB] duplicate */ uint32_t index = initialize_segment(UArray_length(rB_copy). uint32_t rC. Memory_T memory) { UArray_T segment = get_segment(i. UArray_length(segment)). return word. return index. n) = word. UArray_T segment0 = get_segment(index. memory). /* If the array of segments is too small. index) = UArray_new(num_words. segment0 = rB_copy. memory->program_counter = rC.{ UArray_T segment = get_segment(i. memory). UArray_length(memory->segments) + 10). memory). UArray_T rB_copy = UArray_copy(segment. (void)segment0. Then set program_counter to rC. } /* Create a new segment of length num_words */ * (UArray_T *) UArray_at(memory->segments. memory). Memory_T memory) { /* If the segment to be duplicated is already at $m[0] */ if (rB == 0) { memory->program_counter = rC. } /* Frees the memory segment at index i */ . expand the array */ if (index >= (uint32_t) UArray_length(memory->segments)) { UArray_resize(memory->segments. sizeof(uint32_t)). /* Get the segmet at $m[rB] and copy it */ UArray_T segment = get_segment(rB. uint32_t n. } /* Creates space for a new segment and returns an index of a memory segment that is not currently mapped */ extern uint32_t initialize_segment (uint32_t num_words. n). */ extern void load_program (uint32_t rB.

if (segment != NULL) { free_segment(i. if (segment != NULL) { UArray_free(&segment). } } Seq_free(&(memory->unmapped_segments)). memory). *sp = NULL. i). (void *) (uintptr_t) i). } .extern void free_segment (uint32_t i. i < memory->next_unused_index. } } /* Free all previously unfreed memory. memory). Seq_addlo(memory->unmapped_segments. including the Memory_T struct */ extern void free_memory(Memory_T memory) { /* loop to find segments that were not manually freed */ for (unsigned i = 0. i++) { UArray_T segment = get_segment(i. UArray_T segment = get_segment(i. free(memory). Memory_T memory) { UArray_T *sp = (UArray_T *) UArray_at(memory->segments. UArray_free(&(memory->segments)). memory).