URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1389 to Rev 1390
- ↔ Reverse comparison
Rev 1389 → Rev 1390
/trunk/or1ksim/tick/tick.c
70,7 → 70,7
if (!param) { |
sprs[SPR_TTCR] = ttcr = 0; |
cycles_start = runtime.sim.cycles - ttcr; |
SCHED_ADD(tick_job, (void *)0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); |
SCHED_ADD(tick_job, (void *)0, (ttmr & SPR_TTMR_PERIOD) - ttcr); |
} |
case 2: |
if (ttmr & SPR_TTMR_IE) { |
81,7 → 81,7
else |
/* If TEE is currently not set we have to pend tick exception |
by rescheduling. */ |
SCHED_ADD(tick_job, (void *)1, runtime.sim.cycles + 1); |
SCHED_ADD(tick_job, (void *)1, 1); |
} |
break; |
} |
97,7 → 97,7
SCHED_FIND_REMOVE(tick_job, (void *)0); |
SCHED_FIND_REMOVE(tick_job, (void *)1); |
if (mode == 1 || mode == 2) { |
SCHED_ADD(tick_job, (void *)0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); |
SCHED_ADD(tick_job, (void *)0, (ttmr & SPR_TTMR_PERIOD) - ttcr); |
cycles_start = runtime.sim.cycles - ttcr; |
} |
} |
117,7 → 117,7
cycles_start = runtime.sim.cycles; |
SCHED_FIND_REMOVE(tick_job, (void *)0); |
SCHED_FIND_REMOVE(tick_job, (void *)1); |
SCHED_ADD(tick_job, (void *)0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); |
SCHED_ADD(tick_job, (void *)0, (ttmr & SPR_TTMR_PERIOD) - ttcr); |
break; |
case 2: /* Stop the timer when match */ |
SCHED_FIND_REMOVE(tick_job, (void *)0); |
/trunk/or1ksim/peripheral/gpio.c
222,7 → 222,7
/* 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 ); |
SCHED_ADD( gpio_do_int, gpio, 1 ); |
} |
} |
} |
/trunk/or1ksim/peripheral/eth.c
232,7 → 232,7
} |
|
/* Reschedule */ |
SCHED_ADD( eth_controller_tx_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( eth_controller_tx_clock, dat, 1 ); |
} |
/* ========================================================================= */ |
|
434,7 → 434,7
} |
|
/* Reschedule */ |
SCHED_ADD( eth_controller_rx_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( eth_controller_rx_clock, dat, 1 ); |
} |
|
/* ========================================================================= */ |
699,13 → 699,13
|
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) && |
TEST_FLAG( value, ETH_MODER, RXEN) ) |
SCHED_ADD( eth_controller_rx_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( eth_controller_rx_clock, dat, 1 ); |
else if ( !TEST_FLAG( value, ETH_MODER, RXEN) ) |
SCHED_FIND_REMOVE( eth_controller_rx_clock, dat); |
|
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN) && |
TEST_FLAG( value, ETH_MODER, TXEN) ) |
SCHED_ADD( eth_controller_tx_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( eth_controller_tx_clock, dat, 1 ); |
else if ( !TEST_FLAG( value, ETH_MODER, TXEN) ) |
SCHED_FIND_REMOVE( eth_controller_tx_clock, dat); |
|
/trunk/or1ksim/peripheral/ps2kbd.c
259,7 → 259,7
PRINTF("Keyboard Interrupt.... kbd_kresp %lx kbd_buf_count %lx \n", |
kbd->kresp, kbd->buf_count); |
if (kbd_int) report_interrupt(kbd->irq); |
SCHED_ADD(kbd_job, dat, runtime.sim.cycles + kbd->slowdown); |
SCHED_ADD(kbd_job, dat, kbd->slowdown); |
} |
|
/* Reset all (simulated) ps2 controlers/keyboards */ |
280,7 → 280,7
} |
kbd->slowdown = (long) ((config.sim.system_kfreq * 1000.) / KBD_BAUD_RATE); |
if (kbd->slowdown <= 0) kbd->slowdown = 1; |
SCHED_ADD(kbd_job, dat, runtime.sim.cycles + kbd->slowdown); |
SCHED_ADD(kbd_job, dat, kbd->slowdown); |
} |
|
|
/trunk/or1ksim/peripheral/fb.c
284,13 → 284,13
else fb_dump_image8 (fb, temp); |
fb->pic++; |
} |
SCHED_ADD(fb_job, dat, runtime.sim.cycles + fb->refresh_rate - fb->refresh_rate / REFRESH_DIVIDER); |
SCHED_ADD(fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER); |
fb->in_refresh = 0; |
fb->refresh = 0; |
} else { |
fb->refresh_count++; |
fb->refresh = 1; |
SCHED_ADD(fb_job, dat, runtime.sim.cycles + fb->refresh_rate / REFRESH_DIVIDER); |
SCHED_ADD(fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER); |
} |
} |
|
307,7 → 307,7
for (i = 0; i < 256; i++) |
fb->pal[i] = (i << 16) | (i << 8) | (i << 0); |
|
SCHED_ADD(fb_job, dat, runtime.sim.cycles + fb->refresh_rate); |
SCHED_ADD(fb_job, dat, fb->refresh_rate); |
fb->refresh = 0; |
} |
|
/trunk/or1ksim/peripheral/dma.c
239,7 → 239,7
/* Check if we should *start* a transfer */ |
if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) && |
TEST_FLAG( value, DMA_CH_CSR, CH_EN )) |
SCHED_ADD( dma_channel_clock, channel, runtime.sim.cycles + 1 ); |
SCHED_ADD( dma_channel_clock, channel, 1 ); |
else if ( !TEST_FLAG( value, DMA_CH_CSR, CH_EN ) ) |
/* The CH_EN flag is clear, check if we have a transfer in progress and |
* clear it */ |
281,7 → 281,7
/* In HW Handshake mode, only work when dma_req_i asserted */ |
if ( TEST_FLAG(channel->regs.csr, DMA_CH_CSR, MODE) && !channel->dma_req_i ) { |
/* Reschedule */ |
SCHED_ADD( dma_channel_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( dma_channel_clock, dat, 1 ); |
return; |
} |
|
335,7 → 335,7
} |
|
/* Reschedule to transfer the next chunk */ |
SCHED_ADD( dma_channel_clock, dat, runtime.sim.cycles + 1 ); |
SCHED_ADD( dma_channel_clock, dat, 1 ); |
} |
|
|
387,7 → 387,7
dma_load_descriptor( channel ); |
dma_init_transfer( channel ); |
/* Reschedule */ |
SCHED_ADD( dma_channel_clock, channel, runtime.sim.cycles + 1 ); |
SCHED_ADD( dma_channel_clock, channel, 1 ); |
return; |
} |
|
/trunk/or1ksim/peripheral/vga.c
210,7 → 210,7
sprintf (temp, "%s%04i.bmp", vga->filename, vga->pics++); |
vga_dump_image (temp, vga); |
|
SCHED_ADD(vga_job, dat, runtime.sim.cycles + vga->refresh_rate); |
SCHED_ADD(vga_job, dat, vga->refresh_rate); |
} |
|
/* Reset all VGAs */ |
234,7 → 234,7
vga->pindex = 0; |
vga->vbindex = 0; |
|
SCHED_ADD(vga_job, dat, runtime.sim.cycles + vga->refresh_rate); |
SCHED_ADD(vga_job, dat, vga->refresh_rate); |
} |
|
/*----------------------------------------------------[ VGA Configuration ]---*/ |
/trunk/or1ksim/peripheral/16450.c
335,7 → 335,7
int retval; |
|
/* Schedule for later */ |
SCHED_ADD (uart_clock16, dat, runtime.sim.cycles + UART_CLOCK_DIVIDER); |
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER); |
|
/* If VAPI is not selected, UART communicates with two file streams; |
if VAPI is selected, we use VAPI streams. */ |
635,7 → 635,7
uart->vapi_buf_tail_ptr = 0; |
memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf)); |
|
SCHED_ADD (uart_clock16, dat, runtime.sim.cycles + UART_CLOCK_DIVIDER); |
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER); |
} |
|
/* Print register values on stdout. */ |
/trunk/or1ksim/toplevel.c
68,7 → 68,7
#include "cuc.h" |
|
/* CVS revision number. */ |
const char rcsrev[] = "$Revision: 1.117 $"; |
const char rcsrev[] = "$Revision: 1.118 $"; |
|
inline void debug(int level, const char *format, ...) |
{ |
157,7 → 157,8
{ |
struct sim_reset_hook *cur_reset = sim_reset_hooks; |
|
SCHED_INIT(); |
/* We absolutely MUST reset the scheduler first */ |
sched_reset(); |
|
while(cur_reset) { |
cur_reset->reset_hook(cur_reset->dat); |
179,6 → 180,8
init_breakpoints(); |
initstats(); |
build_automata(); |
|
sched_init(); |
|
if (config.sim.profile) { |
runtime.sim.fprof = fopen(config.sim.prof_fn, "wt+"); |
327,16 → 330,17
/* Executes jobs in time queue */ |
static inline void do_scheduler () |
{ |
void (*func)(void *); |
void *param; |
struct sched_entry *tmp; |
|
/* Execute all jobs till now */ |
do { |
func = SCHED_PEEK().func; |
param = SCHED_PEEK().param; |
SCHED_REMOVE(); |
func (param); |
} while (runtime.sim.cycles >= SCHED_PEEK().time); |
tmp = scheduler.job_queue; |
scheduler.job_queue = tmp->next; |
tmp->next = scheduler.free_job_queue; |
scheduler.free_job_queue = tmp; |
|
tmp->func (tmp->param); |
} while (scheduler.job_queue->time <= 0); |
} |
|
/* Main function */ |
399,6 → 403,7
|
/* MM: 'run -1' means endless execution. */ |
while(runtime.sim.cont_run) { |
long long time_start = runtime.sim.cycles; |
if (config.debug.enabled) { |
du_clock(); // reset watchpoints |
if (runtime.cpu.stalled) { |
430,7 → 435,8
if (testsprbits(SPR_DMR1, SPR_DMR1_ST)) set_stall_state (1); |
|
runtime.sim.cycles += runtime.sim.mem_cycles; |
if (runtime.sim.cycles >= SCHED_PEEK().time) do_scheduler (); |
scheduler.job_queue->time -= runtime.sim.cycles - time_start; |
if (scheduler.job_queue->time <= 0) do_scheduler (); |
if (!runtime.sim.hush) dumpreg(); |
} |
runtime.sim.hush = 0; |
/trunk/or1ksim/support/sched.c
45,6 → 45,49
emptying */ |
void sched_guard (void *dat) |
{ |
SCHED_INIT (); |
if(scheduler.job_queue) |
SCHED_ADD(sched_guard, dat, SCHED_TIME_MAX); |
else { |
scheduler.job_queue = scheduler.free_job_queue; |
scheduler.free_job_queue = scheduler.free_job_queue->next; |
scheduler.job_queue->next = NULL; |
scheduler.job_queue->func = sched_guard; |
scheduler.job_queue->time = SCHED_TIME_MAX; |
#if DYNAMIC_EXECUTION |
set_sched_cycle(SCHED_TIME_MAX); |
#endif |
} |
} |
|
void sched_reset(void) |
{ |
struct sched_entry *cur, *next; |
|
for(cur = scheduler.job_queue; cur; cur = next) { |
next = cur->next; |
cur->next = scheduler.free_job_queue; |
scheduler.free_job_queue = cur; |
} |
scheduler.job_queue = NULL; |
sched_guard(NULL); |
} |
|
void sched_init(void) |
{ |
int i; |
struct sched_entry *new; |
|
scheduler.free_job_queue = NULL; |
|
for(i = 0; i < SCHED_HEAP_SIZE; i++) { |
if(!(new = malloc(sizeof(struct sched_entry)))) { |
fprintf(stderr, "Out-of-memory while allocateing scheduler queue\n"); |
exit(1); |
} |
new->next = scheduler.free_job_queue; |
scheduler.free_job_queue = new; |
} |
scheduler.job_queue = NULL; |
sched_guard(NULL); |
} |
#warning Scheduler should continue from previous cycles not current ones |
/trunk/or1ksim/support/dbchs.h
19,3 → 19,4
|
|
/* Declatrations of all debug channels */ |
DECLARE_DEBUG_CHANNEL(sched) |
/trunk/or1ksim/support/sched.h
1,5 → 1,6
/* sched.h -- Abstract entities header file handling job scheduler |
Copyright (C) 2001 Marko Mlinar, markom@opencores.org |
|
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
20,45 → 21,46
#ifndef _SCHED_H_ |
#define _SCHED_H_ |
|
#include "debug.h" |
|
/* Scheduler debug level */ |
#define SCHED_DEBUG 0 |
|
#define SCHED_HEAP_SIZE 128 |
#define SCHED_TIME_MAX 0x7fffffffffffffffLL |
#define SCHED_TIME_MAX INT32_MAX |
|
DECLARE_DEBUG_CHANNEL(sched); |
|
/* Structure for holding one job entry */ |
struct sched_entry { |
long long time; /* Clock cycles before job starts */ |
void *param; /* Parameter to pass to the function */ |
int32_t time; /* Clock cycles before job starts */ |
void *param; /* Parameter to pass to the function */ |
void (*func)(void *); /* Function to call when time reaches 0 */ |
struct sched_entry *next; |
}; |
|
/* Heap of jobs */ |
struct scheduler_struct { |
int size; |
struct sched_entry heap[SCHED_HEAP_SIZE]; |
struct sched_entry *free_job_queue; |
struct sched_entry *job_queue; |
}; |
|
void sched_init(void); |
void sched_reset(void); |
|
extern struct scheduler_struct scheduler; |
|
/* Dummy function, representing a guard, which protects heap from |
emptying */ |
extern void sched_guard (void *); |
#if SCHED_DEBUG > 1 |
#define SCHED_PRINT_JOBS() sched_print_jobs() |
static inline void sched_print_jobs(void) |
{ |
struct sched_entry *cur; |
int i; |
|
/* Init scheduler -- clear the heap */ |
#define SCHED_INIT() {\ |
scheduler.heap[1].func = sched_guard;\ |
scheduler.heap[1].time = SCHED_TIME_MAX;\ |
scheduler.size = 2;\ |
for (cur = scheduler.job_queue, i = 0; cur; cur = cur->next, i++) |
TRACE_(sched)("\t%i: %p $%p @ %"PRIi32"\n", i, cur->func, cur->param, |
cur->time); |
} |
|
#if SCHED_DEBUG > 1 |
#define SCHED_PRINT_JOBS() {\ |
int i;\ |
for (i = 1; i < scheduler.size; i++) \ |
PRINTF ("\t%i: %x $%i @ %i\n", i, scheduler.heap[i].func, scheduler.heap[i].param, scheduler.heap[i].time);\ |
} |
#else |
#define SCHED_PRINT_JOBS() |
#endif |
65,82 → 67,94
|
/* Adds new job to the queue */ |
static inline void sched_add(void (*job_func)(void *), void *job_param, |
long long job_time, const char *func) |
int32_t job_time, const char *func) |
{ |
int i; |
struct sched_entry *cur, *prev, *new_job; |
int32_t alltime; |
|
if (SCHED_DEBUG > 0) |
PRINTF ("%s@%lli:SCHED_ADD(func %p, param %p, time %lli)\n", func, |
runtime.sim.cycles, job_func, job_param, job_time); |
if (SCHED_DEBUG > 1) |
TRACE_(sched)("%s@%lli:SCHED_ADD(time %"PRIi32")\n", func, |
runtime.sim.cycles, job_time); |
SCHED_PRINT_JOBS(); |
|
if (SCHED_DEBUG > 1) PRINTF ("--------\n");\ |
if (SCHED_DEBUG > 1) TRACE_(sched) ("--------\n"); |
|
i = scheduler.size++; |
while (i > 1 && scheduler.heap[i / 2].time > job_time) { |
scheduler.heap[i] = scheduler.heap[i / 2]; |
i /= 2; |
cur = scheduler.job_queue; |
prev = NULL; |
alltime = cur->time; |
while(cur && (alltime < job_time)) { |
prev = cur; |
cur = cur->next; |
if(cur) |
alltime += cur->time; |
} |
|
scheduler.heap[i].func = job_func; |
scheduler.heap[i].param = job_param; |
scheduler.heap[i].time = job_time; |
new_job = scheduler.free_job_queue; |
scheduler.free_job_queue = new_job->next; |
new_job->next = cur; |
|
new_job->func = job_func; |
new_job->param = job_param; |
|
if(prev) { |
new_job->time = job_time - (alltime - (cur ? cur->time : 0)); |
prev->next = new_job; |
TRACE_(sched)("Scheduled job not going to head of queue, relative time: %" |
PRIi32"\n", new_job->time); |
} else { |
scheduler.job_queue = new_job; |
new_job->time = job_time; |
#if DYNAMIC_EXECUTION |
/* If we are replaceing the first job in the queue, then update the |
* recompiler's internal cycle counter */ |
set_sched_cycle(job_time); |
#endif |
TRACE_(sched)("Setting to-go cycles to %"PRIi32" at %lli\n", job_time, |
runtime.sim.cycles); |
} |
|
if(cur) |
cur->time -= new_job->time; |
|
SCHED_PRINT_JOBS(); |
} |
|
#define SCHED_ADD(job_func, job_param, job_time) sched_add(job_func, job_param, job_time, __FUNCTION__) |
|
/* Removes an item from the heap */ |
#define SCHED_REMOVE_ITEM(index) {\ |
struct sched_entry *tmp;\ |
int ___i = (index), ___j;\ |
if (SCHED_DEBUG > 0) PRINTF ("%s@%i:SCHED_REMOVE%i(time %li)\n", __FUNCTION__, runtime.sim.cycles, (index), scheduler.heap[___i].time); \ |
SCHED_PRINT_JOBS();\ |
if (SCHED_DEBUG > 1) PRINTF ("--------\n");\ |
tmp = &scheduler.heap[--scheduler.size];\ |
while (___i <= scheduler.size / 2) {\ |
___j = 2 * ___i;\ |
if (___j < scheduler.size && scheduler.heap[___j].time > scheduler.heap[___j + 1].time) ___j++;\ |
if (scheduler.heap[___j].time >= tmp->time) break;\ |
scheduler.heap[___i] = scheduler.heap[___j];\ |
___i = ___j;\ |
}\ |
scheduler.heap[___i] = *tmp;\ |
SCHED_PRINT_JOBS();\ |
} |
/* Returns a job with specified function and param, NULL if not found */ |
static inline void sched_find_remove(void (*job_func)(void *), void *dat, |
const char *func) |
{ |
struct sched_entry *cur; |
struct sched_entry *prev = NULL; |
|
/* Removes first item from the heap */ |
#define SCHED_REMOVE() SCHED_REMOVE_ITEM(1) |
TRACE_(sched)("%s@%lli:SCHED_REMOVE()\n", func, runtime.sim.cycles); |
|
/* Returns item with lowest time in the heap */ |
#define SCHED_PEEK() scheduler.heap[1] |
for (cur = scheduler.job_queue; cur; prev = cur, cur = cur->next) { |
if ((cur->func == job_func) && (cur->param == dat)) { |
if(cur->next) |
cur->next->time += cur->time; |
|
/* Returns a job with specified function and param, NULL if not found */ |
#define SCHED_FIND(f, p) ({\ |
int i;\ |
struct sched_entry *t = NULL;\ |
for (i = 1; i < scheduler.size; i++)\ |
if (scheduler.heap[i].func == (f) && scheduler.heap[i].param == (p)) {\ |
t = &scheduler.heap[i]; break;\ |
}\ |
tmp;\ |
}) |
if(prev) { |
prev->next = cur->next; |
} else { |
scheduler.job_queue = cur->next; |
#if DYNAMIC_EXECUTION |
if(cur->next) |
set_sched_cycle(cur->next->time); |
#endif |
if(cur->next) |
TRACE_(sched)("Setting to-go cycles to %"PRIi32" at %lli\n", |
cur->next->time, runtime.sim.cycles); |
} |
cur->next = scheduler.free_job_queue; |
scheduler.free_job_queue = cur; |
break; |
} |
} |
} |
|
/* Returns a index of the job with specified function and param, 0 if not found */ |
#define SCHED_FIND_INDEX(f, p) ({\ |
int i, found = 0;\ |
for (i = 1; i < scheduler.size; i++)\ |
if (scheduler.heap[i].func == (f) && scheduler.heap[i].param == (p)) {\ |
found = i; break;\ |
}\ |
found;\ |
}) |
|
/* Deletes job with specified function and param */ |
#define SCHED_FIND_REMOVE(f, p) {\ |
int index;\ |
index = SCHED_FIND_INDEX(f, p);\ |
if (index) SCHED_REMOVE_ITEM(index);\ |
} |
#define SCHED_FIND_REMOVE(f, p) sched_find_remove(f, p, __FUNCTION__) |
|
#endif /* _SCHED_H_ */ |