/* --------------------------------------------------------------------------*/ void or1k_timer_enable(void) { uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); ttmr = OR1K_SPR_TICK_TTMR_IE_SET(ttmr, 1); ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr, OR1K_REENT.or1k_timer_mode); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); uint32_t sr = or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); sr = OR1K_SPR_SYS_SR_TEE_SET(sr, 1); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, sr); }
void interrupt_handler(void) { unsigned mask = or1k_mfspr((9<<11)|0); or1k_mtspr((9<<11),0); unsigned irq = or1k_mfspr(9<<11|2) & mask; or1k_mtspr((9<<11) |2,0); for (int i = 0;i<32;i++){ if (irq & (1<<i)){ if (global_irqhandler[i]){ (*global_irqhandler[i])(); } } } or1k_mtspr((9<<5),mask); }
void or1k_interrupts_restore(uint32_t sr_iee) { uint32_t sr = or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); sr = OR1K_SPR_SYS_SR_IEE_SET(sr, sr_iee); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, sr); }
void or1k_interrupts_enable(void) { uint32_t sr = or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); sr = OR1K_SPR_SYS_SR_IEE_SET(sr, 1); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, sr); }
void _optimsoc_itlb_miss(void) { optimsoc_page_dir_t dir; // Get current thread's page directory dir = _optimsoc_thread_get_pagedir_current(); VERIFY_DIR_ADDR(dir); // Load vaddr from EEAR uint32_t vaddr = or1k_mfspr(OR1K_SPR_SYS_EEAR_ADDR(0)); // Trace debug runtime_trace_itlb_miss(vaddr); // Lookup page optimsoc_pte_t pte = _optimsoc_vmm_lookup(dir, vaddr); if (pte) { // Update TLB _optimsoc_set_itlb(vaddr, pte); } else { // Raise page fault assert(_optimsoc_vmm_ifault_handler); _optimsoc_vmm_ifault_handler(vaddr); } }
void or1k_timer_restore(uint32_t sr_tee) { uint32_t sr = or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); sr = OR1K_SPR_SYS_SR_TEE_SET(sr, sr_tee); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, sr); }
void timer_isr() { _cust_print("<timer interrupt>"); or1k_mtspr(17, or1k_mfspr(17) | 2 ); or1k_mtspr((10<<11)+1, 0); or1k_mtspr((10<<11), 0xa0<<24 | 40000); return; }
void or1k_timer_pause(void) { uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr, OR1K_SPR_TICK_TTMR_MODE_DISABLE); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); }
/* --------------------------------------------------------------------------*/ int or1k_timer_init(unsigned int hz) { uint32_t upr = or1k_mfspr(OR1K_SPR_SYS_UPR_ADDR); if (OR1K_SPR_SYS_UPR_TTP_GET(upr) == 0) { return -1; } /* Set this, for easy access when reloading */ uint32_t period = (_or1k_board_clk_freq/hz) & OR1K_SPR_TICK_TTMR_TP_MASK; OR1K_REENT.or1k_timer_period = period; or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, period); /* Reset timer tick counter */ OR1K_REENT.or1k_timer_ticks = 0; /* Install handler */ or1k_exception_handler_add(0x5, _or1k_timer_interrupt_handler); OR1K_REENT.or1k_timer_mode = OR1K_SPR_TICK_TTMR_MODE_RESTART; /* Reset counter register */ or1k_mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0); return 0; }
void or1k_interrupts_enable(void) { uint32_t sr = or1k_mfspr(SPR_SR); sr |= SPR_SR_IEE; or1k_mtspr(SPR_SR, sr); }
void _optimsoc_ipage_fault(void) { // Load address from EEAR uint32_t vaddr = or1k_mfspr(OR1K_SPR_SYS_EEAR_ADDR(0)); // Call handler assert(_optimsoc_vmm_ifault_handler); _optimsoc_vmm_ifault_handler(vaddr); }
void or1k_timer_reset(void) { uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); ttmr = OR1K_SPR_TICK_TTMR_IP_SET(ttmr, 0); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); or1k_mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0); }
/* --------------------------------------------------------------------------*/ uint32_t or1k_timer_disable(void) { uint32_t oldsr = or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); uint32_t sr = OR1K_SPR_SYS_SR_TEE_SET(oldsr, 0); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, sr); return OR1K_SPR_SYS_SR_TEE_GET(oldsr); }
uint32_t or1k_interrupts_disable(void) { uint32_t oldsr, newsr; oldsr= or1k_mfspr(SPR_SR); newsr = oldsr & ~SPR_SR_IEE; or1k_mtspr(SPR_SR, newsr); return oldsr & SPR_SR_IEE; }
uint32_t or1k_interrupts_disable(void) { uint32_t oldsr, newsr; oldsr= or1k_mfspr(OR1K_SPR_SYS_SR_ADDR); newsr = OR1K_SPR_SYS_SR_IEE_SET(oldsr, 0); or1k_mtspr(OR1K_SPR_SYS_SR_ADDR, newsr); return OR1K_SPR_SYS_SR_IEE_GET(oldsr); }
void or1k_timer_set_period(uint32_t hz) { uint32_t period = (_or1k_board_clk_freq/hz) & OR1K_SPR_TICK_TTMR_TP_MASK; uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); ttmr = OR1K_SPR_TICK_TTMR_TP_SET(ttmr, period); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); OR1K_REENT.or1k_timer_period = period; }
/* --------------------------------------------------------------------------*/ void _or1k_timer_interrupt_handler(void) { OR1K_REENT.or1k_timer_ticks++; uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); ttmr = OR1K_SPR_TICK_TTMR_IE_SET(ttmr, 1); ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr, OR1K_SPR_TICK_TTMR_MODE_RESTART); ttmr = OR1K_SPR_TICK_TTMR_IP_SET(ttmr, 0); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); }
void or1k_timer_set_mode(uint32_t mode) { // Store mode in variable OR1K_REENT.or1k_timer_mode = mode; uint32_t ttmr = or1k_mfspr(OR1K_SPR_TICK_TTMR_ADDR); // If the timer is currently running, we also change the mode if (OR1K_SPR_TICK_TTMR_MODE_GET(ttmr) != 0) { ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr, mode); or1k_mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr); } }
void itlb_miss() { struct optimsoc_scheduler_core *core_ctx; core_ctx = &optimsoc_scheduler_core[optimsoc_get_domain_coreid()]; void *vaddr = (void*) or1k_mfspr(SPR_EEAR_BASE); runtime_trace_itlb_miss(vaddr); /* Look up virtual address in the page table */ struct page_table_entry_t* entry; entry = find_page_entry(core_ctx->active_thread->task->page_table, vaddr); assert(entry != NULL); /* Write address back to ITLB */ arch_set_itlb(entry->vaddr_base, entry->paddr_base); }
void dtlb_miss() { struct optimsoc_scheduler_core *core_ctx; core_ctx = &optimsoc_scheduler_core[optimsoc_get_domain_coreid()]; void *vaddr = (void*) or1k_mfspr(SPR_EEAR_BASE); runtime_trace_dtlb_miss(vaddr); /* Look up virtual address in the page table */ struct page_table_entry_t* entry; entry = find_page_entry(core_ctx->active_thread->task->page_table, vaddr); if(entry != NULL) { /* Write address back to DTLB */ arch_set_dtlb(entry->vaddr_base, entry->paddr_base); } else { void *page = vmm_alloc_page(); assert(page != NULL); entry = malloc(sizeof(struct page_table_entry_t)); entry->vaddr_base = PAGE_BASE(vaddr); entry->paddr_base = page; printf("Allocated new data page %p and mapped to %p\n", entry->paddr_base, entry->vaddr_base); list_add_tail(core_ctx->active_thread->task->page_table, (void*)entry); runtime_trace_dtlb_allocate_page(page); arch_set_dtlb(entry->vaddr_base, entry->paddr_base); } }
void or1k_interrupts_restore(uint32_t sr_iee) { or1k_mtspr(SPR_SR, or1k_mfspr(SPR_SR) | (sr_iee & SPR_SR_IEE)); }
int main(int arcg,char * argv[]){ int i = or1k_mfspr(17); char * newline = "\n"; //_cust_print_int((int)newline); *(volatile char*)0x80000000 = 'm'; *(volatile char*)0x80000000 = 'a'; *(volatile char*)0x80000000 = 'i'; *(volatile char*)0x80000000 = 'n'; *(volatile char*)0x80000000 = ' '; *(volatile char*)0x80000000 = 'c'; *(volatile char*)0x80000000 = 'a'; *(volatile char*)0x80000000 = 'l'; *(volatile char*)0x80000000 = 'l'; *(volatile char*)0x80000000 = 'e'; *(volatile char*)0x80000000 = 'd'; *(volatile char*)0x80000000 = '\n'; for (int i = 0;i<32;i++) global_irqhandler[i] = 0; global_irqhandler[2] = irq2; or1k_exception_handler_add (0x8, &interrupt_handler); or1k_interrupt_enable(2); /*__asm__( ".byte 0x7C,0x00,0x00,0x00" );*/ // Timer interrupt int or1k_timer_period = 40000; or1k_exception_handler_add(0x5, &timer_isr); // Install handler for Timer interrupt or1k_mtspr(10<<11, 0x00<<24 | or1k_timer_period); // Set Timer Mode Register or1k_mtspr(17, or1k_mfspr(17) | 2 ); // Set Special Purpose Register: Enable Timer interrupt or1k_mtspr((10<<11) + 1, 0); // reset counter register (qemu bug: automatic counter reset does not work) for (int i = 1;i<10000; i = i * 2){ _cust_print_int(i); _cust_print(newline); } //or1k_exception_handler_add (0x8, &or1k_interrupt_handler); //or1k_interrupt_handler_add(11, &irq2); //or1k_interrupt_enable(10); /* float x = 0; for (int j = 0;j<(1<<16);j++){ for (int i = 0;i<(100);i++){ x += 0.1; } *((int*)0x0000A000) = (int) x; } *((int*)0x10000000) = 0; */ float p = 2 * F(1); _cust_print("pi 1: "); _cust_print_float(p); _cust_print("\n"); _cust_print("pi 2: "); _cust_print_float(pi()); _cust_print("\n"); //if (pi > 0.0) //_cust_print("\n\n3-pi > 0\n\n\n"); //float c = 0; //for (int i = 0;i < 10000000;i++){ // c+=0.1; //} //return (int)c; return 0; }