diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | device.c | 3 | ||||
-rw-r--r-- | jtag_uart.c | 167 | ||||
-rw-r--r-- | jtag_uart.h | 51 | ||||
-rw-r--r-- | srec.c | 20 | ||||
-rw-r--r-- | timer.c | 307 | ||||
-rw-r--r-- | timer.h | 92 | ||||
-rw-r--r-- | uart.c | 120 | ||||
-rw-r--r-- | uart.h | 11 |
9 files changed, 447 insertions, 328 deletions
@@ -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 @@ -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(®s[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_ */ @@ -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; } @@ -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(®s[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, +}; @@ -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_ */ @@ -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(®s[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(®s[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, }; @@ -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; |