summaryrefslogtreecommitdiff
path: root/src/systemc/tests/systemc/misc/sim_tests/simple_cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/tests/systemc/misc/sim_tests/simple_cpu')
-rw-r--r--src/systemc/tests/systemc/misc/sim_tests/simple_cpu/datamem33
-rw-r--r--src/systemc/tests/systemc/misc/sim_tests/simple_cpu/golden/simple_cpu.log85
-rw-r--r--src/systemc/tests/systemc/misc/sim_tests/simple_cpu/progmem14
-rw-r--r--src/systemc/tests/systemc/misc/sim_tests/simple_cpu/simple_cpu.cpp254
4 files changed, 386 insertions, 0 deletions
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<unsigned> instruction;
+ sc_signal<unsigned>& 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<unsigned>& INSTRUCTION,
+ sc_signal<unsigned>& 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<unsigned> program_counter;
+ sc_signal<unsigned>& instruction;
+
+ unsigned *prog_mem; // The program memory
+
+ fetch( sc_module_name NAME,
+ sc_signal<unsigned>& PROGRAM_COUNTER,
+ sc_signal<unsigned>& 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<unsigned> pc;
+ sc_signal<unsigned> 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;
+}