diff --git a/software/bios/isr.c b/software/bios/isr.c index 80a6bda..22305f8 100644 --- a/software/bios/isr.c +++ b/software/bios/isr.c @@ -30,10 +30,11 @@ void isr() if(irqs & IRQ_UART) uart_isr(); - +/* if(irqs & IRQ_TMU) tmu_isr(); if(irqs & IRQ_USB) usb_isr(); +*/ } diff --git a/software/bios/main.c b/software/bios/main.c index d7a3ff6..5c39a67 100644 --- a/software/bios/main.c +++ b/software/bios/main.c @@ -33,19 +33,20 @@ #include #include -#include -#include +//#include +//#include #include -#include -#include +//#include +//#include +#include #include "boot.h" -#include "splash.h" +//#include "splash.h" enum { CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA, CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3, - CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3, + CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3, CSR_TLBCTRL, CSR_TLBVADDR, CSR_TLBPADDR }; /* General address space functions */ @@ -232,6 +233,9 @@ static int parse_csr(const char *csr) if(!strcmp(csr, "wp1")) return CSR_WP1; if(!strcmp(csr, "wp2")) return CSR_WP2; if(!strcmp(csr, "wp3")) return CSR_WP3; + if(!strcmp(csr, "tlbctrl")) return CSR_TLBCTRL; + if(!strcmp(csr, "tlbvaddr")) return CSR_TLBVADDR; + if(!strcmp(csr, "tlbpaddr")) return CSR_TLBPADDR; return 0; } @@ -308,6 +312,9 @@ static void wcsr(char *csr, char *value) case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break; case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break; case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break; + case CSR_TLBCTRL: asm volatile ("wcsr tlbctrl,%0"::"r"(value2)); break; + case CSR_TLBVADDR: asm volatile ("wcsr tlbvaddr,%0"::"r"(value2)); break; + case CSR_TLBPADDR: asm volatile ("wcsr tlbpaddr,%0"::"r"(value2)); break; default: printf("csr read only\n"); return; } } @@ -415,6 +422,7 @@ static void help() puts("version - display version"); puts("reboot - system reset"); puts("reconf - reload FPGA configuration"); + puts("dtlbtest - runs DTLB MMU test"); } static char *get_token(char **str) @@ -433,6 +441,70 @@ static char *get_token(char **str) return d; } +#define DTLB_CSR (1 << 31) +#define DTLB_CSR_CTRL_FLUSH DTLB_CSR || (1 << 0) +#define DTLB_CSR_CTRL_UPDATE DTLB_CSR || (1 << 1) +#define DTLB_CSR_CTRL_SWITCH_TO_KERNEL_MODE DTLB_CSR || (1 << 30) +#define DTLB_CSR_CTRL_SWITCH_TO_USER_MODE DTLB_CSR || (1 << 29) + +static void dtlbtest(void) +{ +/* volatile unsigned int *addr; + register unsigned int value = 0x43; + puts("Starting DTLB tests..."); + + printf("Data store test : "); + + //Let's try to map Virtual address 0x44001000 to Physical address 0x44000000 + mmu_dtlb_map(0x44001000, 0x44000000); + + //Enable MMU DTLB + enable_dtlb(); + + // Let's write to Virtual address 0x44001000 + // addr = (unsigned int *)0x44001000; + // *addr = 0x42; + + asm volatile ("mvhi r11, 0x4400\n\t" + "ori r11, r11, 0x1000\n\t" + "xor r12, r12, r12\n\t" + "ori r12, r12, 0x42\n\t" + "sw (r11+0), r12":::"r11", "r12"); + + // Disable DTLB -> going back into KERNEL MODE + disable_dtlb(); + + //Let's read back from Physical address 0x44000000 + addr = (unsigned int *)0x44000000; + if (*addr == 0x42) + puts("SUCCESS"); + else + puts("FAILURE"); + + printf("0x44000000 contains %08X\n", *addr); + + printf("Data load test : "); + + //Now let's try to read from Virtual address 0x44001000 + enable_dtlb(); + //Following code means : value = *(unsigned int *)0x44001000; + asm volatile ("mvhi r11, 0x4400\n\t" + "ori r11, r11, 0x1000\n\t" + "lw %0, (r11+0)":"=r"(value)::"r11"); + disable_dtlb(); + + if (value == 0x42) + puts("SUCCESS"); + else + puts("FAILURE"); + + printf("value contains %08X\n", value); +*/ + //Running more dtlb load tests + dtlb_load_test(); + +} + static void do_command(char *c) { char *token; @@ -465,6 +537,7 @@ static void do_command(char *c) else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c)); else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c)); + else if(strcmp(token, "dtlbtest") == 0) dtlbtest(); else if(strcmp(token, "") != 0) printf("Command not found\n"); @@ -612,6 +685,7 @@ static void ethreset() int main(int i, char **c) { char buffer[64]; + unsigned short int k; /* lock gdbstub ROM */ CSR_DBG_CTRL = DBG_CTRL_GDB_ROM_LOCK; @@ -625,27 +699,28 @@ int main(int i, char **c) irq_setmask(0); irq_enable(1); uart_init(); - vga_init(!(rescue || (CSR_GPIO_IN & GPIO_BTN2))); putsnonl(banner); crcbios(); brd_init(); - tmu_init(); /* < for hardware-accelerated scrolling */ - usb_init(); - ukb_init(); if(rescue) printf("I: Booting in rescue mode\n"); - splash_display(); - ethreset(); /* < that pesky ethernet PHY needs two resets at times... */ - print_mac(); boot_sequence(); - vga_unblank(); - vga_set_console(1); + + uart_force_sync(1); + irq_enable(0); + + for (k = 0 ; k < 65000 ; ++k) + asm volatile("nop"); + + dtlb_load_test(); + while(1) { - putsnonl("\e[1mBIOS>\e[0m "); - readstr(buffer, 64); - do_command(buffer); + if (++k == 0) + printf("."); + asm volatile("nop"); } + return 0; } diff --git a/software/bios/mmu_test_gen.c b/software/bios/mmu_test_gen.c new file mode 100644 index 0000000..75bb22d --- /dev/null +++ b/software/bios/mmu_test_gen.c @@ -0,0 +1,115 @@ +/* MMU test generator + * Author : Yann Sionneau + */ + +#include + +static inline void generate_test(int i, int j) { + int k; + + puts("asm volatile("); + puts("\t\"xor r11, r11, r11\\n\\t\""); + puts("\t\"ori r11, r11, 0x11\\n\\t\""); + puts("\t\"wcsr tlbctrl, r11\\n\\t\""); + puts("\t\"xor r0, r0, r0\\n\\t\""); + puts("\t\"xor r0, r0, r0\\n\\t\""); + puts("\t\"xor r0, r0, r0\\n\\t\""); + for (k = 0 ; k < 6 ; k++) { + if (k == i) { + printf("\t\"sw (%2+0), %1"); + } + else if(k == j) { + printf("\t\"lw %0, (%2+0)"); + } + else + printf("\t\"xor r0, r0, r0"); + if (k != 5) + printf("\\n\\t"); + puts("\""); + } + + puts(": \"=&r\"(value_verif) : \"r\"(value), \"r\"(addr) :\"r11\"\n);"); + +} + +int main(void) { + + puts("#include \n"); + puts("#include \n"); + puts("#include \n"); + puts("void dtlb_load_test(void) {\n"); + + puts( + "char a, b, c, d;\n" + "// map vaddr 0x4400 2000 to paddr 0x4400 1000\n" + "register unsigned int value, addr, value_verif, stack, data;\n" + "int success, failure;\n" + "unsigned int count;\n" + "asm volatile(\"mv %0, sp\" : \"=r\"(stack) :: );\n" + "mmu_dtlb_map(0x44002000, 0x44001000);\n" + "mmu_dtlb_map(stack, stack);\n" + "mmu_dtlb_map(stack-0x1000, stack-0x1000);\n" + "printf(\"stack == 0x%08X\\n\", stack);" + "a = 0;\n" + "b = 1;\n" + "c = 2;\n" + "d = 3;\n" + "addr = 0x44002000;\n" + "success = 0;\n" + "failure = 0;" + ); + + int test_num = 0; + int i, j; + + for (i = 0 ; i < 5 ; i++) { + for (j = i+1 ; j < 6 ; j++) { + + puts( "value = a << 24;\n" + "value |= b << 16;\n" + "value |= c << 8;\n" + "value |= d;\n" + "addr += 4;\n" + ); + + + generate_test(i, j); + + puts("disable_dtlb();"); + puts("printf(\"addr == 0x%08X\\n\", addr);"); + puts("printf(\"[MMU OFF] *(0x%08X) == 0x%08X\\n\", addr, *(volatile unsigned int *)addr);"); + puts("enable_dtlb();"); + puts("asm volatile(\"lw %0, (%1+0)\" : \"=&r\"(data) : \"r\"(addr) : );"); + puts("disable_dtlb();"); + puts("printf(\"[MMU ON] *(0x%08X) == 0x%08X\\n\", addr, data);"); + puts("printf(\"[MMU OFF] *(0x%08X) == 0x%08X\\n\", addr-0x1000, *(volatile unsigned int *)(addr - 0x1000));"); + printf("printf(\"Test n° %02d : \");\n", test_num); + puts( "if (value == value_verif) {\n" + "\tputs(\"PASS\");\n" + "\tsuccess++;\n" + "} else {\n" + "\tputs(\"FAIL\");\n" + "\tfailure++;\n" + "}" + ); + + puts( "a++;\n" + "b++;\n" + "c++;\n" + "d++;\n\n" + ); + test_num++; + + puts("\ + for (count = 0 ; count <= 10000000 ; ++count) {\n\ + \t asm volatile(\"nop\");\n\ + }"); + } + } + + puts("printf(\"TOTAL : %d/%d successes | %d/%d failures\\n\", success, success + failure, failure, success + failure);"); + + puts("}"); + + return 0; +} diff --git a/software/include/fpvm/ast.h b/software/include/fpvm/ast.h index fa0159c..fa2b6eb 100644 --- a/software/include/fpvm/ast.h +++ b/software/include/fpvm/ast.h @@ -48,8 +48,6 @@ enum ast_op { op_max, op_int, op_bnot, - op_band, - op_bor, }; /* maximum supported arity is 3 */ diff --git a/software/include/hal/mmu.h b/software/include/hal/mmu.h new file mode 100644 index 0000000..f36641d --- /dev/null +++ b/software/include/hal/mmu.h @@ -0,0 +1,35 @@ +/* + * Milkymist SoC (Software) + * Copyright (C) 2012 Yann Sionneau + * + * 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, version 3 of the License. + * + * 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, see . + */ + + +#define enable_dtlb() do { \ + asm volatile ("xor r11, r11, r11\n\t" \ + "ori r11, r11, 0x11\n\t" \ + "wcsr tlbctrl, r11\n\t" \ + "xor r0, r0, r0":::"r11"); \ +} while(0); + +#define disable_dtlb() do { \ + asm volatile ("xor r11, r11, r11\n\t" \ + "ori r11, r11, 0x9\n\t" \ + "wcsr tlbctrl, r11\n\t" \ + "xor r0, r0, r0\n\t" \ + "xor r0, r0, r0\n\t" \ + "xor r0, r0, r0":::"r11"); \ +} while(0); + +void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn); diff --git a/software/libbase/uart.c b/software/libbase/uart.c index dabddfe..c751aee 100644 --- a/software/libbase/uart.c +++ b/software/libbase/uart.c @@ -49,6 +49,15 @@ void uart_isr(void) { unsigned int stat = CSR_UART_STAT; + mmu_dtlb_map(uart_isr, uart_isr); + mmu_dtlb_map(rx_buf, rx_buf); + mmu_dtlb_map(tx_buf, tx_buf); + mmu_dtlb_map(&tx_produce, &tx_produce); + mmu_dtlb_map(&tx_consume, &tx_consume); + mmu_dtlb_map(&rx_produce, &rx_produce); + mmu_dtlb_map(&tx_cts, &tx_cts); + mmu_dtlb_map(irq_ack, irq_ack); + if(stat & UART_STAT_RX_EVT) { rx_buf[rx_produce] = CSR_UART_RXTX; rx_produce = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX; diff --git a/software/libfpvm/fpvm.c b/software/libfpvm/fpvm.c index b76b13d..75c74f1 100644 --- a/software/libfpvm/fpvm.c +++ b/software/libfpvm/fpvm.c @@ -395,11 +395,6 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod opb = COMPILE(FPVM_INVALID_REG, node->contents.branches.c); (void) COMPILE(FPVM_REG_IFB, node->contents.branches.a); break; - case op_band: - case op_bor: - opa = opb = 0; - (void) COMPILE(FPVM_REG_IFB, node->contents.branches.a); - break; case op_negate: if(node->contents.branches.a->op == op_constant) { /* Node is a negative constant */ @@ -533,26 +528,6 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod return FPVM_INVALID_REG; ADD_ISN(FPVM_OPCODE_EQUAL, opa, opb, reg); break; - case op_band: { - int reg_zero = REG_CONST(0); - int reg_one = REG_CONST(1); - int reg_tmp = REG_ALLOC(); - - ADD_ISN(FPVM_OPCODE_IF, reg_one, reg_zero, reg_tmp); - (void) COMPILE(FPVM_REG_IFB, node->contents.branches.b); - ADD_ISN(FPVM_OPCODE_IF, reg_tmp, reg_zero, reg); - break; - } - case op_bor: { - int reg_zero = REG_CONST(0); - int reg_one = REG_CONST(1); - int reg_tmp = REG_ALLOC(); - - ADD_ISN(FPVM_OPCODE_IF, reg_one, reg_zero, reg_tmp); - (void) COMPILE(FPVM_REG_IFB, node->contents.branches.b); - ADD_ISN(FPVM_OPCODE_IF, reg_one, reg_tmp, reg); - break; - } default: /* Normal case */ opcode = operator2opcode(node->op); diff --git a/software/libhal/Makefile b/software/libhal/Makefile index a33fb9c..3e3dcd0 100644 --- a/software/libhal/Makefile +++ b/software/libhal/Makefile @@ -1,7 +1,7 @@ MMDIR=../.. include $(MMDIR)/software/include.mak -OBJECTS=brd.o dmx.o font8x16.o mem.o pfpu.o snd.o time.o tmu.o ukb.o usb.o vga.o vin.o +OBJECTS=brd.o dmx.o font8x16.o mem.o pfpu.o snd.o time.o tmu.o ukb.o usb.o vga.o vin.o mmu.o all: libhal.a diff --git a/software/libhal/mmu.c b/software/libhal/mmu.c new file mode 100644 index 0000000..c82352b --- /dev/null +++ b/software/libhal/mmu.c @@ -0,0 +1,34 @@ +/* + * Milkymist SoC (Software) + * Copyright (C) 2012 Yann Sionneau + * + * 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, version 3 of the License. + * + * 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, see . + */ + +/* @vpfn : virtual page frame number + * @pfn : physical page frame number + */ +inline void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn) +{ + + asm volatile ("ori %0, %0, 1\n\t" + "wcsr tlbvaddr, %0"::"r"(vpfn):); + + asm volatile ("ori %0, %0, 1\n\t" + "wcsr tlbpaddr, %0"::"r"(pfn):); + + asm volatile ("xor r11, r11, r11\n\t" + "ori r11, r11, 0x5\n\t" + "wcsr tlbctrl, r11":::"r11"); + +}