Bläddra i källkod

Add extended devices (xdevs) that require > 128 bytes

Add support for "extended devices" (xdevs) for I/O devices
requiring more than 128 bytes of address space. These devices can't be
accessed using zero-page addressing, so only do this for devices which
actually need it.
H. Peter Anvin 3 år sedan
förälder
incheckning
3608e21183
12 ändrade filer med 129 tillägg och 65 borttagningar
  1. 24 12
      fpga/iodevs.vh
  2. BIN
      fpga/output_files/max80.jbc
  3. BIN
      fpga/output_files/max80.jic
  4. BIN
      fpga/output_files/max80.pof
  5. BIN
      fpga/output_files/max80.sof
  6. 4 4
      fw/boot.mif
  7. 2 2
      fw/console.c
  8. 2 2
      fw/hello.c
  9. 6 6
      fw/io.h
  10. 19 20
      fw/ioregs.h
  11. 7 4
      iodevs.conf
  12. 65 15
      tools/iodevs.pl

+ 24 - 12
fpga/iodevs.vh

@@ -1,5 +1,7 @@
-	wire [31:0] iodev_rdata;
-	wire [15:0] iodev_valid = iodev_mem_valid << cpu_mem_addr[10:7];
+	reg [31:0]  nxdev_rdata;
+	reg [31:0]  iodev_rdata;
+	wire [3:0]  xdev_valid  = iodev_mem_valid << cpu_mem_addr[29:28];
+	wire [15:0]  iodev_valid = xdev_valid[3] << cpu_mem_addr[10:7];
 
 	wire [31:0] iodev_rdata_led;
 	wire [ 0:0] iodev_valid_led = iodev_valid[0:0];
@@ -33,16 +35,25 @@
 	wire [ 0:0] iodev_valid_esp = iodev_valid[6:6];
 	tri1 [ 0:0] iodev_wait_n_esp;
 
+	wire [31:0] iodev_rdata_abcmemmap;
+	wire [ 0:0] iodev_valid_abcmemmap = xdev_valid[0:0];
+	tri1 [ 0:0] iodev_wait_n_abcmemmap;
+
 	// I/O input MUX
-	always @(*)
-		case (cpu_mem_addr[10:7])
-			4'd0:	 iodev_rdata = iodev_rdata_led;
-			4'd1:	 iodev_rdata = iodev_rdata_reset;
-			4'd2:	 iodev_rdata = iodev_rdata_romcopy;
-			4'd3:	 iodev_rdata = iodev_rdata_sysclock;
-			4'd4:	 iodev_rdata = iodev_rdata_console;
-			4'd5:	 iodev_rdata = iodev_rdata_sdcard;
-			4'd6:	 iodev_rdata = iodev_rdata_esp;
+	always_comb
+		case (cpu_mem_addr[29:28])
+			2'd0:	 iodev_rdata = iodev_rdata_abcmemmap;
+			2'd3:
+			case (cpu_mem_addr[10:7])
+				4'd0:	 iodev_rdata = iodev_rdata_led;
+				4'd1:	 iodev_rdata = iodev_rdata_reset;
+				4'd2:	 iodev_rdata = iodev_rdata_romcopy;
+				4'd3:	 iodev_rdata = iodev_rdata_sysclock;
+				4'd4:	 iodev_rdata = iodev_rdata_console;
+				4'd5:	 iodev_rdata = iodev_rdata_sdcard;
+				4'd6:	 iodev_rdata = iodev_rdata_esp;
+				default: iodev_rdata = 32'hffffffff;
+			endcase
 			default: iodev_rdata = 32'hffffffff;
 		endcase
 
@@ -61,4 +72,5 @@
 		(&iodev_wait_n_sysclock) & 
 		(&iodev_wait_n_console) & 
 		(&iodev_wait_n_sdcard) & 
-		(&iodev_wait_n_esp);
+		(&iodev_wait_n_esp) & 
+		(&iodev_wait_n_abcmemmap);

BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 4 - 4
fw/boot.mif

@@ -3149,11 +3149,11 @@ CONTENT BEGIN
 0C46 : 64656C69;
 0C47 : 3A6E6F20;
 0C48 : 74634F20;
-0C49 : 20392020;
+0C49 : 20313120;
 0C4A : 31323032;
-0C4B : 3A373120;
-0C4C : 353A3635;
-0C4D : 000A0A33;
+0C4B : 3A333120;
+0C4C : 343A3132;
+0C4D : 000A0A30;
 0C4E : 61636473;
 0C4F : 725F6472;
 0C50 : 5F646165;

+ 2 - 2
fw/console.c

@@ -31,8 +31,8 @@ void con_putc(char c)
 	pause();
 
     if (c == '\n')
-	CONSOLE = '\r';
-    CONSOLE = c;
+	CON_DATA = '\r';
+    CON_DATA = c;
 }
 
 void con_puts(const char *str)

+ 2 - 2
fw/hello.c

@@ -57,7 +57,7 @@ static void test_sdram(void)
 	write_check(p, A*w + B);
 
 	if (!(n & 0x3ffff)) {
-	    CONSOLE = err_char;
+	    CON_DATA = err_char;
 	    err_char = '-';
 	}
 
@@ -74,7 +74,7 @@ static void test_sdram(void)
 	data_check(p, A*w + B);
 
 	if (!(n & 0x3ffff)) {
-	    CONSOLE = err_char;
+	    CON_DATA = err_char;
 	    err_char = '-';
 	}
 

+ 6 - 6
fw/io.h

@@ -67,30 +67,30 @@ enum sd_data_flags {
 static inline void sd_writeb(uint8_t d, enum sd_data_flags flags)
 {
     flags ^= (flags & SD_BE) ? 3 : 0;
-    *(volatile uint8_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA) = d;
+    *(volatile uint8_t *)IODEVA(SDCARD,0,flags | SD_DATA) = d;
 }
 static inline void sd_writeh(uint16_t d, enum sd_data_flags flags)
 {
     flags ^= (flags & SD_BE) ? 2 : 0;
-    *(volatile uint16_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA) = d;
+    *(volatile uint16_t *)IODEVA(SDCARD,0,flags | SD_DATA) = d;
 }
 static inline void sd_writel(uint32_t d, enum sd_data_flags flags)
 {
-    *(volatile uint32_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA) = d;
+    *(volatile uint32_t *)IODEVA(SDCARD,0,flags | SD_DATA) = d;
 }
 static inline uint8_t sd_readb(enum sd_data_flags flags)
 {
     flags ^= (flags & SD_BE) ? 0 : 3;
-    return *(volatile uint8_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA);
+    return *(volatile uint8_t *)IODEVA(SDCARD,0,flags | SD_DATA);
 }
 static inline uint16_t sd_readh(enum sd_data_flags flags)
 {
     flags ^= (flags & SD_BE) ? 0 : 2;
-    return *(volatile uint16_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA);
+    return *(volatile uint16_t *)IODEVA(SDCARD,0,flags | SD_DATA);
 }
 static inline uint32_t sd_readl(enum sd_data_flags flags)
 {
-    return *(volatile uint32_t *)IODEVA(SDCARD_DEV,0,flags | SD_DATA);
+    return *(volatile uint32_t *)IODEVA(SDCARD,0,flags | SD_DATA);
 }
 
 static inline uint8_t sd_crc7_rd(void)

+ 19 - 20
fw/ioregs.h

@@ -4,8 +4,7 @@
 #include "iodevs.h"
 
 /* Address for I/O device d, subregister r, offset o */
-#define IODEVA(d,r,o)   ((~0UL << (IODEV_ADDR_BITS+IODEV_ADDR_SHIFT)) + \
-			 +((d) << IODEV_ADDR_SHIFT)+((r) << 2)+(o))
+#define IODEVA(b,r,o)   ((b ## _BASE)+((r) << 2)+(o))
 
 #ifdef __ASSEMBLY__
 
@@ -51,26 +50,26 @@
 
 #define CPU_HZ			84000000
 
-#define LED			IODEVB(LED_DEV,0)
+#define LED			IODEVB(LED,0)
 
-#define RESET_CMD		IODEVL(RESET_DEV,0)
+#define RESET_CMD		IODEVL(RESET,0)
 
-#define ROMCOPY_DONE		IODEVRL(ROMCOPY_DEV,0)
+#define ROMCOPY_DONE		IODEVRL(ROMCOPY,0)
 
-#define CONSOLE			IODEVB(CONSOLE_DEV,0)
-#define CON_BAUDDIV		IODEVL(CONSOLE_DEV,1)
+#define CON_DATA		IODEVB(CONSOLE,0)
+#define CON_BAUDDIV		IODEVL(CONSOLE,1)
 #define CON_BAUD_BASE		(CPU_HZ >> 4)
 #define CON_BAUD_BITS		24
-#define CON_STATUS		IODEVRL(CONSOLE_DEV,2)
-#define CON_IRQEN		IODEVL(CONSOLE_DEV,3)
+#define CON_STATUS		IODEVRL(CONSOLE,2)
+#define CON_IRQEN		IODEVL(CONSOLE,3)
 
-#define SDCARD_CTL		IODEVL(SDCARD_DEV,0)
-#define SDCARD_CTL_SPEED	IODEVB0(SDCARD_DEV,0)
-#define SDCARD_CTL_CLRCRC	IODEVB1(SDCARD_DEV,0)
-#define SDCARD_CRC7_RD		IODEVRB0(SDCARD_DEV,4)
-#define SDCARD_CRC16_RD		IODEVRH1(SDCARD_DEV,4)
-#define SDCARD_CRC7_WR		IODEVRB0(SDCARD_DEV,5)
-#define SDCARD_CRC16_WR		IODEVRH1(SDCARD_DEV,5)
+#define SDCARD_CTL		IODEVL(SDCARD,0)
+#define SDCARD_CTL_SPEED	IODEVB0(SDCARD,0)
+#define SDCARD_CTL_CLRCRC	IODEVB1(SDCARD,0)
+#define SDCARD_CRC7_RD		IODEVRB0(SDCARD,4)
+#define SDCARD_CRC16_RD		IODEVRH1(SDCARD,4)
+#define SDCARD_CRC7_WR		IODEVRB0(SDCARD,5)
+#define SDCARD_CRC16_WR		IODEVRH1(SDCARD,5)
 
 /* Speed values, not including -1 adjustment */
 #define SD_SLOW		128	/* 328 kHz */
@@ -78,9 +77,9 @@
 #define SD_25MHZ	2	/* Really 21 MHz */
 #define SD_50MHZ	1	/* Really 42 MHz */
 
-#define SYSCLOCK_DATETIME	IODEVL(SYSCLOCK_DEV,0)
-#define SYSCLOCK_TICK		IODEVL(SYSCLOCK_DEV,1)
-#define SYSCLOCK_TICK_HOLD	IODEVH0(SYSCLOCK_DEV,1)
-#define SYSCLOCK_TICK_NOW	IODEVH1(SYSCLOCK_DEV,1)
+#define SYSCLOCK_DATETIME	IODEVL(SYSCLOCK,0)
+#define SYSCLOCK_TICK		IODEVL(SYSCLOCK,1)
+#define SYSCLOCK_TICK_HOLD	IODEVH0(SYSCLOCK,1)
+#define SYSCLOCK_TICK_NOW	IODEVH1(SYSCLOCK,1)
 
 #endif /* IODEV_H */

+ 7 - 4
iodevs.conf

@@ -3,6 +3,8 @@
 # I/O device configuration
 #
 
+our $xdev_addr_bits   = 2;
+our $xdev_addr_shift  = 28;
 our $iodev_addr_bits  = 4;
 our $iodev_addr_shift = 7;
 
@@ -15,8 +17,9 @@ our @iodevs = (
     { -name => 'led' },
     { -name => 'reset' },
     { -name => 'romcopy' },
-    { -name => 'sysclock', -irq => 'e' },
-    { -name => 'console',  -irq => 'l' },
-    { -name => 'sdcard',   -irq => 'l' },
-    { -name => 'esp',      -irq => 'l' }
+    { -name => 'sysclock',  -irq => 'e' },
+    { -name => 'console',   -irq => 'l' },
+    { -name => 'sdcard',    -irq => 'l' },
+    { -name => 'esp',       -irq => 'l' },
+    { -name => 'abcmemmap', -xdev => 1 },
 );

+ 65 - 15
tools/iodevs.pl

@@ -10,9 +10,17 @@ use File::Spec;
 # Variables from configuration file
 our $iodev_addr_bits;
 our $iodev_addr_shift;
+our $xdev_addr_bits;
+our $xdev_addr_shift;
 our @sysirqs;
 our @iodevs;
 
+sub base($$$) {
+    my($num,$bits,$shift) = @_;
+
+    my $v = ($num | (~0 << $bits)) << $shift;
+    return $v & 0xffffffff;
+}
 
 sub generate_h($) {
     my($out) = @_;
@@ -23,8 +31,9 @@ sub generate_h($) {
     printf $out "#define IODEV_ADDR_BITS %d\n", $iodev_addr_bits;
     printf $out "#define IODEV_ADDR_SHIFT %d\n", $iodev_addr_shift;
 
-    my $ndev = 0;
-    my $nirq = 0;
+    my $ndev  = 0;
+    my $nxdev = 0;
+    my $nirq  = 0;
 
     print $out "\n";
 
@@ -41,15 +50,25 @@ sub generate_h($) {
 	next unless ($dcount);
 
 	my $name = uc($dev->{-name});
-
-	printf $out "\n#define %s_DEV %d\n", $name, $ndev;
+	my $xdev = $dev->{-xdev};
+
+	if ($xdev) {
+	    printf $out "\n#define %s_XDEV %d\n", $name, $nxdev;
+	    printf $out "#define %s_BASE 0x%08x\n", $name,
+		base($nxdev, $xdev_addr_bits, $xdev_addr_shift);
+	} else {
+	    printf $out "\n#define %s_DEV  %d\n", $name, $ndev;
+	    printf $out "#define %s_BASE 0x%08x\n", $name,
+		base($ndev, $iodev_addr_bits, $iodev_addr_shift);
+	}
 	printf $out "#define %s_DEV_COUNT %d\n", $name, $dcount;
 	if ($icount) {
 	    printf $out "#define %s_IRQ %d\n", $name, $nirq;
 	}
 
-	$ndev += $dcount;
-	$nirq += $dcount * $icount;
+	$ndev  += $xdev ? 0 : $dcount;
+	$nxdev += $xdev ? $dcount : 0;
+	$nirq  += $dcount * $icount;
     }
 
     printf $out "\n#define IRQ_VECTORS %d\n", $nirq;
@@ -111,17 +130,23 @@ sub generate_verilog($)
     my($out) = @_;
 
     my $ndev = 0;
+    my $nxdev = 0;
     my $nirq = scalar(@sysirqs);
     my $irq_edge = 0;
 
     my @imux = ();
+    my @xmux = ();
     my @wait = ();
     my @valid = ();
     my @irqs = ();
 
-    print $out "\twire [31:0] iodev_rdata;\n";
-    printf $out "\twire [%d:0] iodev_valid = iodev_mem_valid << cpu_mem_addr[%d:%d];\n",
-	(1 << $iodev_addr_bits)-1,
+    print $out "\treg [31:0]  nxdev_rdata;\n";
+    print $out "\treg [31:0]  iodev_rdata;\n";
+    printf $out "\twire [%d:0]  xdev_valid  = iodev_mem_valid << cpu_mem_addr[%d:%d];\n",
+	(1 << $xdev_addr_bits)-1,
+	$xdev_addr_shift+$xdev_addr_bits-1, $xdev_addr_shift;
+    printf $out "\twire [%d:0]  iodev_valid = xdev_valid[%d] << cpu_mem_addr[%d:%d];\n",
+	(1 << $iodev_addr_bits)-1, (1 << $xdev_addr_bits)-1,
 	$iodev_addr_shift+$iodev_addr_bits-1, $iodev_addr_shift;
 
     print $out "\n";
@@ -129,6 +154,7 @@ sub generate_verilog($)
     foreach my $dev (@iodevs) {
 	my $dcount = $dev->{-count};
 	my $irq    = $dev->{-irq};
+	my $xdev   = $dev->{-xdev};
 
 	$dcount = 1 unless (defined($dcount));
 
@@ -144,8 +170,13 @@ sub generate_verilog($)
 		length($irq)-1, $name, $didx;
 	}
 
-	printf $out "\twire [%2d:0] iodev_valid_%s = iodev_valid[%d:%d];\n",
-	    $dcount-1, $name, $ndev+$dcount-1, $ndev;
+	if ($xdev) {
+	    printf $out "\twire [%2d:0] iodev_valid_%s = xdev_valid[%d:%d];\n",
+		$dcount-1, $name, $nxdev+$dcount-1, $nxdev;
+	} else {
+	    printf $out "\twire [%2d:0] iodev_valid_%s = iodev_valid[%d:%d];\n",
+		$dcount-1, $name, $ndev+$dcount-1, $ndev;
+	}
 
 	printf $out "\ttri1 [%2d:0] iodev_wait_n_%s;\n", $dcount-1, $name;
 	push(@wait, "(&iodev_wait_n_$name)");
@@ -155,7 +186,11 @@ sub generate_verilog($)
 	for (my $d = 0; $d < $dcount; $d++) {
 	    my $dsuf = ($dcount > 1) ? "[$d]" : '';
 
-	    push(@imux, "iodev_rdata_$name$dsuf");
+	    if ($xdev) {
+		push(@xmux, "iodev_rdata_$name$dsuf");
+	    } else {
+		push(@imux, "iodev_rdata_$name$dsuf");
+	    }
 	    for (my $i = 0; $i < length($irq); $i++) {
 		my $isuf = "[$i]";
 		my $type = substr($irq,$i,1);
@@ -168,19 +203,34 @@ sub generate_verilog($)
 
 		$nirq++;
 	    }
-	    $ndev++;
+	    if ($xdev) {
+		$nxdev++;
+	    } else {
+		$ndev++;
+	    }
 	}
     }
 
     print  $out "\t// I/O input MUX\n";
-    print  $out "\talways \@(\*)\n";
+    print  $out "\talways_comb\n";
     printf $out "\t\tcase (cpu_mem_addr[%d:%d])\n",
+	$xdev_addr_shift+$xdev_addr_bits-1, $xdev_addr_shift;
+    my $nxdev = 0;
+    foreach my $dev (@xmux) {
+	printf $out "\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
+	    $xdev_addr_bits, $nxdev++, $dev;
+    }
+    printf $out "\t\t\t%d'd%d:\n",
+	    $xdev_addr_bits, (1 << $xdev_addr_bits)-1;
+    printf $out "\t\t\tcase (cpu_mem_addr[%d:%d])\n",
 	$iodev_addr_shift+$iodev_addr_bits-1, $iodev_addr_shift;
     my $ndev = 0;
     foreach my $dev (@imux) {
-	printf $out "\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
+	printf $out "\t\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
 	    $iodev_addr_bits, $ndev++, $dev;
     }
+    print $out "\t\t\t\tdefault: iodev_rdata = 32'hffffffff;\n";
+    print $out "\t\t\tendcase\n";
     print $out "\t\t\tdefault: iodev_rdata = 32'hffffffff;\n";
     print $out "\t\tendcase\n";