1/1

|
[or1ksim #29] Cleanup gpio peripheral
by Unknown on Feb 9, 2005 |
Not available! | ||
|
Hi,
This Cleans up the last of the peripherals, gpio. I couldn't find anything to
test this with. There is the acv_gpio test, but I don't understand what I'm
ment to connect to the VAPI. Can anyone help with this?
With the new all-callbacks scheme we could actually implement the memory section
useing peripherals. Is this desired?
I also realised that I basically broke FAST_SIM. Is this still a wanted
feature? It appears to have been bit rotting for quite some time anyway.
About the recompiler, I have now got it to the stage were it's generating code
(I haven't run it yet, though). I kind of hit a rather hard brick wall with
how I'm going to implement the scheduler. I could do a call out to do_scheduler
but then more than half the cpu time would be taken up by executeing the
scheduler. I also tought about inlineing it after every instruction, but
do_scheduler is 444 bytes long. I got it down to ~60 bytes but that would still
constitute ~120 KILO bytes of the recompiled data, so this is not an option. I
also had the brainy idea of useing the host cpu's hardware debug unit, but the
debug unit in the x86 is a piece of crap, which can't set conditional
watchpoints. So do you (or anyone else) have a good idea about how this may be
implemented?
ChangeLog:
* Cleanup the gpio peripheral useing the new callbacks.
nog.
-------------- next part --------------
--- peripheral/gpio.c 2005-02-05 11:26:14.000000000 +0100
+++ ../or1ksim-ac/peripheral/gpio.c 2005-02-09 11:08:47.000000000 +0100
@@ -34,124 +34,55 @@
#include "pic.h"
#include "vapi.h"
#include "debug.h"
-
-static struct gpio_device gpios[MAX_GPIOS];
+#include "sched.h"
static void gpio_vapi_read( unsigned long id, unsigned long data, void *dat );
static uint32_t gpio_read32( oraddr_t addr, void *dat );
static void gpio_write32( oraddr_t addr, uint32_t value, void *dat );
-static void gpio_external_clock( unsigned long value );
+static void gpio_external_clock( unsigned long value, struct gpio_device *gpio );
static void gpio_device_clock( struct gpio_device *gpio );
-static int gpio_find_device( oraddr_t addr, struct gpio_device **gpio, oraddr_t *reladdr );
-static struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which_vapi );
/* Initialize all parameters and state */
-void gpio_reset( void )
+void gpio_reset( void *dat )
{
- static int first_time = 1;
- unsigned i;
+ struct gpio_device *gpio = dat;
- if ( first_time ) {
- memset( gpios, 0, sizeof(gpios) );
- first_time = 0;
- }
-
- for ( i = 0; i gpio_number = i;
- gpio->baseaddr = config.gpios.baseaddr;
-
- if ( gpio->baseaddr != 0 ) {
- /* Get IRQ */
- gpio->irq = config.gpios.irq;
-
- /* Register memory range */
- register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, 0, gpio_read32, gpio_write32, NULL );
-
- /* Possibly connect to VAPI */
- if ( config.gpios.base_vapi_id ) {
- gpio->base_vapi_id = config.gpios.base_vapi_id;
- vapi_install_multi_handler( gpio->base_vapi_id, GPIO_NUM_VAPI_IDS, gpio_vapi_read, NULL );
- }
+ if ( gpio->baseaddr != 0 ) {
+ /* Possibly connect to VAPI */
+ if ( gpio->base_vapi_id ) {
+ vapi_install_multi_handler( gpio->base_vapi_id, GPIO_NUM_VAPI_IDS, gpio_vapi_read, dat );
}
}
}
/* Dump status */
-void gpio_status( void )
+void gpio_status( void *dat )
{
- unsigned i;
+ struct gpio_device *gpio = dat;
- for ( i = 0; i baseaddr == 0 )
- continue;
-
- PRINTF( "\nGPIO %u at 0x%"PRIxADDR":\n", i, gpio->baseaddr );
- PRINTF( "RGPIO_IN : 0x%08lX\n", gpio->curr.in );
- PRINTF( "RGPIO_OUT : 0x%08lX\n", gpio->curr.out );
- PRINTF( "RGPIO_OE : 0x%08lX\n", gpio->curr.oe );
- PRINTF( "RGPIO_INTE : 0x%08lX\n", gpio->curr.inte );
- PRINTF( "RGPIO_PTRIG : 0x%08lX\n", gpio->curr.ptrig );
- PRINTF( "RGPIO_AUX : 0x%08lX\n", gpio->curr.aux );
- PRINTF( "RGPIO_CTRL : 0x%08lX\n", gpio->curr.ctrl );
- PRINTF( "RGPIO_INTS : 0x%08lX\n", gpio->curr.ints );
- }
-}
-
-
-/* Convert a memory address to a device struct and relative address.
- * Return nonzero on success */
-int gpio_find_device( oraddr_t addr, struct gpio_device **gpio, oraddr_t *reladdr )
-{
- unsigned i;
- *gpio = NULL;
-
- for ( i = 0; i = gpios.baseaddr) && (addr baseaddr) % 4 != 0 )
- return 0;
-
- *reladdr = addr - (*gpio)->baseaddr;
- return 1;
-}
-
-
-/* Find device by vapi id */
-struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which )
-{
- unsigned i;
-
- for ( i = 0; i = gpios.base_vapi_id) && (id baseaddr == 0 )
+ return;
- return NULL;
+ PRINTF( "\nGPIO at 0x%"PRIxADDR":\n", gpio->baseaddr );
+ PRINTF( "RGPIO_IN : 0x%08lX\n", gpio->curr.in );
+ PRINTF( "RGPIO_OUT : 0x%08lX\n", gpio->curr.out );
+ PRINTF( "RGPIO_OE : 0x%08lX\n", gpio->curr.oe );
+ PRINTF( "RGPIO_INTE : 0x%08lX\n", gpio->curr.inte );
+ PRINTF( "RGPIO_PTRIG : 0x%08lX\n", gpio->curr.ptrig );
+ PRINTF( "RGPIO_AUX : 0x%08lX\n", gpio->curr.aux );
+ PRINTF( "RGPIO_CTRL : 0x%08lX\n", gpio->curr.ctrl );
+ PRINTF( "RGPIO_INTS : 0x%08lX\n", gpio->curr.ints );
}
/* Wishbone read */
uint32_t gpio_read32( oraddr_t addr, void *dat )
{
- struct gpio_device *gpio;
- if ( !gpio_find_device( addr, &gpio, &addr ) ) {
- debug( 2, "gpio_read32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
- return 0;
- }
+ struct gpio_device *gpio = dat;
+
+ addr -= gpio->baseaddr;
switch( addr ) {
case RGPIO_IN: return gpio->curr.in | gpio->curr.out;
@@ -163,17 +94,17 @@
case RGPIO_CTRL: return gpio->curr.ctrl;
case RGPIO_INTS: return gpio->curr.ints;
}
+
+ return 0;
}
/* Wishbone write */
void gpio_write32( oraddr_t addr, uint32_t value, void *dat )
{
- struct gpio_device *gpio;
- if ( !gpio_find_device( addr, &gpio, &addr ) ) {
- debug( 2, "gpio_write32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
- return;
- }
+ struct gpio_device *gpio = dat;
+
+ addr -= gpio->baseaddr;
switch( addr ) {
case RGPIO_IN: debug( 5, "GPIO: Cannot write to RGPIO_IN\n" ); break;
@@ -192,14 +123,11 @@
void gpio_vapi_read( unsigned long id, unsigned long data, void *dat )
{
unsigned which;
- struct gpio_device *gpio = gpio_find_vapi_device( id, &which );
+ struct gpio_device *gpio = dat;
debug( 5, "GPIO: id %08lx, data %08lx\n", id, data );
- if ( !gpio ) {
- debug( 1, "GPIO: VAPI ID %08lx is not ours!\n", id );
- return;
- }
+ which = id - gpio->base_vapi_id;
switch( which ) {
case GPIO_VAPI_DATA:
@@ -226,45 +154,42 @@
gpio->next.ctrl = data;
break;
case GPIO_VAPI_CLOCK:
- gpio_external_clock( data );
+ gpio_external_clock( data, gpio );
break;
}
-}
-
-/* System Clock. */
-void gpio_clock( void )
-{
- unsigned i;
- for ( i = 0; i curr.ctrl & RGPIO_CTRL_ECLK) )
+ gpio_device_clock( gpio );
}
/* External Clock. */
-void gpio_external_clock( unsigned long value )
+static void gpio_external_clock( unsigned long value, struct gpio_device *gpio )
{
- unsigned i;
+ int use_external_clock = ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
+ int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
/* "Normalize" clock value */
value = (value != 0);
- for ( i = 0; i next.external_clock = value;
- int use_external_clock = ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
- int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
-
- gpio->next.external_clock = value;
-
- if ( use_external_clock && (gpio->next.external_clock != gpio->curr.external_clock) && (value != negative_edge) )
+ if ( use_external_clock && (gpio->next.external_clock != gpio->curr.external_clock) && (value != negative_edge) )
+ /* Make sure that in vapi_read, we don't clock the device */
+ if ( gpio->curr.ctrl & RGPIO_CTRL_ECLK )
gpio_device_clock( gpio );
- }
}
+/* Report an interrupt to the sim */
+void gpio_do_int( void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ report_interrupt( gpio->irq );
+}
/* Clock as handld by one device. */
-void gpio_device_clock( struct gpio_device *gpio )
+static void gpio_device_clock( struct gpio_device *gpio )
{
/* Calculate new inputs and outputs */
gpio->next.in &= ~gpio->next.oe; /* Only input bits */
@@ -292,9 +217,12 @@
if ( relevant_bits & gpio->next.inte ) {
debug( 3, "GPIO: Reporting interrupt %d\n", gpio->irq );
- report_interrupt( gpio->irq );
gpio->next.ctrl |= RGPIO_CTRL_INTS;
gpio->next.ints |= relevant_bits & gpio->next.inte;
+ /* Since we can't report an interrupt during a readmem/writemem
+ * schedule the scheduler to do it. Read the comment above
+ * report_interrupt in pic/pic.c */
+ SCHED_ADD( gpio_do_int, gpio, runtime.sim.cycles + 1 );
}
}
}
@@ -304,46 +232,56 @@
}
/*---------------------------------------------------[ GPIO configuration ]---*/
-void gpio_ngpios(union param_val val, void *dat)
-{
- if (val.int_val >= 0 && val.int_val = 0 && current_device baseaddr = val.addr_val;
}
void gpio_irq(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device irq = val.int_val;
}
void gpio_base_vapi_id(union param_val val, void *dat)
{
- if (current_device >= 0 && current_device base_vapi_id = val.int_val;
+}
+
+void *gpio_sec_start(void)
+{
+ struct gpio_device *new = malloc(sizeof(struct gpio_device));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral Test: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->auxiliary_inputs = 0;
+ memset(&new->curr, 0, sizeof(new->curr));
+ memset(&new->next, 0, sizeof(new->next));
+
+ return new;
+}
+
+void gpio_sec_end(void *dat)
+{
+ struct gpio_device *gpio = dat;
+
+ /* Register memory range */
+ register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, 0, gpio_read32, gpio_write32, dat );
+
+ reg_sim_reset(gpio_reset, dat);
+ reg_sim_stat(gpio_status, dat);
}
void reg_gpio_sec(void)
{
struct config_section *sec = reg_config_sec("gpio", NULL, NULL);
- reg_config_param(sec, "ngpios", paramt_int, gpio_ngpios);
- reg_config_param(sec, "device", paramt_int, change_device);
reg_config_param(sec, "baseaddr", paramt_addr, gpio_baseaddr);
reg_config_param(sec, "irq", paramt_int, gpio_irq);
reg_config_param(sec, "base_vapi_id", paramt_int, gpio_base_vapi_id);
- reg_config_param(sec, "enddevice", paramt_none, end_device);
}
--- peripheral/gpio.h 2002-01-02 11:38:36.000000000 +0100
+++ ../or1ksim-ac/peripheral/gpio.h 2005-02-09 10:30:12.000000000 +0100
@@ -21,13 +21,7 @@
#ifndef __OR1KSIM_PERIPHERAL_GPIO_H
#define __OR1KSIM_PERIPHERAL_GPIO_H
-/* Exported function prototypes */
-void gpio_reset( void );
-void gpio_clock( void );
-void gpio_status( void );
-
-
-/* Address space required by one Ethernet MAC */
+/* Address space required by one GPIO */
#define GPIO_ADDR_SPACE 0x20
/* Relative Register Addresses */
--- sim-config.c 2005-02-05 15:55:00.000000000 +0100
+++ ../or1ksim-ac/sim-config.c 2005-02-09 11:07:48.000000000 +0100
@@ -144,9 +143,6 @@
config.vapi.enabled = 0;
strcpy (config.vapi.vapi_fn, "vapi.log");
- /* GPIO */
- config.ngpios = 0;
-
/* PM */
config.pm.enabled = 0;
@@ -892,16 +893,6 @@
fprintf (f, " tick:{enabled:%i},\n", config.tick.enabled);
- fprintf (f, " ngpios:%i, gpios:{", config.ngpios);
- comma = 0;
- for (i = 0; i
- make specified number of instances, configure each
- instance within device - enddevice construct.
-
- instance specific:
baseaddr =
address of first GPIO register for this device
@@ -728,13 +723,9 @@
*/
section gpio
- ngpios = 1
-
- device 0
- baseaddr = 0x91000000
- irq = 3
- base_vapi_id = 0x0200
- enddevice
+ baseaddr = 0x91000000
+ irq = 3
+ base_vapi_id = 0x0200
end
/* VGA SECTION
--- sim-cmd.c 2005-02-09 14:23:10.000000000 +0100
+++ ../or1ksim-ac/sim-cmd.c 2005-02-09 11:08:05.000000000 +0100
@@ -59,7 +59,6 @@
#include "icache_model.h"
#include "dcache_model.h"
#include "branch_predict.h"
-#include "gpio.h"
struct sim_stat {
void (*stat_func)(void *dat);
@@ -418,8 +427,6 @@
if (config.bpb.enabled) bpb_info();
if (config.bpb.btic) btic_info();
- if (config.ngpios) gpio_status();
-
while(cur_stat) {
cur_stat->stat_func(cur_stat->dat);
cur_stat = cur_stat->next;
--- toplevel.c 2005-02-09 14:23:10.000000000 +0100
+++ ../or1ksim-ac/toplevel.c 2005-02-09 11:07:33.000000000 +0100
@@ -54,7 +54,6 @@
#include "sched.h"
#include "profiler.h"
#include "mprofiler.h"
-#include "gpio.h"
#include "pm.h"
#include "pic.h"
#include "opcode/or32.h"
@@ -165,7 +164,6 @@
cur_reset = cur_reset->next;
}
- gpio_reset();
tick_reset();
pm_reset();
pic_reset();
@@ -438,7 +436,6 @@
if (config.ic.enabled) ic_clock();
}
- if (config.ngpios) gpio_clock();
if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
IFF(config.debug.enabled)
|
|||
1/1

