From 45e7712b4debe764d31b66706abebb18cbc7c6a5 Mon Sep 17 00:00:00 2001
From: Michel Pollet <buserror@gmail.com>
Date: Tue, 14 Jul 2015 19:04:05 +0100
Subject: [PATCH] interrupts: Converted to use the standard fifo

There's already a standard way to make FIFO's, so converted the
interrupt code to use that.

Signed-off-by: Michel Pollet <buserror@gmail.com>
---
 simavr/sim/fifo_declare.h   |  2 +-
 simavr/sim/sim_interrupts.c | 27 ++++++++++-----------------
 simavr/sim/sim_interrupts.h | 10 ++++++----
 3 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/simavr/sim/fifo_declare.h b/simavr/sim/fifo_declare.h
index 35f45fe..8a3b2fb 100644
--- a/simavr/sim/fifo_declare.h
+++ b/simavr/sim/fifo_declare.h
@@ -53,7 +53,7 @@ extern "C" {
 		void myfifo_write_at(myfifo_t *c, uint16_t o, uint8_t b);
 
 	In your .c you need to 'implement' the fifo:
-	DEFINE_FIFO(uint8_t, myfifo, 128)
+	DEFINE_FIFO(uint8_t, myfifo)
 
 	To use the fifo, you must declare at least one :
 	myfifo_t fifo = FIFO_NULL;
diff --git a/simavr/sim/sim_interrupts.c b/simavr/sim/sim_interrupts.c
index b153907..0022795 100644
--- a/simavr/sim/sim_interrupts.c
+++ b/simavr/sim/sim_interrupts.c
@@ -28,9 +28,7 @@
 #include "sim_avr.h"
 #include "sim_core.h"
 
-// modulo a cursor value on the pending interrupt fifo
-#define INT_FIFO_SIZE (sizeof(table->pending) / sizeof(avr_int_vector_t *))
-#define INT_FIFO_MOD(_v) ((_v) &  (INT_FIFO_SIZE - 1))
+DEFINE_FIFO(avr_int_vector_p, avr_int_pending);
 
 void
 avr_interrupt_init(
@@ -39,7 +37,6 @@ avr_interrupt_init(
 	avr_int_table_p table = &avr->interrupts;
 	memset(table, 0, sizeof(*table));
 
-	printf("%s\n", __func__);
 	static const char *names[] = { ">global_int_pending", ">global_int_running" };
 	avr_init_irq(&avr->irq_pool, table->irq,
 			0, // base number
@@ -53,7 +50,7 @@ avr_interrupt_reset(
 	avr_int_table_p table = &avr->interrupts;
 
 	table->running_ptr = 0;
-	table->pending_r = table->pending_w = 0;
+	avr_int_pending_reset(&table->pending);
 	avr->interrupt_state = 0;
 	for (int i = 0; i < table->vector_count; i++)
 		table->vector[i]->pending = 0;
@@ -73,7 +70,6 @@ avr_register_vector(
 	avr_init_irq(&avr->irq_pool, vector->irq,
 			vector->vector * 256, // base number
 			AVR_INT_IRQ_COUNT, names);
-//	vector->irq.irq = vector->vector;
 	table->vector[table->vector_count++] = vector;
 	if (vector->trace)
 		printf("%s register vector %d (enabled %04x:%d)\n", __FUNCTION__, vector->vector, vector->enable.reg, vector->enable.bit);
@@ -87,7 +83,7 @@ avr_has_pending_interrupts(
 		avr_t * avr)
 {
 	avr_int_table_p table = &avr->interrupts;
-	return table->pending_r != table->pending_w;
+	return !avr_int_pending_isempty(&table->pending); // table->pending_r != table->pending_w;
 }
 
 int
@@ -136,8 +132,7 @@ avr_raise_interrupt(
 
 		avr_int_table_p table = &avr->interrupts;
 
-		table->pending[table->pending_w++] = vector;
-		table->pending_w = INT_FIFO_MOD(table->pending_w);
+		avr_int_pending_write(&table->pending, vector);
 
 		if (avr->sreg[S_I] && avr->interrupt_state == 0)
 			avr->interrupt_state = 1;
@@ -238,25 +233,23 @@ avr_service_interrupts(
 	avr_int_table_p table = &avr->interrupts;
 
 	// how many are pending...
-	int cnt = INT_FIFO_MOD(
-				(table->pending_w + INT_FIFO_SIZE) - table->pending_r);
+	int cnt = avr_int_pending_get_read_size(&table->pending);
 	// locate the highest priority one
 	int min = 0xff;
 	int mini = 0;
 	for (int ii = 0; ii < cnt; ii++) {
-		int vi = INT_FIFO_MOD(table->pending_r + ii);
-		avr_int_vector_t * v = table->pending[vi];
+		avr_int_vector_t * v = avr_int_pending_read_at(&table->pending, ii);
 		if (v->vector < min) {
 			min = v->vector;
-			mini = vi;
+			mini = ii;
 		}
 	}
-	avr_int_vector_t * vector = table->pending[mini];
+	avr_int_vector_t * vector = avr_int_pending_read_at(&table->pending, mini);
 
 	// now move the one at the front of the fifo in the slot of
 	// the one we service
-	table->pending[mini] = table->pending[table->pending_r++];
-	table->pending_r = INT_FIFO_MOD(table->pending_r);
+	table->pending.buffer[mini % avr_int_pending_fifo_size] = 
+			avr_int_pending_read(&table->pending);
 	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
 			avr_has_pending_interrupts(avr));
 
diff --git a/simavr/sim/sim_interrupts.h b/simavr/sim/sim_interrupts.h
index 0ee9294..b55ad17 100644
--- a/simavr/sim/sim_interrupts.h
+++ b/simavr/sim/sim_interrupts.h
@@ -24,6 +24,7 @@
 
 #include "sim_avr_types.h"
 #include "sim_irq.h"
+#include "fifo_declare.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -47,15 +48,16 @@ typedef struct avr_int_vector_t {
 					trace : 1,		// only for debug of a vector
 					raise_sticky : 1;	// 1 if the interrupt flag (= the raised regbit) is not cleared
 										// by the hardware when executing the interrupt routine (see TWINT)
-} avr_int_vector_t;
+} avr_int_vector_t, *avr_int_vector_p;
+
+// Size needs to be >= max number of vectors, and a power of two
+DECLARE_FIFO(avr_int_vector_p, avr_int_pending, 64);
 
 // interrupt vectors, and their enable/clear registers
 typedef struct  avr_int_table_t {
 	avr_int_vector_t * vector[64];
 	uint8_t			vector_count;
-	avr_int_vector_t * pending[64]; // needs to be >= vectors and a power of two
-	uint8_t			pending_w,
-					pending_r;	// fifo cursors
+	avr_int_pending_t pending;
 	uint8_t			running_ptr;
 	avr_int_vector_t *running[64]; // stack of nested interrupts
 	// global status for pending + running in interrupt context
-- 
2.39.5