/* main.c This file is part of the "First" CPU simulator project. Copyright (c) 2024 Efthymios Kritikos This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "gui.h" #include "simdata.h" #include #include #include "assembly.h" #include "cpu.h" #include void help(char* progname){ printf("Usage: %s -i \n", progname); } #define ADDR_SIZE 16777216 int dump_rom(char* filename, struct simdata_t *simdata){ FILE* outfile=fopen(filename,"w"); for(int i=0;iRAM+i),outfile); fclose(outfile); return 0; } int main(int argc, char* argd[] ){ /// PARSE COMMAND LINE /// char *infile = NULL; char *assemble = NULL; int opt; while ((opt = getopt(argc, argd, "hi:a:")) != -1) { switch (opt) { case 'h': help(argd[0]); return 0; break; case 'i': infile=optarg; break; case 'a': assemble=optarg; break; default: help(argd[0]); return 1; break; } } if (infile==NULL){ help(argd[0]); return 1; } /// READ INPUT FILE /// FILE* rom=fopen(infile,"r"); if(!rom){ printf("Couldn't open input file %s\n",infile); return 1; } struct simdata_t *simdata = init_simdata(); if(!simdata){ printf("Couldn't allocate memory\n"); return 1; } if ( assemble != NULL ){ /* RUN ASSEMBLER */ struct assembler_context_t *assembler_context=malloc(sizeof(struct assembler_context_t)); for (int i=0;iRAM[i]=0; int linec=0; if (rom != NULL) { char line [1000]; uint32_t opcode; uint32_t addr=0; while(fgets(line,sizeof(line),rom)!= NULL){ for(int i=0;line[i];i++) if(line[i]==0x0a) line[i]=0; opcode=assemble_line(line,assembler_context); if(opcode>0xFFFFFFF1){ printf("Error assembling %s:%d\n", infile,linec+1); fclose(rom); free_assembler_context(assembler_context); free_simdata(simdata); return 1; }else{ simdata->RAM[addr]=(0xFF000000&opcode)>>24; addr++; simdata->RAM[addr]=(0xFF0000&opcode)>>16; addr++; simdata->RAM[addr]=(0xFF00&opcode)>>8; addr++; simdata->RAM[addr]=(0xFF&opcode); addr++; } linec++; } } free_assembler_context(assembler_context); dump_rom(assemble,simdata); free_simdata(simdata); }else{ /* RUN SIMULATOR */ if (rom == NULL) { printf("ERROR: Couldn't open rom file\n"); perror(infile); fclose(rom); free_simdata(simdata); return 1; } fseek(rom, 0, SEEK_END); if(ftell(rom)!=ADDR_SIZE){ printf("ERROR: ROM file isn't 16MiB\n"); fclose(rom); free_simdata(simdata); return 1; } fseek(rom, 0, SEEK_SET); if(!simdata){ gui_error("failed to initialise simdata\n"); fclose(rom); free_simdata(simdata); return 1; } if(fread(simdata->RAM, ADDR_SIZE, 1, rom)==0){ printf("ERROR: failed to read input file\n"); free_simdata(simdata); fclose(rom); return 1; } fclose(rom); /// INITIALISE GUI /// if(start_gui()){ printf("Failed on start_gui()\n"); cpu_simdata_free(simdata); free_simdata(simdata); return 1; } cpu_simdata_malloc(simdata); while(1){ update_gui(simdata); int ret_code; if((ret_code=gui_continue_request(simdata))){ if(ret_code==2) break; end_gui(); printf("Failed on gui_continue_request()\n"); cpu_simdata_free(simdata); free_simdata(simdata); return 1; } if(simdata->cpu_state==CPU_RUNNING){ int ret; if((ret=cpu_cycle_clock(simdata))){ cpu_simdata_free(simdata); free_simdata(simdata); end_gui(); switch(ret){ case 1: printf("Failed to execute instruction\n"); break; case 2: printf("Failed to decode instruction\n"); break; case 3: printf("Failed to fetch instruction\n"); break; case 4: printf("Internal simulator error\n"); break; default: printf("Unkown CPU failure\n"); } return 1; } }else usleep(100000); } if(end_gui()){ printf("Failed on end_gui()\n"); cpu_simdata_free(simdata); free_simdata(simdata); return 1; } cpu_simdata_free(simdata); free_simdata(simdata); } return 0; }