diff options
author | Gabe Black <gabeblack@google.com> | 2018-05-24 01:37:55 -0700 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2018-08-08 10:09:54 +0000 |
commit | 16fa8d7cc8c92f5ab879e4cf9c6c0bbb3567860f (patch) | |
tree | 7b6faaacb4574a555e561534aa4a8508c0624c32 /src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo | |
parent | 7235d3b5211d0ba8f528d930a4c1e7ad62eec51a (diff) | |
download | gem5-16fa8d7cc8c92f5ab879e4cf9c6c0bbb3567860f.tar.xz |
systemc: Import tests from the Accellera systemc distribution.
Change-Id: Iad76b398949a55d768a34d027a2d8e3739953da6
Reviewed-on: https://gem5-review.googlesource.com/10845
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>
Diffstat (limited to 'src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo')
9 files changed, 2402 insertions, 0 deletions
diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/common.h b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/common.h new file mode 100644 index 000000000..1a045ca83 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/common.h @@ -0,0 +1,46 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + common.h -- + + 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: + + *****************************************************************************/ + +#ifndef COMMON_H +#define COMMON_H + +#include "systemc.h" + +typedef sc_signal<sc_bv<8> > signal_bool_vector8; +typedef sc_signal<sc_bv<16> > signal_bool_vector16; + +#endif diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_dw8051_demo.f b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_dw8051_demo.f new file mode 100644 index 000000000..23d42bc71 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_dw8051_demo.f @@ -0,0 +1,3 @@ +cycle_dw8051_demo/cycle_model.cpp +cycle_dw8051_demo/peripheral.cpp +cycle_dw8051_demo/main.cpp diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.cpp b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.cpp new file mode 100644 index 000000000..1b77ef1a4 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.cpp @@ -0,0 +1,1761 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + cycle_model.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: + + *****************************************************************************/ + +//*************************************************************************** +// FILE: cycle_model.cc +// +// AUTHOR: Luc Semeria September, 21, 1998 +// +// ABSTRACT: cycle-accurate model based on the dw8051 architecture +// +// +// MODIFICATION HISTORY: +// Luc Semeria: 21/9/98 created +// +//*************************************************************************** +// +// DESCRIPTION +// +// During initialization, the model parses the Intel hex file and put the +// program into memory. +// Then the cycle-accurate model does the following operations: +// +// main loop: +// fetch instruction +// decode instruction +// execute instruction /read instr mem +// |\- fetch operand 1 (and 2) < /mem bus access +// | \fetch data < +// | \read data mem +// |\- execute operation +// | /mem bus access +// |\- write back data < +// | \write data mem +// | +// \- compute next address +// +// +// The external instruction and data memories are part of the model +// so these memory accesses are just read and write in internal memory +// The simulation is then speeded up because no bus transactions occurs. +// The model doesn't switch from one process to another. +// +// To communicate with peripheral on the memory bus, the bus can be +// used and the model automatically switches to a real cycle-accurate mode +// for a given number of cycle. This is implemented within the function: +// request_address(int addr); +// +// This cycle-accurate model implements only parts of the dw8051. The +// limitations are the following: +// - some instructions are not supported (cf decode function) +// - SFR, timers, io_interface and interrupts are not supported +// +//*************************************************************************** + +#include "cycle_model.h" +#include <string.h> + +/* useful macros for sc_aproc */ +#define AT_POSEDGE(CLK) wait(); while(!clk.posedge()) wait(); +#define AT_NEGEDGE(CLK) wait(); while(!clk.negedge()) wait(); + +bool ALL_CYCLES; /* flag to execute all cycles */ + + +//------------------------------------------------------------------------- +// void cycle_model::parse_hex(char *name) +// +// parse Intel HEX file +// more information on hex format on-line at: +// http://www.8052.com/tutintel.htm +// +//------------------------------------------------------------------------ +void cycle_model::parse_hex(char *name) { + char line_buffer[MEM_SIZE]; + FILE *hex_file; + + // open file + hex_file = fopen(name,"r"); + if(hex_file==NULL) { + fprintf(stderr,"Error in opening file %s\n",name); + exit(-1); + } + + // read new line at each loop ------------------------------------------ + while(fgets(line_buffer,MEM_SIZE,hex_file)!=NULL) { +#ifdef DEBUG + printf("Read new line -> %s",line_buffer); +#endif + + // parse line -------------------------------------------------------- + + // parse ':' (line[0]) + if(line_buffer[0]!=':') { + continue; + } + + + // parse length (line[1..2]) + int length; + // char length_string[2]; + char length_string[3]; + if(strncpy(length_string,&(line_buffer[1]),2)==NULL) { + fprintf(stderr,"Error in parsing length\n"); + exit(-1); + } + length_string[2] = 0; + length = (int)strtol(length_string, (char **)NULL, 16); +#ifdef DEBUG + printf("length=%x\n",length); +#endif + + // parse address (line[3..6]) + int address; + // char address_string[4]; + char address_string[5]; + if(strncpy(address_string,&(line_buffer[3]),4)==NULL) { + fprintf(stderr,"Error in parsing address\n"); + exit(-1); + } + address_string[4] = 0; + address = (int)strtol(address_string, (char **)NULL, 16); +#ifdef DEBUG + printf("address=%x\n",address); +#endif + + + // parse Record Type (line[7..8]) + int record_type; + // char record_string[2]; + char record_string[3]; + if(strncpy(record_string,&(line_buffer[7]),2)==NULL) { + fprintf(stderr,"Error in parsing record type\n"); + exit(-1); + } + record_string[2] = 0; + record_type = (int)strtol(record_string, (char **)NULL, 16); +#ifdef DEBUG + printf("record_type=%x\n",record_type); +#endif + if(record_type==01) { + // end of file + // return; +#ifdef DEBUG + printf("end of file => return\n"); +#endif + fclose(hex_file); + return; + } + + // parse data bytes + char instr_string[3]; + for(int i=0;i<length;i++) { + if(strncpy(instr_string,&(line_buffer[2*i+9]),2)==NULL) { + fprintf(stderr,"Error in parsing data byte %d\n",i); + exit(-1); + } + + instr_string[2] = 0; + int temp = (int)strtol(instr_string, (char **)NULL, 16); + instr_mem[address++] = temp; +#ifdef DEBUG + printf("data byte = %x\n",temp); +#endif + } + + // skip the checksum bits + + // verify end of line + if(line_buffer[2*length+9+2]!='\n') { + fprintf(stderr,"Error in parsing hex file: end of line expected\n"); + exit(-1); + } + + } + + fprintf(stderr,"Error in parsing hex file: end of file record type expected\n"); + exit(-1); + +} + + +//--------------------------------------------------------------------- +//void cycle_model::decode(int opcode, instr* i) +// +// take an opcode as an input and output the instruction with the +// proper operand types. +// +//--------------------------------------------------------------------- +void cycle_model::decode(int opcode, instr* i) { + + // default + i->type = i_nop; + i->n_src = 0; + i->src1.type = o_null; + i->src1.val = -1; + i->src2.type = o_null; + i->src2.val = -1; + i->dst.type = o_null; + i->dst.val = -1; + + switch(opcode) { + // arithmetic operations ----------------------------------------- + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2d: + case 0x2e: + case 0x2f: { + // add register to A + i->type = i_add; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x25: { + // add direct byte to A + i->type = i_add; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x26: + case 0x27: { + // add data memory to A + i->type = i_add; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x24: { + // add immediate to A + i->type = i_add; + i->n_src = 2; + i->src1.type = o_cst; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9d: + case 0x9e: + case 0x9f: { + // sub register to A + i->type = i_sub; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x95: { + // sub direct byte to A + i->type = i_sub; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x96: + case 0x97: { + // sub data memory to A + i->type = i_sub; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x94: { + // sub immediate to A + i->type = i_sub; + i->n_src = 2; + i->src1.type = o_cst; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x04: { + // increment A + i->type = i_inc; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0d: + case 0x0e: + case 0x0f: { + // increment register + i->type = i_inc; + i->n_src = 1; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->dst.type = o_reg; + i->dst.val = opcode&0x07; + i->cycle = 1; + break; + } + case 0x05: { + // increment direct byte + i->type = i_inc; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x06: + case 0x07: { + // increment data memory + i->type = i_inc; + i->n_src = 1; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->dst.type = o_ind; + i->dst.val = opcode&1; + i->cycle = 1; + break; + } + case 0x14: { + // decrement A + i->type = i_dec; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1d: + case 0x1e: + case 0x1f: { + // decrement register + i->type = i_dec; + i->n_src = 1; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->dst.type = o_reg; + i->dst.val = opcode&0x07; + i->cycle = 1; + break; + } + case 0x15: { + // decrement direct byte + i->type = i_dec; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x16: + case 0x17: { + // increment data memory + i->type = i_dec; + i->n_src = 1; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->dst.type = o_ind; + i->dst.val = opcode&1; + i->cycle = 1; + break; + } + // logic operation -------------------------------------------------- + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5d: + case 0x5e: + case 0x5f: { + // and register to A + i->type = i_and; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x55: { + // and direct byte to A + i->type = i_and; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x56: + case 0x57: { + // and data memory to A + i->type = i_and; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x54: { + // and immediate to A + i->type = i_and; + i->n_src = 2; + i->src1.type = o_cst; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x52: { + // and A to direct byte + i->type = i_and; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x53: { + // and immdiate to direct byte + i->type = i_and; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_cst; + i->dst.type = o_dir; + i->cycle = 3; + break; + } + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4d: + case 0x4e: + case 0x4f: { + // or register to A + i->type = i_or; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x45: { + // or direct byte to A + i->type = i_or; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x46: + case 0x47: { + // or data memory to A + i->type = i_or; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x44: { + // or immediate to A + i->type = i_or; + i->n_src = 2; + i->src1.type = o_cst; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x42: { + // or A to direct byte + i->type = i_or; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x43: { + // or immediate to direct byte + i->type = i_or; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_cst; + i->dst.type = o_dir; + i->cycle = 3; + break; + } + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6d: + case 0x6e: + case 0x6f: { + // xor register to A + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x65: { + // xor direct byte to A + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x66: + case 0x67: { + // xor data memory to A + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x64: { + // xor immediate to A + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_cst; + i->src2.type = o_acc; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0x62: { + // and A to direct byte + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_acc; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x63: { + // xor immdiate to direct byte + i->type = i_xor; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_cst; + i->dst.type = o_dir; + i->cycle = 3; + break; + } + case 0xf4: { + // complement A + i->type = i_cpl; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x23: { + // rotate A left + i->type = i_rl; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x03: { + // rotate A right + i->type = i_rr; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + // data transfer ----------------------------------------------- + case 0xe8: + case 0xe9: + case 0xeA: + case 0xeB: + case 0xeC: + case 0xed: + case 0xee: + case 0xef: { + // move register to A + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0xe5: { + // move direct bit to A + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0xe6: + case 0xe7: { + // move data memory to A + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_ind; + i->src1.val = opcode&1; + i->dst.type = o_acc; + i->cycle = 1; + break; + } + case 0x74: { + // move immediate to A + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_cst; + i->dst.type = o_acc; + i->cycle = 2; + break; + } + case 0xf8: + case 0xf9: + case 0xfA: + case 0xfB: + case 0xfC: + case 0xfd: + case 0xfe: + case 0xff: { + // move A to register + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_reg; + i->dst.val = opcode&0x07; + i->cycle = 1; + break; + } + case 0xa8: + case 0xa9: + case 0xaA: + case 0xaB: + case 0xaC: + case 0xad: + case 0xae: + case 0xaf: { + // move direct to register + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_reg; + i->dst.val = opcode&0x07; + i->cycle = 2; + break; + } + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7d: + case 0x7e: + case 0x7f: { + // move immediate to register + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_cst; + i->dst.type = o_reg; + i->dst.val = opcode&0x07; + i->cycle = 2; + break; + } + case 0xf5: { + // move A to direct byte + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_dir; + i->cycle = 2; + } + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8d: + case 0x8e: + case 0x8f: { + // move register to direct byte + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_reg; + i->src1.val = opcode&0x07; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x85: { + // move direct byte to direct byte + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_dir; + i->cycle = 3; + break; + } + case 0x86: + case 0x87: { + // move data memory to direct byte + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_ind; + i->src1.val = opcode&0x01; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0x75: { + // move immediate to direct byte + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_cst; + i->dst.type = o_dir; + i->cycle = 2; + break; + } + case 0xf6: + case 0xf7: { + // move A to data memory + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_ind; + i->dst.val = opcode&1; + i->cycle = 1; + break; + } + case 0xa6: + case 0xa7: { + // move direct byte to data memory + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_dir; + i->dst.type = o_ind; + i->dst.val = opcode&1; + i->cycle = 2; + break; + } + case 0x76: + case 0x77: { + // move immediate to data memory + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_cst; + i->dst.type = o_ind; + i->dst.val = opcode&1; + i->cycle = 2; + break; + } + case 0xe2: + case 0xe3: { + // move external data to A + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_ext; + i->src1.val = opcode&1; + i->dst.type = o_acc; + i->cycle = 2+stretch_cycles; + break; + } + case 0xf2: + case 0xf3: { + // move A to external data + i->type = i_mov; + i->n_src = 1; + i->src1.type = o_acc; + i->dst.type = o_ext; + i->dst.val = opcode&1; + i->cycle = 2+stretch_cycles; + break; + } + // branching ---------------------------------------------------- + case 0x11: + case 0x31: + case 0x51: + case 0x71: + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: { + // absolute call to subroutine + i->type = i_call; + i->n_src = 1; + i->src1.type = o_add; + i->src1.val = (opcode>>5)&7; + i->cycle = 3; + break; + } + case 0x12: { + // Long call to subroutine + i->type = i_call; + i->n_src = 1; + i->src1.type = o_ladd; + i->cycle = 4; + break; + } + case 0x22: { + // return from subroutine + i->type = i_ret; + i->cycle = 4; + break; + } + case 0x01: + case 0x21: + case 0x41: + case 0x61: + case 0x81: + case 0xa1: + case 0xc1: + case 0xe1: { + // absolute jump unconditional + i->type = i_jmp; + i->n_src = 1; + i->src1.type = o_add; + i->src1.val = (opcode>>5)&7; + i->cycle = 3; + break; + } + case 0x02: { + // Long jump unconditional + i->type = i_jmp; + i->n_src = 1; + i->src1.type = o_ladd; + i->cycle = 4; + break; + } + case 0x60: { + // jump on accumulator = 0 + i->type = i_jz; + i->n_src = 1; + i->src1.type = o_rel; + i->cycle = 3; + break; + } + case 0x70: { + // jump on accumulator != 0 + i->type = i_jnz; + i->n_src = 1; + i->src1.type = o_rel; + i->cycle = 3; + break; + } + case 0xb5: { + // compare A,direct JNE + i->type = i_cjne; + i->n_src = 2; + i->src1.type = o_acc; + i->src2.type = o_dir; + i->dst.type = o_rel; + i->cycle = 4; + break; + } + case 0xb4: { + // compare A,immeditate JNE + i->type = i_cjne; + i->n_src = 2; + i->src1.type = o_acc; + i->src2.type = o_cst; + i->dst.type = o_rel; + i->cycle = 4; + break; + } + case 0xB8: + case 0xB9: + case 0xBa: + case 0xBb: + case 0xBc: + case 0xBd: + case 0xBe: + case 0xBf: { + // compare reg,immeditate JNE + i->type = i_cjne; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode & 0x7; + i->src2.type = o_cst; + i->dst.type = o_rel; + i->cycle = 4; + break; + } + case 0xb6: + case 0xb7: { + // compare memory byte,immeditate JNE + i->type = i_cjne; + i->n_src = 2; + i->src1.type = o_ind; + i->src1.val = opcode & 0x1; + i->src2.type = o_cst; + i->dst.type = o_rel; + i->cycle = 4; + break; + } + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: { + // decrement reg, JNZ relative + i->type = i_djnz; + i->n_src = 2; + i->src1.type = o_reg; + i->src1.val = opcode & 0x7; + i->src2.type = o_rel; + i->cycle = 3; + break; + } + case 0xd5: { + // decrement direct byte, JNZ relative + i->type = i_djnz; + i->n_src = 2; + i->src1.type = o_dir; + i->src2.type = o_rel; + i->cycle = 4; + break; + } + // NOP -------------------------------------------------------------- + case 0x00: { + break; + } + default: { + + break; + fprintf(stderr,"opcode 0x%x not supported\n",opcode); + break; + } + } + +#ifdef DEBUG + printf("decode instr type:%d, src1: %d, src2: %d, dest %d, nb_cycles: %d\n",i->type, i->src1.type, i->src2.type, i->dst.type, i->cycle); +#endif +} + + +//-------------------------------------------------------------------- +// bool request_address(int ad); +// +// return 0 if the memory adress is external (i.e. external peripheral) +// update cycles2execute so that the simulation runs for a given +// number of clock cycles. +// +//-------------------------------------------------------------------- +bool cycle_model::request_address(int ad) { + // add peripheral driver here + // + // if(ad==<ADDRESS OF THE PERIPH>) { + // if(cycles2execute<=<NB_CYCLES>) + // cycles2execute = <NB_CYCLES>; + // return 0; + // } + + if(ad==0x10) { + if(cycles2execute<=30) + cycles2execute = 30; + return 0; + } + + if(ad==0x11) { + return 0; + } + + return 1; +} + + +//-------------------------------------------------------------------- +// exec_bus_cycle(bus_cycle_type op, int addr, int data, int* result) +// +// executes a bus cycle (IDLE, MEM_READ, MEM_WRITE). +// - IDLE: executes an idle cycle (4 clocks) +// - MEM_READ: reads from the memory bus (stretch+1 clocks) +// - MEM_WRITE: writes on the memory bus (stretch+1 clocks) +// +//-------------------------------------------------------------------- +void cycle_model::exec_bus_cycle(bus_cycle_type op, int addr, int data, int* result) { + int cycles = 0; + int mem_idle =0; + + + if(op==OP_IDLE) { + // OP_IDLE + if((cycles2execute>0)||ALL_CYCLES) { + // wait 4 cycles + mem_ale.write(0); + mem_wr_n.write(1); + mem_pswr_n.write(1); + mem_rd_n.write(1); + mem_psrd_n.write(1); + p0_mem_reg_n.write(0); + p0_addr_data_n.write(0); + AT_POSEDGE(clk); + AT_POSEDGE(clk); + AT_POSEDGE(clk); + AT_POSEDGE(clk); + cycles2execute -= 1; + } + + cycle_count += 1; + return; + } + + + // OP_MEM_READ or OP_MEM_WRITE + do { + cycles++; + + // Cycle 1 ********************************************************* + if(mem_idle==0) { + mem_ale.write(1); + mem_wr_n.write(1); + mem_pswr_n.write(1); + mem_rd_n.write(1); + mem_psrd_n.write(1); + p0_mem_reg_n.write(0); + p0_addr_data_n.write(0); + + if(op==OP_MEM_WRITE) { + mem_data_out.write( sc_bv<8>( data ) ); + p0_mem_reg_n.write(1); + p0_addr_data_n.write(1); + } + } + + AT_POSEDGE(clk); + + + // Cycle 2 ********************************************************* + if(mem_idle==0) { + switch (op) { + case OP_MEM_READ: { + mem_addr.write( sc_bv<16>( addr & 0x0000ffff ) ); + p0_mem_reg_n.write(1); + p0_addr_data_n.write(1); + p2_mem_reg_n.write(1); + break; + } + case OP_MEM_WRITE: { + mem_addr.write( sc_bv<16>( addr & 0x0000ffff ) ); + p0_addr_data_n.write(0); + p2_mem_reg_n.write(1); + break; + } + default: { + // do nothing + break; + } + } + } + if(mem_idle==0) { + AT_NEGEDGE(clk); + mem_ale.write(0); + } + + AT_POSEDGE(clk); + + + // Cycle 3 ********************************************************* + if(mem_idle==0) { + switch (op) { + case OP_MEM_READ: { + p0_mem_reg_n.write(0); + p0_addr_data_n.write(0); + + if(stretch_cycles==0) + mem_rd_n.write(0); // read RAM + break; + } + case OP_MEM_WRITE: { + if(stretch_cycles==0) + mem_wr_n.write(0); // write RAM + break; + } + default: { + // do nothing + break; + } + } + } + AT_POSEDGE(clk); + + + // Cycle 4 ********************************************************* + if (mem_idle==0) { + switch (op) { + case OP_MEM_READ: { + if(stretch_cycles>0) { + mem_idle=stretch_cycles+1; + mem_rd_n.write(0); // read RAM + } + break; + } + case OP_MEM_WRITE: { + if(stretch_cycles>0) { + mem_idle=stretch_cycles+1; + mem_wr_n.write(0); // write RAM + } + break; + } + default: { + // do nothing + break; + } + } + } + else if(mem_idle==1) { + // read/write enable <- 1 when stretch>0 + switch (op) { + case OP_MEM_READ: { + if(stretch_cycles>0) { + // read value + *result = mem_data_in.read().to_uint(); + // reset read enable + mem_rd_n.write(1); // read RAM + } + break; + } + case OP_MEM_WRITE: { + if(stretch_cycles>0) { + // reset write enable + mem_wr_n.write(1); // write RAM + } + break; + } + default: { + break; + } + } + } + AT_POSEDGE(clk); + + + // Cycle 1 (1st part) ********************************************** + if(mem_idle>0) + mem_idle--; + + if(mem_idle==0){ + switch(op) { + case OP_MEM_READ: + if(stretch_cycles==0) { + mem_rd_n.write(1); + *result = mem_data_in.read().to_uint(); + } + break; + case OP_MEM_WRITE: + if(stretch_cycles==0) + mem_wr_n.write(1); + break; + default: + break; + } + } + } while(mem_idle>0); + + sc_assert(cycles==(stretch_cycles+1)); + cycle_count += cycles; + cycles2execute-=cycles; + return; +} + + + + +//------------------------------------------------------------------------ +// int cycle_model::fetch_instr(int ad) +// +// fetches data (1byte) from instruction memory +// +//------------------------------------------------------------------------ +int cycle_model::fetch_instr(int ad) { + + sc_assert((ad<MEM_SIZE)&&(ad>=0)); + + int temp; + exec_bus_cycle(OP_IDLE, 0,0, &temp); + + int opcode = instr_mem[ad]; +#ifdef DEBUG + printf("Fetch instruction @0x%x (= 0x%x)\n",ad,opcode); +#endif + return opcode; +} + +//------------------------------------------------------------------------ +// int cycle_model::fetch_data(int ad) +// +// fetches data from memory which can be internal to the block or +// external (case of an hardware peripheral) +// +//------------------------------------------------------------------------ +int cycle_model::fetch_data(int addr) { + + int data = 0, result; + + bool is_internal = request_address(addr); + if(is_internal) { + // is internal + if((cycles2execute>0)||ALL_CYCLES) { + // Wait + for(int i=0; i<stretch_cycles+1; i++) { + exec_bus_cycle(OP_IDLE,addr,data,&result); + } + } + result = ext_mem[addr]; + } else { + // is external + exec_bus_cycle(OP_MEM_READ,addr,data,&result); + } + + return result; +} + + + +//------------------------------------------------------------------------ +// int cycle_model::write_data(int addr, int data) +// +// writes data on data memory which can be internal to the block or +// external (case of an hardware peripheral) +// +//------------------------------------------------------------------------ +int cycle_model::write_data(int addr, int data) { + + int result = 0; + + bool is_internal = request_address(addr); + + if(is_internal) { + // is internal + if((cycles2execute>0)||ALL_CYCLES) { + for(int i=0; i<stretch_cycles+1; i++) { + exec_bus_cycle(OP_IDLE,addr,data,&result); + } + } + ext_mem[addr]=data; + } else { + // is external + exec_bus_cycle(OP_MEM_WRITE,addr,data,&result); + } + + return result; +} + + +//-------------------------------------------------------------------- +// int cycle_model::fetch_operand(operand* op) +// +// returns the value of the operand +// +//-------------------------------------------------------------------- +int cycle_model::fetch_operand(operand* op) { + switch(op->type) { + case o_acc: { + return A; + break; + } + case o_reg: { + sc_assert((op->val<8)&&(op->val>=0)); +#ifdef DEBUG + printf("read R%d=%d\n",op->val,R[op->val]); +#endif + return R[op->val]; + break; + } + case o_dir: { + // fetch address + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + sc_assert((op->val<INT_SIZE)&&(op->val>=0)); + return int_mem[temp]; + break; + } + case o_ind: { + sc_assert((op->val==0)||(op->val==1)); + sc_assert((R[op->val]<INT_SIZE)&&(R[op->val]>=0)); + return int_mem[R[op->val]]; + break; + } + case o_ext: { + sc_assert((op->val==1)||(op->val==0)); + int addr = R[op->val]; + sc_assert((addr<MEM_SIZE)&&(addr>=0)); + + int result = fetch_data(addr); + + return result; + break; + } + case o_cst: { + // fetch next byte + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + return temp; + break; + } + case o_lcst: { + // fetch next 2 bytes + + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + + my_stack->address += 1; + sc_assert(my_stack->address<=MEM_SIZE); + temp = (temp<<8) + fetch_instr(my_stack->address); + + return temp; + break; + } + case o_add: { + // fetch next byte + my_stack->address += 1; + int temp = ((op->val)<<8) + fetch_instr(my_stack->address); + return temp; + break; + } + case o_ladd: { + // fetch next 2 bytes + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + + my_stack->address += 1; + temp = (temp<<8) + fetch_instr(my_stack->address); + return temp; + break; + } + case o_rel: { + // fetch next byte + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + if(temp<0x80) + return temp; + else + return -(0x100-temp); + break; + } + default: { + return -1; + break; + } + } + return -1; +} + +//-------------------------------------------------------------------- +// int write_back(operand *op, int value) +// +// write the value into the operand +// +//-------------------------------------------------------------------- +int cycle_model::write_back(operand* op, int v) { + switch(op->type) { + case o_acc: { + A = v; + return A; + break; + } + case o_reg: { + sc_assert((op->val<8)&&(op->val>=0)); + R[op->val] = v; +#ifdef DEBUG + printf("write R%d <- %d\n",op->val,R[op->val]); +#endif + return R[op->val]; + break; + } + case o_dir: { + // write address + my_stack->address += 1; + int temp = fetch_instr(my_stack->address); + sc_assert((temp<INT_SIZE)&&(temp>=0)); + int_mem[temp] = v; + return int_mem[temp]; + break; + } + case o_ind: { + sc_assert((op->val==0)||(op->val==1)); + sc_assert((R[op->val]<INT_SIZE)&&(R[op->val]>=0)); + int_mem[R[op->val]] = v; + return int_mem[R[op->val]]; + break; + } + case o_ext: { + sc_assert((op->val==1)||(op->val==0)); + int addr = R[op->val]; + sc_assert((addr<MEM_SIZE)&&(addr>=0)); + int data, result; + data = v; + result = write_data(addr,data); + return result; + break; + } + default: { + return -1; + break; + } + } + return -1; +} + + + +//-------------------------------------------------------------------- +// void execute(instr *i) +// +// execute consists of the following tasks: +// - fetch the operands +// - execute the operation in the intruction +// - write the data back in the destination +// - compute the next address for (jmp, call, return...) +// +//-------------------------------------------------------------------- +void cycle_model::execute(instr *i) { + int in1, in2, out = 0; + + // fetch operands --------------------------------------------------- + if(i->n_src>=1) + in1 = fetch_operand(&(i->src1)); + + if(i->n_src>=2) + in2 = fetch_operand(&(i->src2)); + +#ifdef DEBUG + printf("execute %d, with in1=%d and in2=%d\n",i->type,in1, in2); +#endif + + // execute ---------------------------------------------------------- + switch(i->type) { + case i_add: { + out = in1 + in2; + break; + } + case i_sub: { + out = in1 - in2; + break; + } + case i_inc: { + out = in1+1; + break; + } + case i_dec: { + out = in1-1; + break; + } + case i_mul: { + out = in1 * in2; + break; + } + case i_div: { + out = in1/in2; + break; + } + // logic operations + case i_and: { + out = in1 & in2; + break; + } + case i_or: { + out = in1 | in2; + break; + } + case i_xor: { + out = in1 ^ in2; + break; + } + case i_rl: { + out = in1<<1; + break; + } + case i_rr: { + out = in2>>1; + break; + } + // data transfer + case i_mov: { + out = in1; + break; + } + // branching (out==0 -> don't branch) + case i_call: + case i_ret: + case i_jmp: + case i_sjmp: { + out = 1; + break; + } + case i_jz: { + out = (A==0); + break; + } + case i_jnz: { + out = (A!=0); + break; + } + case i_cjne: { + out = (in1!=in2); + break; + } + case i_djnz: { + out=in1-1; // decrement reg/direct and jump if != 0 + break; + } + default: { + break; + } + } + + + // write back -------------------------------------------------------- + write_back(&(i->dst),out); + + // compute next address ---------------------------------------------- + switch(i->type) { + case i_call: { + stack_el *new_stack_el= (stack_el *) malloc(sizeof(stack_el)); + new_stack_el->up = my_stack; + new_stack_el->address = in1; + my_stack = new_stack_el; + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + + break; + } + case i_ret: { + stack_el *new_stack_el = my_stack->up; + free(my_stack); + my_stack = new_stack_el; + if(my_stack!=NULL) + my_stack->address += 1; // increment address after jump + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + exec_bus_cycle(OP_IDLE,0,0,&result); + exec_bus_cycle(OP_IDLE,0,0,&result); + break; + } + case i_jmp: { + my_stack->address = in1; + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + + break; + } + case i_sjmp: + case i_jz: + case i_jnz: { + if(out!=0) + my_stack->address += in1+1; + else + my_stack->address += 1; + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + + break; + } + case i_cjne: { + int in3 = fetch_operand(&i->dst); + if(out!=0) + my_stack->address += in3+1; + else + my_stack->address += 1; + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + + break; + } + case i_djnz: { + if(out!=0) + my_stack->address += in2+1; + else + my_stack->address += 1; + + /* wait additional cycles */ + int result; + exec_bus_cycle(OP_IDLE,0,0,&result); + + break; + } + default: { + my_stack->address += 1; + break; + } + } +} + + + +//--------------------------------------------------------------------- +// cycle_model::init() +// +// initialize the stack +// +//--------------------------------------------------------------------- +void cycle_model::init() { + + cycles2execute = 0; + cycle_count = 0; + stretch_cycles = 0; + + // initialize stack + my_stack = (stack_el *) malloc(sizeof(stack_el)); + my_stack->up = NULL; + my_stack->address = 0; +} + + + +//------------------------------------------------------------------------ +// void cycle_mode::entry() +// +// main loop: fetch instruction +// decode opcode +// execute instruction +// +//------------------------------------------------------------------------ +void cycle_model::entry() { + + wait(); + + mem_ale.write(0); + mem_wr_n.write(1); + mem_pswr_n.write(1); + mem_rd_n.write(1); + mem_psrd_n.write(1); + p0_mem_reg_n.write(0); + p0_addr_data_n.write(0); + wait(); + + while(true) { + instr the_instr; + // fetch instruction + if(my_stack==NULL) { + // printf("cycles count = %d\n",cycle_count); + sc_stop(); + wait(); + } else { + int opcode = fetch_instr(my_stack->address); + + // decode instruction + decode(opcode, &the_instr); + + // execute + execute(&the_instr); + } + } +} diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.h b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.h new file mode 100644 index 000000000..7aa0b1e89 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/cycle_model.h @@ -0,0 +1,230 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + cycle_model.h -- + + 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 "common.h" + +#define MEM_SIZE 65536 +#define INT_SIZE 2048 + +/* types of operands */ +enum op_type { + o_null, + o_acc, // accumulator + o_reg, // registers Ri + o_dir, // internal register direct + o_ind, // internal register pointed to by R0 or R1 + o_ext, // external memory pointed to by R0 or R1 + o_rel, // 2complement offset byte + o_cst, // 8bit constant + o_lcst, // 16bit constant + o_add, // 11bit destination address + o_ladd // 16bit destination address +}; + + +/* limited set of instruction types */ +enum instr_type { + // arithmetic operations + i_add, // 0 + i_sub, // 1 + i_inc, // 2 + i_dec, // 3 + i_mul, // 4 + i_div, // 5 + // logic operations + i_and, // 6 + i_or, // 7 + i_xor, // 8 + i_clr, // 9 + i_cpl, // 10 + i_rl, // 11 + i_rr, // 12 + // data transfer + i_mov, // 13 + // branching + i_call,// 14 + i_ret, // 15 + i_jmp, // 16 + i_sjmp,// 17 + i_jz, // 18 + i_jnz, // 19 + i_cjne,// 20 + i_djnz,// 21 + i_nop // 22 +}; + + +/* cycle types for memory bus */ +enum bus_cycle_type { + OP_IDLE, + OP_MEM_READ, + OP_MEM_WRITE +}; + + +/* ------------------------------------------------------------------------ + * struct operand + * ----------------------------------------------------------------------*/ +struct operand { + op_type type; + int val; /* value encoded with the opcode (i.e. register number) */ +}; + + +/* ------------------------------------------------------------------------ + * struct instr ( instruction ) + * ----------------------------------------------------------------------*/ +struct instr { + instr_type type; + int n_src; /* number of source operands */ + operand src1; /* source operand 1 */ + operand src2; /* source operand 2 */ + operand dst; /* destination operand */ + int cycle; // number of cycles +}; + + +/* ------------------------------------------------------------------------ + * struct stack_el ( stack element ) + * ----------------------------------------------------------------------*/ +struct stack_el { + int address; + stack_el *up; +}; + + + +/* ------------------------------------------------------------------------ + * struct cycle_model: public sc_aproc + * + * ----------------------------------------------------------------------*/ + +SC_MODULE( cycle_model ) +{ + SC_HAS_PROCESS( cycle_model ); + + sc_in_clk clk; + + /* functions */ + void init(); + void parse_hex(char *name); + void exec_bus_cycle(bus_cycle_type op, int addr, int data, int* result); + bool request_address(int addr); + int fetch_instr(int ad); + int fetch_data(int ad); + int write_data(int ad, int data); + int fetch_operand(operand* op); + int write_back(operand *, int); + void execute(instr *i); + void decode(int opcode, instr* i); + + + /* memory bus */ + signal_bool_vector16& mem_addr; + signal_bool_vector8& mem_data_out; + const signal_bool_vector8& mem_data_in; + sc_signal<bool>& mem_wr_n; + sc_signal<bool>& mem_rd_n; + sc_signal<bool>& mem_pswr_n; + sc_signal<bool>& mem_psrd_n; + sc_signal<bool>& mem_ale; + const sc_signal<bool>& mem_ea_n; + + sc_signal<bool>& p0_mem_reg_n; + sc_signal<bool>& p0_addr_data_n; + sc_signal<bool>& p2_mem_reg_n; + + /* internal variables */ + /* memories registers and stack */ + int instr_mem[MEM_SIZE]; /* instruction memory */ + int ext_mem[MEM_SIZE]; /* 'external' data memory */ + int int_mem[INT_SIZE]; /* internal data memory */ + int A; /* accumulator */ + int R[8]; /* registers */ + stack_el *my_stack; /* stack */ + /* others */ + int cycles2execute; /* number of cycles to execute */ + int cycle_count; /* total number of cycles executed */ + int stretch_cycles; /* memory stretch cycles */ + + + + /* Constructor */ + cycle_model(sc_module_name NAME, + const sc_signal_in_if<bool>& CLK, + char* hex_file_name, + + signal_bool_vector16& MEM_ADDR, + signal_bool_vector8& MEM_DATA_OUT, + const signal_bool_vector8& MEM_DATA_IN, + sc_signal<bool>& MEM_WR_N, + sc_signal<bool>& MEM_RD_N, + sc_signal<bool>& MEM_PSWR_N, + sc_signal<bool>& MEM_PSRD_N, + sc_signal<bool>& MEM_ALE, + const sc_signal<bool>& MEM_EA_N, + + sc_signal<bool>& P0_MEM_REG_N, + sc_signal<bool>& P0_ADDR_DATA_N, + sc_signal<bool>& P2_MEM_REG_N + ) + : + + mem_addr(MEM_ADDR), + mem_data_out(MEM_DATA_OUT), + mem_data_in(MEM_DATA_IN), + mem_wr_n(MEM_WR_N), + mem_rd_n(MEM_RD_N), + mem_pswr_n(MEM_PSWR_N), + mem_psrd_n(MEM_PSRD_N), + mem_ale(MEM_ALE), + mem_ea_n(MEM_EA_N), + p0_mem_reg_n(P0_MEM_REG_N), + p0_addr_data_n(P0_ADDR_DATA_N), + p2_mem_reg_n(P2_MEM_REG_N) + { + clk(CLK); + SC_THREAD( entry ); + sensitive << clk; + + parse_hex(hex_file_name); + init(); + } + + /* Process functionality in member function below */ + void entry(); +}; diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/golden/cycle_dw8051_demo.log b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/golden/cycle_dw8051_demo.log new file mode 100644 index 000000000..d487dd01f --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/golden/cycle_dw8051_demo.log @@ -0,0 +1,23 @@ +SystemC Simulation +peripheral: receive 10 +peripheral: send 10 +peripheral: receive 9 +peripheral: send 9 +peripheral: receive 8 +peripheral: send 8 +peripheral: receive 7 +peripheral: send 7 +peripheral: receive 6 +peripheral: send 6 +peripheral: receive 5 +peripheral: send 5 +peripheral: receive 4 +peripheral: send 4 +peripheral: receive 3 +peripheral: send 3 +peripheral: receive 2 +peripheral: send 2 +peripheral: receive 1 +peripheral: send 1 + +Info: /OSCI/SystemC: Simulation stopped by user. diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/main.cpp b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/main.cpp new file mode 100644 index 000000000..11366c74a --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/main.cpp @@ -0,0 +1,172 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + main.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: + + *****************************************************************************/ + +//*************************************************************************** +// FILE: main.cc +// +// AUTHOR: Luc Semeria September, 21, 1998 +// +// ABSTRACT: main (instanciates dw8051 cycle-accurate model and +// and peripheral on memory bus +// +// MODIFICATION HISTORY: +// Luc Semeria: 9/21/98 created +// +//*************************************************************************** +// +// DESCRIPTION +// +// This program tests the communication between the cycle-accurate model +// and the peripheral on the memory bus +// +// The peripheral copies the input after a given number of clocks +// +// Reference: Synopsys DesignWare DW8051 MacroCell Databook +// +//*************************************************************************** +#include "cycle_model.h" +#include "peripheral.h" +// #define DEBUG +char *hex_file_name; + + +void usage() { + fprintf(stdout,"\nusage: hw_sim.x [-a] filename.hex\n"); + exit(-1); +} + +void parse_arg(int argc, char *argv[]) { + extern bool ALL_CYCLES; + int i = 1; + + ALL_CYCLES = 0; + +#if 0 + // parse -a + if(argc<=i) + usage(); + + if(!strcmp(argv[i],"-a")) { + ALL_CYCLES = 1; + i++; + } + + // parse file name + if(argc<=i) + usage(); + + hex_file_name=(char *)malloc(strlen(argv[i])*sizeof(char)); + strcpy(hex_file_name,argv[i]); + i++; + + // no more param + if(i<argc) + usage(); +#else + hex_file_name = (char*)malloc(50*sizeof(char)); + strcpy(hex_file_name,"cycle_dw8051_demo/test.hex"); +#endif + return; +} + +//------------------------------------------------------------------------- +// int sc_main(int argc, char **argv) +// +//------------------------------------------------------------------------- +int sc_main(int argc, char *argv[]) +{ + // clock ------------------------------------------------------------------- + sc_clock clock ("CLOCK", 40, SC_NS, 0.5); // assume 25MHz + + // signals for read/write to External RAM/ROM + signal_bool_vector16 mem_addr("mem_addr"); // address bus + signal_bool_vector8 mem_data_out("mem_data_out"); // data out bus + signal_bool_vector8 mem_data_in("mem_data_in"); // data in bus + sc_signal<bool> mem_wr_n("mem_wr_n"); // write strobe + sc_signal<bool> mem_rd_n("mem_rd_n"); // read enable sampled + sc_signal<bool> mem_pswr_n("mem_pswr_n"); // write enable (ROM) + sc_signal<bool> mem_psrd_n("mem_psrd_n"); // read enable (ROM) + sc_signal<bool> mem_ale("mem_ale"); // ext latch enable + sc_signal<bool> mem_ea_n("mem_ea_n"); // ext prog mem enable + + // sc_signal<bool> port_pin_reg_n(); // select read from ext reg or pin + sc_signal<bool> p0_mem_reg_n("p0_mem_reg_n"); // select port reg + sc_signal<bool> p0_addr_data_n("p0_addr_data_n");// select data + sc_signal<bool> p2_mem_reg_n("p2_mem_reg_n"); // cf p0_mem_reg_n + + parse_arg(argc, argv); + + cycle_model CYCLE_MODEL("dw8051", + clock, + hex_file_name, // name of the hex file + + mem_addr, + mem_data_out, + mem_data_in, + mem_wr_n, + mem_rd_n, + mem_pswr_n, + mem_psrd_n, + mem_ale, + mem_ea_n, + + // port_pin_reg_n, + p0_mem_reg_n, + p0_addr_data_n, + p2_mem_reg_n); + + peripheral PERIPHERAL("peripheral", + clock, + mem_addr, + mem_data_out, + mem_data_in, + mem_wr_n, + mem_rd_n, + mem_pswr_n, + mem_psrd_n, + mem_ale, + mem_ea_n, + + p0_mem_reg_n, + p0_addr_data_n, + p2_mem_reg_n); + + + + sc_start(); + return 0; +} diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.cpp b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.cpp new file mode 100644 index 000000000..2fdb37151 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.cpp @@ -0,0 +1,65 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + peripheral.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 "peripheral.h" + +void peripheral::entry() { + unsigned int buffer_in = 0; + unsigned int buffer_out = 0; + wait(); + + while(true) { + unsigned int addr = mem_addr.read().to_uint(); + unsigned int data = mem_data_out.read().to_uint(); + + if(!mem_wr_n.read() && (addr==0x10)) { + // write + cout << "peripheral: receive " << data << endl; + buffer_in = data; + wait(100); + buffer_out = buffer_in; + } + + if(!mem_rd_n.read() && (addr==0x11)) { + // read + mem_data_in.write( sc_bv<8>( buffer_out ) ); + cout << "peripheral: send " << buffer_out << endl; + wait(); + } + wait(); + } +} diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.h b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.h new file mode 100644 index 000000000..d0e73ffb3 --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/peripheral.h @@ -0,0 +1,97 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + peripheral.h -- + + 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 "common.h" + +SC_MODULE( peripheral ) +{ + SC_HAS_PROCESS( peripheral ); + + sc_in_clk clk; + + /* Ports( other than clk) */ + const signal_bool_vector16& mem_addr; + const signal_bool_vector8& mem_data_out; + signal_bool_vector8& mem_data_in; + const sc_signal<bool>& mem_wr_n; + const sc_signal<bool>& mem_rd_n; + const sc_signal<bool>& mem_pswr_n; + const sc_signal<bool>& mem_psrd_n; + const sc_signal<bool>& mem_ale; + sc_signal<bool>& mem_ea_n; + + const sc_signal<bool>& p0_mem_reg_n; + const sc_signal<bool>& p0_addr_data_n; + const sc_signal<bool>& p2_mem_reg_n; + + peripheral(sc_module_name NAME, + sc_clock& TICK, + const signal_bool_vector16& MEM_ADDR, + const signal_bool_vector8& MEM_DATA_OUT, + signal_bool_vector8& MEM_DATA_IN, + const sc_signal<bool>& MEM_WR_N, + const sc_signal<bool>& MEM_RD_N, + const sc_signal<bool>& MEM_PSWR_N, + const sc_signal<bool>& MEM_PSRD_N, + const sc_signal<bool>& MEM_ALE, + sc_signal<bool>& MEM_EA_N, + + const sc_signal<bool>& P0_MEM_REG_N, + const sc_signal<bool>& P0_ADDR_DATA_N, + const sc_signal<bool>& P2_MEM_REG_N + ) + : + mem_addr(MEM_ADDR), + mem_data_out(MEM_DATA_OUT), + mem_data_in(MEM_DATA_IN), + mem_wr_n(MEM_WR_N), + mem_rd_n(MEM_RD_N), + mem_pswr_n(MEM_PSWR_N), + mem_psrd_n(MEM_PSRD_N), + mem_ale(MEM_ALE), + mem_ea_n(MEM_EA_N), + p0_mem_reg_n(P0_MEM_REG_N), + p0_addr_data_n(P0_ADDR_DATA_N), + p2_mem_reg_n(P2_MEM_REG_N) + { + clk(TICK); + SC_CTHREAD( entry, clk.pos() ); + } + + /* Process functionality in member function below */ + void entry(); +}; diff --git a/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/test.hex b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/test.hex new file mode 100644 index 000000000..ca3d9bb1a --- /dev/null +++ b/src/systemc/tests/systemc/misc/sim_tests/cycle_dw8051_demo/test.hex @@ -0,0 +1,5 @@ +:03000000020100fa +:160100007c0a78107911120200ecf2120200e31cec70f3020300f8 +:100200007a0a007b0a001beb0070fa1aea70f322ec +:0103000022da +:00000001ff |