CPU: Created a basic CPU that can run a loop, along with several small bugfixes elsewhere to make it work
This commit is contained in:
parent
bd84eb5b2e
commit
5595ea91f2
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
*.o
|
*.o
|
||||||
first
|
first
|
||||||
test.rom
|
test.rom
|
||||||
|
make.deps
|
||||||
|
8
Makefile
8
Makefile
@ -2,7 +2,13 @@ QUIET=1
|
|||||||
|
|
||||||
all:first
|
all:first
|
||||||
|
|
||||||
OBJECT_FILES=gui.o main.o simdata.o assembly.o
|
OBJECT_FILES=gui.o main.o simdata.o assembly.o cpu.o
|
||||||
|
|
||||||
|
make.deps: $(subst .o,.c,${OBJECT_FILES}) $(wildcard *.h)
|
||||||
|
@$(CC) -MM $(subst .o,.c,${OBJECT_FILES}) > make.deps
|
||||||
|
|
||||||
|
include make.deps
|
||||||
|
|
||||||
|
|
||||||
ifeq "${QUIET}" "1"
|
ifeq "${QUIET}" "1"
|
||||||
QUIET_CC = @echo ' CC '$@;
|
QUIET_CC = @echo ' CC '$@;
|
||||||
|
136
cpu.c
Normal file
136
cpu.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "simdata.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct fetch_data_t *malloc_fetch_data(){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void free_fetch_data(__attribute__((unused)) struct fetch_data_t *tofree){
|
||||||
|
}
|
||||||
|
int fetch(struct simdata_t *simdata){
|
||||||
|
simdata->decode_data->in_bytecode=(uint32_t)(simdata->RAM[simdata->PC])<<24|(uint32_t)(simdata->RAM[simdata->PC+1])<<16|(uint32_t)(simdata->RAM[simdata->PC+2])<<8|(uint32_t)(simdata->RAM[simdata->PC+3]);
|
||||||
|
simdata->PC+=4;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct decode_data_t *malloc_decode_data(){
|
||||||
|
return malloc(sizeof(struct decode_data_t));
|
||||||
|
}
|
||||||
|
void free_decode_data(struct decode_data_t *tofree){
|
||||||
|
free(tofree);
|
||||||
|
}
|
||||||
|
int decode(struct simdata_t *simdata){
|
||||||
|
uint16_t opcode;
|
||||||
|
switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){
|
||||||
|
case 0:
|
||||||
|
opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24;
|
||||||
|
switch(opcode){
|
||||||
|
case 1:
|
||||||
|
simdata->exec_data->out_op->OP_ADDR=IMMEDIATE;
|
||||||
|
simdata->exec_data->out_op->data=simdata->decode_data->in_bytecode&0x00FFFFFF;
|
||||||
|
simdata->exec_data->EXEC_ACTION=JUMP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct exec_data_t *malloc_exec_data(){
|
||||||
|
struct exec_data_t *ret;
|
||||||
|
ret=malloc(sizeof(struct exec_data_t));
|
||||||
|
if(!ret)
|
||||||
|
return 0;
|
||||||
|
ret->in_op1=malloc(sizeof(struct exec_op_t));
|
||||||
|
if(!ret->in_op1){
|
||||||
|
free(ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret->in_op2=malloc(sizeof(struct exec_op_t));
|
||||||
|
if(!ret->in_op2){
|
||||||
|
free(ret->in_op1);
|
||||||
|
free(ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret->out_op=malloc(sizeof(struct exec_op_t));
|
||||||
|
if(!ret->out_op){
|
||||||
|
free(ret->in_op1);
|
||||||
|
free(ret->in_op2);
|
||||||
|
free(ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void free_exec_data(struct exec_data_t *tofree){
|
||||||
|
free(tofree->in_op1);
|
||||||
|
free(tofree->in_op2);
|
||||||
|
free(tofree->out_op);
|
||||||
|
free(tofree);
|
||||||
|
}
|
||||||
|
int exec(struct simdata_t *simdata){
|
||||||
|
switch(simdata->exec_data->EXEC_ACTION){
|
||||||
|
case JUMP:
|
||||||
|
if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE)
|
||||||
|
simdata->PC=simdata->exec_data->out_op->data;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case EXEC_ALU:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int state=0;
|
||||||
|
|
||||||
|
int cpu_cycle_clock(struct simdata_t *simdata){
|
||||||
|
switch(state){
|
||||||
|
case 0: if( fetch(simdata) ) return 1; break;
|
||||||
|
case 1: if( decode(simdata) ) return 1; break;
|
||||||
|
case 2: if( exec(simdata) ) return 1; break;
|
||||||
|
}
|
||||||
|
if(state==2)
|
||||||
|
state=0;
|
||||||
|
else
|
||||||
|
state++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cpu_simdata_malloc(struct simdata_t *simdata){
|
||||||
|
simdata->fetch_data=malloc_fetch_data();
|
||||||
|
simdata->decode_data=malloc_decode_data();
|
||||||
|
simdata->exec_data=malloc_exec_data();
|
||||||
|
if((simdata->fetch_data!=NULL)&&(simdata->decode_data!=NULL)&&(simdata->exec_data!=NULL))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_simdata_free(struct simdata_t *simdata){
|
||||||
|
free_fetch_data(simdata->fetch_data);
|
||||||
|
free_decode_data(simdata->decode_data);
|
||||||
|
free_exec_data(simdata->exec_data);
|
||||||
|
}
|
54
cpu.h
Normal file
54
cpu.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef CPU_HEADER
|
||||||
|
#include "simdata.h"
|
||||||
|
|
||||||
|
struct fetch_data_t{
|
||||||
|
|
||||||
|
};
|
||||||
|
struct decode_data_t{
|
||||||
|
uint32_t in_bytecode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///// EXEC DATA STRUCTURES ///////
|
||||||
|
enum EXEC_ACTION_t {
|
||||||
|
EXEC_ALU,
|
||||||
|
JUMP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ALU_OP_t {
|
||||||
|
ALU_ADD,
|
||||||
|
ALU_SUB,
|
||||||
|
ALU_SL,
|
||||||
|
ALU_SR,
|
||||||
|
ALU_CMP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OP_ADDR_t {
|
||||||
|
IMMEDIATE,
|
||||||
|
REGISTER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct exec_op_t {
|
||||||
|
enum OP_ADDR_t OP_ADDR;
|
||||||
|
uint32_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct exec_data_t {
|
||||||
|
enum EXEC_ACTION_t EXEC_ACTION;
|
||||||
|
enum ALU_OP_t ALU_OP;
|
||||||
|
struct exec_op_t *in_op1;
|
||||||
|
struct exec_op_t *in_op2;
|
||||||
|
struct exec_op_t *out_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cpu_simdata_free(struct simdata_t *simdata);
|
||||||
|
int cpu_simdata_malloc(struct simdata_t *simdata);
|
||||||
|
int cpu_cycle_clock(struct simdata_t *simdata);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#define CPU_HEADER
|
7
gui.c
7
gui.c
@ -170,6 +170,7 @@ int gui_error(char *str){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int update_general_disas(struct simdata_t *simdata){
|
int update_general_disas(struct simdata_t *simdata){
|
||||||
|
wclear(general_disas);
|
||||||
int width,height;
|
int width,height;
|
||||||
getmaxyx(general_disas,height,width);
|
getmaxyx(general_disas,height,width);
|
||||||
box(general_disas, 0 , 0);
|
box(general_disas, 0 , 0);
|
||||||
@ -219,6 +220,7 @@ int update_general_disas(struct simdata_t *simdata){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int update_general_stack(struct simdata_t *simdata){
|
int update_general_stack(struct simdata_t *simdata){
|
||||||
|
wclear(general_stack);
|
||||||
int width,height;
|
int width,height;
|
||||||
getmaxyx(general_stack,height,width);
|
getmaxyx(general_stack,height,width);
|
||||||
box(general_stack, 0 , 0);
|
box(general_stack, 0 , 0);
|
||||||
@ -275,6 +277,7 @@ int update_general_stack(struct simdata_t *simdata){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int update_general_memdump(struct simdata_t *simdata){
|
int update_general_memdump(struct simdata_t *simdata){
|
||||||
|
wclear(general_memdump);
|
||||||
int width,height;
|
int width,height;
|
||||||
getmaxyx(general_memdump,height,width);
|
getmaxyx(general_memdump,height,width);
|
||||||
box(general_memdump, 0 , 0);
|
box(general_memdump, 0 , 0);
|
||||||
@ -292,7 +295,7 @@ int update_general_memdump(struct simdata_t *simdata){
|
|||||||
wprintw(general_memdump,"%06x ",ADDRESS);
|
wprintw(general_memdump,"%06x ",ADDRESS);
|
||||||
uint32_t temp_address=ADDRESS;
|
uint32_t temp_address=ADDRESS;
|
||||||
for (int i=0;i<n;i++){
|
for (int i=0;i<n;i++){
|
||||||
if(ADDRESS>=simdata->PC&&ADDRESS<=simdata->PC+4)
|
if(ADDRESS>=simdata->PC&&ADDRESS<=simdata->PC+3)
|
||||||
wattron(general_memdump,A_BOLD);
|
wattron(general_memdump,A_BOLD);
|
||||||
else
|
else
|
||||||
wattroff(general_memdump,A_BOLD);
|
wattroff(general_memdump,A_BOLD);
|
||||||
@ -301,7 +304,7 @@ int update_general_memdump(struct simdata_t *simdata){
|
|||||||
}
|
}
|
||||||
ADDRESS=temp_address;
|
ADDRESS=temp_address;
|
||||||
for (int i=0;i<n;i++){
|
for (int i=0;i<n;i++){
|
||||||
if(ADDRESS>=simdata->PC&&ADDRESS<=simdata->PC+4)
|
if(ADDRESS>=simdata->PC&&ADDRESS<=simdata->PC+3)
|
||||||
wattron(general_memdump,A_BOLD);
|
wattron(general_memdump,A_BOLD);
|
||||||
else
|
else
|
||||||
wattroff(general_memdump,A_BOLD);
|
wattroff(general_memdump,A_BOLD);
|
||||||
|
24
main.c
24
main.c
@ -24,6 +24,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "assembly.h"
|
#include "assembly.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
void help(char* progname){
|
void help(char* progname){
|
||||||
printf("Usage: %s -i <file> \n", progname);
|
printf("Usage: %s -i <file> \n", progname);
|
||||||
@ -71,6 +72,10 @@ int main(int argc, char* argd[] ){
|
|||||||
FILE* rom=fopen(infile,"r");
|
FILE* rom=fopen(infile,"r");
|
||||||
|
|
||||||
struct simdata_t *simdata = init_simdata();
|
struct simdata_t *simdata = init_simdata();
|
||||||
|
if(!simdata){
|
||||||
|
printf("Couldn't allocate memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( assemble != NULL ){
|
if ( assemble != NULL ){
|
||||||
/* RUN ASSEMBLER */
|
/* RUN ASSEMBLER */
|
||||||
@ -127,7 +132,7 @@ int main(int argc, char* argd[] ){
|
|||||||
fseek(rom, 0, SEEK_SET);
|
fseek(rom, 0, SEEK_SET);
|
||||||
|
|
||||||
if(!simdata){
|
if(!simdata){
|
||||||
gui_error("failed to initialise simdata");
|
gui_error("failed to initialise simdata\n");
|
||||||
fclose(rom);
|
fclose(rom);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
return 1;
|
return 1;
|
||||||
@ -144,25 +149,42 @@ int main(int argc, char* argd[] ){
|
|||||||
/// INITIALISE GUI ///
|
/// INITIALISE GUI ///
|
||||||
if(start_gui()){
|
if(start_gui()){
|
||||||
printf("Failed on start_gui()\n");
|
printf("Failed on start_gui()\n");
|
||||||
|
cpu_simdata_free(simdata);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_simdata_malloc(simdata);
|
||||||
|
|
||||||
|
while(1){
|
||||||
update_gui(simdata);
|
update_gui(simdata);
|
||||||
|
|
||||||
if(gui_continue_request()){
|
if(gui_continue_request()){
|
||||||
end_gui();
|
end_gui();
|
||||||
printf("Failed on gui_continue_request()\n");
|
printf("Failed on gui_continue_request()\n");
|
||||||
|
cpu_simdata_free(simdata);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(cpu_cycle_clock(simdata)){
|
||||||
|
cpu_simdata_free(simdata);
|
||||||
|
free_simdata(simdata);
|
||||||
|
end_gui();
|
||||||
|
printf("Failed to execute instruction\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(end_gui()){
|
if(end_gui()){
|
||||||
printf("Failed on end_gui()\n");
|
printf("Failed on end_gui()\n");
|
||||||
|
cpu_simdata_free(simdata);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cpu_simdata_free(simdata);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6,6 +6,9 @@ struct simdata_t{
|
|||||||
uint8_t *RAM;
|
uint8_t *RAM;
|
||||||
uint32_t PC;
|
uint32_t PC;
|
||||||
uint32_t SP;
|
uint32_t SP;
|
||||||
|
struct fetch_data_t *fetch_data;
|
||||||
|
struct decode_data_t *decode_data;
|
||||||
|
struct exec_data_t *exec_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct simdata_t *init_simdata();
|
struct simdata_t *init_simdata();
|
||||||
@ -17,5 +20,6 @@ enum CPU_STATE_t{
|
|||||||
SINGLE_STEPPING,
|
SINGLE_STEPPING,
|
||||||
STOPPED
|
STOPPED
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#define SIMDATA_HEADER
|
#define SIMDATA_HEADER
|
||||||
|
Loading…
Reference in New Issue
Block a user