summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile25
-rw-r--r--custom_instr.c34
-rw-r--r--i_type_handler.c496
-rw-r--r--instruction.h120
-rw-r--r--io_device.c155
-rw-r--r--io_device.h65
-rw-r--r--j_type_handler.c46
-rw-r--r--jtag_uart.c169
-rw-r--r--jtag_uart.h56
-rw-r--r--load_image.c620
-rw-r--r--main.c123
-rwxr-xr-xnios-simbin0 -> 124940 bytes
-rw-r--r--niosii.c603
-rw-r--r--niosii.h182
-rw-r--r--nor_flash.c108
-rw-r--r--nor_flash.h57
-rw-r--r--public.h85
-rw-r--r--r_type_handler.c458
-rw-r--r--simulator.c420
-rw-r--r--simulator.h32
-rw-r--r--timer.c215
-rw-r--r--timer.h55
-rw-r--r--uart_core.c157
-rw-r--r--uart_core.h79
24 files changed, 4360 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a2f4ad9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+#
+# Make file for compiling simulator for NIOSII
+#
+
+TARGET=nios-sim
+
+SRC=main.c load_image.c simulator.c niosii.c i_type_handler.c j_type_handler.c \
+ r_type_handler.c custom_instr.c io_device.c jtag_uart.c timer.c uart_core.c \
+ nor_flash.c
+
+CFLAGS= -g -Wall
+
+all:
+ gcc -o ${TARGET} ${CFLAGS} ${SRC}
+
+.phony:
+ clean distclean
+
+clean:
+ @rm -rf ${TARGET} *.o
+
+distclean: clean
+ @rm -rf *~
+ @rm -rf #*
+ @rm -rf tags \ No newline at end of file
diff --git a/custom_instr.c b/custom_instr.c
new file mode 100644
index 0000000..c9e5abf
--- /dev/null
+++ b/custom_instr.c
@@ -0,0 +1,34 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "public.h"
+#include "niosii.h"
+#include "instruction.h"
+
+uint32_t custom_instr(struct NIOS_CPU * cpu, uint32_t code)
+{
+ printf("%s\n",__func__);
+ return PC_INC_NORMAL;
+}
+
+/*----------------------------------------------------------------------------*/
+
diff --git a/i_type_handler.c b/i_type_handler.c
new file mode 100644
index 0000000..be1ff76
--- /dev/null
+++ b/i_type_handler.c
@@ -0,0 +1,496 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "instruction.h"
+
+
+static uint32_t ldbu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int32_t addr = 0;
+
+ addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16);
+ cpu->gp_regs[instr->b] = get_byte(addr) & 0x000000FF;
+
+ return PC_INC_NORMAL;
+}
+
+static uint32_t addi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t stb(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t addr = 0;
+
+ addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16);
+ store_byte(addr, (cpu->gp_regs[instr->b] & 0xFF));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t br(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t imm16 = (int16_t)instr->imm16;
+
+ cpu->pc = cpu->pc + 4 + (int16_t)(imm16 & 0xFFFC);
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldb(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16);
+
+ cpu->gp_regs[instr->b] = (int)((char)(get_byte(addr)));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpgei(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) >= (int32_t)((int16_t)(instr->imm16))){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmplti(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) < (int32_t)((int16_t)(instr->imm16))){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ldhu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t offset = (int16_t) instr->imm16;
+ int16_t value = 0;
+
+ value = get_half_word((int16_t)offset + cpu->gp_regs[instr->a]);
+ cpu->gp_regs[instr->b] = ((uint32_t)value) & 0xFFFF;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t andi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t temp = instr->imm16;
+
+ temp = temp & 0xFFFF;
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] & temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sth(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t offset = (int16_t)instr->imm16;
+ uint32_t addr = 0;
+
+ addr = cpu->gp_regs[instr->a] + (int16_t)offset;
+ store_half_word(addr, (uint16_t)(cpu->gp_regs[instr->b] & 0xFFFF));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t bge(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ int32_t a = (int32_t)(cpu->gp_regs[instr->a]);
+ int32_t b = (int32_t)(cpu->gp_regs[instr->b]);
+
+ if (a >= b){
+ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC);
+ }
+ else{
+ cpu->pc = cpu->pc + 4;
+ }
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldh(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t value = 0;
+
+ value = (int16_t)get_half_word(cpu->gp_regs[instr->a] + (int16_t)(instr->imm16));
+ cpu->gp_regs[instr->b] = (int32_t)value;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t initda(struct NIOS_CPU * cpu, uint32_t code)
+{
+#if 0
+ def_i_type_code;
+#endif
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ori(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int32_t temp = (int16_t)instr->imm16;
+
+ temp = temp & 0xFFFF;
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t stw(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ int16_t offset = (int16_t)(instr->imm16);
+
+ store_word(cpu->gp_regs[instr->a] + (int16_t)offset, cpu->gp_regs[instr->b]);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t blt(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int32_t a = (int32_t)(cpu->gp_regs[instr->a]);
+ int32_t b = (int32_t)(cpu->gp_regs[instr->b]);
+ int16_t imm16 = (int16_t)(instr->imm16);
+
+ if (a < b){
+ cpu->pc = cpu->pc + 4 + (int16_t)(imm16 & 0xFFFC);
+ }
+ else{
+ cpu->pc = cpu->pc + 4;
+ }
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldw(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t offset = (int16_t)(instr->imm16);
+ cpu->gp_regs[instr->b] = get_word(cpu->gp_regs[instr->a] + (int16_t)offset);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpnei(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int16_t value = (int16_t)(instr->imm16);
+
+ if (cpu->gp_regs[instr->a] != (int16_t)value){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushda(struct NIOS_CPU * cpu, uint32_t code)
+{
+#if 0
+ def_i_type_code;
+#endif
+ return PC_INC_NORMAL;
+}
+
+static uint32_t xori(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t value = 0;
+
+ value = (uint16_t)instr->imm16;
+ value &= 0xFFFF;
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] ^ value;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t bne(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if (cpu->gp_regs[instr->a] != cpu->gp_regs[instr->b]){
+ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC);
+ }
+ else {
+ cpu->pc = cpu->pc + 4;
+ }
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t cmpeqi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if(cpu->gp_regs[instr->a] == (int32_t)(instr->imm16)){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ldbuio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return ldbu(cpu, code);
+}
+
+static uint32_t muli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ unsigned long long data = 0;
+ uint32_t a = cpu->gp_regs[instr->a];
+ int32_t b = (int32_t)((int16_t)instr->imm16);
+
+ data = (a * b);
+ cpu->gp_regs[instr->b] = (uint32_t)(data & 0xFFFFFFFF);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t stbio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16);
+
+ store_byte(addr, (uint8_t)(cpu->gp_regs[instr->b] & 0xFF));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t beq(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ int16_t temp = (int16_t)instr->imm16;
+
+ if (cpu->gp_regs[instr->a] == cpu->gp_regs[instr->b]){
+ cpu->pc = cpu->pc + 4 + (int16_t)(temp & 0xFFFC);
+ }
+ else{
+ cpu->pc = cpu->pc + 4;
+ }
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldbio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return ldb(cpu, code);
+}
+
+static uint32_t cmpgeui(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t value = 0;
+
+ value = (uint32_t)(((uint16_t)(instr->imm16)) & 0xFFFF);
+ if ((uint32_t)(cpu->gp_regs[instr->a]) >= value){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ldhuio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return ldhu(cpu, code);
+}
+
+static uint32_t andhi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ int32_t value = 0;
+ int32_t temp = (int32_t)(instr->imm16);
+
+ value = temp << 16;
+ value = value & 0xFFFF0000;
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] & value;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sthio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return sth(cpu, code);
+}
+
+static uint32_t bgeu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if (cpu->gp_regs[instr->a] >= cpu->gp_regs[instr->b]){
+ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)(instr->imm16) & 0xFFFC);
+ }
+ else{
+ cpu->pc = cpu->pc + 4;
+ }
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldhio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return ldh(cpu, code);
+}
+
+static uint32_t cmpltui(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if (cpu->gp_regs[instr->a] < ((uint32_t)((uint16_t)instr->imm16) & 0xFFFF)){
+ cpu->gp_regs[instr->b] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->b] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t custom(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return custom_instr(cpu, code);
+}
+
+static uint32_t initd(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t orhi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] | (((uint32_t)((uint16_t)instr->imm16) << 16) & 0xFFFF0000);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t stwio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return stw(cpu, code);
+}
+
+static uint32_t bltu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+
+ if (cpu->gp_regs[instr->a] < cpu->gp_regs[instr->b]){
+ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC);
+ }
+ else{
+ cpu->pc = cpu->pc + 4;
+ }
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ldwio(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return ldw(cpu, code);
+}
+
+static uint32_t rdprs(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushd(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t xorhi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_i_type_code;
+ uint32_t value = (uint16_t)(instr->imm16);
+
+ value = value << 16;
+ value = value & 0xFFFF0000;
+ cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] ^ value;
+ return PC_INC_NORMAL;
+}
+
+/*----------------------------------------------------------------------------*/
+#define I_TYPE_HANDLER_COUNT (0x40)
+struct i_type_handler i_type_handlers[I_TYPE_HANDLER_COUNT] = {
+ [LDBU] = handler_item(ldbu),
+ [ADDI] = handler_item(addi),
+ [STB] = handler_item(stb),
+ [BR] = handler_item(br),
+ [LDB] = handler_item(ldb),
+ [CMPGEI] = handler_item(cmpgei),
+ [LDHU] = handler_item(ldhu),
+ [ANDI] = handler_item(andi),
+ [STH] = handler_item(sth),
+ [BGE] = handler_item(bge),
+ [LDH] = handler_item(ldh),
+ [CMPLTI] = handler_item(cmplti),
+ [INITDA] = handler_item(initda),
+ [ORI] = handler_item(ori),
+ [STW] = handler_item(stw),
+ [BLT] = handler_item(blt),
+ [LDW] = handler_item(ldw),
+ [CMPNEI] = handler_item(cmpnei),
+ [FLUSHDA] = handler_item(flushda),
+ [XORI] = handler_item(xori),
+ [BNE] = handler_item(bne),
+ [CMPEQI] = handler_item(cmpeqi),
+ [LDBUIO] = handler_item(ldbuio),
+ [MULI] = handler_item(muli),
+ [STBIO] = handler_item(stbio),
+ [BEQ] = handler_item(beq),
+ [LDBIO] = handler_item(ldbio),
+ [CMPGEUI] = handler_item(cmpgeui),
+ [LDHUIO] = handler_item(ldhuio),
+ [ANDHI] = handler_item(andhi),
+ [STHIO] = handler_item(sthio),
+ [BGEU] = handler_item(bgeu),
+ [LDHIO] = handler_item(ldhio),
+ [CMPLTUI] = handler_item(cmpltui),
+ [CUSTOM] = handler_item(custom),
+ [INITD] = handler_item(initd),
+ [ORHI] = handler_item(orhi),
+ [STWIO] = handler_item(stwio),
+ [BLTU] = handler_item(bltu),
+ [LDWIO] = handler_item(ldwio),
+ [RDPRS] = handler_item(rdprs),
+ [FLUSHD] = handler_item(flushd),
+ [XORHI] = handler_item(xorhi)
+};
+
+/*----------------------------------------------------------------------------*/
+
diff --git a/instruction.h b/instruction.h
new file mode 100644
index 0000000..2253c86
--- /dev/null
+++ b/instruction.h
@@ -0,0 +1,120 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __INSTRUCTION_H__
+#define __INSTRUCTION_H__
+
+/*--J_TYPE-------------------------------------------------------------*/
+/*--R_TYPE-------------------------------------------------------------*/
+enum OPX_TYPE_INSTR{
+ ERET = 0x01,
+ ROLI = 0x02,
+ ROL = 0x03,
+ FLUSHP = 0x04,
+ RET = 0x05,
+ NOR = 0x06,
+ MULXUU = 0x07,
+ CMPGE = 0x08,
+ BRET = 0x09,
+ ROR=0x0B,
+ FLUSHI=0x0c,
+ JMP=0x0d,
+ AND=0x0e,
+ CMPLT = 0x10,
+ SLLI = 0x12,
+ SLL=0x13,
+ WRPRS = 0x14,
+ OR = 0x16,
+ MULXSU=0x17,
+ CMPNE=0x18,
+ SRLI = 0x1A,
+ SRL=0x1b,
+ NEXTPC=0x1c,
+ CALLR = 0x1D,
+ XOR=0x1e,
+ MULXSS=0x1f,
+ CMPEQ=0x20,
+ DIVU = 0x24,
+ DIV=0x25,
+ RDCTL,
+ MUL,
+ CMPGEU,
+ INITI,
+ TRAP = 0x2D,
+ WRCTL,
+ CMPLTU = 0x30,
+ ADD,
+ BREAK = 0x34,
+ SYNC = 0x36,
+ SUB = 0x39,
+ SRAI = 0x3A,
+ SRA=0x3b
+};
+/*--I_TYPE-------------------------------------------------------------*/
+enum OP_TYPE_INSTR{
+ CALL = 0x00,
+ JMPI = 0x01,
+ LDBU = 0x03,
+ ADDI = 0x04,
+ STB = 0x05,
+ BR = 0x06,
+ LDB = 0x07,
+ CMPGEI = 0x08,
+ LDHU = 0x0B,
+ ANDI = 0x0C,
+ STH = 0x0D,
+ BGE = 0x0E,
+ LDH = 0x0F,
+ CMPLTI = 0x10,
+ INITDA = 0x13,
+ ORI,
+ STW,
+ BLT,
+ LDW,
+ CMPNEI=0x18,
+ FLUSHDA = 0x1B,
+ XORI = 0x1C,
+ BNE = 0x1E,
+ CMPEQI = 0x20,
+ LDBUIO = 0x23,
+ MULI,
+ STBIO,
+ BEQ,
+ LDBIO,
+ CMPGEUI=0x28,
+ LDHUIO = 0x2B,
+ ANDHI = 0x2C,
+ STHIO = 0x2D,
+ BGEU = 0x2E,
+ LDHIO = 0x2F,
+ CMPLTUI = 0x30,
+ CUSTOM = 0x32,
+ INITD,
+ ORHI,
+ STWIO,
+ BLTU,
+ LDWIO,
+ RDPRS,
+ R_TYPE = 0x3A,
+ FLUSHD = 0x3B,
+ XORHI = 0x3C
+};
+#endif
+
+
diff --git a/io_device.c b/io_device.c
new file mode 100644
index 0000000..e650608
--- /dev/null
+++ b/io_device.c
@@ -0,0 +1,155 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include "public.h"
+#include "io_device.h"
+#include "jtag_uart.h"
+#include "timer.h"
+#include "uart_core.h"
+#include "nor_flash.h"
+
+static struct io_device * devices[] = {
+ &jtag_uart_io_device,
+ &timer_core,
+ &uart_core,
+ &nor_flash_core
+};
+
+#define DEVICES_COUNT (sizeof(devices)/sizeof(devices[0]))
+
+static struct io_device * last_used_device = NULL;
+
+struct io_device * get_device(uint32_t address)
+{
+ struct io_device * ret_val = NULL;
+ uint32_t i = 0;
+
+ if (last_used_device != NULL){
+ if(last_used_device->is_belong(address) == ADDR_IS_DEV){
+ return last_used_device;
+ }
+ }
+
+ for (i=0;i<DEVICES_COUNT; i++){
+ if (devices[i]->is_belong != NULL){
+ if (devices[i]->is_belong(address) == ADDR_IS_DEV){
+ ret_val = devices[i];
+ last_used_device = ret_val;
+ break;
+ }
+ }
+ }
+
+ return ret_val;
+}
+
+void init_devices(void)
+{
+ uint32_t i = 0;
+
+ printf("--------------------------------------------------\n");
+ printf(" Init H/W Device Module!\n");
+ printf("--------------------------------------------------\n");
+ for (i=0;i<DEVICES_COUNT; i++){
+ if (devices[i]->init != NULL){
+ devices[i]->init(devices[i]);
+ }
+ }
+ printf("--------------------------------------------------\n");
+}
+
+static const uint32_t data_mask[5] = {
+ [1] = 0xFF,
+ [2] = 0xFFFF,
+ [4] = 0xFFFFFFFF,
+};
+
+uint32_t io_write_data(uint32_t old_data, uint32_t new_data,
+ uint32_t data_len)
+{
+ uint32_t mask = data_mask[data_len];
+
+ old_data = old_data & (~mask);
+ new_data = new_data & mask;
+ return (old_data | new_data);
+}
+
+uint32_t io_write_data_mask(uint32_t old_data, uint32_t new_data,
+ uint32_t data_len, uint32_t valid_mask,
+ uint32_t only_read_mask)
+{
+ uint32_t mask = data_mask[data_len];
+
+ new_data = new_data & mask; /* remove as the access bus width */
+ new_data = new_data & valid_mask; /* remove as the valid bits */
+ new_data = new_data & (~only_read_mask); /* remove the read-only bits */
+
+ old_data = old_data &(~mask | only_read_mask);
+
+ return (old_data | new_data);
+}
+
+uint32_t io_read_data(unsigned old_data, uint32_t data_len)
+{
+ uint32_t mask = data_mask[data_len];
+ return (old_data & mask);
+}
+
+void hw_simulating(void)
+{
+ int i = 0;
+ struct io_device * device = NULL;
+
+ for (i=0;i<DEVICES_COUNT; i++){
+ device = devices[i];
+ if(device->simulate != NULL){
+ device->simulate(device);
+ }
+ }
+}
+
+uint32_t get_io_irq_status(void)
+{
+ int i = 0;
+ uint32_t irq_mask = 0;
+ struct io_device * device = NULL;
+
+ for (i=0;i<DEVICES_COUNT; i++){
+ device = devices[i];
+ if(device->has_irq != NULL){
+ if (device->has_irq(device) == DEV_HAS_IRQ){
+ irq_mask |= device->irq_enable_mask;
+ }
+ }
+ }
+
+ return irq_mask;
+}
+
+uint32_t check_reg_bit(uint32_t value, uint32_t mask)
+{
+ if ((value & mask) == mask){
+ return SIM_TRUE;
+ }
+ else {
+ return SIM_FALSE;
+ }
+}
+/*--------------------------------------------------------------------------*/
diff --git a/io_device.h b/io_device.h
new file mode 100644
index 0000000..e520ff0
--- /dev/null
+++ b/io_device.h
@@ -0,0 +1,65 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+#ifndef __IO_DEVICE_H__
+#define __IO_DEVICE_H__
+#include <stdio.h>
+
+#define ADDR_IS_NOT_DEV (0)
+#define ADDR_IS_DEV (1)
+
+#define DEV_HAS_IRQ (1)
+#define DEV_NO_IRQ (0)
+
+struct io_device;
+struct io_device {
+ void * priv_data;
+ char * name;
+ uint32_t irq_enable_mask;
+ void (*init)(struct io_device * self);
+ int32_t (*is_belong)(uint32_t address);
+ uint32_t (*read_data)(struct io_device * self, uint32_t addr, uint32_t data_len);
+ void (*write_data)(struct io_device * self, uint32_t addr, uint32_t data, uint32_t data_len);
+ int32_t (*has_irq)(struct io_device * self);
+ void (*simulate)(struct io_device * self);
+
+};
+
+struct io_reg {
+ uint32_t addr;
+ uint32_t value;
+ uint32_t valid_mask;
+ uint32_t only_read_mask;
+};
+
+extern void init_devices(void);
+extern struct io_device * get_device(uint32_t address);
+
+extern uint32_t io_write_data(uint32_t old_data, uint32_t new_data, uint32_t data_len);
+extern uint32_t io_read_data(uint32_t old_data, uint32_t data_len);
+extern uint32_t io_write_data_mask(uint32_t old_data, uint32_t new_data, uint32_t data_len,
+ uint32_t valid_mask, uint32_t only_read_mask);
+extern void hw_simulating(void);
+extern uint32_t get_io_irq_status(void);
+
+extern uint32_t check_reg_bit(uint32_t value, uint32_t mask);
+#endif
+
+
diff --git a/j_type_handler.c b/j_type_handler.c
new file mode 100644
index 0000000..648e882
--- /dev/null
+++ b/j_type_handler.c
@@ -0,0 +1,46 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "instruction.h"
+
+static uint32_t call(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_j_type_code;
+ uint32_t imm26 = (uint32_t)instr->imm26;
+
+ cpu->gp_regs[ra] = cpu->pc + 4;
+ cpu->pc = (imm26 * 4) | (cpu->pc & 0xF0000000);
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t jmpi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_j_type_code;
+ cpu->pc = (((uint32_t)(instr->imm26) * 4) & 0xFFFFFFF)| (cpu->pc & 0xF0000000);
+ return PC_INC_BY_INSTR;
+}
+
+#define J_TYPE_HANDLER_COUNT (0x40)
+struct j_type_handler j_type_handlers[J_TYPE_HANDLER_COUNT] = {
+ [CALL] = handler_item(call),
+ [JMPI] = handler_item(jmpi)
+};
diff --git a/jtag_uart.c b/jtag_uart.c
new file mode 100644
index 0000000..052c42c
--- /dev/null
+++ b/jtag_uart.c
@@ -0,0 +1,169 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "public.h"
+#include "jtag_uart.h"
+
+static struct jtag_uart_priv priv;
+static void uart_init(struct io_device * self)
+{
+ memset(&priv, 0x00, sizeof(struct jtag_uart_priv));
+
+ if (self != NULL){
+ self->priv_data = &priv;
+ priv.regs[JTAG_UART_DATA_REG].addr = JTAG_UART_BASE_ADDR;
+ priv.regs[JTAG_UART_CTRL_REG].addr = JTAG_UART_BASE_ADDR + 4;
+ /* init control register */
+ priv.regs[JTAG_UART_CTRL_REG].value = (JTAG_UART_FIFO_SIZE) << ALTERA_JTAGUART_CONTROL_WSPACE_OFST; /* FIFO is empty */
+ }
+
+ printf("Jtag UART at 0x%08x\n",JTAG_UART_BASE_ADDR);
+}
+
+static int32_t uart_is_belong(uint32_t address)
+{
+ int32_t i = 0;
+
+ for (i=0;i<JTAG_UART_REG_COUNT;i++){
+ if (priv.regs[i].addr == address){
+ return ADDR_IS_DEV;
+ }
+ }
+ return ADDR_IS_NOT_DEV;
+}
+
+static uint32_t uart_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+{
+ if (addr == priv.regs[JTAG_UART_CTRL_REG].addr){
+ return priv.regs[JTAG_UART_CTRL_REG].value;
+ }
+ else if (addr == priv.regs[JTAG_UART_DATA_REG].addr){
+ return priv.regs[JTAG_UART_DATA_REG].value;
+ }
+
+ return 0;
+}
+
+static void write_tx_fifo(uint32_t data)
+{
+ priv.tx_fifo.data = data & 0xFF;
+ priv.tx_fifo.is_write = 1;
+ /* clean WI bit */
+ priv.regs[JTAG_UART_CTRL_REG].value &= (~ALTERA_JTAGUART_CONTROL_WI_MSK);
+ /* clean write space bits */
+ priv.regs[JTAG_UART_CTRL_REG].value &= 0xFFFF;
+}
+
+static void uart_write(struct io_device * self, uint32_t addr, uint32_t data, uint32_t data_len)
+{
+ int32_t i = 0;
+
+ for (i=0;i<JTAG_UART_REG_COUNT;i++){
+ if (priv.regs[i].addr == addr){
+ if (i == JTAG_UART_DATA_REG){
+ priv.regs[i].value = io_write_data(priv.regs[i].value, data, data_len);
+ write_tx_fifo(data);
+ }
+ else if(i == JTAG_UART_CTRL_REG){
+ priv.regs[i].value |= (io_write_data(priv.regs[i].value, data, data_len) & 0x3);
+ /* if change the interrupt enable bits */
+ if (data & 0x03){
+ priv.regs[i].value = priv.regs[i].value & (~ALTERA_JTAGUART_CONTROL_WI_MSK);
+ }
+ }
+ }
+ }
+}
+
+static uint32_t jtag_trans_clk = 500;
+static int32_t jtag_uart_has_irq(struct io_device * self)
+{
+ int32_t ret_val = DEV_NO_IRQ;
+ uint32_t reg_ctrl_val = priv.regs[JTAG_UART_CTRL_REG].value;
+
+ if (jtag_trans_clk > 0){
+ jtag_trans_clk --;
+ return ret_val;
+ }
+ else {
+ jtag_trans_clk = 500;
+ }
+
+ /* handle TX write fifo empty interrupt */
+ if (reg_ctrl_val & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ if ((reg_ctrl_val & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) != 0){
+ ret_val = DEV_HAS_IRQ;
+ }
+ }
+
+#if 0
+ /* handle RX data available interrupt */
+ if (reg_ctrl_val & ALTERA_JTAGUART_CONTROL_RE_MSK){
+ if (reg_ctrl_val & ALTERA_JTAGUART_DATA_RVALID_MSK){
+ ret_val = DEV_HAS_IRQ;
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_RI_MSK;
+ }
+ else{
+ priv.regs[JTAG_UART_CTRL_REG].value &= (~ALTERA_JTAGUART_CONTROL_RI_MSK);
+ }
+ }
+#endif
+ return ret_val;
+}
+
+static void jtag_uart_simulate(struct io_device * self)
+{
+ /* if has data to send */
+ if (priv.tx_fifo.is_write){
+ printf("%c", priv.tx_fifo.data);
+ priv.tx_fifo.is_write = 0;
+ /* set available fifo size */
+ priv.regs[JTAG_UART_CTRL_REG].value |= (JTAG_UART_FIFO_SIZE << ALTERA_JTAGUART_CONTROL_WSPACE_OFST);
+ /* if set write interrupt enable */
+ if (priv.regs[JTAG_UART_CTRL_REG].value & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ /* set write interrupt bit */
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_WI_MSK;
+ }
+ }
+ else {
+ if (priv.regs[JTAG_UART_CTRL_REG].value & (JTAG_UART_FIFO_SIZE << ALTERA_JTAGUART_CONTROL_WSPACE_OFST)){
+ /* if set write interrupt enable */
+ if (priv.regs[JTAG_UART_CTRL_REG].value & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ /* set write interrupt bit */
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_WI_MSK;
+ }
+ }
+ }
+}
+
+struct io_device jtag_uart_io_device = {
+ .name = "Jtag UART Core",
+ .init = uart_init,
+ .is_belong = uart_is_belong,
+ .read_data = uart_read,
+ .write_data = uart_write,
+ .has_irq = jtag_uart_has_irq,
+ .simulate = jtag_uart_simulate,
+ .irq_enable_mask = JTAG_IRQ_MASK
+};
+
+
diff --git a/jtag_uart.h b/jtag_uart.h
new file mode 100644
index 0000000..d855e39
--- /dev/null
+++ b/jtag_uart.h
@@ -0,0 +1,56 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __JTAG_UART_H__
+#define __JTAG_UART_H__
+
+#include "io_device.h"
+#define JTAG_UART_REG_COUNT (2)
+#define JTAG_UART_CTRL_REG (0)
+#define JTAG_UART_DATA_REG (1)
+#define JTAG_UART_BASE_ADDR (0x806810F0)
+#define JTAG_IRQ_MASK (1 << 1)
+#define JTAG_UART_FIFO_SIZE (1)
+
+struct fifo {
+ uint8_t data;
+ uint8_t is_write;
+};
+
+struct jtag_uart_priv{
+ struct io_reg regs[JTAG_UART_REG_COUNT];
+ struct fifo tx_fifo;
+};
+
+#define ALTERA_JTAGUART_DATA_DATA_MSK (0x000000FF)
+#define ALTERA_JTAGUART_DATA_RVALID_MSK (0x00008000)
+#define ALTERA_JTAGUART_DATA_RAVAIL_MSK (0xFFFF0000)
+#define ALTERA_JTAGUART_DATA_RAVAIL_OFST (16)
+
+#define ALTERA_JTAGUART_CONTROL_RE_MSK (0x00000001)
+#define ALTERA_JTAGUART_CONTROL_WE_MSK (0x00000002)
+#define ALTERA_JTAGUART_CONTROL_RI_MSK (0x00000100)
+#define ALTERA_JTAGUART_CONTROL_RI_OFST (8)
+#define ALTERA_JTAGUART_CONTROL_WI_MSK (0x00000200)
+#define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400)
+#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000)
+#define ALTERA_JTAGUART_CONTROL_WSPACE_OFST (16)
+
+extern struct io_device jtag_uart_io_device;
+#endif /* __JTAG_UART_H__*/
diff --git a/load_image.c b/load_image.c
new file mode 100644
index 0000000..6a10e47
--- /dev/null
+++ b/load_image.c
@@ -0,0 +1,620 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "public.h"
+#include "nor_flash.h"
+
+typedef enum {
+ S_INVALID = 0x00,
+ S0 = 0x01,
+ S1 = 0x02,
+ S2 = 0x03,
+ S3 = 0x04,
+ S4 = 0x05,
+ S5 = 0x06,
+ S6 = 0x07,
+ S7 = 0x08,
+ S8 = 0x09,
+ S9 = 0x0A
+} SREC_TYPE;
+
+static struct image_info image_info;
+
+static int32_t is_line_end(char data)
+{
+ if (data == '\n'){
+ return 0;
+ }
+ else{
+ return -1;
+ }
+}
+
+static void get_line(FILE * fp, char * buf, int32_t buf_len, int32_t * line_len)
+{
+ char data = '\0';
+ int32_t index = 0;
+
+ memset(buf, 0x00, buf_len);
+ while(1){
+ if(feof(fp) != 0 || ferror(fp) != 0){
+ return ;
+ }
+
+ data = '\0';
+ if (fread(&data, 1, 1, fp) == 1){
+ if (is_line_end(data) != 0){
+ buf[index++] = data;
+ *line_len = index;
+ }
+ else {
+ return ;
+ }
+ }
+ else {
+ return ;
+ }
+ }
+}
+
+static SREC_TYPE get_srec_type(char * buf)
+{
+ if (buf[1] >= 0x30 && buf[1] <= 0x39){
+ return S0 + buf[1] - 0x30;
+ }
+ else{
+ return S_INVALID;
+ }
+}
+
+static uint32_t __factors [] = {
+ 1,
+ 16,
+ 256,
+ 16 * 16 * 16,
+ 16 * 16 * 16 * 16,
+ 16 * 16 * 16 * 16 * 16,
+ 16 * 16 * 16 * 16 * 16 * 16,
+ 16 * 16 * 16 * 16 * 16 * 16 * 16
+};
+
+static uint32_t single_ascii_to_hex(char data)
+{
+ if (data >= 0x30 && data <= 0x39)
+ return data - 0x30;
+ if (data >= 0x41 && data <= 0x46)
+ return data - 0x41 + 10;
+ if (data >= 0x61 && data <= 0x66)
+ return data - 0x61 + 10;
+ return 0;
+}
+
+uint32_t ascii_to_hex(char * buf, uint32_t buf_len)
+{
+ uint32_t ret = 0x0000;
+ int32_t i = 0;
+ for (i=0;i<buf_len;i++){
+ ret = ret + (single_ascii_to_hex(buf[i]) * __factors[buf_len - i - 1]);
+ }
+ return ret;
+}
+
+static uint32_t get_srec_data_count(char * buf)
+{
+ uint32_t count = 0;
+ count = ascii_to_hex(buf + 2, 2);
+ return count;
+}
+
+static uint32_t to_le(uint32_t data)
+{
+ uint32_t ret = 0;
+ ret = ret | ((data & 0xFF000000) >> 24);
+ ret = ret | ((data & 0x00FF0000) >> 8);
+ ret = ret | ((data & 0x0000FF00) << 8);
+ ret = ret | ((data & 0x000000FF) << 24);
+ return ret;
+}
+
+#define S0_DATA_OFFSET (8)
+#define S0_ADDR_CRC_CNT (3)
+static uint32_t handle_S0(char * buf, uint32_t data_count, uint32_t * mem_base)
+{
+ int32_t i = 0;
+ char * data_buf = buf;
+
+ data_buf = data_buf + S0_DATA_OFFSET;
+ for (i=0;i<data_count - S0_ADDR_CRC_CNT; i++){
+ data_buf += 2;
+ }
+ return 0;
+}
+
+#define S3_ADDR_OFFSET (4)
+#define S3_DATA_OFFSET (S3_ADDR_OFFSET + 8)
+#define S3_ADDR_CRC_CNT (5)
+
+static uint32_t get_S3_address(char * buf)
+{
+ uint32_t ret = 0;
+ buf = buf + S3_ADDR_OFFSET;
+ ret = ascii_to_hex(buf, 8);
+ return ret;
+}
+
+static uint32_t handle_S3(char * buf, uint32_t data_count, uint32_t * mem_base,
+ uint32_t base_addr)
+{
+ uint32_t start_addr = 0;
+ uint32_t offset = 0;
+ uint32_t data = 0;
+ char * data_buf = buf;
+ int32_t i;
+
+ start_addr = get_S3_address(buf);
+
+ if (base_addr == 0){
+ offset = 0;
+ }
+ else{
+ offset = (start_addr - base_addr)/4;
+ }
+ data_buf = data_buf + S3_DATA_OFFSET;
+ for (i=0;i<(data_count-S3_ADDR_CRC_CNT)/4;i++){
+ data = to_le(ascii_to_hex(data_buf, 8));
+ data_buf += 8;
+ mem_base[offset + i] = data;
+ }
+
+ return start_addr;
+}
+
+#define S2_ADDR_OFFSET (4)
+#define S2_DATA_OFFSET (S2_ADDR_OFFSET + 6)
+#define S2_ADDR_CRC_CNT (4)
+
+static uint32_t get_S2_address(char * buf)
+{
+ uint32_t ret = 0;
+ buf = buf + S2_ADDR_OFFSET;
+ ret = ascii_to_hex(buf, 6);
+ return ret;
+}
+
+static uint32_t handle_S2(char * buf, uint32_t data_count, uint32_t * mem_base,
+ uint32_t base_addr)
+{
+ uint32_t start_addr = 0;
+ uint32_t offset = 0;
+ uint32_t data = 0;
+ char * data_buf = buf;
+ int32_t i;
+
+ start_addr = get_S2_address(buf);
+
+ if (base_addr == 0){
+ offset = 0;
+ }
+ else{
+ offset = (start_addr - base_addr)/4;
+ }
+
+ data_buf = data_buf + S2_DATA_OFFSET;
+ for (i=0;i<(data_count-S2_ADDR_CRC_CNT)/4;i++){
+ data = to_le(ascii_to_hex(data_buf, 8));
+ data_buf += 8;
+ mem_base[offset + i] = data;
+ }
+
+ return start_addr;
+}
+
+
+#define S7_DATA_OFFSET (4)
+#define S7_CRC_CNT (2)
+static uint32_t handle_S7(char * buf, uint32_t data_count, uint32_t * mem_base)
+{
+ char * data_buf = buf;
+
+ data_buf = data_buf + S7_DATA_OFFSET;
+ return ascii_to_hex(data_buf, 8);
+}
+
+#define S8_DATA_OFFSET (4)
+#define S8_CRC_CNT (2)
+static uint32_t handle_S8(char * buf, uint32_t data_count, uint32_t * mem_base)
+{
+ char * data_buf = buf;
+
+ data_buf = data_buf + S8_DATA_OFFSET;
+ return ascii_to_hex(data_buf, 6);
+}
+
+static void dummy_srec_handler(char * name)
+{
+ printf("%s: for %s\n",__func__, name);
+}
+
+static void handle_srec_line(char * buf, int line_len, uint32_t * mem_base)
+{
+ SREC_TYPE srec_type = S_INVALID;
+ uint32_t data_count = 0;
+ uint32_t start_addr = 0;
+
+ srec_type = get_srec_type(buf);
+ data_count = get_srec_data_count(buf);
+
+ switch(srec_type){
+ case S0:
+ handle_S0(buf, data_count, mem_base);
+ break;
+ case S1:
+ dummy_srec_handler("S1");
+ break;
+ case S2:
+ if (image_info.base_addr == 0){
+ image_info.base_addr = handle_S2(buf, data_count, mem_base, image_info.base_addr);
+ }
+ else {
+ handle_S2(buf, data_count, mem_base, image_info.base_addr);
+ }
+ break;
+ case S3:
+ if (image_info.base_addr == 0){
+ image_info.base_addr = handle_S3(buf, data_count, mem_base, image_info.base_addr);
+ }
+ else {
+ handle_S3(buf, data_count, mem_base, image_info.base_addr);
+ }
+ break;
+ case S4:
+ dummy_srec_handler("S4");
+ break;
+ case S5:
+ dummy_srec_handler("S5");
+ break;
+ case S6:
+ dummy_srec_handler("S6");
+ break;
+ case S7:
+ start_addr = handle_S7(buf, data_count, mem_base);
+ set_image_entry_addr(start_addr);
+ break;
+ case S8:
+ start_addr = handle_S8(buf, data_count, mem_base);
+ set_image_entry_addr(start_addr);
+ break;
+ case S9:
+ dummy_srec_handler("S9");
+ break;
+ default:
+ return;
+ }
+ return;
+}
+
+#define SREC_LINE_LENGTH (515)
+static char data_buf[SREC_LINE_LENGTH] = {0};
+
+static void load_srec(const char * image_path_name, uint32_t * image_addr)
+{
+ FILE * fp = NULL;
+ int32_t line_len = 0;
+
+ fp = fopen(image_path_name, "r");
+ if (fp != NULL){
+ while(1){
+ memset(data_buf, 0x00, SREC_LINE_LENGTH);
+ line_len = 0;
+ get_line(fp, data_buf, SREC_LINE_LENGTH, &line_len);
+ if (line_len == 0){
+ break;
+ }
+ else
+ {
+ handle_srec_line(data_buf, line_len, image_addr);
+ }
+ }
+ fclose(fp);
+ }
+ else{
+ printf("ERROR--> can not open image at %s\n", image_path_name);
+ }
+}
+
+void load_image(void)
+{
+ switch(image_info.image_format){
+ case SREC_FMT:
+ load_srec(image_info.path_name, image_info.mem_base);
+ break;
+ default:
+ break;
+ }
+}
+
+void alloc_image_mem(void)
+{
+ char * address = NULL;
+ struct image_info * info = &image_info;
+ uint32_t temp = 0;
+
+ address = (char *)malloc(info->mem_size);
+ temp = info->mem_size % 4;
+ if (temp != 0){
+ address = address + temp;
+ }
+ info->mem_base = (uint32_t *)address;
+}
+
+void set_image_pathname(char * pathname)
+{
+ image_info.path_name = pathname;
+}
+
+void set_image_format(IMG_FORMAT format)
+{
+ image_info.image_format = format;
+}
+
+void set_image_memsize(char * size)
+{
+ int32_t str_len = strlen(size);
+ char * temp = NULL;
+
+ if (size[str_len - 1] == 'M' || size[str_len - 1] == 'm'){
+ temp = malloc(str_len);
+ memset(temp, 0x00, str_len);
+ memcpy(temp, size, str_len);
+ temp[str_len - 1] = '\0';
+ image_info.mem_size = atoi(temp) * 1024 * 1024;
+ free(temp);
+ }
+}
+
+void set_image_entry_addr(uint32_t addr)
+{
+ image_info.entry_addr = addr;
+}
+
+void set_image_base_addr(char * addr)
+{
+ sscanf(addr, "0x%X\n", &image_info.base_addr);
+}
+static char cmd_line[256] = {0};
+static uint32_t initrd_start = 0;
+static uint32_t initrd_size = 0;
+static char fs_image[256] = {0};
+
+void print_image_info(void)
+{
+ printf("--------------------------------------------------\n");
+ printf(" NIOS Simulator (Built at %s-%s)\n",__DATE__,__TIME__);
+ printf("--------------------------------------------------\n");
+ printf("Image File:%s\n",image_info.path_name);
+
+ if (image_info.image_format == SREC_FMT){
+ printf("Format:SREC\n");
+ }
+
+ printf("Mem size:0x%08X, loading at %p\n", image_info.mem_size,
+ image_info.mem_base);
+ printf("Base address:0x%08X, Entry address:0x%08X\n",image_info.base_addr,
+ image_info.entry_addr);
+ printf("Set command line:%s\n", cmd_line);
+ printf("Initrd: 0x%08x size:0x%08x\n",initrd_start, initrd_size);
+ printf("rootfs: %s \n",fs_image);
+ printf("--------------------------------------------------\n");
+}
+
+struct image_info * get_image_info(void)
+{
+ return &image_info;
+}
+
+static struct symbol_obj * sym_hash[256] = {NULL};
+
+static struct symbol_obj * get_head_list(uint32_t addr)
+{
+ return sym_hash[addr % 256];
+}
+
+static void insert_symbol_obj(struct symbol_obj * list, struct symbol_obj * obj)
+{
+ if (list == NULL){
+ sym_hash[obj->addr % 256] = obj;
+ }
+ else{
+ while(list != NULL){
+ if (list->next != NULL){
+ list = list->next;
+ }
+ else{
+ break;
+ }
+
+ }
+ list->next = obj;
+ }
+}
+
+static struct symbol_obj * alloc_symbol_obj(char * addr, char * name)
+{
+ struct symbol_obj * obj = NULL;
+ uint32_t size = 0;
+
+ obj = (struct symbol_obj *)malloc(sizeof(struct symbol_obj));
+ memset(obj, 0x00, sizeof(struct symbol_obj));
+
+ if (obj != NULL){
+ obj->addr = ascii_to_hex(addr, 8);
+ obj->next = NULL;
+ size = strlen(name) + 1;
+ obj->sym_name = (char *)malloc(size);
+ if (obj->sym_name != NULL){
+ memset(obj->sym_name, 0x00, size);
+ strncpy(obj->sym_name, name, size - 1);
+ }
+ else{
+ printf("[ERROR] %s --> can not allocate symname %s \n",__func__, name);
+ }
+ }
+
+ return obj;
+}
+
+static void handle_symbol_line(char * line)
+{
+ char addr[10] = {0};
+ char sym_name[64] = {0};
+ char type[2] = {0};
+ struct symbol_obj * obj = NULL;
+ struct symbol_obj * list = NULL;
+
+ memset(sym_name, 0x00, 64);
+ sscanf(line, "%s %s %s\n", addr, type, sym_name);
+ obj = alloc_symbol_obj(addr, sym_name);
+
+ if (obj != NULL){
+ list = get_head_list(obj->addr);
+ insert_symbol_obj(list, obj);
+ }
+}
+
+void load_symbol_file(char * symbol_file)
+{
+ char line[256] = {0};
+ int32_t line_len = 0;
+ FILE * fp = NULL;
+
+ memset(sym_hash, 0x00, sizeof(sym_hash));
+ fp = fopen(symbol_file, "r");
+ if (fp != NULL){
+ while(1){
+ memset(line, 0x00, 256);
+ line_len = 0;
+ get_line(fp, line, 256, &line_len);
+ if (line_len == 0){
+ break;
+ }
+ else{
+ line[line_len] = '\0';
+ handle_symbol_line(line);
+ }
+ }
+ fclose(fp);
+ }
+}
+
+static struct symbol_obj * find_symbol_obj(struct symbol_obj * list, uint32_t addr)
+{
+ struct symbol_obj * ret = NULL;
+
+ ret = list;
+ while(ret != NULL){
+ if (ret->addr == addr){
+ break;
+ }
+ else{
+ ret = ret->next;
+ }
+ }
+ return ret;
+}
+
+struct symbol_obj * get_symbol(uint32_t addr)
+{
+ struct symbol_obj * ret = NULL;
+ struct symbol_obj * lst = NULL;
+
+ lst = get_head_list(addr);
+ if (lst != NULL){
+ ret = find_symbol_obj(lst, addr);
+ }
+
+ return ret;
+}
+
+void set_cmdline(char * optarg)
+{
+ strcpy(cmd_line,optarg);
+}
+
+void init_cmdline(struct NIOS_CPU * cpu)
+{
+
+ char * addr = (char *)image_info.mem_base;
+
+ /* R7 is stored the start address of command line */
+ memcpy((char *)(addr + 0x700000), cmd_line, 255);
+ /* Set magic number.
+ * this is copied from arch/nios2/kernel/setup.c <setup_arch>
+ */
+ if (cmd_line[0] != '\0'){
+ cpu->gp_regs[4] = 0x534f494e;
+ cpu->gp_regs[7] = 0xF00000;
+ }
+
+}
+
+void set_initrd(char * optarg)
+{
+ sscanf(optarg,"0x%08x,0x%08x",&initrd_start,&initrd_size);
+}
+
+void init_initrd(struct NIOS_CPU * cpu)
+{
+ cpu->gp_regs[5] = initrd_start & 0xFFFFFFFC;
+ cpu->gp_regs[6] = (initrd_start + initrd_size) & 0xFFFFFFFC;
+}
+
+void set_fs_image(char * optarg)
+{
+ sscanf(optarg,"%s",fs_image);
+}
+
+void init_fs_image(struct NIOS_CPU * cpu)
+{
+ int32_t fd = open(fs_image,O_RDWR);
+ int32_t size = 0;
+ uint8_t buf [256] = {0};
+ uint8_t * mem_load_addr = NULL;
+
+ /* set the load memory address */
+ mem_load_addr = nor_flash_mem_addr();
+
+ if (fd){
+ printf("loading rootfs at %p\n", mem_load_addr);
+ while((size = read(fd,buf, 256)) > 0){
+ memcpy(mem_load_addr, buf, size);
+ mem_load_addr += size;
+ }
+
+ close(fd);
+ }
+ else {
+ printf("Can not load rootfs image at %s\n",fs_image);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..40fc250
--- /dev/null
+++ b/main.c
@@ -0,0 +1,123 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include "public.h"
+
+static void print_help(void)
+{
+ printf("\n----------------------------------------------\n");
+ printf(" HELP INFORMATION of NIOS2 Simulator\n");
+ printf("----------------------------------------------\n");
+ printf(" --image|-i image path name\n");
+ printf(" --srec|-s image format is SREC\n");
+ printf(" --mem_size|-m memory size of board\n");
+ printf(" --debug_mode|-d enter debug mode\n");
+ printf(" --base_addr|-b base address of memory\n");
+ printf(" --sys_map|-p load symbol table\n");
+ printf(" --cmdline|-c set kernel command line\n");
+ printf(" --initrd|-r set the address of initrd\n");
+ printf(" --fs_image|-f set the file system image\n");
+ printf(" --version|-v print the version information\n");
+ printf("----------------------------------------------\n");
+ printf(" For Example:\n");
+ printf(" nios-sim -s -i [srec file] -m [memsize] -d [set to debug mode] \n");
+ printf(" -b [base addr of mem] -p [symbol file]\n");
+ printf(" -c [kernel command line]\n");
+ printf("----------------------------------------------\n");
+}
+
+static const char * version = "Simulator for NIOSII(None-MMU) Version 0.1\n Copyright@chysun2000@gmail.com\n";
+static void print_version(void)
+{
+ printf("\n---------------------------------------------\n");
+ printf("%s", version);
+ printf("---------------------------------------------\n");
+}
+
+int main(int argc, char * argv[])
+{
+ struct option long_opt [] = {
+ {"image",required_argument,NULL,'i'},
+ {"srec",no_argument, NULL, 's'},
+ {"mem_size",required_argument, NULL, 'm'},
+ {"debug_mode",no_argument, NULL, 'd'},
+ {"base_addr", required_argument, NULL, 'b'},
+ {"sys_map", required_argument, NULL, 'p'},
+ {"cmdline", required_argument, NULL, 'c'},
+ {"initrd", required_argument, NULL, 'r'},
+ {"fs_image",required_argument, NULL, 'f'},
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {0,0,0,0}
+ };
+
+ char * short_opt = "i:sm:db:p:c:vhr:f:";
+ int32_t c = 0;
+
+ while((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1){
+ switch(c){
+ case 'i':
+ set_image_pathname(optarg);
+ break;
+ case 's':
+ set_image_format(SREC_FMT);
+ break;
+ case 'm':
+ set_image_memsize(optarg);
+ break;
+ case 'd':
+ set_debug_mode(get_nios_cpu());
+ break;
+ case 'b':
+ set_image_base_addr(optarg);
+ break;
+ case 'p':
+ load_symbol_file(optarg);
+ break;
+ case 'c':
+ set_cmdline(optarg);
+ break;
+ case 'r':
+ set_initrd(optarg);
+ break;
+ case 'f':
+ set_fs_image(optarg);
+ break;
+ case 'v':
+ print_version();
+ return 0;
+ case 'h':
+ print_help();
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ alloc_image_mem();
+ load_image();
+ print_image_info();
+ simulating();
+ return 0;
+}
diff --git a/nios-sim b/nios-sim
new file mode 100755
index 0000000..2ff346d
--- /dev/null
+++ b/nios-sim
Binary files differ
diff --git a/niosii.c b/niosii.c
new file mode 100644
index 0000000..4db4ce2
--- /dev/null
+++ b/niosii.c
@@ -0,0 +1,603 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+#include "instruction.h"
+
+static struct NIOS_CPU cpu;
+static struct image_info * img_info = NULL;
+
+void reset_cpu(void)
+{
+ img_info = get_image_info();
+ memset(&cpu, 0x00, sizeof(struct NIOS_CPU));
+ /* set the default to control register */
+ cpu.ctrl_regs[status] = 0x00800000;
+ cpu.gp_regs[4] = 0x00;
+ cpu.gp_regs[7] = 0x00;
+ cpu.trace_index = 0;
+}
+
+static uint32_t get_opcode(uint32_t intr)
+{
+ struct i_type_code * code = (struct i_type_code*)&intr;
+ return code->op;
+}
+
+static uint32_t get_opxcode(uint32_t intr)
+{
+ struct r_type_code * code = (struct r_type_code *)&intr;
+ return code->opx;
+}
+
+struct NIOS_CPU * get_nios_cpu(void)
+{
+ return &cpu;
+}
+
+static uint32_t handle_r_type_code(uint32_t opxcode, uint32_t code)
+{
+ return (r_type_handlers[opxcode]).handler(&cpu, code);
+}
+
+static uint32_t handle_i_type_code(uint32_t opcode, uint32_t code)
+{
+ return i_type_handlers[opcode].handler(&cpu, code);
+}
+
+static uint32_t handle_j_type_code(uint32_t opcode, uint32_t code)
+{
+ return j_type_handlers[opcode].handler(&cpu, code);
+}
+
+uint32_t get_offset_pc(uint32_t pc, uint32_t base_addr)
+{
+ return (pc - base_addr) / 4;
+}
+
+uint32_t get_instruct(struct NIOS_CPU * cpu, uint32_t * mem_base,
+ uint32_t base_addr)
+{
+ uint32_t code = 0;
+ uint32_t offset = get_offset_pc(cpu->pc, base_addr);
+
+ code = mem_base[offset];
+ return code;
+}
+
+static int is_j_type(uint32_t opcode)
+{
+ if (opcode == CALL || opcode == JMPI){
+ return SIM_TRUE;
+ }
+ else {
+ return SIM_FALSE;
+ }
+}
+
+uint32_t execute(uint32_t code)
+{
+ uint32_t opcode = 0;
+ uint32_t opxcode = 0;
+ uint32_t pc_mod_type = 0;
+
+ opcode = get_opcode(code);
+
+ if (is_j_type(opcode) == SIM_TRUE){
+ pc_mod_type = handle_j_type_code(opcode, code);
+ }
+ else if (opcode != OP_R_TYPE){
+ pc_mod_type = handle_i_type_code(opcode, code);
+ }
+ else{
+ opxcode = get_opxcode(code);
+ pc_mod_type = handle_r_type_code(opxcode, code);
+ }
+ return pc_mod_type;
+}
+
+int32_t get_addr_type(uint32_t addr)
+{
+ if ((addr >= img_info->base_addr)
+ && ((addr - img_info->base_addr) <= img_info->mem_size)){
+ return MEM_ADDR;
+ }
+ else{
+ return IO_ADDR;
+ }
+}
+
+uint8_t get_byte(uint32_t addr)
+{
+ if (get_addr_type(addr) == MEM_ADDR){
+ uint8_t * buf = (uint8_t *)img_info->mem_base;
+ return buf[addr - img_info->base_addr];
+ }
+ else{
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ return dev->read_data(dev, addr, 1);
+ }
+ else {
+ printf("%s->error at %x\n",__func__,addr);
+ return 0;
+ }
+ }
+}
+
+void store_byte(uint32_t addr, unsigned char data)
+{
+ if(get_addr_type(addr) == MEM_ADDR){
+ uint8_t * buf = (uint8_t *)img_info->mem_base;
+ buf[addr - img_info->base_addr] = data;
+ }
+ else {
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ dev->write_data(dev, addr, data, 1);
+ }
+ else {
+ printf("%s->unhandled data:%x at %x\n",__func__,data,addr);
+ }
+ }
+}
+
+uint16_t get_half_word(uint32_t addr)
+{
+ if (get_addr_type(addr) == MEM_ADDR){
+ uint16_t * buf = (uint16_t *)img_info->mem_base;
+ return buf[(addr - img_info->base_addr)/2];
+ }
+ else {
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ return dev->read_data(dev, addr, 2);
+ }
+ else {
+ printf("%s->error at %x\n",__func__,addr);
+ return 0;
+ }
+ }
+}
+
+void store_half_word(uint32_t addr, unsigned short data)
+{
+ if (get_addr_type(addr) == MEM_ADDR){
+ uint16_t * buf = (uint16_t *)img_info->mem_base;
+ buf[(addr - img_info->base_addr) / 2] = data;
+ }
+ else {
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ dev->write_data(dev, addr, data, 2);
+ }
+ else {
+ printf("%s->unhandled data:%x at %x\n",__func__,data,addr);
+ }
+ }
+}
+
+uint32_t get_word(uint32_t addr)
+{
+ if (get_addr_type(addr) == MEM_ADDR){
+ uint32_t * buf = (uint32_t * )img_info->mem_base;
+ return buf[(addr - img_info->base_addr) / 4];
+ }
+ else {
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ return dev->read_data(dev, addr, 4);
+ }
+ else {
+ printf("%s->error at %x\n",__func__,addr);
+ return 0;
+ }
+ }
+}
+
+void store_word(uint32_t addr, uint32_t data)
+{
+ if (get_addr_type(addr) == MEM_ADDR){
+ uint32_t * buf = (uint32_t *)img_info->mem_base;
+ buf[(addr - img_info->base_addr) / 4] = data;
+ }
+ else {
+ struct io_device * dev = get_device(addr);
+ if (dev != NULL){
+ dev->write_data(dev, addr, data, 4);
+ }
+ else {
+ printf("%s->unhandled data:%x at %x\n",__func__,data,addr);
+ }
+ }
+}
+
+static uint32_t has_irq(struct NIOS_CPU * cpu)
+{
+ uint32_t ret_val = CPU_HAS_NO_EVENT;
+ uint32_t irq_mask = 0;
+ uint32_t temp = 0;
+
+ /* 1. judge the device has irq */
+ irq_mask = get_io_irq_status();
+
+ if (irq_mask != 0){
+ if ((cpu->ctrl_regs[status] & REG_STATUS_PIE) == REG_STATUS_PIE){
+ temp = cpu->ctrl_regs[ienable] & irq_mask;
+#if 1
+ if (temp != 0 && (temp != cpu->ctrl_regs[ipending])){
+#else
+ if (temp != 0){
+#endif
+ /* 2. modify the control register */
+ cpu->ctrl_regs[ipending] |= temp;
+ ret_val = CPU_HAS_IRQ;
+ }
+ }
+ }
+
+ return ret_val;
+}
+
+static uint32_t has_exception(struct NIOS_CPU * cpu)
+{
+ uint32_t ret_val = CPU_HAS_NO_EVENT;
+
+ return ret_val;
+}
+
+static uint32_t get_cpu_status(struct NIOS_CPU * cpu)
+{
+ uint32_t ret_val = CPU_HAS_NO_EVENT;
+ ret_val |= has_irq(cpu);
+ ret_val |= has_exception(cpu);
+
+ return ret_val;
+}
+
+static void handle_irq(struct NIOS_CPU * cpu)
+{
+ uint32_t reg_status_val = 0;
+ uint32_t temp_pc = 0;
+ /* according to the kind of interrupt or exception,
+ * set PC to the address of IRQ or exception vector.
+ */
+ temp_pc = cpu->pc;
+ cpu->pc = EXCEPTION_HANDLER_ADDR;
+ reg_status_val = cpu->ctrl_regs[status];
+ cpu->ctrl_regs[status] &= 0xFFFFFFFE; /* clear PIE */
+ if((reg_status_val & REG_STATUS_EH) == 0){
+ cpu->ctrl_regs[estatus] = reg_status_val;
+ cpu->gp_regs[ea] = temp_pc + 4;
+ }
+}
+
+static void handle_exception(struct NIOS_CPU * cpu)
+{
+
+}
+
+void handle_irq_exception(struct NIOS_CPU * cpu)
+{
+ uint32_t cpu_status = CPU_HAS_NO_EVENT;
+
+ cpu_status = get_cpu_status(cpu);
+ if(cpu_status & CPU_HAS_IRQ){
+ handle_irq(cpu);
+ }
+ else if (cpu_status & CPU_HAS_EXCEPTION){
+ handle_exception(cpu);
+ }
+}
+
+static void dump_j_code(uint32_t code)
+{
+ def_j_type_code;
+
+ printf("TYPE: J Code [%08X]\n", code);
+ printf("OP: 0x%02X\n",instr->op);
+ printf("IMM26: 0x%X\n",instr->imm26);
+}
+
+static void dump_r_code(uint32_t code)
+{
+ def_r_type_code;
+
+ printf("TYPE: R Code [%08X]\n", code);
+ printf("OP: 0x%02X\n", instr->op);
+ printf("A=0x%X B=0x%X C=0x%X OPX=0x%X N=0x%X\n",
+ instr->a, instr->b, instr->c, instr->opx, instr->n);
+}
+
+static void dump_i_code(uint32_t code)
+{
+ def_i_type_code;
+
+ printf("TYPE: I Code [%08X]\n", code);
+ printf("OP: 0x%02X\n", instr->op);
+ printf("A=0x%X B=0x%X IMM16=0x%04X\n", instr->a, instr->b, instr->imm16);
+}
+
+static void dump_code(uint32_t code)
+{
+ uint32_t code_type = get_opcode(code);
+ printf("\n");
+ printf("--------------Code Dump--------------\n");
+ switch(code_type){
+ case OP_J_TYPE:
+ dump_j_code(code);
+ break;
+ case OP_R_TYPE:
+ dump_r_code(code);
+ break;
+ default:
+ dump_i_code(code);
+ break;
+ }
+ printf("-------------------------------------\n");
+}
+
+void dump_curr_code(uint32_t code)
+{
+ dump_code(code);
+}
+
+void dump_next_code(struct NIOS_CPU * cpu)
+{
+ uint32_t code = get_instruct(cpu,img_info->mem_base, img_info->base_addr);
+ dump_code(code);
+}
+
+void dump_pc(struct NIOS_CPU * cpu)
+{
+ int32_t i = 0;
+ printf("============================================================\n");
+ printf("ERROR PC=%08X\n",cpu->pc);
+ printf("PC Trace Index :%d\n", cpu->trace_index);
+ printf("============================================================\n");
+ for (i=0;i<PC_TRACE_CNT;i++){
+ if (i == (cpu->trace_index - 1)){
+ printf("(%08X) ",cpu->pc_trace[i]);
+ }
+ else {
+ printf("%08X ",cpu->pc_trace[i]);
+ }
+ if (((i+1)% 8) == 0){
+ printf("\n");
+ }
+ }
+ printf("\n============================================================\n");
+}
+
+static const char * g_regs_name[] = {
+ " ZERO",
+ " AT",
+ "REG02",
+ "REG03",
+ "REG04",
+ "REG05",
+ "REG06",
+ "REG07",
+ "REG08",
+ "REG09",
+ "REG10",
+ "REG11",
+ "REG12",
+ "REG13",
+ "REG14",
+ "REG15",
+ "REG16",
+ "REG17",
+ "REG18",
+ "REG19",
+ "REG20",
+ "REG21",
+ "REG22",
+ "REG23",
+ " ET",
+ " BT",
+ " GP",
+ " SP",
+ " FP",
+ " EA",
+ " BA",
+ " RA"
+};
+
+static const char * c_regs_name[] = {
+ "SSTAT",
+ "ESTAT",
+ "BSTAT",
+ "IENAB",
+ "IPEND",
+ "CPUID",
+ "RESER",
+ "EXCEP",
+ "PTEAD",
+ "TLBAD",
+ "TLBMI",
+ "RESER",
+ "BADAD",
+ "CONFI",
+ "MPUBA",
+ "MPUAD"
+};
+
+void dump_register(struct NIOS_CPU * cpu)
+{
+ int32_t i = 0;
+
+ printf("\n");
+ printf("============================================================\n");
+ printf("[Genernal Register]\n");
+ printf("============================================================\n");
+ for (i=0;i<NIOS_REG_CNT;i++){
+ printf("%s=%08X ",g_regs_name[i],cpu->gp_regs[i]);
+ if (((i+1) % 4) == 0)
+ printf("\n");
+ }
+ printf("============================================================\n");
+ printf("[Control Register]\n");
+ printf("============================================================\n");
+ for (i=0;i<16;i++){
+ printf("%s=%08X ",c_regs_name[i],cpu->ctrl_regs[i]);
+ if (((i+1) % 4) == 0)
+ printf("\n");
+ }
+ printf("============================================================\n");
+}
+
+/**
+ * Parse the options of break command
+ */
+#define SPACE_CHAR (' ')
+#define BREAK_CMD_LEN (16)
+extern char break_func_name[256];
+static uint32_t get_break_pc(char * input)
+{
+ uint32_t ret_pc = 0x0;
+ uint32_t input_len = 0;
+
+ input_len = strlen(input);
+ /*
+ * TODO: the judgement of option's format is not full implemented.
+ */
+ if (input_len == BREAK_CMD_LEN){
+ sscanf(input, "break 0x%08x\n", &ret_pc);
+ }
+
+ if (strstr(input, "func") != NULL){
+ memset(break_func_name, 0x00, 256);
+ sscanf(input, "break func=%s", break_func_name);
+ return 0xFFFFFFFF;
+ }
+ return ret_pc;
+}
+
+void set_break(struct NIOS_CPU * cpu, char * input)
+{
+ uint32_t break_pc = 0x0;
+
+ break_pc = get_break_pc(input);
+ if (break_pc != 0x0){
+ if (break_pc == 0xFFFFFFFF){
+ cpu->mode = BREAK_MODE;
+ }
+ else {
+ cpu->mode = BREAK_MODE;
+ cpu->break_pc = break_pc;
+ }
+ }
+ else{
+ printf("Error Address\n");
+ cpu->mode = SINGLE_STEP;
+ }
+}
+
+static void output_char(char c)
+{
+ if (c == '\r' || c == '\n'){
+ printf(".");
+ }
+ else {
+ printf("%c",c);
+ }
+}
+static void output_ascii(uint32_t * buf)
+{
+ uint32_t val = 0;
+ char temp = 0;
+ uint32_t i = 0;
+
+ printf("\t");
+ for (i = 0; i < 4; i++){
+ val = buf[i];
+ temp = val & 0xFF;
+ output_char(temp);
+ temp = (val >> 8) & 0xFF;
+ output_char(temp);
+ temp = (val >> 16) & 0xFF;
+ output_char(temp);
+ temp = (val >> 24) & 0xFF;
+ output_char(temp);
+ }
+}
+/*
+ * dump the content of memory
+ */
+void dump_mem(struct NIOS_CPU * cpu, char * input)
+{
+ uint32_t addr, size;
+ struct image_info * info = get_image_info();
+ int32_t i = 0;
+ uint32_t * buf = NULL;
+ uint32_t temp_buf[4] = {0};
+ uint32_t index = 0;
+ sscanf(input, "dump 0x%X %d", &addr, &size);
+
+ addr = addr & (~0x3);
+ size = size / 4 * 4;
+ if (addr >= info->base_addr && size < info->mem_size){
+ buf = info->mem_base + (addr - info->base_addr) / 4 ;
+ printf("================================================\n");
+ printf("[Memory Dump start:0x%08X size:%d]\n", addr, size);
+ printf("================================================\n");
+ for (i=0;i<size/4;i++){
+ temp_buf[index] = buf[i];
+ index = index + 1;
+ if (i % 4 == 0){
+ printf("[%08X]",addr + i * 4);
+ }
+ printf("%08X ", (uint32_t)buf[i]);
+
+ if (((i+1) % 4) == 0){
+ output_ascii(temp_buf);
+ index = 0;
+ printf("\n");
+ }
+ else if (i == (size/4 - 1)){
+ printf("\n");
+ }
+ }
+ printf("================================================\n");
+ }
+}
+
+void clean_ipending(uint32_t mask)
+{
+ cpu.ctrl_regs[ipending] &= (~mask);
+}
+
+/* Record the pc trace. It is used when segment fault happening. */
+void trace_pc(struct NIOS_CPU * cpu)
+{
+ cpu->pc_trace[cpu->trace_index] = cpu->pc;
+ cpu->trace_index ++;
+ if (cpu->trace_index >= PC_TRACE_CNT){
+ cpu->trace_index = 0;
+ }
+}
+/*----------------------------------------------------------------------------*/
+
diff --git a/niosii.h b/niosii.h
new file mode 100644
index 0000000..cd4ba80
--- /dev/null
+++ b/niosii.h
@@ -0,0 +1,182 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __NIOS_II_H__
+#define __NIOS_II_H__
+
+#include <stdio.h>
+#include "public.h"
+
+#define NIOS_REG_CNT (32)
+#define D_CACHE_SIZE (16 * 1024)
+#define I_CACHE_SIZE (16 * 1024)
+#define PC_TRACE_CNT (128)
+
+enum {
+ NORMAL_MODE = 0x00,
+ SINGLE_STEP = 0x01,
+ BREAK_MODE = 0x02,
+};
+
+struct NIOS_CPU {
+ uint32_t gp_regs[NIOS_REG_CNT]; /* default value is 0 */
+ uint32_t ctrl_regs[NIOS_REG_CNT]; /* is defined in Processor Reference Handbook */
+ uint32_t pc;
+ uint32_t break_pc;
+ uint32_t mode;
+ uint32_t pc_trace[PC_TRACE_CNT];
+ uint32_t trace_index;
+};
+
+#define EXCEPTION_HANDLER_ADDR (0x00800020) /* exc_hook, exception handler address */
+#define BREAK_HANDLER_ADDRESS (0x00000000) /* break handler address */
+
+#define OP_R_TYPE 0x3A
+#define OP_J_TYPE 0x00
+
+struct i_type_handler {
+ uint32_t (*handler)(struct NIOS_CPU * cpu, uint32_t code);
+};
+
+struct r_type_handler{
+ uint32_t (*handler)(struct NIOS_CPU * cpu, uint32_t code);
+};
+
+struct j_type_handler{
+ uint32_t (*handler)(struct NIOS_CPU * cpu, uint32_t code);
+};
+
+struct custom_type_handler{
+ uint32_t (*handler)(struct NIOS_CPU * cpu, uint32_t code);
+};
+
+extern struct i_type_handler i_type_handlers[];
+extern struct r_type_handler r_type_handlers[];
+extern struct j_type_handler j_type_handlers[];
+
+struct i_type_code{
+ uint32_t op:6;
+ uint32_t imm16:16;
+ uint32_t b:5;
+ uint32_t a:5;
+}__attribute__ ((__packed__));
+
+struct j_type_code{
+ uint32_t op:6;
+ uint32_t imm26:26;
+}__attribute__ ((__packed__));
+
+struct r_type_code{
+ uint32_t op:6;
+ uint32_t n:5;
+ uint32_t opx:6;
+ uint32_t c:5;
+ uint32_t b:5;
+ uint32_t a:5;
+}__attribute__ ((__packed__));
+
+#define handler_item(func) {.handler = func}
+
+struct custom_type_code {
+ uint32_t op:6;
+ uint32_t n:8;
+ uint32_t rc:1;
+ uint32_t rb:1;
+ uint32_t ra:1;
+ uint32_t c:5;
+ uint32_t b:5;
+ uint32_t a:5;
+};
+
+enum GP_REG_ALIAS{
+ zero = 0,
+ at = 1,
+ et = 24,
+ bt = 25,
+ gp = 26,
+ sp = 27,
+ fp = 28,
+ ea = 29,
+ ba = 30,
+ ra = 31,
+};
+enum CTRL_REG_ALIAS{
+ status = 0,
+ estatus,
+ bstatus,
+ ienable,
+ ipending,
+ cpuid,
+ exception = 7,
+ pteaddr,
+ tlbacc,
+ tlbmisc,
+ badaddr = 12,
+ config,
+ mpubase,
+ mpuacc
+};
+
+
+
+#define MEM_ADDR (0)
+#define IO_ADDR (1)
+
+#define PC_INC_NORMAL (0)
+#define PC_INC_BY_INSTR (1)
+
+extern uint32_t custom_instr(struct NIOS_CPU * cpu, uint32_t code);
+extern void reset_cpu(void);
+extern struct NIOS_CPU * get_nios_cpu(void);
+extern uint32_t execute(uint32_t code);
+extern int32_t get_addr_type(uint32_t addr);
+extern uint8_t get_byte(uint32_t addr);
+extern void store_byte(uint32_t addr, uint8_t data);
+extern uint16_t get_half_word(uint32_t addr);
+extern void store_half_word(uint32_t addr, uint16_t data);
+extern uint32_t get_word(uint32_t addr);
+extern void store_word(uint32_t addr, uint32_t data);
+extern uint32_t get_instruct(struct NIOS_CPU * cpu, uint32_t * mem_base,
+ uint32_t base_addr);
+extern void dump_register(struct NIOS_CPU * cpu);
+extern void dump_curr_code(uint32_t code);
+extern void dump_next_code(struct NIOS_CPU * cpu);
+extern void dump_pc(struct NIOS_CPU * cpu);
+extern void set_break(struct NIOS_CPU * cpu, char * input);
+extern void dump_mem(struct NIOS_CPU * cpu, char * input);
+extern uint32_t ascii_to_hex(char * buf, uint32_t buf_len);
+
+#define def_i_type_code struct i_type_code * instr = (struct i_type_code *)&code
+#define def_j_type_code struct j_type_code * instr = (struct j_type_code *)&code
+#define def_r_type_code struct r_type_code * instr = (struct r_type_code *)&code
+
+
+/* BIT Definition for Control register */
+#define REG_STATUS_PIE (0x01)
+#define REG_STATUS_EH (1<<2)
+
+#define CPU_HAS_IRQ (0x01)
+#define CPU_HAS_EXCEPTION (0x02)
+#define CPU_HAS_NO_EVENT (0)
+
+extern void handle_irq_exception(struct NIOS_CPU * cpu);
+extern void clean_ipending(uint32_t mask);
+extern void trace_pc(struct NIOS_CPU * cpu);
+#endif
+
diff --git a/nor_flash.c b/nor_flash.c
new file mode 100644
index 0000000..3083735
--- /dev/null
+++ b/nor_flash.c
@@ -0,0 +1,108 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+#include "nor_flash.h"
+
+static struct nor_flash_core_hw hw;
+
+static void flash_init(struct io_device * self)
+{
+ memset(&hw, 0x00, sizeof(struct nor_flash_core_hw));
+ self->priv_data = &hw;
+
+ hw.phys_base_addr = NOR_FLASH_BASE_ADDR;
+ hw.size = NOR_FLASH_SIZE;
+ hw.status = STATUS_READ;
+ hw.mem_base_addr = (unsigned char *)malloc(hw.size);
+
+ printf("NOR Flash Module: PHYS:0x%08X at %p size:0x%08X\n",
+ hw.phys_base_addr, hw.mem_base_addr, hw.size);
+}
+
+static int32_t flash_is_belong(uint32_t address)
+{
+ int32_t ret_val = ADDR_IS_NOT_DEV;
+
+ if (address >= hw.phys_base_addr && address <(hw.phys_base_addr + hw.size)){
+ ret_val = ADDR_IS_DEV;
+ }
+ return ret_val;
+}
+
+/* only support 8bit access */
+static uint32_t flash_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+{
+ uint32_t ret_val = 0;
+ uint8_t * data = (uint8_t *)hw.mem_base_addr;
+
+ if(data_len == (hw.bus_width / 8)){
+ ret_val = (uint32_t)(data[addr - hw.phys_base_addr]);
+ printf("%s->%x:%x\n",__func__,addr,ret_val);
+ }
+ return ret_val;
+}
+
+static int32_t judge_special_addr(uint32_t addr)
+{
+ int32_t ret_val = SIM_TRUE;
+ return ret_val;
+}
+
+static void handle_special_operation(uint32_t addr, uint32_t data)
+{
+
+}
+
+static void flash_write(struct io_device * self, uint32_t addr, uint32_t data,
+ uint32_t data_len)
+{
+ uint8_t * data_buf = (uint8_t *)hw.mem_base_addr;
+
+ /* judge whether the address is the special address */
+ if (judge_special_addr(addr) == SIM_TRUE){
+ handle_special_operation(addr, data);
+ } else {
+ if (hw.status == STATUS_CHIP_ERASE || hw.status == STATUS_SECTION_ERASE){
+ if (data_len == (hw.bus_width/8)){
+ data_buf[(addr - hw.phys_base_addr)] = (uint8_t)(data & 0xFF);
+ }
+ }
+ }
+}
+
+struct io_device nor_flash_core = {
+ .name = "NOR Flash Core",
+ .init = flash_init,
+ .is_belong = flash_is_belong,
+ .read_data = flash_read,
+ .write_data = flash_write,
+ .has_irq = NULL,
+ .simulate = NULL,
+ .irq_enable_mask = 0,
+};
+
+uint8_t * nor_flash_mem_addr(void)
+{
+ return hw.mem_base_addr;
+}
+
+
diff --git a/nor_flash.h b/nor_flash.h
new file mode 100644
index 0000000..a5e5e9e
--- /dev/null
+++ b/nor_flash.h
@@ -0,0 +1,57 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __NOR_FLASH_H__
+#define __NOR_FLASH_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "io_device.h"
+
+#define NOR_FLASH_OPS_CNT (10)
+struct nor_flash_operations{
+ uint32_t addr;
+ uint32_t value;
+};
+
+#define STATUS_READ (0)
+#define STATUS_WRITE (1)
+#define STATUS_CHIP_ERASE (2)
+#define STATUS_SECTION_ERASE (3)
+
+#define NOR_FLASH_BASE_ADDR (0x0000)
+#define NOR_FLASH_SIZE (0x400000)
+#define NOR_FLASH_BUS_WIDTH (8)
+
+struct nor_flash_core_hw {
+ struct nor_flash_operations ops[10];
+ uint32_t phys_base_addr;
+ uint32_t size;
+ uint32_t status;
+ uint8_t * mem_base_addr;
+ uint32_t bus_width;
+};
+
+extern struct io_device nor_flash_core;
+extern uint8_t * nor_flash_mem_addr(void);
+#endif /* end of nor_flash.h */
+
+
+
diff --git a/public.h b/public.h
new file mode 100644
index 0000000..a84b6f6
--- /dev/null
+++ b/public.h
@@ -0,0 +1,85 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __PUBLIC_H__
+#define __PUBLIC_H__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "niosii.h"
+
+#define SIM_FALSE (0)
+#define SIM_TRUE (1)
+
+typedef enum {
+ INVALID_FMT=0x00,
+ SREC_FMT=0x01
+}IMG_FORMAT;
+
+struct image_info{
+ char * path_name;
+ IMG_FORMAT image_format;
+ uint32_t mem_size;
+ uint32_t * mem_base;
+ uint32_t entry_addr;
+ uint32_t base_addr;
+};
+
+struct symbol_obj;
+
+struct symbol_obj{
+ char * sym_name;
+ uint32_t addr;
+ struct symbol_obj * next;
+};
+
+extern void load_image(void);
+extern void alloc_image_mem(void);
+extern void set_image_pathname(char * pathname);
+extern void set_image_format(IMG_FORMAT format);
+extern void set_image_memsize(char * size);
+extern void set_image_entry_addr(uint32_t addr);
+extern void set_image_base_addr(char * addr);
+extern void set_cmdline(char * optarg);
+extern void set_initrd(char * optarg);
+extern void set_fs_image(char * optarg);
+extern void init_cmdline(struct NIOS_CPU * cpu);
+extern void init_initrd(struct NIOS_CPU * cpu);
+extern void init_fs_image(struct NIOS_CPU * cpu);
+extern void print_image_info(void);
+extern void simulating(void);
+extern struct image_info * get_image_info(void);
+extern void set_debug_mode(struct NIOS_CPU * cpu);
+extern void load_symbol_file(char * symbol_file);
+extern struct symbol_obj * get_symbol(uint32_t addr);
+
+#define SIM_MODE (0)
+#define DEBUG_MODE (1)
+#define EXIT_MODE (2)
+extern int32_t get_run_mode(void);
+
+#endif /*__PUBLIC_H__*/
+
+
diff --git a/r_type_handler.c b/r_type_handler.c
new file mode 100644
index 0000000..a5d5d1d
--- /dev/null
+++ b/r_type_handler.c
@@ -0,0 +1,458 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "instruction.h"
+
+static uint32_t wrctl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->ctrl_regs[instr->n] = cpu->gp_regs[instr->a];
+
+ return PC_INC_NORMAL;
+}
+
+
+static uint32_t eret(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[estatus];
+ cpu->pc = cpu->gp_regs[ea];
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t roli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = (instr->n) ;
+ uint32_t value = cpu->gp_regs[instr->a];
+ uint32_t temp = 0;
+
+ temp = value >> (32 - shift_bit);
+ cpu->gp_regs[instr->c] = value << shift_bit;
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->c] | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t rol(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = cpu->gp_regs[instr->b] & 0x1F;
+ uint32_t temp = (cpu->gp_regs[instr->a]) >> (32 - shift_bit);
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] << shift_bit) | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushp(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ret(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->pc = cpu->gp_regs[ra];
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t nor(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = ~(cpu->gp_regs[instr->a] | cpu->gp_regs[instr->b]);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxuu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint64_t temp = 0;
+
+ temp = (uint32_t)cpu->gp_regs[instr->a];
+ temp = temp * (uint32_t)cpu->gp_regs[instr->b];
+ cpu->gp_regs[instr->c] = ((uint32_t)(temp >> 32)) & (0xFFFFFFFF);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpge(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) >= (int32_t)(cpu->gp_regs[instr->b])){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else {
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t bret(struct NIOS_CPU * cpu, uint32_t code)
+{
+
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[bstatus];
+ cpu->pc = cpu->gp_regs[ba];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ror(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = cpu->gp_regs[instr->b] & 0x1F;
+ uint32_t temp = cpu->gp_regs[instr->a] << (32 - shift_bit);
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] >> shift_bit) | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t jmp(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->pc = cpu->gp_regs[instr->a];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t and(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] & cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmplt(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) < (int32_t)(cpu->gp_regs[instr->b])){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t slli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] << instr->n;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sll(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] << (cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t wrprs(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t or(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] | cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxsu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int64_t a = (int32_t)(cpu->gp_regs[instr->a]);
+ int64_t temp = 0;
+
+ temp = a * cpu->gp_regs[instr->b];
+ cpu->gp_regs[instr->c] = (uint32_t)((temp >> 32));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpne(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] != cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+static uint32_t srli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] >> (uint32_t)(instr->n);
+ return PC_INC_NORMAL;
+}
+static uint32_t srl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] >> (cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t nextpc(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->pc + 4;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t callr(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ cpu->gp_regs[ra] = cpu->pc + 4;
+ cpu->pc = cpu->gp_regs[instr->a];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t xor(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t a = cpu->gp_regs[instr->a];
+ uint32_t b = cpu->gp_regs[instr->b];
+
+ cpu->gp_regs[instr->c] = a ^ b;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxss(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ int32_t b = (int32_t)cpu->gp_regs[instr->b];
+ uint64_t temp = 0;
+
+ temp = a * b;
+ cpu->gp_regs[instr->c] = (uint32_t) (temp >> 32);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpeq(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if(cpu->gp_regs[instr->a] == cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t divu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->b] != 0){
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] / cpu->gp_regs[instr->b];
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t div(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ int32_t b = (int32_t)cpu->gp_regs[instr->b];
+
+ if (b != 0){
+ cpu->gp_regs[instr->c] = a / b;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t rdctl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->n];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mul(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] * cpu->gp_regs[instr->b]) & 0xFFFFFFFF;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpgeu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] >= cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t initi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t trap(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->ctrl_regs[estatus] = cpu->ctrl_regs[status];
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[status] & 0xFFFFFFFC;
+ cpu->gp_regs[ea] = cpu->pc + 4;
+ cpu->pc = EXCEPTION_HANDLER_ADDR;
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t cmpltu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] < cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else {
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t add(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] + cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t instr_break(struct NIOS_CPU * cpu, uint32_t code)
+{
+#ifdef NIOS_SIM_SUPPORT_BREAK
+ cpu->ctrl_regs[bstatus] = cpu->ctrl_regs[status];
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[status] & 0xFFFFFFFC;
+ cpu->gp_regs[ba] = cpu->pc + 4;
+ cpu->pc = BREAK_HANDLER_ADDRESS;
+ return PC_INC_BY_INSTR;
+#else
+ return PC_INC_NORMAL;
+#endif
+}
+
+static uint32_t instr_sync(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sub(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] - cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t srai(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ cpu->gp_regs[instr->c] = a >> (uint32_t)(instr->n);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sra(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int32_t a = (int32_t) cpu->gp_regs[instr->a];
+
+ cpu->gp_regs[instr->c] = a >> (uint32_t)(cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+#define R_TYPE_HANDLER_COUNT (0x40)
+
+struct r_type_handler r_type_handlers[R_TYPE_HANDLER_COUNT] = {
+ [ERET] = handler_item(eret),
+ [ROLI] = handler_item(roli),
+ [ROL] = handler_item(rol),
+ [FLUSHP] = handler_item(flushp),
+ [RET] = handler_item(ret),
+ [NOR] = handler_item(nor),
+ [MULXUU] = handler_item(mulxuu),
+ [CMPGE] = handler_item(cmpge),
+ [BRET] = handler_item(bret),
+ [ROR] = handler_item(ror),
+ [FLUSHI] = handler_item(flushi),
+ [JMP] = handler_item(jmp),
+ [AND] = handler_item(and),
+ [CMPLT] = handler_item(cmplt),
+ [SLLI] = handler_item(slli),
+ [SLL] = handler_item(sll),
+ [WRPRS] = handler_item(wrprs),
+ [OR] = handler_item(or),
+ [MULXSU] = handler_item(mulxsu),
+ [CMPNE] = handler_item(cmpne),
+ [SRLI] = handler_item(srli),
+ [SRL] = handler_item(srl),
+ [NEXTPC] = handler_item(nextpc),
+ [CALLR] = handler_item(callr),
+ [XOR] = handler_item(xor),
+ [MULXSS] = handler_item(mulxss),
+ [CMPEQ] = handler_item(cmpeq),
+ [DIVU] = handler_item(divu),
+ [DIV] = handler_item(div),
+ [RDCTL] = handler_item(rdctl),
+ [MUL] = handler_item(mul),
+ [CMPGEU] = handler_item(cmpgeu),
+ [INITI] = handler_item(initi),
+ [TRAP] = handler_item(trap),
+ [WRCTL] = handler_item(wrctl),
+ [CMPLTU] = handler_item(cmpltu),
+ [ADD] = handler_item(add),
+ [BREAK] = handler_item(instr_break),
+ [SYNC] = handler_item(instr_sync),
+ [SUB] = handler_item(sub),
+ [SRAI] = handler_item(srai),
+ [SRA] = handler_item(sra)
+};
+
+
+
diff --git a/simulator.c b/simulator.c
new file mode 100644
index 0000000..e4880e9
--- /dev/null
+++ b/simulator.c
@@ -0,0 +1,420 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+#include "simulator.h"
+
+static int32_t simulator_mode = SIM_MODE;
+
+static void modify_pc(struct NIOS_CPU * cpu)
+{
+ cpu->pc += 4;
+}
+
+static void set_init_pc(struct NIOS_CPU * cpu, uint32_t pc)
+{
+ cpu->pc = pc;
+}
+
+static void quit_debug_mode(struct NIOS_CPU * cpu)
+{
+ simulator_mode = SIM_MODE;
+ cpu->mode = NORMAL_MODE;
+ cpu->break_pc = 0;
+}
+
+int32_t get_run_mode(void)
+{
+ return simulator_mode;
+}
+
+void set_debug_mode(struct NIOS_CPU * cpu)
+{
+ simulator_mode = DEBUG_MODE;
+ cpu->break_pc = 0;
+ cpu->mode = NORMAL_MODE;
+}
+
+#define CMD_CHAR_SIZE (256)
+
+static char input_char[CMD_CHAR_SIZE] = {0};
+enum {
+ DISP_CURR = 0x01,
+ DISP_NEXT,
+ DUMP_REG,
+ HELP,
+ GO,
+ DISP_PC,
+ SET_BREAK,
+ QUIT,
+ DUMP_MEM,
+ CALL_STACK,
+ QUIT_SIM
+};
+
+static const struct debug_command debug_cmds[] = {
+ {"c", "disp_curr", "display the contents of current code", DISP_CURR},
+ {"n", "disp_next", "display the contents of next code", DISP_NEXT},
+ {"r", "dump_reg", "display the contents of register", DUMP_REG},
+ {"h", "help", "display the help information", HELP},
+ {"g", "go", "continue executing", GO},
+ {"p", "disp_pc", "display current PC Value", DISP_PC},
+ {NULL, "break", "set break address.For example:\n\t(1)break 08000010\n\t(2)break func=function name", SET_BREAK},
+ {"qd", "quit_debug","quit debug mode", QUIT},
+ {NULL, "dump", "dump memory",DUMP_MEM},
+ {"cs", "call_stack", "dump call stack", CALL_STACK},
+ {"qs", "quit_sim", "quit simulator", QUIT_SIM}
+};
+
+#define CMD_COUNT (sizeof(debug_cmds) / sizeof(debug_cmds[0]))
+
+static void disp_help(void)
+{
+ int32_t i;
+ printf("\n[HELP INFORMATION]\n");
+ printf("==============================================\n");
+ for (i=0;i<CMD_COUNT;i++){
+ printf("[%d] \"%s\" or \"%s\"\n %s\n",
+ debug_cmds[i].code,
+ debug_cmds[i].short_cmd,
+ debug_cmds[i].long_cmd,
+ debug_cmds[i].desc);
+ }
+ printf("==============================================\n");
+}
+
+static int32_t get_cmd_code(char * input_char)
+{
+ int32_t ret_val = 0;
+ int32_t i = 0;
+
+ if (strlen(input_char) == 0){
+ return GO;
+ }
+
+ for(i=0;i<CMD_COUNT;i++){
+ if (debug_cmds[i].short_cmd != NULL
+ && strcmp(input_char, debug_cmds[i].short_cmd) == 0){
+ ret_val = debug_cmds[i].code;
+ break;
+ }
+
+ if (debug_cmds[i].long_cmd != NULL
+ && strcmp(input_char, debug_cmds[i].long_cmd) == 0){
+ ret_val = debug_cmds[i].code;
+ break;
+ }
+
+ if (debug_cmds[i].short_cmd == NULL && debug_cmds[i].long_cmd != NULL
+ && strstr(input_char, debug_cmds[i].long_cmd) != NULL){
+ ret_val = debug_cmds[i].code;
+ break;
+ }
+ }
+ return ret_val;
+}
+
+static void quit_simulator(void)
+{
+ simulator_mode = EXIT_MODE;
+}
+
+static void dump_call_stack(void);
+static const char *DEBUG_PMT = "(dbg)";
+char break_func_name[256] = {0};
+static int32_t exec_this_func(char * func_name);
+static void debug_mode(struct NIOS_CPU * cpu, uint32_t code, uint32_t exec_ret)
+{
+ int32_t input_key = 0;
+ int32_t index = 0;
+
+ if (cpu->mode == BREAK_MODE){
+ if (cpu->break_pc == cpu->pc){
+ cpu->break_pc = 0;
+ cpu->mode = SINGLE_STEP;
+ }
+ else if (exec_this_func(break_func_name) == SIM_TRUE){
+ cpu->break_pc = 0;
+ cpu->mode = SINGLE_STEP;
+ }
+ else {
+ return;
+ }
+ }
+
+ for (;;){
+ memset(input_char, 0x00, CMD_CHAR_SIZE);
+ index = 0;
+ printf("%s-(PC:%08X)#",DEBUG_PMT,cpu->pc);
+
+ while(1){
+ input_key = getchar();
+ if (input_key != '\n' && index < CMD_CHAR_SIZE){
+ input_char[index++] = (char)input_key;
+ }
+ else {
+ break;
+ }
+ }
+
+ input_key = get_cmd_code(input_char);
+ switch(input_key){
+ case DISP_CURR:
+ dump_curr_code(code);
+ break;
+ case DISP_NEXT:
+ dump_next_code(cpu);
+ break;
+ case DUMP_REG:
+ dump_register(cpu);
+ break;
+ case HELP:
+ disp_help();
+ break;
+ case GO:
+ return;
+ case DISP_PC:
+ dump_pc(cpu);
+ break;
+ case SET_BREAK:
+ set_break(cpu, input_char);
+ break;
+ case DUMP_MEM:
+ dump_mem(cpu, input_char);
+ break;
+ case QUIT:
+ quit_debug_mode(cpu);
+ return;
+ case QUIT_SIM:
+ quit_debug_mode(cpu);
+ quit_simulator();
+ return;
+ case CALL_STACK:
+ dump_call_stack();
+ break;
+ default:
+ printf("INVALID COMMAND\n");
+ continue;
+ }
+ }
+}
+
+static void sigint_handler(int sig)
+{
+ int32_t input = '\0';
+ struct NIOS_CPU * cpu = get_nios_cpu();
+
+ signal(sig, SIG_IGN);
+
+ while(1){
+ printf("\nPlease select what you want?\n");
+ printf("Q for Quit Simulator\n");
+ printf("D for enter Debug Mode\n");
+ printf("R for Resume the simulating\n");
+ printf("N for do Nothing\n#");
+
+ input = getchar();
+ if ((char)input == '\n'){
+ goto handler_out;
+ }
+
+ switch((char)input){
+ case 'Q':
+ quit_debug_mode(cpu);
+ simulator_mode = EXIT_MODE;
+ return;
+ case 'D':
+ set_debug_mode(cpu);
+ goto handler_out;
+ case 'R':
+ quit_debug_mode(cpu);
+ goto handler_out;
+ case 'N':
+ goto handler_out;
+ default:
+ continue;
+ }
+ }
+
+handler_out:
+ signal(SIGINT, sigint_handler);
+}
+
+static void sigsegv_handler(int sig)
+{
+ struct NIOS_CPU * cpu = get_nios_cpu();
+
+ signal(sig, SIG_IGN);
+ printf("\n--------------Segmentation fault------------------\n");
+ dump_pc(cpu);
+ dump_register(cpu);
+ printf("----------------------------------------------------\n");
+ dump_call_stack();
+ _exit(0);
+}
+
+static void register_signal_handler(void)
+{
+ signal(SIGINT, sigint_handler);
+ signal(SIGSEGV, sigsegv_handler);
+}
+
+#define CS_LEN (32)
+struct call_stack {
+ struct symbol_obj * stack[CS_LEN];
+ uint32_t pos;
+};
+
+static struct call_stack cs = {
+ .stack = {NULL},
+ .pos = 0,
+};
+
+static int32_t exec_this_func(char * func_name)
+{
+ struct symbol_obj * obj = NULL;
+
+ if (cs.pos == 0){
+ obj = cs.stack[0];
+ }
+ else{
+ obj = cs.stack[cs.pos-1];
+ }
+
+ if (obj != NULL){
+ if (strcmp(obj->sym_name, func_name) == 0){
+ return SIM_TRUE;
+ }
+ }
+
+ return SIM_FALSE;
+}
+static void dump_call_stack(void);
+static void record_call_stack(uint32_t addr)
+{
+ struct symbol_obj * obj = NULL;
+
+ obj = get_symbol(addr);
+ if (obj != NULL){
+ if (cs.pos == 0){
+ cs.stack[cs.pos] = obj;
+ cs.pos ++;
+ }
+ else {
+ if (cs.stack[cs.pos-1] != obj){
+ cs.stack[cs.pos] = obj;
+ cs.pos ++;
+ if (cs.pos == CS_LEN){
+ cs.pos = 0;
+ }
+ }
+ }
+ }
+}
+
+static void dump_call_stack(void)
+{
+ int32_t i = 0;
+ struct symbol_obj * obj = NULL;
+
+ printf("\n============================================================\n");
+ printf("[Function Call Trace]\n");
+ printf("============================================================\n");
+ for(i=0;i<CS_LEN;i++){
+ if(cs.stack[i] != NULL){
+ obj = cs.stack[i];
+ if (cs.pos == (i + 1)){
+ printf("[%03d] %s (0x%08x)**\n", i, obj->sym_name, obj->addr);
+ }
+ else {
+ printf("[%03d] %s (0x%08x)\n", i, obj->sym_name, obj->addr);
+ }
+ }
+ }
+ printf("============================================================\n");
+}
+
+void simulating(void)
+{
+ struct image_info * info = get_image_info();
+ struct NIOS_CPU * cpu = NULL;
+ uint32_t code = 0;
+ uint32_t exec_result = 0;
+
+ /* register the segment fault and Ctrl-C handler */
+ register_signal_handler();
+
+ /* init cpu*/
+ reset_cpu();
+ cpu = get_nios_cpu();
+ set_init_pc(cpu, info->entry_addr); /* Set the init value of PC */
+ cpu = get_nios_cpu();
+
+ /* init device modules */
+ init_devices();
+ /* init the boot parameter setting for u-boot */
+ init_cmdline(cpu);
+ init_initrd(cpu);
+
+ /* main loop to simulating the execute of NIOSII */
+ printf("Enter simulating ..................\n");
+ while(1){
+ /* Get the instruction */
+ code = get_instruct(cpu, info->mem_base, info->base_addr);
+
+ /* Judge whether into debug mode */
+ if (get_run_mode() == DEBUG_MODE){
+ if (cpu->mode == NORMAL_MODE){
+ cpu->mode = SINGLE_STEP;
+ }
+ trace_pc(cpu);
+ debug_mode(cpu, code, exec_result);
+ }
+ else if(get_run_mode() == EXIT_MODE) {
+ printf("NIOS SIMULATOR EXIT!\n");
+ return;
+ }
+ /* Execute the code */
+ exec_result = execute(code);
+ if (exec_result == PC_INC_NORMAL){
+ modify_pc(cpu);
+ }
+ else {
+ if(get_run_mode() == DEBUG_MODE){
+ record_call_stack(cpu->pc);
+ }
+ }
+
+ /* Simulate the hardware running. */
+ hw_simulating();
+ /* judge whether IRQ or exception happen, if yes, then handle it.*/
+ handle_irq_exception(cpu);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+
diff --git a/simulator.h b/simulator.h
new file mode 100644
index 0000000..4773fb6
--- /dev/null
+++ b/simulator.h
@@ -0,0 +1,32 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __SIMULATOR_H__
+#define __SIMULATOR_H__
+
+#include <stdio.h>
+#include "public.h"
+
+struct debug_command {
+ char * short_cmd;
+ char * long_cmd;
+ char * desc;
+ int32_t code;
+};
+#endif /* __SIMULATOR_H__*/
diff --git a/timer.c b/timer.c
new file mode 100644
index 0000000..b468f9b
--- /dev/null
+++ b/timer.c
@@ -0,0 +1,215 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "public.h"
+#include "timer.h"
+#include "niosii.h"
+
+
+static struct timer_hw hw;
+static uint32_t valid_mask[TIMER_REG_CNT] = {
+ 0x3,0xF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
+};
+
+static uint32_t only_read_mask[TIMER_REG_CNT] = {
+ 0x2,0,0,0,0,0
+};
+
+static void update_period_reg(void);
+static void timer_init(struct io_device * self)
+{
+ int32_t i = 0;
+
+ self->priv_data = &hw;
+
+ for (i=0;i<TIMER_REG_CNT;i++){
+ hw.io_regs[i].addr = TIMER_BASE_ADDR + 4 * i;
+ hw.io_regs[i].value = 0;
+ hw.io_regs[i].valid_mask = valid_mask[i];
+ hw.io_regs[i].only_read_mask = only_read_mask[i];
+ }
+
+ hw.set_period = 0;
+ hw.curr_count = 0;
+
+ printf("Timer Core at 0x%08X-0x%08X\n", hw.io_regs[0].addr,
+ hw.io_regs[TIMER_REG_CNT-1].addr);
+}
+
+static int timer_is_belong(uint32_t address)
+{
+ int32_t ret_val = ADDR_IS_NOT_DEV;
+ if ((address >= TIMER_BASE_ADDR) && (address < (TIMER_BASE_ADDR + TIMER_REG_CNT * 4))){
+ ret_val = ADDR_IS_DEV;
+ }
+
+ return ret_val;
+}
+static void copy_snapshot(void);
+static uint32_t timer_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+{
+ uint32_t ret_val = 0;
+ uint32_t index = 0;
+
+ index = (addr - TIMER_BASE_ADDR) / 4;
+ if (index >= 0 && index < TIMER_REG_CNT){
+ if (index == TIM_REG_SNAPL || index == TIM_REG_SNAPH){
+ copy_snapshot();
+ }
+ ret_val = hw.io_regs[index].value & hw.io_regs[index].valid_mask;
+ ret_val = io_read_data(ret_val, data_len);
+ }
+ return ret_val;
+}
+
+static void timer_write(struct io_device * self, uint32_t addr, uint32_t data, uint32_t data_len)
+{
+ uint32_t index = 0;
+ uint32_t temp = 0;
+ uint32_t only_read_mask = 0;
+ uint32_t valid_mask = 0;
+
+ index = (addr - TIMER_BASE_ADDR) / 4;
+
+ if (index >= 0 && index < TIMER_REG_CNT){
+ temp = hw.io_regs[index].value;
+ valid_mask = hw.io_regs[index].valid_mask;
+ only_read_mask = hw.io_regs[index].only_read_mask;
+ hw.io_regs[index].value = io_write_data_mask(temp, data, data_len, valid_mask, only_read_mask);
+
+
+ if (index == TIM_REG_PERIODL){
+ hw.set_period = hw.set_period &0xFFFF0000;
+ hw.set_period = hw.set_period | (data & 0xFFFF);
+ hw.curr_count = hw.set_period;
+ update_period_reg();
+ }
+ else if (index == TIM_REG_PERIODH){
+ hw.set_period = hw.set_period & 0xFFFF;
+ hw.set_period = hw.set_period | ((data & 0xFFFF) <<16);
+ hw.curr_count = hw.set_period;
+ update_period_reg();
+ }
+ else if (index == TIM_REG_STATUS){
+ if ((hw.io_regs[index].value & STATUS_TO_MASK) == 0){
+ clean_ipending(self->irq_enable_mask);
+ }
+ }
+ }
+}
+
+static int32_t timer_has_irq(struct io_device * self)
+{
+ int32_t ret_val = DEV_NO_IRQ;
+ uint32_t ctrl_reg_val = 0;
+ uint32_t status_reg_val = 0;
+
+ ctrl_reg_val = hw.io_regs[TIM_REG_CTRL].value & hw.io_regs[TIM_REG_CTRL].valid_mask;
+ status_reg_val = hw.io_regs[TIM_REG_STATUS].value & hw.io_regs[TIM_REG_STATUS].valid_mask;
+
+ if ((ctrl_reg_val & CTRL_ITO_MASK) == CTRL_ITO_MASK){
+ if ((status_reg_val & STATUS_TO_MASK) == STATUS_TO_MASK){
+ ret_val = DEV_HAS_IRQ;
+ }
+ }
+ return ret_val;
+}
+
+static void copy_snapshot(void)
+{
+ hw.io_regs[TIM_REG_SNAPL].value = hw.io_regs[TIM_REG_PERIODL].value;
+ hw.io_regs[TIM_REG_SNAPH].value = hw.io_regs[TIM_REG_PERIODH].value;
+}
+
+static void update_period_reg(void)
+{
+ hw.io_regs[TIM_REG_PERIODL].value = hw.curr_count & 0xFFFF;
+ hw.io_regs[TIM_REG_PERIODH].value = (hw.curr_count & 0xFFFF0000) >> 16;
+ //copy_snapshot();
+}
+
+static void decrease_counter(void)
+{
+ if (hw.curr_count > 2){
+ hw.curr_count -= 2;
+ }
+ else {
+ hw.curr_count = 0;
+ }
+ update_period_reg();
+}
+
+static int32_t timer_can_decrease(void)
+{
+ int32_t ret = SIM_TRUE;
+ uint32_t reg_ctrl_val = hw.io_regs[TIM_REG_CTRL].value;
+
+ if ((reg_ctrl_val & CTRL_START_MASK) == 0){
+ ret = SIM_FALSE;
+ goto out;
+ }
+
+ if ((reg_ctrl_val & CTRL_STOP_MASK) != 0){
+ ret = SIM_FALSE;
+ goto out;
+ }
+
+ if (hw.set_period == hw.curr_count){
+ if ((reg_ctrl_val & CTRL_CONT_MASK) == 0){
+ ret = SIM_FALSE;
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+static void update_status(void)
+{
+ if(hw.curr_count <= 0){
+ hw.io_regs[TIM_REG_CTRL].value |= CTRL_ITO_MASK;
+ hw.curr_count = hw.set_period;
+ update_period_reg();
+ hw.io_regs[TIM_REG_STATUS].value |= STATUS_TO_MASK;
+ }
+}
+
+static void timer_simulate(struct io_device * self)
+{
+ if (timer_can_decrease() == SIM_TRUE) {
+ decrease_counter();
+ update_status();
+ }
+}
+
+struct io_device timer_core = {
+ .name = "timer_core",
+ .init = timer_init,
+ .is_belong = timer_is_belong,
+ .read_data = timer_read,
+ .write_data = timer_write,
+ .has_irq = timer_has_irq,
+ .simulate = timer_simulate,
+ .irq_enable_mask = TIM_IRQ_MASK,
+};
+
+
diff --git a/timer.h b/timer.h
new file mode 100644
index 0000000..6f4ec9f
--- /dev/null
+++ b/timer.h
@@ -0,0 +1,55 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+
+#define TIMER_REG_CNT (6)
+#define TIMER_BASE_ADDR (0x80681020)
+
+#define CTRL_ITO_MASK (0x01)
+#define CTRL_CONT_MASK (0x02)
+#define CTRL_START_MASK (0x04)
+#define CTRL_STOP_MASK (0x08)
+
+#define STATUS_TO_MASK (0x01)
+#define TIM_IRQ_MASK (1 << 3)
+struct timer_hw{
+ struct io_reg io_regs[TIMER_REG_CNT];
+ uint32_t set_period;
+ uint32_t curr_count;
+
+};
+
+/* the index */
+#define TIM_REG_STATUS (0)
+#define TIM_REG_CTRL (1)
+#define TIM_REG_PERIODL (2)
+#define TIM_REG_PERIODH (3)
+#define TIM_REG_SNAPL (4)
+#define TIM_REG_SNAPH (5)
+
+extern struct io_device timer_core;
+#endif
+
diff --git a/uart_core.c b/uart_core.c
new file mode 100644
index 0000000..ae58154
--- /dev/null
+++ b/uart_core.c
@@ -0,0 +1,157 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+#include "uart_core.h"
+
+#define REG_RXDATA (0)
+#define REG_TXDATA (1)
+#define REG_STATUS (2)
+#define REG_CONTROL (3)
+#define REG_DIVISOR (4)
+#define REG_ENDOFPACKET (5)
+
+static struct uart_core_hw hw;
+static uint32_t valid_mask[UART_CORE_REG_CNT] = {
+ 0x1FF,0x1FF,0x1FFF,0x1FFF,0xFFFF,0x1FF
+};
+
+static uint32_t only_read_mask[UART_CORE_REG_CNT] = {
+ 0x1FF,0x00,0x00,0x00,0x00,0x00
+};
+
+static void uart_init(struct io_device * self)
+{
+ int32_t i = 0;
+
+ self->priv_data = &hw;
+ for (i=0;i<UART_CORE_REG_CNT; i++){
+ hw.io_regs[i].addr = UART_CORE_BASE_ADDR + i * 4;
+ hw.io_regs[i].value = 0;
+ hw.io_regs[i].valid_mask = valid_mask[i];
+ hw.io_regs[i].only_read_mask = only_read_mask[i];
+ }
+
+ hw.rx_status = 0;
+ hw.tx_status = 0;
+ printf("%s at 0x%08X-0x%08X\n",self->name, UART_CORE_BASE_ADDR, UART_CORE_BASE_ADDR + i * 4 - 4);
+}
+
+static int32_t uart_is_belong(uint32_t address)
+{
+ int32_t ret_val = ADDR_IS_NOT_DEV;
+
+ if ((address >= UART_CORE_BASE_ADDR) && (address < (UART_CORE_BASE_ADDR + UART_CORE_REG_CNT * 4))){
+ ret_val = ADDR_IS_DEV;
+ }
+ return ret_val;
+}
+
+static uint32_t uart_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+{
+ uint32_t ret_val = 0;
+ uint32_t index = 0;
+
+ index = (addr - UART_CORE_BASE_ADDR) / 4;
+ if (index >= 0 && index < UART_CORE_REG_CNT){
+ ret_val = hw.io_regs[index].value & hw.io_regs[index].valid_mask;
+ ret_val = io_read_data(ret_val, data_len);
+
+ if (index == REG_RXDATA){
+ hw.rx_status = UART_HAS_NO_DATA_TO_RX;
+ hw.io_regs[REG_STATUS].value &= (~ALTERA_UART_STATUS_RRDY_MSK);
+ }
+ }
+ return ret_val;
+}
+
+static void uart_write(struct io_device * self, uint32_t addr, uint32_t data, uint32_t data_len)
+{
+ uint32_t index = 0;
+ uint32_t temp = 0;
+ uint32_t only_read_mask = 0;
+ uint32_t valid_mask = 0;
+
+ index = (addr - UART_CORE_BASE_ADDR) / 4;
+
+ if (index >= 0 && index < UART_CORE_REG_CNT){
+ temp = hw.io_regs[index].value;
+ valid_mask = hw.io_regs[index].valid_mask;
+ only_read_mask = hw.io_regs[index].only_read_mask;
+ hw.io_regs[index].value = io_write_data_mask(temp, data, data_len, valid_mask, only_read_mask);
+ if(index == REG_TXDATA){
+ hw.tx_status = UART_HAS_DATA_TO_TX;
+ hw.io_regs[REG_STATUS].value &= (~ALTERA_UART_STATUS_TRDY_MSK);
+ }
+ }
+}
+
+static int32_t uart_has_irq(struct io_device * self)
+{
+ int32_t ret_val = DEV_NO_IRQ;
+ uint32_t reg_ctrl_val = hw.io_regs[REG_CONTROL].value;
+ uint32_t reg_status_val = hw.io_regs[REG_STATUS].value;
+
+ /* Check TX ready Interrupt */
+ if (check_reg_bit(reg_ctrl_val, ALTERA_UART_CONTROL_TRDY_MSK) == SIM_TRUE){
+ if (check_reg_bit(reg_status_val, ALTERA_UART_STATUS_TRDY_MSK) == SIM_TRUE){
+ ret_val = DEV_HAS_IRQ;
+ }
+ }
+
+ /* Check RX ready Interrupt */
+ if (check_reg_bit(reg_ctrl_val, ALTERA_UART_CONTROL_RRDY_MSK) == SIM_TRUE){
+ if (check_reg_bit(reg_status_val, ALTERA_UART_STATUS_RRDY_MSK) == SIM_TRUE){
+ ret_val = DEV_HAS_IRQ;
+ }
+ }
+
+ return ret_val;
+}
+
+static void uart_simulate(struct io_device * self)
+{
+ /* handler TX */
+ if (hw.tx_status == UART_HAS_DATA_TO_TX){
+ hw.io_regs[REG_STATUS].value &= (~ALTERA_UART_STATUS_TRDY_MSK);
+ hw.tx_status = UART_HAS_NO_DATA_TO_TX;
+ /* Set status TRDY bit */
+ hw.io_regs[REG_STATUS].value |= ALTERA_UART_STATUS_TRDY_MSK;
+ }
+ /* handler RX */
+ if(hw.rx_status == UART_HAS_NO_DATA_TO_RX){
+ /* ToDo: Get the input data */
+ hw.rx_status = UART_HAS_DATA_TO_RX;
+ /* Set status RRDY bit */
+ hw.io_regs[REG_STATUS].value |= ALTERA_UART_STATUS_RRDY_MSK;
+ }
+}
+
+struct io_device uart_core = {
+ .name = "UART Core",
+ .init = uart_init,
+ .is_belong = uart_is_belong,
+ .read_data = uart_read,
+ .write_data = uart_write,
+ .has_irq = uart_has_irq,
+ .simulate = uart_simulate,
+ .irq_enable_mask = UART_IRQ_MASK,
+};
diff --git a/uart_core.h b/uart_core.h
new file mode 100644
index 0000000..4cab207
--- /dev/null
+++ b/uart_core.h
@@ -0,0 +1,79 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __UART_CORE_H__
+#define __UART_CORE_H__
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "io_device.h"
+
+#define UART_IRQ_MASK (1 << 2)
+#define UART_CORE_BASE_ADDR (0x80681000)
+#define UART_CORE_REG_CNT (8)
+
+/* Mask for registers */
+/* copy from /drivers/serial/altuart.c */
+#define ALTERA_UART_STATUS_PE_MSK (0x1)
+#define ALTERA_UART_STATUS_FE_MSK (0x2)
+#define ALTERA_UART_STATUS_BRK_MSK (0x4)
+#define ALTERA_UART_STATUS_ROE_MSK (0x8)
+#define ALTERA_UART_STATUS_TOE_MSK (0x10)
+#define ALTERA_UART_STATUS_TMT_MSK (0x20)
+#define ALTERA_UART_STATUS_TRDY_MSK (0x40)
+#define ALTERA_UART_STATUS_RRDY_MSK (0x80)
+#define ALTERA_UART_STATUS_E_MSK (0x100)
+#define ALTERA_UART_STATUS_DCTS_MSK (0x400)
+#define ALTERA_UART_STATUS_CTS_MSK (0x800)
+#define ALTERA_UART_STATUS_EOP_MSK (0x1000)
+
+#define ALTERA_UART_CONTROL_PE_MSK (0x1)
+#define ALTERA_UART_CONTROL_FE_MSK (0x2)
+#define ALTERA_UART_CONTROL_BRK_MSK (0x4)
+#define ALTERA_UART_CONTROL_ROE_MSK (0x8)
+#define ALTERA_UART_CONTROL_TOE_MSK (0x10)
+#define ALTERA_UART_CONTROL_TMT_MSK (0x20)
+#define ALTERA_UART_CONTROL_TRDY_MSK (0x40)
+#define ALTERA_UART_CONTROL_RRDY_MSK (0x80)
+#define ALTERA_UART_CONTROL_E_MSK (0x100)
+#define ALTERA_UART_CONTROL_TRBK_MSK (0x200)
+#define ALTERA_UART_CONTROL_DCTS_MSK (0x400)
+#define ALTERA_UART_CONTROL_RTS_MSK (0x800)
+#define ALTERA_UART_CONTROL_EOP_MSK (0x1000)
+
+#define ALTERA_UART_EOP_MSK (0xFF)
+#define ALTERA_UART_EOP_OFST (0)
+
+#define UART_HAS_NO_DATA_TO_RX (0x00)
+#define UART_HAS_DATA_TO_RX (0x01)
+#define UART_HAS_DATA_TO_TX (0x01)
+#define UART_HAS_NO_DATA_TO_TX (0x00)
+
+struct uart_core_hw {
+ struct io_reg io_regs[UART_CORE_REG_CNT];
+ uint32_t rx_status;
+ uint32_t tx_status;
+};
+
+extern struct io_device uart_core;
+#endif
+
+
+