Question: Question: For this lab, you have to add a command-processing loop: You read a line containing a simulator command and execute it, read another line
Question: For this lab, you have to add a command-processing loop: You read a line containing a simulator command and execute it, read another line and execute it, and so on until you are given the quit command. There are six commands (q for quit, d for dump control unit and memory, h and ? for help, an integer (to execute that many instruction cycles), or an empty line (to execute one instruction cycle). 1. To start the command loop, prompt for and read a command line. (You'll want to use the fgets / sscanf technique from the previous lab.) See if the line is empty or has a command. If you hit end-of-file on standard input, exit the program. 2. For command q, note that youve seen a quit command and exit the program. (Dont dump things back out, just quit.) 3. For command d, dump out the control unit and the memory values. 4. For h or ?, print out a help message. 5. For an integer (lets call it N), execute the instruction cycles that many times but make sure N is reasonable first. a. If N < 1, complain to the user and go on to the next command. b. If N is unreasonably large, warn the user and change N to a reasonable limit. c. Now run the instruction cycle N times. Check after each cycle to make sure the running flag is still true; if it becomes false, skip the rest of the N cycles. 6. If the command was empty (a newline), then if the running flag is true, run the instruction cycle once.. Otherwise, if the running flag is false, just tell the user that the CPU has halted. (Dont run a cycle.) 7. Continue the loop (go to step 1). Note you do this if even if CPU execution has halted; that way the user has the option of entering a d command before quitting
/ (Remove this entire comment block)
// Note: this skeleton doesn't execute well.
// *** Your name and section (replace this with the correct information ***
// CS 350, Fall 2017
// Lab 6: SDC Simulator, part 2
//
// Illinois Institute of Technology, (c) 2017, James Sasaki
#include
#include // For error exit()
// CPU Declarations -- a CPU is a structure with fields for the
// different parts of the CPU.
//
typedef short int Word; // type that represents a word of SDC memory
typedef unsigned char Address; // type that represents an SDC address
#define MEMLEN 100
#define NREG 10
struct CPU {
Word mem[MEMLEN];
Word reg[NREG]; // Note: "register" is a reserved word
Address pc; // Program Counter
int running; // running = 1 iff CPU is executing instructions
Word ir; // Instruction Register
int instr_sign; // sign of instruction
int opcode; // opcode field
int reg_R; // register field
int addr_MM; // memory field
};
typedef struct CPU CPU;
// Prototypes [note the functions are also declared in this order]
//
// *** STUB *** Lab 5 items omitted ....
void initialize_control_unit(CPU *cpu);
void initialize_memory(int argc, char *argv[], CPU *cpu);
FILE *get_datafile(int argc, char *argv[]);
void dump_control_unit(CPU *cpu);
void dump_memory(CPU *cpu);
void print_instr(int instr);
int read_execute_command(CPU *cpu);
int execute_command(char cmd_char, CPU *cpu);
void help_message(void);
void many_instruction_cycles(int nbr_cycles, CPU *cpu);
void one_instruction_cycle(CPU *cpu);
void exec_HLT(CPU *cpu);
// *** STUB ***
void exec_LD(CPU *cpu);
void exec_ST(CPU *cpu);
void exec_ADD(CPU *cpu);
void exec_NEG(CPU *cpu);
void exec_POSITVELDM(CPU *cpu);
void exec_NEGLDM(CPU *cpu);
void exec_ADDM(CPU *cpu);
void exec_SUBM(CPU *cpu);
void exec_BR(CPU *cpu);
void exec_BRGE(CPU *cpu);
void exec_BRLE(CPU *cpu);
void exec_GETC(CPU *cpu);
void exec_OUT(CPU *cpu);
void exec_PUTS(CPU *cpu);
void exec_DMP(CPU *cpu);
void exec_MEM(CPU *cpu);
// Main program: Initialize the cpu, and read the initial memory values.
// Then run the command loop to let the user execute the program.
//
int main(int argc, char *argv[]) {
printf("SDC Simulator pt 2 for "); // STUB
CPU cpu_value, *cpu = &cpu_value;
// *** STUB *** Lab 5 items omitted (initialize CPU and memory) ....
initialize_control_unit(cpu);
initialize_memory(argc, argv, cpu);
dump_control_unit(cpu);
dump_memory(cpu);
// Run the command loop
//
char *prompt = "> ";
printf(" Beginning execution; type h for help %s", prompt);
int done = read_execute_command(cpu);
while (!done) {
printf("%s", prompt);
done = read_execute_command(cpu);
}
return 0;
}
// *** STUB *** Rest of Lab 5 items omitted
// (initialize_control_unit, ..., print_instr)
void initialize_control_unit(CPU *cpu) {
// *** STUB ***
cpu -> pc = 00;
cpu -> ir = 0000;
cpu -> instr_sign = 1;
cpu -> running = 1;
//Word reg[NREG] = {0};
for(int i = 0; i < NREG; i++)
{
cpu->reg[i] = 0;
}
//dump_control_unit(cpu);
printf(" ");
}
void initialize_memory(int argc, char *argv[], CPU *cpu) {
FILE *datafile = get_datafile(argc, argv);
// *** STUB *** (Maybe want a message here or inside get_datafile)
// Buffer to read next line of text into
#define DATA_BUFFER_LEN 256
char buffer[DATA_BUFFER_LEN];
// Will read the next line (words_read = 1 if it started
// with a memory value). Will set memory location loc to
// value_read
//
int value_read, words_read, loc = 0, done = 0;
char *read_success; // NULL if reading in a line fails.
read_success = fgets(buffer, DATA_BUFFER_LEN, datafile);
while (read_success != NULL && !done) {
// If the line of input begins with an integer, treat
// it as the memory value to read in. Ignore junk
// after the number and ignore blank lines and lines
// that don't begin with a number.
//
words_read = sscanf(buffer, "%d", &value_read);
// *** STUB ***
// if an integer was actually read in, then
// set memory value at current location to
// value_read and increment location. Exceptions: If
// loc is out of range, complain and quit the loop. If
// value_read is outside -9999...9999, then it's a
// sentinel -- we should say so and quit the loop.
// Get next line and continue the loop
if(value_read < -9999 || value_read > 9999)
{
printf("it's a sentinel: %d, at location %d, quit the loop ", value_read, loc);
read_success = NULL;
}
else if(value_read >= -9999 && value_read <= 9999)
{
cpu -> mem[loc++] = value_read;
// cpu -> pc++;
//loc++;
//value_read = NULL;
}
// *** STUB ***
if(loc > 99)
{
printf("Loc is out of range: %d ", loc);
}
//Getting the next line and continue looping
read_success = fgets(buffer, DATA_BUFFER_LEN, datafile);
}
fclose(datafile);
// Initialize rest of memory
//
while (loc < MEMLEN) {
cpu -> mem[loc++] = 0;
}
}
// Get the data file to initialize memory with. If it was
// specified on the command line as argv[1], use that file
// otherwise use default.sdc. If file opening fails, complain
// and terminate program execution with an error.
// See linux command man 3 exit for details.
//
FILE *get_datafile(int argc, char *argv[]) {
char *default_datafile_name = "default.sdc";
char *datafile_name = NULL;
// *** STUB *** set datafile name to argv[1] or default
if(argc != 2)
{
datafile_name = default_datafile_name; // *** STUB ***
printf("FILE IS MISSING, DEFAULT FILE OPENING: %s ", default_datafile_name);
}
else
{
datafile_name = argv[1];
}
FILE *datafile = fopen(datafile_name, "r");
// *** STUB *** if the open failed, complain and call
// exit(EXIT_FAILURE); to quit the entire program
// If open succeeded, you might want to print a message here
// or in caller.
if(datafile == NULL)
{
printf("FILE FAILED TO OPEN!! ");
exit(EXIT_FAILURE);
}
else
printf("File opened from default.sdc ");
return datafile;
}
// dump_control_unit(CPU *cpu): Print out the control unit
// (PC, IR, running flag, and general-purpose registers).
//
void dump_control_unit(CPU *cpu) {
printf(" Control and Data Registers:");
printf("PC: %d IR: %d Running: %d ", cpu->pc, cpu->ir, cpu->running);
// Dumped the registers
// dump_registers(cpu);
for(int i = 0; i < NREG; i++)
{
printf("R%d:\t%d ",i,cpu->reg[i]);
}
}
// dump_memory(CPU *cpu): For each memory address that
// contains a non-zero value, print out a line with the
// address, the value as an integer, and the value
// interpreted as an instruction.
//
void dump_memory(CPU *cpu) {
printf(" Memory Dump: (nonzero values only): ");
// *** STUB ****
//int loc = 0;
for(int i = 0; i < MEMLEN; i++)
{
if(cpu -> mem[i] != 0)
{
int instr = cpu -> mem[i];
printf("%02d\t%04d ", i, instr);
print_instr(instr);
printf(" ");
}
}
// for each location, if the value is nonzero, then
// print the location and value (as an integer),
// and call print_instr on the value to print out
// the value as an instruction
}
// print_instr(instr) prints the 4-digit instruction in a mnemonic format.
//
void print_instr(int instr) {
int LD = 1;
int ST = 2;
int ADD = 3;
int NEG = 4;
int LDM = 5;
int LDM_neg = -5;
int ADDM = 6;
// int SUBM = -6;
int BR = 7;
int BRGE = 8;
int BRLE = -8;
int GETC = 0;
int OUT = 1;
int PUTS = 2;
int REG = 3;
int MEM = 4;
if (abs(instr) < 1000) {
printf(" HALT\t\t");
} else {
int opcode = abs(instr / 1000);
int reg_operand = abs((instr / 100) % 10);
int mem_operand = (instr % 100);
if (opcode == LD) {
printf(" LD\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == ST) {
printf(" ST\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == ADD) {
printf(" ADD\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == NEG) {
printf(" NEG\tR%d", reg_operand);
}
else if (opcode == LDM) {
printf(" LDM\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == LDM_neg) {
printf(" -LDM\tR%d,\t%d", reg_operand, mem_operand);
} else if (opcode == ADDM)
{
if(instr < 0){
printf(" SUBM\tR%d,\t%d", reg_operand, mem_operand);}
else{
printf(" ADDM\tR%d,\t%d", reg_operand, mem_operand);
}
}
else if (opcode == BR) {
printf(" BR\t%d", mem_operand);
}
else if (opcode == BRGE) {
printf(" BRGE\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == BRLE) {
printf(" BRLE\tR%d,\t%d", reg_operand, mem_operand);
}
else if (opcode == 9) {
if (reg_operand == GETC) {
printf(" GETC");
}
else if (reg_operand == OUT) {
printf(" OUT");
} else if (reg_operand == PUTS) {
printf(" PUTS\t%d",mem_operand);
} else if (reg_operand == REG) {
printf(" REG");
} else if (reg_operand == MEM) {
printf(" MEM");
} else {
printf(" NOP");
}
}
}
}
// Read a simulator command from the keyboard (q, h, ?, d, number,
// or empty line) and execute it. Return true if we hit end-of-input
// or execute_command told us to quit. Otherwise return false.
//
int read_execute_command(CPU *cpu) {
// Buffer to read next command line into
#define CMD_LINE_LEN 256
char cmd_line[CMD_LINE_LEN];
char *read_success; // NULL if reading in a line fails.
int nbr_cycles; // Number of instruction cycles to execute
char cmd_char; // Command 'q', 'h', '?', 'd', or ' '
int done = 0; // Should simulator stop?
int numbers_read = 0;
read_success = fgets(cmd_line, CMD_LINE_LEN, stdin);
// *** STUB *** done if we have we hit eof
// *** STUB ***
// while not done,
// Handle q, h, ?, d commands, integer (nbr of instruction cycles),
// or empty line (one instruction cycle)
// Read next command line, check for eof
while(!done){
numbers_read= sscanf(cmd_line, "%d", &nbr_cycles);
read_success = fgets(cmd_line, CMD_LINE_LEN, stdin);
if(numbers_read == 1){
many_instruction_cycles(nbr_cycles, cpu);
}
else{
execute_command(cmd_char, cpu);
}
}
return done;
}
// Execute a nonnumeric command; complain if it's not 'h', '?',
// 'd', 'q' or ' '. Return true for the q command, false otherwise.
//
int execute_command(char cmd_char, CPU *cpu) {
if (cmd_char == '?' || cmd_char == 'h') {
help_message();
}
// *** STUB ****
else if(cmd_char == 'd'){
dump_control_unit(cpu);
dump_memory(cpu);
}
else if(cmd_char == 'q' || ' '){
return 0;
}
return 0;
}
// Print standard message for simulator help command ('h' or '?')
//
void help_message(void) {
// *** STUB ****
printf("Instruction set: ");
printf("0xxx: HALT ");
printf("1RMM: Load R <- M[MM] ");
printf("2RMM: Store M[MM] <- R ");
printf("3RMM: Add M[MM] to R ");
printf("4Rxx: Negate R ");
printf("5RMM: Load Immediate R <- MM ");
printf("6RMM: Add Immediate R <- R + MM ");
printf("7xMM: Branch to MM ");
printf("8RMM: Branch Positive to MM if R > 0; ");
printf("90xx: Read char into R0 ");
printf("91xx: Print char in R0 ");
printf("92MM: Print string starting at MM. ");
printf("93MM: Dump registers. ");
printf("94MM: Dump memory. ");
}
// Execute a number of instruction cycles. Exceptions: If the
// number of cycles is <= 0, complain and return; if the CPU is
// not running, say so and return; if the number of cycles is
// unreasonably large, warn the user and substitute a limit.
//
// If, as we execute the many cycles, the CPU stops running,
// just stop and return.
//
void many_instruction_cycles(int nbr_cycles, CPU *cpu) {
int REASONABLE_NBR_CYCLES = 100;
// *** STUB ****
if(nbr_cycles <= 0 || nbr_cycles > 100){
printf("ERROR");
}
for(int i = 0; i < nbr_cycles; i++){
one_instruction_cycle(cpu);
}
}
// Execute one instruction cycle
//
void one_instruction_cycle(CPU *cpu) {
// If the CPU isn't running, say so and return.
// If the pc is out of range, complain and stop running the CPU.
//
// *** STUB ****
// Get instruction and increment pc
//
// For printing purposes, we'll save the location of
// the instruction (the pc before the increment).
//
int instr_loc = cpu -> pc;
cpu -> ir = cpu -> mem[cpu -> pc];
(cpu -> pc)++;
int opcode = abs(instr / 1000);
int reg_operand = abs((instr / 100) % 10);
int mem_operand = (instr % 100);
// Decode instruction into opcode, reg_R, addr_MM, and instruction sign
//
// *** STUB ****
// Echo instruction
// *** STUB ***
switch (cpu -> opcode) {
case 0: exec_HLT(cpu); break;
// *** STUB ****
default: printf("Bad opcode!? %d ", cpu -> opcode);
}
}
// Execute the halt instruction (make CPU stop running)
//
void exec_HLT(CPU *cpu) {
// *** STUB *** Print a message?
cpu -> running = 0;
}
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
