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 <hw/flash.h>
#include <hw/minimac.h>
-#include <hal/vga.h>
-#include <hal/tmu.h>
+//#include <hal/vga.h>
+//#include <hal/tmu.h>
#include <hal/brd.h>
-#include <hal/usb.h>
-#include <hal/ukb.h>
+//#include <hal/usb.h>
+//#include <hal/ukb.h>
+#include <hal/mmu.h>
#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 <yann.sionneau@gmail.com>
+ */
+
+#include <stdio.h>
+
+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 <hal/mmu.h>\n");
+ puts("#include <base/console.h>\n");
+ puts("#include <stdio.h>\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 <yann.sionneau@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 <yann.sionneau@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* @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");
+
+}