112855Sgabeblack@google.com/***************************************************************************** 212855Sgabeblack@google.com 312855Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412855Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 512855Sgabeblack@google.com with this work for additional information regarding copyright ownership. 612855Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 712855Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 812855Sgabeblack@google.com License. You may obtain a copy of the License at 912855Sgabeblack@google.com 1012855Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1112855Sgabeblack@google.com 1212855Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1312855Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1412855Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512855Sgabeblack@google.com implied. See the License for the specific language governing 1612855Sgabeblack@google.com permissions and limitations under the License. 1712855Sgabeblack@google.com 1812855Sgabeblack@google.com *****************************************************************************/ 1912855Sgabeblack@google.com 2012855Sgabeblack@google.com/***************************************************************************** 2112855Sgabeblack@google.com 2212855Sgabeblack@google.com simple_cpu.cpp -- 2312855Sgabeblack@google.com 2412855Sgabeblack@google.com Original Author: Martin Janssen, Synopsys, Inc., 2002-02-15 2512855Sgabeblack@google.com 2612855Sgabeblack@google.com *****************************************************************************/ 2712855Sgabeblack@google.com 2812855Sgabeblack@google.com/***************************************************************************** 2912855Sgabeblack@google.com 3012855Sgabeblack@google.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 3112855Sgabeblack@google.com changes you are making here. 3212855Sgabeblack@google.com 3312855Sgabeblack@google.com Name, Affiliation, Date: 3412855Sgabeblack@google.com Description of Modification: 3512855Sgabeblack@google.com 3612855Sgabeblack@google.com *****************************************************************************/ 3712855Sgabeblack@google.com 3812855Sgabeblack@google.com#include "systemc.h" 3912855Sgabeblack@google.com 4012855Sgabeblack@google.com#define READ 0 4112855Sgabeblack@google.com#define WRITE 1 4212855Sgabeblack@google.com 4312855Sgabeblack@google.comSC_MODULE( exec_decode ) 4412855Sgabeblack@google.com{ 4512855Sgabeblack@google.com SC_HAS_PROCESS( exec_decode ); 4612855Sgabeblack@google.com 4712855Sgabeblack@google.com sc_in<unsigned> instruction; 4812855Sgabeblack@google.com sc_signal<unsigned>& program_counter; 4912855Sgabeblack@google.com 5012855Sgabeblack@google.com unsigned pc; // Program counter 5112855Sgabeblack@google.com unsigned cpu_reg[32]; // Cpu registers 5212855Sgabeblack@google.com 5312855Sgabeblack@google.com unsigned *data_mem; // The data memory 5412855Sgabeblack@google.com 5512855Sgabeblack@google.com exec_decode( sc_module_name NAME, 5612855Sgabeblack@google.com sc_signal<unsigned>& INSTRUCTION, 5712855Sgabeblack@google.com sc_signal<unsigned>& PROGRAM_COUNTER ) 5812855Sgabeblack@google.com : program_counter(PROGRAM_COUNTER) 5912855Sgabeblack@google.com { 6012855Sgabeblack@google.com instruction(INSTRUCTION); 6112855Sgabeblack@google.com SC_METHOD( entry ); 6212855Sgabeblack@google.com // sensitive only to the clock 6312855Sgabeblack@google.com sensitive << instruction; 6412855Sgabeblack@google.com 6512855Sgabeblack@google.com pc = 0x000000; // Power up reset value 6612855Sgabeblack@google.com for (int i =0; i<32; i++) cpu_reg[i] = 0; 6712855Sgabeblack@google.com 6812855Sgabeblack@google.com // Initialize the data memory from file datamem 6912855Sgabeblack@google.com FILE *fp = fopen("simple_cpu/datamem", "r"); 7012855Sgabeblack@google.com if (fp == (FILE *) 0) return; // No data mem file to read 7112855Sgabeblack@google.com // First field in this file is the size of data memory desired 7212855Sgabeblack@google.com int size; 7312855Sgabeblack@google.com fscanf(fp, "%d", &size); 7412855Sgabeblack@google.com data_mem = new unsigned[size]; 7512855Sgabeblack@google.com if (data_mem == (unsigned *) 0) { 7612855Sgabeblack@google.com printf("Not enough memory left\n"); 7712855Sgabeblack@google.com return; 7812855Sgabeblack@google.com } 7912855Sgabeblack@google.com unsigned mem_word; 8012855Sgabeblack@google.com size = 0; 8112855Sgabeblack@google.com while (fscanf(fp, "%x", &mem_word) != EOF) { 8212855Sgabeblack@google.com data_mem[size++] = mem_word; 8312855Sgabeblack@google.com } 8412855Sgabeblack@google.com 8512855Sgabeblack@google.com // Start off simulation by writing program_counter 8612855Sgabeblack@google.com program_counter.write(pc); 8712855Sgabeblack@google.com } 8812855Sgabeblack@google.com 8912855Sgabeblack@google.com // Functionality 9012855Sgabeblack@google.com void entry(); 9112855Sgabeblack@google.com}; 9212855Sgabeblack@google.com 9312855Sgabeblack@google.comvoid 9412855Sgabeblack@google.comexec_decode::entry() 9512855Sgabeblack@google.com{ 9612855Sgabeblack@google.com unsigned instr; 9712855Sgabeblack@google.com unsigned opcode; 9812855Sgabeblack@google.com unsigned regnum1, regnum2, regnum3; 9912855Sgabeblack@google.com unsigned addr; 10012855Sgabeblack@google.com 10112855Sgabeblack@google.com int i; 10212855Sgabeblack@google.com 10312855Sgabeblack@google.com instr = instruction.read(); 10412855Sgabeblack@google.com opcode = (instr & 0xe0000000) >> 29; // Extract opcode 10512855Sgabeblack@google.com switch(opcode) { 10612855Sgabeblack@google.com case 0x0: // Halt 10712855Sgabeblack@google.com printf("CPU Halted\n"); 10812855Sgabeblack@google.com printf("\tPC = 0x%x\n", pc); 10912855Sgabeblack@google.com for (i = 0; i < 32; i++) 11012855Sgabeblack@google.com printf("\tR[%d] = %x\n", i, cpu_reg[i]); 11112855Sgabeblack@google.com // Don't write pc and execution will stop 11212855Sgabeblack@google.com break; 11312855Sgabeblack@google.com case 0x1: // Store 11412855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 11512855Sgabeblack@google.com addr = (instr & 0x00ffffff); // Extract address 11612855Sgabeblack@google.com printf("Store: Memory[0x%x] = R[%d]\n", addr, regnum1); 11712855Sgabeblack@google.com data_mem[addr] = cpu_reg[regnum1]; 11812855Sgabeblack@google.com pc = pc + 1; 11912855Sgabeblack@google.com program_counter.write(pc); 12012855Sgabeblack@google.com break; 12112855Sgabeblack@google.com case 0x2: // Load 12212855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 12312855Sgabeblack@google.com addr = (instr & 0x00ffffff); // Extract address 12412855Sgabeblack@google.com printf("Load: R[%d] = Memory[0x%x]\n", regnum1, addr); 12512855Sgabeblack@google.com cpu_reg[regnum1] = data_mem[addr]; 12612855Sgabeblack@google.com pc = pc + 1; 12712855Sgabeblack@google.com program_counter.write(pc); 12812855Sgabeblack@google.com break; 12912855Sgabeblack@google.com case 0x3: // Add 13012855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 13112855Sgabeblack@google.com regnum2 = (instr & 0x00f80000) >> 19; // Extract register number 13212855Sgabeblack@google.com regnum3 = (instr & 0x0007c000) >> 14; // Extract register number 13312855Sgabeblack@google.com printf("R[%d] = R[%d] + R[%d]\n", regnum3, regnum1, regnum2); 13412855Sgabeblack@google.com cpu_reg[regnum3] = cpu_reg[regnum1] + cpu_reg[regnum2]; 13512855Sgabeblack@google.com pc = pc + 1; 13612855Sgabeblack@google.com program_counter.write(pc); 13712855Sgabeblack@google.com break; 13812855Sgabeblack@google.com case 0x4: // Subtract 13912855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 14012855Sgabeblack@google.com regnum2 = (instr & 0x00f80000) >> 19; // Extract register number 14112855Sgabeblack@google.com regnum3 = (instr & 0x0007c000) >> 14; // Extract register number 14212855Sgabeblack@google.com printf("R[%d] = R[%d] - R[%d]\n", regnum3, regnum1, regnum2); 14312855Sgabeblack@google.com cpu_reg[regnum3] = cpu_reg[regnum1] - cpu_reg[regnum2]; 14412855Sgabeblack@google.com pc = pc + 1; 14512855Sgabeblack@google.com program_counter.write(pc); 14612855Sgabeblack@google.com break; 14712855Sgabeblack@google.com case 0x5: // Multiply 14812855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 14912855Sgabeblack@google.com regnum2 = (instr & 0x00f80000) >> 19; // Extract register number 15012855Sgabeblack@google.com regnum3 = (instr & 0x0007c000) >> 14; // Extract register number 15112855Sgabeblack@google.com printf("R[%d] = R[%d] * R[%d]\n", regnum3, regnum1, regnum2); 15212855Sgabeblack@google.com cpu_reg[regnum3] = cpu_reg[regnum1] * cpu_reg[regnum2]; 15312855Sgabeblack@google.com pc = pc + 1; 15412855Sgabeblack@google.com program_counter.write(pc); 15512855Sgabeblack@google.com break; 15612855Sgabeblack@google.com case 0x6: // Divide 15712855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 15812855Sgabeblack@google.com regnum2 = (instr & 0x00f80000) >> 19; // Extract register number 15912855Sgabeblack@google.com regnum3 = (instr & 0x0007c000) >> 14; // Extract register number 16012855Sgabeblack@google.com printf("R[%d] = R[%d] / R[%d]\n", regnum3, regnum1, regnum2); 16112855Sgabeblack@google.com if (cpu_reg[regnum2] == 0) { 16212855Sgabeblack@google.com printf("Division exception - divide by zero\n"); 16312855Sgabeblack@google.com } 16412855Sgabeblack@google.com else { 16512855Sgabeblack@google.com cpu_reg[regnum3] = cpu_reg[regnum1] / cpu_reg[regnum2]; 16612855Sgabeblack@google.com } 16712855Sgabeblack@google.com pc = pc + 1; 16812855Sgabeblack@google.com program_counter.write(pc); 16912855Sgabeblack@google.com break; 17012855Sgabeblack@google.com case 0x7: // JNZ 17112855Sgabeblack@google.com regnum1 = (instr & 0x1f000000) >> 24; // Extract register number 17212855Sgabeblack@google.com addr = (instr & 0x00ffffff); // Extract address 17312855Sgabeblack@google.com printf("JNZ R[%d] 0x%x\n", regnum1, addr); 17412855Sgabeblack@google.com if (cpu_reg[regnum1] == 0x0) 17512855Sgabeblack@google.com pc = pc + 1; 17612855Sgabeblack@google.com else 17712855Sgabeblack@google.com pc = addr; 17812855Sgabeblack@google.com program_counter.write(pc); 17912855Sgabeblack@google.com break; 18012855Sgabeblack@google.com default: // Bad opcode 18112855Sgabeblack@google.com printf("Bad opcode 0x%x\n", opcode); 18212855Sgabeblack@google.com pc = pc + 1; 18312855Sgabeblack@google.com program_counter.write(pc); 18412855Sgabeblack@google.com break; 18512855Sgabeblack@google.com } 18612855Sgabeblack@google.com} 18712855Sgabeblack@google.com 18812855Sgabeblack@google.com 18912855Sgabeblack@google.comSC_MODULE( fetch ) 19012855Sgabeblack@google.com{ 19112855Sgabeblack@google.com SC_HAS_PROCESS( fetch ); 19212855Sgabeblack@google.com 19312855Sgabeblack@google.com sc_in<unsigned> program_counter; 19412855Sgabeblack@google.com sc_signal<unsigned>& instruction; 19512855Sgabeblack@google.com 19612855Sgabeblack@google.com unsigned *prog_mem; // The program memory 19712855Sgabeblack@google.com 19812855Sgabeblack@google.com fetch( sc_module_name NAME, 19912855Sgabeblack@google.com sc_signal<unsigned>& PROGRAM_COUNTER, 20012855Sgabeblack@google.com sc_signal<unsigned>& INSTRUCTION ) 20112855Sgabeblack@google.com : instruction(INSTRUCTION) 20212855Sgabeblack@google.com { 20312855Sgabeblack@google.com program_counter(PROGRAM_COUNTER); 20412855Sgabeblack@google.com SC_METHOD( entry ); 20512855Sgabeblack@google.com sensitive << program_counter; 20612855Sgabeblack@google.com 20712855Sgabeblack@google.com // Initialize the program memory from file progmem 20812855Sgabeblack@google.com FILE *fp = fopen("simple_cpu/progmem", "r"); 20912855Sgabeblack@google.com if (fp == (FILE *) 0) return; // No prog mem file to read 21012855Sgabeblack@google.com // First field in this file is the size of program memory desired 21112855Sgabeblack@google.com int size; 21212855Sgabeblack@google.com fscanf(fp, "%d", &size); 21312855Sgabeblack@google.com prog_mem = new unsigned[size]; 21412855Sgabeblack@google.com if (prog_mem == (unsigned *) 0) { 21512855Sgabeblack@google.com printf("Not enough memory left\n"); 21612855Sgabeblack@google.com return; 21712855Sgabeblack@google.com } 21812855Sgabeblack@google.com unsigned mem_word; 21912855Sgabeblack@google.com size = 0; 22012855Sgabeblack@google.com while (fscanf(fp, "%x", &mem_word) != EOF) { 22112855Sgabeblack@google.com prog_mem[size++] = mem_word; 22212855Sgabeblack@google.com } 22312855Sgabeblack@google.com instruction.write(0); 22412855Sgabeblack@google.com } 22512855Sgabeblack@google.com 22612855Sgabeblack@google.com // Functionality 22712855Sgabeblack@google.com void entry(); 22812855Sgabeblack@google.com}; 22912855Sgabeblack@google.com 23012855Sgabeblack@google.comvoid fetch::entry() 23112855Sgabeblack@google.com{ 23212855Sgabeblack@google.com unsigned pc, instr; 23312855Sgabeblack@google.com pc = program_counter.read(); 23412855Sgabeblack@google.com instr = prog_mem[pc]; 23512855Sgabeblack@google.com instruction.write(instr); 23612855Sgabeblack@google.com} 23712855Sgabeblack@google.com 23812855Sgabeblack@google.comint 23912855Sgabeblack@google.comsc_main(int ac, char *av[]) 24012855Sgabeblack@google.com{ 24112855Sgabeblack@google.com sc_signal<unsigned> pc; 24212855Sgabeblack@google.com sc_signal<unsigned> instr; 24312855Sgabeblack@google.com 24412855Sgabeblack@google.com exec_decode ED("ED", instr, pc); 24512855Sgabeblack@google.com fetch F("F", pc, instr); 24612855Sgabeblack@google.com 24712855Sgabeblack@google.com // instead of a testbench routine, we include the testbench here 24812855Sgabeblack@google.com sc_start(1, SC_NS); 24912855Sgabeblack@google.com sc_start( 10, SC_NS ); 25012855Sgabeblack@google.com 25112855Sgabeblack@google.com fflush( stdout ); 25212855Sgabeblack@google.com 25312855Sgabeblack@google.com return 0; 25412855Sgabeblack@google.com} 255