From 16fa8d7cc8c92f5ab879e4cf9c6c0bbb3567860f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 24 May 2018 01:37:55 -0700 Subject: systemc: Import tests from the Accellera systemc distribution. Change-Id: Iad76b398949a55d768a34d027a2d8e3739953da6 Reviewed-on: https://gem5-review.googlesource.com/10845 Reviewed-by: Giacomo Travaglini Maintainer: Gabe Black --- .../systemc/misc/sim_tests/simple_cpu/datamem | 33 +++ .../sim_tests/simple_cpu/golden/simple_cpu.log | 85 +++++++ .../systemc/misc/sim_tests/simple_cpu/progmem | 14 ++ .../misc/sim_tests/simple_cpu/simple_cpu.cpp | 254 +++++++++++++++++++++ 4 files changed, 386 insertions(+) create mode 100644 src/systemc/tests/systemc/misc/sim_tests/simple_cpu/datamem create mode 100644 src/systemc/tests/systemc/misc/sim_tests/simple_cpu/golden/simple_cpu.log create mode 100644 src/systemc/tests/systemc/misc/sim_tests/simple_cpu/progmem create mode 100644 src/systemc/tests/systemc/misc/sim_tests/simple_cpu/simple_cpu.cpp (limited to 'src/systemc/tests/systemc/misc/sim_tests/simple_cpu') diff --git a/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/datamem b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/datamem new file mode 100644 index 000000000..8cc9b815c --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/datamem @@ -0,0 +1,33 @@ +200 +0x00000007 +0x00000001 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 +0x00000000 diff --git a/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/golden/simple_cpu.log b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/golden/simple_cpu.log new file mode 100644 index 000000000..66b206ee8 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/golden/simple_cpu.log @@ -0,0 +1,85 @@ +SystemC Simulation +CPU Halted + PC = 0x0 + R[0] = 0 + R[1] = 0 + R[2] = 0 + R[3] = 0 + R[4] = 0 + R[5] = 0 + R[6] = 0 + R[7] = 0 + R[8] = 0 + R[9] = 0 + R[10] = 0 + R[11] = 0 + R[12] = 0 + R[13] = 0 + R[14] = 0 + R[15] = 0 + R[16] = 0 + R[17] = 0 + R[18] = 0 + R[19] = 0 + R[20] = 0 + R[21] = 0 + R[22] = 0 + R[23] = 0 + R[24] = 0 + R[25] = 0 + R[26] = 0 + R[27] = 0 + R[28] = 0 + R[29] = 0 + R[30] = 0 + R[31] = 0 +Load: R[5] = Memory[0x0] +Load: R[6] = Memory[0x1] +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +R[5] = R[5] - R[6] +JNZ R[5] 0x2 +CPU Halted + PC = 0x4 + R[0] = 0 + R[1] = 0 + R[2] = 0 + R[3] = 0 + R[4] = 0 + R[5] = 0 + R[6] = 1 + R[7] = 0 + R[8] = 0 + R[9] = 0 + R[10] = 0 + R[11] = 0 + R[12] = 0 + R[13] = 0 + R[14] = 0 + R[15] = 0 + R[16] = 0 + R[17] = 0 + R[18] = 0 + R[19] = 0 + R[20] = 0 + R[21] = 0 + R[22] = 0 + R[23] = 0 + R[24] = 0 + R[25] = 0 + R[26] = 0 + R[27] = 0 + R[28] = 0 + R[29] = 0 + R[30] = 0 + R[31] = 0 diff --git a/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/progmem b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/progmem new file mode 100644 index 000000000..234d243f3 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/progmem @@ -0,0 +1,14 @@ +100 +0x45000000 +0x46000001 +0x85314000 +0xe5000002 +0x00000000 +0x20000004 +0x5f000010 +0x6110c000 +0x884a8000 +0xb8d5c000 +0xcf734000 +0x00000000 + diff --git a/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/simple_cpu.cpp b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/simple_cpu.cpp new file mode 100644 index 000000000..5e7b0cc4a --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/simple_cpu/simple_cpu.cpp @@ -0,0 +1,254 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + simple_cpu.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc., 2002-02-15 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#include "systemc.h" + +#define READ 0 +#define WRITE 1 + +SC_MODULE( exec_decode ) +{ + SC_HAS_PROCESS( exec_decode ); + + sc_in instruction; + sc_signal& program_counter; + + unsigned pc; // Program counter + unsigned cpu_reg[32]; // Cpu registers + + unsigned *data_mem; // The data memory + + exec_decode( sc_module_name NAME, + sc_signal& INSTRUCTION, + sc_signal& PROGRAM_COUNTER ) + : program_counter(PROGRAM_COUNTER) + { + instruction(INSTRUCTION); + SC_METHOD( entry ); + // sensitive only to the clock + sensitive << instruction; + + pc = 0x000000; // Power up reset value + for (int i =0; i<32; i++) cpu_reg[i] = 0; + + // Initialize the data memory from file datamem + FILE *fp = fopen("simple_cpu/datamem", "r"); + if (fp == (FILE *) 0) return; // No data mem file to read + // First field in this file is the size of data memory desired + int size; + fscanf(fp, "%d", &size); + data_mem = new unsigned[size]; + if (data_mem == (unsigned *) 0) { + printf("Not enough memory left\n"); + return; + } + unsigned mem_word; + size = 0; + while (fscanf(fp, "%x", &mem_word) != EOF) { + data_mem[size++] = mem_word; + } + + // Start off simulation by writing program_counter + program_counter.write(pc); + } + + // Functionality + void entry(); +}; + +void +exec_decode::entry() +{ + unsigned instr; + unsigned opcode; + unsigned regnum1, regnum2, regnum3; + unsigned addr; + + int i; + + instr = instruction.read(); + opcode = (instr & 0xe0000000) >> 29; // Extract opcode + switch(opcode) { + case 0x0: // Halt + printf("CPU Halted\n"); + printf("\tPC = 0x%x\n", pc); + for (i = 0; i < 32; i++) + printf("\tR[%d] = %x\n", i, cpu_reg[i]); + // Don't write pc and execution will stop + break; + case 0x1: // Store + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + addr = (instr & 0x00ffffff); // Extract address + printf("Store: Memory[0x%x] = R[%d]\n", addr, regnum1); + data_mem[addr] = cpu_reg[regnum1]; + pc = pc + 1; + program_counter.write(pc); + break; + case 0x2: // Load + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + addr = (instr & 0x00ffffff); // Extract address + printf("Load: R[%d] = Memory[0x%x]\n", regnum1, addr); + cpu_reg[regnum1] = data_mem[addr]; + pc = pc + 1; + program_counter.write(pc); + break; + case 0x3: // Add + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + regnum2 = (instr & 0x00f80000) >> 19; // Extract register number + regnum3 = (instr & 0x0007c000) >> 14; // Extract register number + printf("R[%d] = R[%d] + R[%d]\n", regnum3, regnum1, regnum2); + cpu_reg[regnum3] = cpu_reg[regnum1] + cpu_reg[regnum2]; + pc = pc + 1; + program_counter.write(pc); + break; + case 0x4: // Subtract + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + regnum2 = (instr & 0x00f80000) >> 19; // Extract register number + regnum3 = (instr & 0x0007c000) >> 14; // Extract register number + printf("R[%d] = R[%d] - R[%d]\n", regnum3, regnum1, regnum2); + cpu_reg[regnum3] = cpu_reg[regnum1] - cpu_reg[regnum2]; + pc = pc + 1; + program_counter.write(pc); + break; + case 0x5: // Multiply + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + regnum2 = (instr & 0x00f80000) >> 19; // Extract register number + regnum3 = (instr & 0x0007c000) >> 14; // Extract register number + printf("R[%d] = R[%d] * R[%d]\n", regnum3, regnum1, regnum2); + cpu_reg[regnum3] = cpu_reg[regnum1] * cpu_reg[regnum2]; + pc = pc + 1; + program_counter.write(pc); + break; + case 0x6: // Divide + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + regnum2 = (instr & 0x00f80000) >> 19; // Extract register number + regnum3 = (instr & 0x0007c000) >> 14; // Extract register number + printf("R[%d] = R[%d] / R[%d]\n", regnum3, regnum1, regnum2); + if (cpu_reg[regnum2] == 0) { + printf("Division exception - divide by zero\n"); + } + else { + cpu_reg[regnum3] = cpu_reg[regnum1] / cpu_reg[regnum2]; + } + pc = pc + 1; + program_counter.write(pc); + break; + case 0x7: // JNZ + regnum1 = (instr & 0x1f000000) >> 24; // Extract register number + addr = (instr & 0x00ffffff); // Extract address + printf("JNZ R[%d] 0x%x\n", regnum1, addr); + if (cpu_reg[regnum1] == 0x0) + pc = pc + 1; + else + pc = addr; + program_counter.write(pc); + break; + default: // Bad opcode + printf("Bad opcode 0x%x\n", opcode); + pc = pc + 1; + program_counter.write(pc); + break; + } +} + + +SC_MODULE( fetch ) +{ + SC_HAS_PROCESS( fetch ); + + sc_in program_counter; + sc_signal& instruction; + + unsigned *prog_mem; // The program memory + + fetch( sc_module_name NAME, + sc_signal& PROGRAM_COUNTER, + sc_signal& INSTRUCTION ) + : instruction(INSTRUCTION) + { + program_counter(PROGRAM_COUNTER); + SC_METHOD( entry ); + sensitive << program_counter; + + // Initialize the program memory from file progmem + FILE *fp = fopen("simple_cpu/progmem", "r"); + if (fp == (FILE *) 0) return; // No prog mem file to read + // First field in this file is the size of program memory desired + int size; + fscanf(fp, "%d", &size); + prog_mem = new unsigned[size]; + if (prog_mem == (unsigned *) 0) { + printf("Not enough memory left\n"); + return; + } + unsigned mem_word; + size = 0; + while (fscanf(fp, "%x", &mem_word) != EOF) { + prog_mem[size++] = mem_word; + } + instruction.write(0); + } + + // Functionality + void entry(); +}; + +void fetch::entry() +{ + unsigned pc, instr; + pc = program_counter.read(); + instr = prog_mem[pc]; + instruction.write(instr); +} + +int +sc_main(int ac, char *av[]) +{ + sc_signal pc; + sc_signal instr; + + exec_decode ED("ED", instr, pc); + fetch F("F", pc, instr); + + // instead of a testbench routine, we include the testbench here + sc_start(1, SC_NS); + sc_start( 10, SC_NS ); + + fflush( stdout ); + + return 0; +} -- cgit v1.2.3