summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--device.c3
-rw-r--r--jtag_uart.c167
-rw-r--r--jtag_uart.h51
-rw-r--r--srec.c20
-rw-r--r--timer.c307
-rw-r--r--timer.h92
-rw-r--r--uart.c120
-rw-r--r--uart.h11
9 files changed, 447 insertions, 328 deletions
diff --git a/Makefile b/Makefile
index 049d114..610bff9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,14 +2,14 @@ P = nios2sim-ng
VERSION = 0.1
OBJS = main.o image.o elf.o srec.o nios2.o memory.o instruction.o simulator.o \
- device.o uart.o jtag_uart.o util.o
+ device.o timer.o uart.o jtag_uart.o util.o
#OBJS += load_image.o nor_flash.o simulator.o simulator.o niosii.o i_type_handler.o j_type_handler.o \
# r_type_handler.o custom_instr.o timer.o
DEFS = -DVERSION="\"$(VERSION)\"" -DDEBUG
CFLAGS += -g -W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes \
- -Wno-packed-bitfield-compat \
+ -Wno-packed-bitfield-compat -Wshadow \
$(DEFS)
LDFLAGS += -lelf
diff --git a/device.c b/device.c
index bec5a1a..33be8c7 100644
--- a/device.c
+++ b/device.c
@@ -13,10 +13,12 @@
#include "nios2sim-ng.h"
#include "device.h"
+#include "timer.h"
#include "uart.h"
#include "jtag_uart.h"
static struct device *devices[] = {
+ &timer_core,
&uart_core,
&jtag_uart_core,
};
@@ -24,6 +26,7 @@ static struct device *devices[] = {
bool device_generic_is_dev_addr(struct device *dev, uint32_t addr)
{
+ /* XXX: Also check alignment? */
if (addr >= dev->base && addr < dev->base + dev->size)
return true;
diff --git a/jtag_uart.c b/jtag_uart.c
index ba0bf5f..5f3e9d8 100644
--- a/jtag_uart.c
+++ b/jtag_uart.c
@@ -9,64 +9,137 @@
* for more details.
*/
+#include <stdio.h>
+#include <stdlib.h>
+
#include "nios2sim-ng.h"
#include "device.h"
#include "jtag_uart.h"
+#define JTAG_UART_CLK_COUNT_INIT 500
+
+#define jtag_uart_printf(fmt, args...) fprintf(stdout, fmt, ##args)
+
+struct jtag_uart_fifo {
+ uint8_t data;
+ bool has_data;
+};
+
+struct jtag_uart {
+ struct io_register regs[JTAG_UART_REG_COUNT];
+ struct jtag_uart_fifo tx_fifo;
+ unsigned int clk_count;
+};
+
+static const uint32_t jtag_uart_valid_mask[JTAG_UART_REG_COUNT] = {
+ 0xFFFF80FF, /* data */
+ 0xFFFF0703, /* control */
+};
+
+static const uint32_t jtag_uart_readonly_mask[JTAG_UART_REG_COUNT] = {
+ 0xFFFF8000, /* data */
+ 0xFFFF0300, /* control */
+};
+
static int jtag_uart_init(struct device *dev)
{
+ struct jtag_uart *ju;
+ struct io_register *regs;
+ unsigned int i;
+
+ ju = malloc(sizeof(struct jtag_uart));
+ if (unlikely(ju == NULL))
+ return -1;
+
+ /* Initialite registers */
+ regs = ju->regs;
+ for (i = 0; i < JTAG_UART_REG_COUNT; i++) {
+ io_register_init(&regs[i],
+ JTAG_UART_BASE + REG_TO_OFF(i),
+ jtag_uart_valid_mask[i],
+ jtag_uart_readonly_mask[i],
+ 0);
+ }
+
+ /* Explicitely initialize control register */
+ regs[JTAG_UART_CTRL_REG].value =
+ (JTAG_UART_FIFO_SIZE << JTAG_UART_CTRL_WSPACE_OFF)
+ & JTAG_UART_CTRL_WSPACE_MASK;
+
+ ju->clk_count = JTAG_UART_CLK_COUNT_INIT;
+ dev->priv = ju;
+
return 0;
}
static bool jtag_uart_is_dev_addr(struct device *dev, uint32_t addr)
{
+ struct jtag_uart *ju = dev->priv;
+ unsigned int i;
+
+ for (i = 0; i < JTAG_UART_REG_COUNT; i++)
+ if (ju->regs[i].addr == addr)
+ return true;
+
+ return false;
+}
+
+static bool jtag_uart_has_irq(struct device *dev)
+{
+ struct jtag_uart *ju = dev->priv;
+ uint32_t ctrl_val;
+
+ ju->clk_count--;
+ if (ju->clk_count > 0)
+ return false;
+
+ ctrl_val = ju->regs[JTAG_UART_CTRL_REG].value;
+
+ /* handle write interrupt */
+ if (ctrl_val & JTAG_UART_CTRL_WE_MASK)
+ if ((ctrl_val & JTAG_UART_CTRL_WSPACE_MASK) != 0)
+ return true;
+
+ /* TODO: Read interrupt */
+
return false;
}
static void jtag_uart_simulate(struct device *dev)
{
+ struct jtag_uart *ju = dev->priv;
+ struct io_register *regs = ju->regs;
+
+ if (ju->tx_fifo.has_data) {
+ jtag_uart_printf("%c", ju->tx_fifo.data);
+ ju->tx_fifo.has_data = false;
+ /* set available fifo size */
+ regs[JTAG_UART_CTRL_REG].value |=
+ (JTAG_UART_FIFO_SIZE << JTAG_UART_CTRL_WSPACE_OFF)
+ & JTAG_UART_CTRL_WSPACE_MASK;
+
+ if (regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WE_MASK)
+ regs[JTAG_UART_CTRL_REG].value |= JTAG_UART_CTRL_WI_MASK;
+ } else {
+ if ((regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WSPACE_MASK) != 0
+ && (regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WE_MASK))
+ regs[JTAG_UART_CTRL_REG].value |= JTAG_UART_CTRL_WI_MASK;
+ }
}
struct device jtag_uart_core = {
.name = "JTAG UART Core",
.base = JTAG_UART_BASE,
.size = JTAG_UART_SIZE,
+ .irq_mask = IRQ_TO_MASK(IRQ_JTAG_UART),
.init = jtag_uart_init,
.is_dev_addr = jtag_uart_is_dev_addr,
+ .has_irq = jtag_uart_has_irq,
.simulate = jtag_uart_simulate,
};
-
#if 0
-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){
@@ -110,42 +183,6 @@ static void uart_write(struct io_device * self, uint32_t addr, uint32_t data, ui
}
}
-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 */
diff --git a/jtag_uart.h b/jtag_uart.h
index 4328be7..24317eb 100644
--- a/jtag_uart.h
+++ b/jtag_uart.h
@@ -16,44 +16,27 @@
#define JTAG_UART_BASE 0x806810F0
#define JTAG_UART_SIZE 8
+#define JTAG_UART_IRQ IRQ_JTAG_UART
+#define JTAG_UART_REG_COUNT (JTAG_UART_SIZE / sizeof(uint32_t))
+#define JTAG_UART_FIFO_SIZE 1
#define JTAG_UART_DATA_REG 0
#define JTAG_UART_CTRL_REG 1
-extern struct device jtag_uart_core;
+#define JTAG_UART_DATA_DATA_MASK 0x000000FF
+#define JTAG_UART_DATA_RVALID_MASK 0x00008000
+#define JTAG_UART_DATA_RAVAIL_MASK 0xFFFF0000
+#define JTAG_UART_DATA_RAVAIL_OFF 16
+
+#define JTAG_UART_CTRL_RE_MASK 0x00000001
+#define JTAG_UART_CTRL_WE_MASK 0x00000002
+#define JTAG_UART_CTRL_RI_MASK 0x00000100
+#define JTAG_UART_CTRL_RI_OFF 8
+#define JTAG_UART_CTRL_WI_MASK 0x00000200
+#define JTAG_UART_CTRL_AC_MASK 0x00000400
+#define JTAG_UART_CTRL_WSPACE_MASK 0xFFFF0000
+#define JTAG_UART_CTRL_WSPACE_OFF 16
-#if 0
-#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
+extern struct device jtag_uart_core;
#endif /* _JTAG_UART_H_ */
diff --git a/srec.c b/srec.c
index 7c3aaf4..9179317 100644
--- a/srec.c
+++ b/srec.c
@@ -55,10 +55,11 @@ err_out:
}
static int srec_load_S3(char *buf, size_t data_count,
- off_t offset, uint8_t *mem_base, size_t mem_size)
+ uint32_t load_addr, struct memory *mem)
{
size_t i;
- uint32_t *base = (uint32_t *) mem_base;
+ size_t mem_size = mem->size;
+ uint32_t *base = mem->base;
for (i = 0; i < data_count; i += 4) {
uint32_t tmp;
@@ -70,19 +71,19 @@ static int srec_load_S3(char *buf, size_t data_count,
/* SREC is Big Endian, NiosII is Little Endian */
tmp = bswap_32(tmp);
- if (offset + i >= mem_size) {
+ if (load_addr + i >= mem_size) {
err("Image file too large for allocated memory of %zu bytes\n", mem_size);
return -1;
}
/* Store in memory */
- base[offset / 4 + i] = tmp;
+ base[(load_addr + i) / 4] = tmp;
}
return 0;
}
-static int srec_handle_line(char *buf, size_t len, uint8_t *mem_base, size_t mem_size)
+static int srec_handle_line(char *buf, size_t len, struct memory *mem)
{
unsigned int data_count = 0;
unsigned int start_addr;
@@ -114,7 +115,10 @@ static int srec_handle_line(char *buf, size_t len, uint8_t *mem_base, size_t mem
return -1;
}
- if (srec_load_S3(buf + 12, data_count - 4, start_addr, mem_base, mem_size) != 0)
+ if (mem->image_base == IMAGE_BASE_UNINITIALIZED)
+ mem->image_base = start_addr;
+
+ if (srec_load_S3(buf + 12, data_count - 4, start_addr, mem) != 0)
return -1;
break;
case '4':
@@ -143,7 +147,7 @@ static int srec_handle_line(char *buf, size_t len, uint8_t *mem_base, size_t mem
return 0;
}
-int srec_load(FILE *fp, const char *name __unused, uint8_t *mem_base, size_t mem_size)
+int srec_load(FILE *fp, const char *name __unused, struct memory *mem)
{
ssize_t len;
int ret = 0;
@@ -158,7 +162,7 @@ int srec_load(FILE *fp, const char *name __unused, uint8_t *mem_base, size_t mem
ret = 0;
break;
} else {
- ret = srec_handle_line(data_buf, len, mem_base, mem_size);
+ ret = srec_handle_line(data_buf, len, mem);
if (ret < 0)
break;
}
diff --git a/timer.c b/timer.c
index b468f9b..198f672 100644
--- a/timer.c
+++ b/timer.c
@@ -1,215 +1,200 @@
/*
- 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.
-*/
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2010 chysun2000@gmail.com
+ *
+ * This file is part of nios2sim-ng.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include "public.h"
+#include "nios2sim-ng.h"
+#include "device.h"
#include "timer.h"
-#include "niosii.h"
+struct timer {
+ struct io_register regs[TIMER_REG_COUNT];
+ uint32_t set_period;
+ uint32_t curr_count;
+};
-static struct timer_hw hw;
-static uint32_t valid_mask[TIMER_REG_CNT] = {
- 0x3,0xF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
+static const uint32_t timer_valid_mask[TIMER_REG_COUNT] = {
+ 0x3, 0xF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
};
-static uint32_t only_read_mask[TIMER_REG_CNT] = {
- 0x2,0,0,0,0,0
+static const uint32_t timer_read_only_mask[TIMER_REG_COUNT] = {
+ 0x2, 0, 0, 0, 0, 0
};
-static void update_period_reg(void);
-static void timer_init(struct io_device * self)
+static int timer_init(struct device *dev)
{
- 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];
+ unsigned int i;
+ struct timer *t = malloc(sizeof(struct timer));
+ struct io_register *regs;
+
+ if (unlikely(t == NULL))
+ return -1;
+
+ /* Initialite registers */
+ regs = t->regs;
+ for (i = 0; i < TIMER_REG_COUNT; i++) {
+ io_register_init(&regs[i],
+ TIMER_BASE + REG_TO_OFF(i),
+ timer_valid_mask[i],
+ timer_read_only_mask[i],
+ 0);
}
-
- 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);
+ t->set_period = 0;
+ t->curr_count = 0;
+ dev->priv = t;
+
+ return 0;
}
-static int timer_is_belong(uint32_t address)
+static void update_period_reg(struct timer *t)
{
- 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;
- }
+ t->regs[TIMER_PERIODL_REG].value = t->curr_count & 0xFFFF;
+ t->regs[TIMER_PERIODH_REG].value = (t->curr_count & 0xFFFF0000) >> 16;
+ //copy_snapshot();
+}
- return ret_val;
+#if 0
+static void copy_snapshot(struct timer *t)
+{
+ t->regs[TIMER_SNAPL_REG].value = t->regs[TIMER_PERIODL_REG].value;
+ t->regs[TIMER_SNAPH_REG].value = t->regs[TIMER_PERIODH_REG].value;
}
-static void copy_snapshot(void);
-static uint32_t timer_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+
+static uint32_t timer_read(struct device *dev, uint32_t addr, uint32_t data_len)
{
+ struct timer *t = dev->priv;
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);
- }
+
+ index = (addr - dev->base) / 4;
+ if (index >= TIMER_REG_COUNT)
+ return 0;
+
+ if (index == TIMER_SNAPL_REG || index == TIMER_SNAPH_REG)
+ copy_snapshot(t);
+ ret_val = io_register_read(&t->regs[index]);
+ 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)
+static void timer_write(struct device *dev, uint32_t addr, uint32_t data, size_t count)
{
+ struct timer *t = dev->priv;
+ struct io_register *regs;
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;
- }
+ index = (addr - dev->base) / 4;
+
+ if (index >= TIMER_REG_COUNT)
+ return;
+
+ temp = regs[index].value;
+ valid_mask = regs[index].valid_mask;
+ only_read_mask = regs[index].readonly_mask;
+ regs[index].value = io_write_data_mask(temp, data, data_len, valid_mask, only_read_mask);
+
+ if (index == TIMER_PERIODL_REG){
+ t->set_period &= 0xFFFF0000;
+ t->set_period |= data & 0xFFFF;
+ t->curr_count = t->set_period;
+ update_period_reg(t);
+ } else if (index == TIMER_PERIODH_REG) {
+ 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(t);
+ } else if (index == TIMER_STATUS_REG) {
+ if ((regs[index].value & STATUS_TO_MASK) == 0)
+ clean_ipending(dev->irq_mask);
}
- return ret_val;
}
+#endif
-static void copy_snapshot(void)
+static bool timer_has_irq(struct device *dev)
{
- 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;
-}
+ struct timer *t = dev->priv;
+ uint32_t ctrl_val = io_register_read(&t->regs[TIMER_CTRL_REG]);
+ uint32_t status_val = io_register_read(&t->regs[TIMER_STATUS_REG]);
-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();
+ if ((ctrl_val & TIMER_CTRL_ITO_MASK) == TIMER_CTRL_ITO_MASK)
+ if ((status_val & TIMER_STATUS_TO_MASK) == TIMER_STATUS_TO_MASK)
+ return true;
+
+ return false;
}
-static void decrease_counter(void)
+static void decrease_counter(struct timer *t)
{
- if (hw.curr_count > 2){
- hw.curr_count -= 2;
- }
- else {
- hw.curr_count = 0;
- }
- update_period_reg();
+ if (t->curr_count > 2)
+ t->curr_count -= 2;
+ else
+ t->curr_count = 0;
+ update_period_reg(t);
}
-static int32_t timer_can_decrease(void)
+static bool timer_can_decrease(struct timer *t)
{
- 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;
+ uint32_t ctrl_val = t->regs[TIMER_CTRL_REG].value;
+
+ /* Timer started? */
+ if ((ctrl_val & TIMER_CTRL_START_MASK) == 0)
+ return false;
+
+ /* Timer stopped? */
+ if ((ctrl_val & TIMER_CTRL_STOP_MASK) != 0)
+ return false;
+
+ /* If timer is not in continuous mode and counter has reached period */
+ if ((ctrl_val & TIMER_CTRL_CONT_MASK) == 0
+ && t->set_period == t->curr_count)
+ return false;
+
+ return true;
}
-static void update_status(void)
+static void update_status(struct timer *t)
{
- 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;
+ if (t->curr_count <= 0) {
+ t->regs[TIMER_CTRL_REG].value |= TIMER_CTRL_ITO_MASK;
+ t->curr_count = t->set_period;
+ update_period_reg(t);
+ t->regs[TIMER_STATUS_REG].value |= TIMER_STATUS_TO_MASK;
}
}
-static void timer_simulate(struct io_device * self)
+static void timer_simulate(struct device *dev)
{
- if (timer_can_decrease() == SIM_TRUE) {
- decrease_counter();
- update_status();
+ struct timer *t = dev->priv;
+
+ if (timer_can_decrease(t)) {
+ decrease_counter(t);
+ update_status(t);
}
}
-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,
-};
-
+struct device timer_core = {
+ .name = "Timer Core",
+ .base = TIMER_BASE,
+ .size = TIMER_SIZE,
+ .irq_mask = IRQ_TO_MASK(TIMER_IRQ),
+ .init = timer_init,
+ .is_dev_addr = NULL, /* use generic */
+ .has_irq = timer_has_irq,
+ .simulate = timer_simulate,
+};
diff --git a/timer.h b/timer.h
index 6f4ec9f..2b99de6 100644
--- a/timer.h
+++ b/timer.h
@@ -1,55 +1,39 @@
/*
- 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
-
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2010 chysun2000@gmail.com
+ *
+ * This file is part of nios2sim-ng.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#include "device.h"
+
+#define TIMER_BASE 0x84842000
+#define TIMER_SIZE 48
+#define TIMER_IRQ IRQ_TIMER
+#define TIMER_REG_COUNT (TIMER_SIZE / sizeof(uint32_t))
+
+#define TIMER_STATUS_REG 0
+#define TIMER_CTRL_REG 1
+#define TIMER_PERIODL_REG 2
+#define TIMER_PERIODH_REG 3
+#define TIMER_SNAPL_REG 4
+#define TIMER_SNAPH_REG 5
+
+#define TIMER_STATUS_TO_MASK 0x01
+#define TIMER_STATUS_RUN_MASK 0x02
+
+#define TIMER_CTRL_ITO_MASK 0x01
+#define TIMER_CTRL_CONT_MASK 0x02
+#define TIMER_CTRL_START_MASK 0x04
+#define TIMER_CTRL_STOP_MASK 0x08
+
+extern struct device timer_core;
+
+#endif /* _TIMER_H_ */
diff --git a/uart.c b/uart.c
index f49c1cb..e53978b 100644
--- a/uart.c
+++ b/uart.c
@@ -9,18 +9,119 @@
* for more details.
*/
+#include <stdio.h>
+#include <stdlib.h>
+
#include "nios2sim-ng.h"
#include "device.h"
#include "uart.h"
+#define uart_printf(fmt, args...) fprintf(stdout, fmt, ##args)
+
+struct uart {
+ struct io_register regs[UART_REG_COUNT];
+ bool has_rx_data;
+ bool has_tx_data;
+};
+
+static const uint32_t uart_valid_mask[UART_REG_COUNT] = {
+ 0x000001FF, /* rxdata */
+ 0x000001FF, /* txdata */
+ 0x00001FFF, /* status */
+ 0x00001FFF, /* control */
+ 0x0000FFFF, /* divisor */
+ 0x000001FF, /* endofpacket */
+};
+
+static const uint32_t uart_readonly_mask[UART_REG_COUNT] = {
+ 0x000001FF, /* rxdata */
+ 0x00000000, /* txdata */
+ 0x00000000, /* status */
+ 0x00000000, /* control */
+ 0x00000000, /* divisor */
+ 0x00000000, /* endofpacket */
+};
+
static int uart_init(struct device *dev)
{
+ struct uart *u;
+ struct io_register *regs;
+ unsigned int i;
+
+ u = malloc(sizeof(struct uart));
+ if (unlikely(u == NULL))
+ return -1;
+
+ regs = u->regs;
+ for (i = 0; i < UART_REG_COUNT; i++) {
+ io_register_init(&regs[i],
+ UART_BASE + REG_TO_OFF(i),
+ uart_valid_mask[i],
+ uart_readonly_mask[i],
+ 0);
+ }
+
+ u->has_rx_data = false;
+ u->has_tx_data = false;
+
+ dev->priv = u;
+
return 0;
}
-static bool uart_is_dev_addr(struct device *dev, uint32_t addr)
+static size_t uart_read(struct device *dev, uint32_t addr, uint8_t *data, size_t count)
{
- if (addr >= dev->base && addr < dev->base + dev->size)
+ struct uart *u = dev->priv;
+ struct io_register *regs = u->regs;
+ unsigned int reg;
+ uint32_t val;
+ size_t ret;
+
+ trace("count=%zu\n", count);
+
+ if (addr < dev->base || addr >= dev->base + dev->size)
+ return 0;
+
+ reg = OFF_TO_REG(addr - dev->base);
+ val = io_register_read(&regs[reg]);
+
+ if (reg == UART_RXDATA_REG) {
+ u->has_rx_data = false;
+ regs[UART_STATUS_REG].value &= ~UART_CONTROL_RRDY_MASK;
+ }
+
+ return count;
+}
+
+static size_t uart_write(struct device *dev, uint32_t addr, uint8_t *data, size_t count)
+{
+ struct uart *u = dev->priv;
+ struct io_register *regs = u->regs;
+ unsigned int reg;
+ uint32_t val;
+ size_t ret;
+
+ trace("count=%zu\n", count);
+
+ if (addr < dev->base || addr >= dev->base + dev->size)
+ return 0;
+
+
+ return count;
+}
+
+static bool uart_has_irq(struct device *dev)
+{
+ struct uart *u = dev->priv;
+ uint32_t ctrl = u->regs[UART_CONTROL_REG].value;
+ uint32_t status = u->regs[UART_STATUS_REG].value;
+
+ /* Check TX ready IRQ */
+ if ((ctrl & UART_CONTROL_TRDY_MASK) && (status & UART_STATUS_TRDY_MASK))
+ return true;
+
+ /* Check RX ready IRQ */
+ if ((ctrl & UART_CONTROL_RRDY_MASK) && (status & UART_STATUS_RRDY_MASK))
return true;
return false;
@@ -28,14 +129,27 @@ static bool uart_is_dev_addr(struct device *dev, uint32_t addr)
static void uart_simulate(struct device *dev)
{
+ struct uart *u = dev->priv;
+ struct io_register *regs = u->regs;
+
+ if (u->has_tx_data) {
+ regs[UART_STATUS_REG].value &= ~UART_STATUS_TRDY_MASK;
+ }
+
+ if (u->has_rx_data) {
+ }
}
struct device uart_core = {
.name = "UART Core",
.base = UART_BASE,
.size = UART_SIZE,
+ .irq_mask = IRQ_TO_MASK(IRQ_UART),
.init = uart_init,
- .is_dev_addr = uart_is_dev_addr,
+ .is_dev_addr = NULL, /* use generic */
+ .read = uart_read,
+ .write = uart_write,
+ .has_irq = uart_has_irq,
.simulate = uart_simulate,
};
diff --git a/uart.h b/uart.h
index 4845150..b2c686d 100644
--- a/uart.h
+++ b/uart.h
@@ -11,13 +11,22 @@
#ifndef _UART_H_
#define _UART_H_
-#define UART_BASE 0x80681000
+#define UART_BASE 0x84842020
#define UART_SIZE 32
+#define UART_REG_COUNT (UART_SIZE / sizeof(uint32_t))
#define UART_RXDATA_REG 0
#define UART_TXDATA_REG 1
#define UART_STATUS_REG 2
#define UART_CONTROL_REG 3
+#define UART_DIVISOR_REG 4
+#define UART_EOP_REG 5
+
+#define UART_STATUS_TRDY_MASK 0x40
+#define UART_STATUS_RRDY_MASK 0x80
+
+#define UART_CONTROL_TRDY_MASK 0x40
+#define UART_CONTROL_RRDY_MASK 0x80
extern struct device uart_core;