From b534a9ec6cfeccab3588d98fb95f49449da67fc7 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 4 Mar 2019 15:25:35 -0500 Subject: [PATCH 01/16] initial commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e81f54cf..66248aa4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Computer Architecture +# Computer Architecture - ## Project From d6d31d4f17da187dea51f3542ffdaa187efd2a8f Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 4 Mar 2019 16:59:06 -0500 Subject: [PATCH 02/16] working on cpu_init() method --- ls8/cpu.c | 11 +++++++++++ ls8/cpu.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/ls8/cpu.c b/ls8/cpu.c index bdb1f506..f920789f 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -64,4 +64,15 @@ void cpu_run(struct cpu *cpu) void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers + cpu->PC = 0; } + +unsigned char cpu_ram_read(struct cpu *cpu, int address) +{ + return cpu->ram[address]; +} + +void cpu_ram_write(struct cpu *cpu, int address, unsigned char value) +{ + cpu->ram[address] = value; +} \ No newline at end of file diff --git a/ls8/cpu.h b/ls8/cpu.h index 46e49c44..052ead49 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -5,8 +5,11 @@ struct cpu { // TODO // PC + int PC; // registers (array) + int registers[8]; // ram (array) + unsigned char ram[8]; }; // ALU operations From af2e45ee5855b4d06e0c8d844e3c12ffb8f6ccb0 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 4 Mar 2019 17:06:01 -0500 Subject: [PATCH 03/16] cpu_init initializes PC, registers, and ram to 0 --- ls8/cpu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ls8/cpu.c b/ls8/cpu.c index f920789f..1e995587 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -65,6 +65,11 @@ void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers cpu->PC = 0; + + memset(cpu->registers, 0, 8*sizeof(int)); + + memset(cpu->ram, 0, 8*(sizeof(unsigned char))); + } unsigned char cpu_ram_read(struct cpu *cpu, int address) From 09ee1311778267f1d6ac0e3b1345bf112855eb4e Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 4 Mar 2019 18:24:19 -0500 Subject: [PATCH 04/16] working on cpu_run --- ls8/cpu.c | 23 ++++++++++++++++++++++- ls8/cpu.h | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 1e995587..a7e9a340 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -47,14 +47,35 @@ void cpu_run(struct cpu *cpu) { int running = 1; // True until we get a HLT instruction + int PC = cpu->PC; + int value; + while (running) { // TODO // 1. Get the value of the current instruction (in address PC). + unsigned char instruction = cpu->ram[PC]; // 2. Figure out how many operands this next instruction requires + + //int num_operands = instruction[0]; + // 3. Get the appropriate value(s) of the operands following this instruction // 4. switch() over it to decide on a course of action. // 5. Do whatever the instruction should do according to the spec. // 6. Move the PC to the next instruction. + switch(instruction) { + case HLT: + PC++; + break; + case LDI: + cpu->registers[PC] = value; + PC++; + break; + case PRN: + int reg_value = cpu->registers[PC]; + printf("%d", reg_value); + PC++; + break; + } } } @@ -66,7 +87,7 @@ void cpu_init(struct cpu *cpu) // TODO: Initialize the PC and other special registers cpu->PC = 0; - memset(cpu->registers, 0, 8*sizeof(int)); + memset(cpu->registers, 0, 8*sizeof(unsigned char)); memset(cpu->ram, 0, 8*(sizeof(unsigned char))); diff --git a/ls8/cpu.h b/ls8/cpu.h index 052ead49..9b9655e5 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -7,7 +7,7 @@ struct cpu { // PC int PC; // registers (array) - int registers[8]; + unsigned char registers[8]; // ram (array) unsigned char ram[8]; }; From 1775f6f63852e911add41666d7ec90ab5762fcd9 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 5 Mar 2019 15:18:56 -0500 Subject: [PATCH 05/16] fixed cpu_run --- ls8/cpu.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index a7e9a340..b9421ba2 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -1,4 +1,6 @@ #include "cpu.h" +#include "string.h" +#include "stdio.h" #define DATA_LEN 6 @@ -26,6 +28,16 @@ void cpu_load(struct cpu *cpu) // TODO: Replace this with something less hard-coded } +unsigned char cpu_ram_read(struct cpu *cpu, unsigned char address) +{ + return cpu->ram[address]; +} + +void cpu_ram_write(struct cpu *cpu, int address, unsigned char value) +{ + cpu->ram[address] = value; +} + /** * ALU */ @@ -47,14 +59,20 @@ void cpu_run(struct cpu *cpu) { int running = 1; // True until we get a HLT instruction - int PC = cpu->PC; - int value; + //int PC = cpu->PC; + //unsigned char value; while (running) { // TODO // 1. Get the value of the current instruction (in address PC). - unsigned char instruction = cpu->ram[PC]; + //unsigned char instruction = cpu->ram[PC]; + + unsigned char instruction = cpu_ram_read(cpu, cpu->PC); // 2. Figure out how many operands this next instruction requires + unsigned char operandA = cpu_ram_read(cpu, cpu->PC + 1); + unsigned char operandB = cpu_ram_read(cpu, cpu->PC + 2); + + //bitwise right shift //int num_operands = instruction[0]; @@ -64,16 +82,15 @@ void cpu_run(struct cpu *cpu) // 6. Move the PC to the next instruction. switch(instruction) { case HLT: - PC++; + running = 0; break; case LDI: - cpu->registers[PC] = value; - PC++; + cpu->registers[operandA] = operandB; + cpu->PC += 3; break; case PRN: - int reg_value = cpu->registers[PC]; - printf("%d", reg_value); - PC++; + printf("%d\n", cpu->registers[operandA]); + cpu->PC += 2; break; } } @@ -89,16 +106,6 @@ void cpu_init(struct cpu *cpu) memset(cpu->registers, 0, 8*sizeof(unsigned char)); - memset(cpu->ram, 0, 8*(sizeof(unsigned char))); - -} + memset(cpu->ram, 0, 8*sizeof(unsigned char)); -unsigned char cpu_ram_read(struct cpu *cpu, int address) -{ - return cpu->ram[address]; } - -void cpu_ram_write(struct cpu *cpu, int address, unsigned char value) -{ - cpu->ram[address] = value; -} \ No newline at end of file From 39c12cdb74e34c8473a00f2958c2a326e5a58271 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 5 Mar 2019 16:44:00 -0500 Subject: [PATCH 06/16] working on reading from files --- ls8/cpu.c | 21 ++++++++++++++++++++- ls8/cpu.h | 2 +- ls8/ls8.c | 20 ++++++++++++++++---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index b9421ba2..08c8606c 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -4,11 +4,14 @@ #define DATA_LEN 6 +FILE *fp; + /** * Load the binary bytes from a .ls8 source file into a RAM array */ -void cpu_load(struct cpu *cpu) +void cpu_load(struct cpu *cpu, char *program) { + /* char data[DATA_LEN] = { // From print8.ls8 0b10000010, // LDI R0,8 @@ -24,6 +27,22 @@ void cpu_load(struct cpu *cpu) for (int i = 0; i < DATA_LEN; i++) { cpu->ram[address++] = data[i]; } + */ + + unsigned char line[8]; + + fp = fopen(program, "r"); + + if( fp == NULL) { + fprintf(stderr, "Error opening file.\n"); + } + + int i; + while( fgets(line, 8, fp) != NULL ) { + cpu_ram_write(cpu, i, line); + } + + fclose(fp); // TODO: Replace this with something less hard-coded } diff --git a/ls8/cpu.h b/ls8/cpu.h index 9b9655e5..2a7ff459 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -30,7 +30,7 @@ enum alu_op { // Function declarations -extern void cpu_load(struct cpu *cpu); +extern void cpu_load(struct cpu *cpu, char *program); extern void cpu_init(struct cpu *cpu); extern void cpu_run(struct cpu *cpu); diff --git a/ls8/ls8.c b/ls8/ls8.c index d24578ee..32c98a19 100644 --- a/ls8/ls8.c +++ b/ls8/ls8.c @@ -1,16 +1,28 @@ #include #include "cpu.h" +#include /** * Main */ -int main(void) +int main(int argc, char **argv) { struct cpu cpu; + char *program; - cpu_init(&cpu); - cpu_load(&cpu); - cpu_run(&cpu); + if (argc < 2) { + fprintf(stderr, "Please specify which program the LS8 should run.\nUsage: ls8 program\n"); + exit(1); + + } else { + program = argv[1]; + + printf("%s\n", program); + + cpu_init(&cpu); + cpu_load(&cpu, program); + cpu_run(&cpu); + } return 0; } \ No newline at end of file From 220939534bf75299e9ca178a253548bc1c6da9e0 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 5 Mar 2019 17:11:20 -0500 Subject: [PATCH 07/16] added MUL instruction --- ls8/cpu.c | 30 +++++++++++++++++++++++++++++- ls8/cpu.h | 1 + ls8/ls8.c | 4 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 08c8606c..d4680e13 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -2,7 +2,7 @@ #include "string.h" #include "stdio.h" -#define DATA_LEN 6 +#define DATA_LEN 12 FILE *fp; @@ -11,8 +11,10 @@ FILE *fp; */ void cpu_load(struct cpu *cpu, char *program) { + /* char data[DATA_LEN] = { + // From print8.ls8 0b10000010, // LDI R0,8 0b00000000, @@ -20,6 +22,23 @@ void cpu_load(struct cpu *cpu, char *program) 0b01000111, // PRN R0 0b00000000, 0b00000001 // HLT + + + // Testing Mult instruction + 0b10000010, // LDI R0,8 + 0b00000000, + 0b00001000, + 0b10000010, // LDI R1,9 + 0b00000001, + 0b00001001, + 0b10100010, // MUL R0,R1 + 0b00000000, + 0b00000001, + 0b01000111, // PRN R0 + 0b00000000, + 0b00000001, // HLT + + }; int address = 0; @@ -100,17 +119,26 @@ void cpu_run(struct cpu *cpu) // 5. Do whatever the instruction should do according to the spec. // 6. Move the PC to the next instruction. switch(instruction) { + case HLT: running = 0; break; + case LDI: cpu->registers[operandA] = operandB; cpu->PC += 3; break; + case PRN: printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; break; + + case MUL: + cpu->registers[operandA] = (cpu->registers[operandA] * cpu->registers[operandB]); + cpu->PC += 2; + break; + } } } diff --git a/ls8/cpu.h b/ls8/cpu.h index 2a7ff459..260faaf5 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -26,6 +26,7 @@ enum alu_op { #define LDI 0b10000010 #define HLT 0b00000001 #define PRN 0b01000111 +#define MUL 0b10100010 // TODO: more instructions here. These can be used in cpu_run(). // Function declarations diff --git a/ls8/ls8.c b/ls8/ls8.c index 32c98a19..29dc25b0 100644 --- a/ls8/ls8.c +++ b/ls8/ls8.c @@ -24,5 +24,9 @@ int main(int argc, char **argv) cpu_run(&cpu); } + //cpu_init(&cpu); + //cpu_load(&cpu); + //cpu_run(&cpu); + return 0; } \ No newline at end of file From b166ef5bdd56971ef3b6e94f2a96a6b62e138fda Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 5 Mar 2019 18:10:24 -0500 Subject: [PATCH 08/16] working on reading from a file --- ls8/cpu.c | 12 +++++++----- ls8/mult.ls8 | 12 ++++++++++++ ls8/print8.ls8 | 6 ++++++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 ls8/mult.ls8 create mode 100644 ls8/print8.ls8 diff --git a/ls8/cpu.c b/ls8/cpu.c index d4680e13..9669f451 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -4,13 +4,13 @@ #define DATA_LEN 12 -FILE *fp; - /** * Load the binary bytes from a .ls8 source file into a RAM array */ void cpu_load(struct cpu *cpu, char *program) { + + FILE *fp; /* char data[DATA_LEN] = { @@ -48,7 +48,8 @@ void cpu_load(struct cpu *cpu, char *program) } */ - unsigned char line[8]; + char line[8*sizeof(unsigned char)]; + //char *read; fp = fopen(program, "r"); @@ -56,9 +57,10 @@ void cpu_load(struct cpu *cpu, char *program) fprintf(stderr, "Error opening file.\n"); } - int i; - while( fgets(line, 8, fp) != NULL ) { + int i = 0; + while( fgets(line, 8*sizeof(unsigned char), fp) != NULL ) { cpu_ram_write(cpu, i, line); + i++; } fclose(fp); diff --git a/ls8/mult.ls8 b/ls8/mult.ls8 new file mode 100644 index 00000000..c75dac2a --- /dev/null +++ b/ls8/mult.ls8 @@ -0,0 +1,12 @@ +10000010 # LDI R0,8 +00000000 +00001000 +10000010 # LDI R1,9 +00000001 +00001001 +10100010 # MUL R0,R1 +00000000 +00000001 +01000111 # PRN R0 +00000000 +00000001 # HLT diff --git a/ls8/print8.ls8 b/ls8/print8.ls8 new file mode 100644 index 00000000..f42540bc --- /dev/null +++ b/ls8/print8.ls8 @@ -0,0 +1,6 @@ +10000010 # LDI R0,8 +00000000 +00001000 +01000111 # PRN R0 +00000000 +00000001 # HLT From 93b85a6153886a7744d2c33b150343f709d8352d Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 5 Mar 2019 18:46:29 -0500 Subject: [PATCH 09/16] working on reading from a file --- ls8/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 9669f451..1669f738 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -59,11 +59,12 @@ void cpu_load(struct cpu *cpu, char *program) int i = 0; while( fgets(line, 8*sizeof(unsigned char), fp) != NULL ) { + printf("%s", line); cpu_ram_write(cpu, i, line); i++; } - fclose(fp); + //fclose(fp); // TODO: Replace this with something less hard-coded } From 44eed72430cb0a740b5954cd9f0780eea3f4dfe9 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 6 Mar 2019 15:08:34 -0500 Subject: [PATCH 10/16] fixed loading instructions from ls8 files --- ls8/cpu.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 1669f738..ad4699e9 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -1,6 +1,7 @@ #include "cpu.h" #include "string.h" #include "stdio.h" +#include #define DATA_LEN 12 @@ -48,23 +49,33 @@ void cpu_load(struct cpu *cpu, char *program) } */ - char line[8*sizeof(unsigned char)]; + char line[1024]; //char *read; fp = fopen(program, "r"); if( fp == NULL) { fprintf(stderr, "Error opening file.\n"); + exit(1); } int i = 0; - while( fgets(line, 8*sizeof(unsigned char), fp) != NULL ) { - printf("%s", line); - cpu_ram_write(cpu, i, line); + while( fgets(line, sizeof(line), fp) != NULL ) { + char *endPtr; + + unsigned char byte = strtol(line, &endPtr, 2); + + if(endPtr == line) { + continue; + } + + + //printf("%d", byte); + cpu_ram_write(cpu, i, byte); i++; } - //fclose(fp); + fclose(fp); // TODO: Replace this with something less hard-coded } @@ -139,6 +150,8 @@ void cpu_run(struct cpu *cpu) case MUL: cpu->registers[operandA] = (cpu->registers[operandA] * cpu->registers[operandB]); + //test that MUL completed successfully + printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; break; From e0a7c4973702e3f9fba0cd6127689cf3c6fdd92f Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 6 Mar 2019 16:22:31 -0500 Subject: [PATCH 11/16] working on system stack --- README.md | 26 ++++++++++++++------------ ls8/cpu.c | 15 +++++++++++++-- ls8/cpu.h | 2 ++ ls8/mult.ls8 | 12 ------------ ls8/print8.ls8 | 6 ------ 5 files changed, 29 insertions(+), 32 deletions(-) delete mode 100644 ls8/mult.ls8 delete mode 100644 ls8/print8.ls8 diff --git a/README.md b/README.md index 66248aa4..ec4fa468 100644 --- a/README.md +++ b/README.md @@ -7,22 +7,24 @@ ## Task List: add this to the first comment of your Pull Request ### Day 1: Get `print8.ls8` running -- [ ] Inventory what is here -- [ ] Implement `struct cpu` in `cpu.h` -- [ ] Add RAM functions `cpu_ram_read` and `cpu_ram_write` -- [ ] Implement `cpu_init()` -- [ ] Implement the core of `cpu_run()` -- [ ] Implement the `HLT` instruction handler -- [ ] Add the `LDI` instruction -- [ ] Add the `PRN` instruction +- [x] Inventory what is here +- [x] Implement `struct cpu` in `cpu.h` +- [x] Add RAM functions `cpu_ram_read` and `cpu_ram_write` +- [x] Implement `cpu_init()` +- [x] Implement the core of `cpu_run()` +- [x] Implement the `HLT` instruction handler +- [x] Add the `LDI` instruction +- [x] Add the `PRN` instruction ### Day 2: Add the ability to load files dynamically, get `mult.ls8` and `stack.ls8` running -- [ ] Un-hardcode the machine code -- [ ] Implement the `cpu_load` function to load an `.ls8` file given the filename passed in as an argument -- [ ] Implement a Multiply instruction and Print the result (run `mult8.ls8`) +- [x] Un-hardcode the machine code +- [x] Implement the `cpu_load` function to load an `.ls8` file given the filename passed in as an argument +- [x] Implement a Multiply instruction and Print the result (run `mult8.ls8`) + +### Day 3: - [ ] Implement the System Stack and be able to run the `stack.ls8` program -### Day 3: Get `call.ls8` running +### Day 4: Get `call.ls8` running - [ ] Implement the CALL and RET instructions - [ ] Implement Subroutine Calls and be able to run the `call.ls8` program diff --git a/ls8/cpu.c b/ls8/cpu.c index ad4699e9..fde1983f 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -62,14 +62,12 @@ void cpu_load(struct cpu *cpu, char *program) int i = 0; while( fgets(line, sizeof(line), fp) != NULL ) { char *endPtr; - unsigned char byte = strtol(line, &endPtr, 2); if(endPtr == line) { continue; } - //printf("%d", byte); cpu_ram_write(cpu, i, byte); i++; @@ -111,6 +109,9 @@ void cpu_run(struct cpu *cpu) { int running = 1; // True until we get a HLT instruction + int stack[256]; + int sp = 0xf4; + //int PC = cpu->PC; //unsigned char value; @@ -155,6 +156,16 @@ void cpu_run(struct cpu *cpu) cpu->PC += 2; break; + case PUSH: + sp--; + stack[sp] = cpu->registers[operandA]; + break; + + case POP: + cpu->registers[operandA] = stack[sp]; + sp++; + //printf("%d\n", cpu->registers[operandA]); + break; } } } diff --git a/ls8/cpu.h b/ls8/cpu.h index 260faaf5..dd0eb2c2 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -27,6 +27,8 @@ enum alu_op { #define HLT 0b00000001 #define PRN 0b01000111 #define MUL 0b10100010 +#define PUSH 0b01000101 +#define POP 0b01000110 // TODO: more instructions here. These can be used in cpu_run(). // Function declarations diff --git a/ls8/mult.ls8 b/ls8/mult.ls8 deleted file mode 100644 index c75dac2a..00000000 --- a/ls8/mult.ls8 +++ /dev/null @@ -1,12 +0,0 @@ -10000010 # LDI R0,8 -00000000 -00001000 -10000010 # LDI R1,9 -00000001 -00001001 -10100010 # MUL R0,R1 -00000000 -00000001 -01000111 # PRN R0 -00000000 -00000001 # HLT diff --git a/ls8/print8.ls8 b/ls8/print8.ls8 deleted file mode 100644 index f42540bc..00000000 --- a/ls8/print8.ls8 +++ /dev/null @@ -1,6 +0,0 @@ -10000010 # LDI R0,8 -00000000 -00001000 -01000111 # PRN R0 -00000000 -00000001 # HLT From 49922c4691d4fd3b0ad07d5a229e189a1692ac34 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 6 Mar 2019 16:44:35 -0500 Subject: [PATCH 12/16] system stack added, stack.ls8 runs --- ls8/cpu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index fde1983f..6f64e340 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -110,7 +110,7 @@ void cpu_run(struct cpu *cpu) int running = 1; // True until we get a HLT instruction int stack[256]; - int sp = 0xf4; + int sp = 0; //int PC = cpu->PC; //unsigned char value; @@ -159,12 +159,14 @@ void cpu_run(struct cpu *cpu) case PUSH: sp--; stack[sp] = cpu->registers[operandA]; + cpu->PC += 2; break; case POP: cpu->registers[operandA] = stack[sp]; sp++; //printf("%d\n", cpu->registers[operandA]); + cpu->PC += 2; break; } } From b571fe13871149b83b86bc74bc60125c96f1cb1d Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 6 Mar 2019 16:58:25 -0500 Subject: [PATCH 13/16] fixed a bug in system stack --- ls8/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 6f64e340..5038d58c 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -110,7 +110,7 @@ void cpu_run(struct cpu *cpu) int running = 1; // True until we get a HLT instruction int stack[256]; - int sp = 0; + int sp = 7; //int PC = cpu->PC; //unsigned char value; From 0937a082adf08b020f2e8147f3d226fac61046bf Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Thu, 7 Mar 2019 16:06:54 -0500 Subject: [PATCH 14/16] working on CALL and RET instructions --- ls8/cpu.c | 63 +++++++++++++------------------------------------------ ls8/cpu.h | 2 ++ ls8/ls8.c | 4 ---- 3 files changed, 17 insertions(+), 52 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 5038d58c..dd7f53bf 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -12,45 +12,8 @@ void cpu_load(struct cpu *cpu, char *program) { FILE *fp; - - /* - char data[DATA_LEN] = { - - // From print8.ls8 - 0b10000010, // LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, // PRN R0 - 0b00000000, - 0b00000001 // HLT - - - // Testing Mult instruction - 0b10000010, // LDI R0,8 - 0b00000000, - 0b00001000, - 0b10000010, // LDI R1,9 - 0b00000001, - 0b00001001, - 0b10100010, // MUL R0,R1 - 0b00000000, - 0b00000001, - 0b01000111, // PRN R0 - 0b00000000, - 0b00000001, // HLT - - - }; - - int address = 0; - - for (int i = 0; i < DATA_LEN; i++) { - cpu->ram[address++] = data[i]; - } - */ char line[1024]; - //char *read; fp = fopen(program, "r"); @@ -68,14 +31,12 @@ void cpu_load(struct cpu *cpu, char *program) continue; } - //printf("%d", byte); cpu_ram_write(cpu, i, byte); i++; } fclose(fp); - // TODO: Replace this with something less hard-coded } unsigned char cpu_ram_read(struct cpu *cpu, unsigned char address) @@ -118,18 +79,12 @@ void cpu_run(struct cpu *cpu) while (running) { // TODO // 1. Get the value of the current instruction (in address PC). - //unsigned char instruction = cpu->ram[PC]; - unsigned char instruction = cpu_ram_read(cpu, cpu->PC); // 2. Figure out how many operands this next instruction requires + // 3. Get the appropriate value(s) of the operands following this instruction unsigned char operandA = cpu_ram_read(cpu, cpu->PC + 1); unsigned char operandB = cpu_ram_read(cpu, cpu->PC + 2); - //bitwise right shift - - //int num_operands = instruction[0]; - - // 3. Get the appropriate value(s) of the operands following this instruction // 4. switch() over it to decide on a course of action. // 5. Do whatever the instruction should do according to the spec. // 6. Move the PC to the next instruction. @@ -165,9 +120,22 @@ void cpu_run(struct cpu *cpu) case POP: cpu->registers[operandA] = stack[sp]; sp++; - //printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; break; + + case CALL: + sp--; + stack[sp] = cpu->registers[operandA]; + cpu->PC = operandA; + stack[operandA]; + break; + + case RET: + cpu->PC = stack[sp]; + sp++; + break; + + } } } @@ -177,7 +145,6 @@ void cpu_run(struct cpu *cpu) */ void cpu_init(struct cpu *cpu) { - // TODO: Initialize the PC and other special registers cpu->PC = 0; memset(cpu->registers, 0, 8*sizeof(unsigned char)); diff --git a/ls8/cpu.h b/ls8/cpu.h index dd0eb2c2..eefc3d32 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -29,6 +29,8 @@ enum alu_op { #define MUL 0b10100010 #define PUSH 0b01000101 #define POP 0b01000110 +#define CALL 0b01010000 +#define RET 0b00010001 // TODO: more instructions here. These can be used in cpu_run(). // Function declarations diff --git a/ls8/ls8.c b/ls8/ls8.c index 29dc25b0..32c98a19 100644 --- a/ls8/ls8.c +++ b/ls8/ls8.c @@ -24,9 +24,5 @@ int main(int argc, char **argv) cpu_run(&cpu); } - //cpu_init(&cpu); - //cpu_load(&cpu); - //cpu_run(&cpu); - return 0; } \ No newline at end of file From 751d1673f2d2f08c5ac67ced81529102d3231273 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Thu, 7 Mar 2019 17:06:17 -0500 Subject: [PATCH 15/16] working on CALL instruction --- ls8/cpu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index dd7f53bf..50e0529c 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -126,13 +126,16 @@ void cpu_run(struct cpu *cpu) case CALL: sp--; stack[sp] = cpu->registers[operandA]; - cpu->PC = operandA; - stack[operandA]; + cpu->PC = cpu->registers[operandA]; + + cpu_ram_read(cpu, cpu->PC); break; case RET: - cpu->PC = stack[sp]; + cpu->registers[operandA] = stack[sp]; sp++; + + cpu->PC = cpu->registers[operandA]; break; From 21938c4a651105e9057e58e8fca435a0d556740c Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Fri, 8 Mar 2019 12:57:30 -0500 Subject: [PATCH 16/16] all tests pass MVP complete --- ls8/README.1.md | 174 ++++++++++++++++++++++++++++++++++++++++ ls8/cpu.c | 74 +++++++++++++---- ls8/cpu.h | 7 ++ ls8/examples/sctest.ls8 | 86 ++++++++++++++++++++ 4 files changed, 327 insertions(+), 14 deletions(-) create mode 100644 ls8/README.1.md create mode 100644 ls8/examples/sctest.ls8 diff --git a/ls8/README.1.md b/ls8/README.1.md new file mode 100644 index 00000000..c0e12237 --- /dev/null +++ b/ls8/README.1.md @@ -0,0 +1,174 @@ +# Sprint Challenge: Computer Architecture - Conditional Jumps + +This challenge allows you to practice the concepts and techniques learned over +the past week and apply them in a concrete project. This Sprint explored TOPIC. +During this Sprint, you studied CPU components, number bases, bitwise +operations, CPU stack, interrupts, and subroutines. + +In your challenge this week, you will demonstrate proficiency by adding _conditional jumps_ to your LS-8 emulator as well as answering a few questions during a one-on-one session with a PM. + +## Instructions + +**Read these instructions carefully. Understand exactly what is expected +_before_ starting this Sprint Challenge.** + +This is an individual assessment. All work must be your own. Your challenge +score is a measure of your ability to work independently using the material +covered through this sprint. You need to demonstrate proficiency in the concepts +and objectives introduced and practiced in preceding days. + +You are not allowed to collaborate during the Sprint Challenge. However, you are +encouraged to follow the twenty-minute rule and seek support from your PM and +Instructor in your cohort help channel on Slack. Your work reflects your +proficiency with Computer Architecture and your command of the related concepts +and techniques. + +You have three hours to complete this challenge. Plan your time accordingly. + +## Commits + +Commit your code regularly and meaningfully. This helps both you (in case you +ever need to return to old code for any number of reasons and your project manager. + +## Description + +In this code challenge, you will add _conditional jumps_ (AKA _conditional branching_) to your LS-8 emulator. + +## Project Set Up + +Options for submission, whichever is easier for you: + +* Copy your source into this repo, or... + +* Submit a PR for the Sprint Challenge from the `Computer-Architecture` repo + you've been using all along (in addition to the PR for `ANSWERS.md`) + +## Minimum Viable Product + +Your finished project must include all of the following requirements: + +- [ ] Add the `CMP` instruction and `equal` flag to your LS-8. + +- [ ] Add the `JMP` instruction. + +- [ ] Add the `JEQ` and `JNE` instructions. + +[See the LS-8 spec for details](https://github.com/LambdaSchool/Computer-Architecture/blob/master/LS8-spec.md) + +In your solution, it is essential that you follow best practices and produce +clean and professional results. Schedule time to review, refine, and assess your +work and perform basic professional polishing including spell-checking and +grammar-checking on your work. It is better to submit a challenge that meets MVP +than one that attempts too much and does not. + +Validate your work through testing and ensure that your code operates as designed. + +[Here is some code](sctest.ls8) that exercises the above instructions. It should +print: + +``` +1 +4 +5 +``` + +``` +# Code to test the Sprint Challenge +# +# Expected output: +# 1 +# 4 +# 5 + +10000010 # LDI R0,10 +00000000 +00001010 +10000010 # LDI R1,20 +00000001 +00010100 +10000010 # LDI R2,TEST1 +00000010 +00010011 +10100111 # CMP R0,R1 +00000000 +00000001 +01010101 # JEQ R2 +00000010 +10000010 # LDI R3,1 +00000011 +00000001 +01000111 # PRN R3 +00000011 +# TEST1 (address 19): +10000010 # LDI R2,TEST2 +00000010 +00100000 +10100111 # CMP R0,R1 +00000000 +00000001 +01010110 # JNE R2 +00000010 +10000010 # LDI R3,2 +00000011 +00000010 +01000111 # PRN R3 +00000011 +# TEST2 (address 32): +10000010 # LDI R1,10 +00000001 +00001010 +10000010 # LDI R2,TEST3 +00000010 +00110000 +10100111 # CMP R0,R1 +00000000 +00000001 +01010101 # JEQ R2 +00000010 +10000010 # LDI R3,3 +00000011 +00000011 +01000111 # PRN R3 +00000011 +# TEST3 (address 48): +10000010 # LDI R2,TEST4 +00000010 +00111101 +10100111 # CMP R0,R1 +00000000 +00000001 +01010110 # JNE R2 +00000010 +10000010 # LDI R3,4 +00000011 +00000100 +01000111 # PRN R3 +00000011 +# TEST4 (address 61): +10000010 # LDI R3,5 +00000011 +00000101 +01000111 # PRN R3 +00000011 +10000010 # LDI R2,TEST5 +00000010 +01001001 +01010100 # JMP R2 +00000010 +01000111 # PRN R3 +00000011 +# TEST5 (address 73): +00000001 # HLT +``` + +## Stretch Problems + +After finishing your required elements, you can push your work further. These +goals may or may not be things you have learned in this module but they build on +the material you just studied. Time allowing, stretch your limits and see if you +can deliver on the following optional goals: + +- [ ] Add the ALU operations: `AND` `OR` `XOR` `NOT` `SHL` `SHR` `MOD` +- [ ] Add an `ADDI` extension instruction to add an immediate value to a register +- [ ] Add timer interrupts +- [ ] Add keyboard interrupts diff --git a/ls8/cpu.c b/ls8/cpu.c index 50e0529c..76398eb7 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -22,7 +22,7 @@ void cpu_load(struct cpu *cpu, char *program) exit(1); } - int i = 0; + int i = 0x00; while( fgets(line, sizeof(line), fp) != NULL ) { char *endPtr; unsigned char byte = strtol(line, &endPtr, 2); @@ -31,8 +31,8 @@ void cpu_load(struct cpu *cpu, char *program) continue; } - cpu_ram_write(cpu, i, byte); - i++; + cpu_ram_write(cpu, i++, byte); + } fclose(fp); @@ -70,8 +70,8 @@ void cpu_run(struct cpu *cpu) { int running = 1; // True until we get a HLT instruction - int stack[256]; - int sp = 7; + //int stack[256]; + //int sp = cpu->registers[7]; //int PC = cpu->PC; //unsigned char value; @@ -110,34 +110,77 @@ void cpu_run(struct cpu *cpu) printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; break; - +/* case PUSH: sp--; - stack[sp] = cpu->registers[operandA]; + //cpu->registers[sp] = cpu->registers[operandA]; + cpu_ram_write(cpu, sp, cpu->registers[operandA]); cpu->PC += 2; break; case POP: - cpu->registers[operandA] = stack[sp]; + cpu->registers[operandA] = cpu_ram_read(cpu, sp); sp++; cpu->PC += 2; break; case CALL: sp--; - stack[sp] = cpu->registers[operandA]; - cpu->PC = cpu->registers[operandA]; - - cpu_ram_read(cpu, cpu->PC); + cpu->registers[sp] = cpu->registers[operandA]; + cpu_ram_write(cpu, cpu->PC, operandA); + cpu->PC = cpu->registers[sp]; break; case RET: - cpu->registers[operandA] = stack[sp]; + cpu->registers[operandA] = cpu_ram_read(cpu, sp); + cpu->PC = cpu->registers[operandA]; sp++; - + break; + */ + + case JMP: + //printf("jumping to instruction\n"); cpu->PC = cpu->registers[operandA]; break; + case CMP: + if(cpu->registers[operandA] == cpu->registers[operandB]) { + //printf("setting FL to 1\n"); + cpu->FL = 1; + cpu->PC += 3; + break; + + } else { + //printf("setting FL to 0\n"); + cpu->FL = 0; + cpu->PC += 3; + break; + } + //break; + + case JEQ: + if(cpu->FL == 1) { + cpu->PC = cpu->registers[operandA]; + break; + } else { + cpu->PC += 2; + break; + } + //break; + + case JNE: + if(cpu->FL == 0) { + cpu->PC = cpu->registers[operandA]; + break; + } else { + cpu->PC += 2; + break; + } + //break; + + default: + fprintf(stderr, "PC %02x: unknown instruction %02x\n", cpu->PC, instruction); + exit(3); } } @@ -149,9 +192,12 @@ void cpu_run(struct cpu *cpu) void cpu_init(struct cpu *cpu) { cpu->PC = 0; + cpu->FL = 0; memset(cpu->registers, 0, 8*sizeof(unsigned char)); memset(cpu->ram, 0, 8*sizeof(unsigned char)); + //cpu->registers[7] = 0xF4; + } diff --git a/ls8/cpu.h b/ls8/cpu.h index eefc3d32..5365b92d 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -6,6 +6,7 @@ struct cpu { // TODO // PC int PC; + int FL; // registers (array) unsigned char registers[8]; // ram (array) @@ -31,6 +32,12 @@ enum alu_op { #define POP 0b01000110 #define CALL 0b01010000 #define RET 0b00010001 + +#define CMP 0b10100111 +#define JMP 0b01010100 +#define JEQ 0b01010101 +#define JNE 0b01010110 + // TODO: more instructions here. These can be used in cpu_run(). // Function declarations diff --git a/ls8/examples/sctest.ls8 b/ls8/examples/sctest.ls8 new file mode 100644 index 00000000..8f86bba7 --- /dev/null +++ b/ls8/examples/sctest.ls8 @@ -0,0 +1,86 @@ +# Code to test the Sprint Challenge +# +# Expected output: +# 1 +# 4 +# 5 + +10000010 # LDI R0,10 +00000000 +00001010 +10000010 # LDI R1,20 +00000001 +00010100 +10000010 # LDI R2,TEST1 +00000010 +00010011 +10100111 # CMP R0,R1 +00000000 +00000001 +01010101 # JEQ R2 +00000010 +10000010 # LDI R3,1 +00000011 +00000001 +01000111 # PRN R3 +00000011 +# TEST1 (address 19): +10000010 # LDI R2,TEST2 +00000010 +00100000 +10100111 # CMP R0,R1 +00000000 +00000001 +01010110 # JNE R2 +00000010 +10000010 # LDI R3,2 +00000011 +00000010 +01000111 # PRN R3 +00000011 +# TEST2 (address 32): +10000010 # LDI R1,10 +00000001 +00001010 +10000010 # LDI R2,TEST3 +00000010 +00110000 +10100111 # CMP R0,R1 +00000000 +00000001 +01010101 # JEQ R2 +00000010 +10000010 # LDI R3,3 +00000011 +00000011 +01000111 # PRN R3 +00000011 +# TEST3 (address 48): +10000010 # LDI R2,TEST4 +00000010 +00111101 +10100111 # CMP R0,R1 +00000000 +00000001 +01010110 # JNE R2 +00000010 +10000010 # LDI R3,4 +00000011 +00000100 +01000111 # PRN R3 +00000011 +# TEST4 (address 61): +10000010 # LDI R3,5 +00000011 +00000101 +01000111 # PRN R3 +00000011 +10000010 # LDI R2,TEST5 +00000010 +01001001 +01010100 # JMP R2 +00000010 +01000111 # PRN R3 +00000011 +# TEST5 (address 73): +00000001 # HLT