Browse Source

iodevs: auto-generate common constants

Add a mechanism for sharing constants between C, ld script, and
Verilog, rather than needing to keep the constants in sync manually.
H. Peter Anvin 3 years ago
parent
commit
80cd70eb57
11 changed files with 77 additions and 46 deletions
  1. 17 6
      fpga/iodevs.vh
  2. 3 3
      fpga/max80.sv
  3. BIN
      fpga/output_files/max80.jbc
  4. BIN
      fpga/output_files/max80.jic
  5. BIN
      fpga/output_files/max80.pof
  6. BIN
      fpga/output_files/max80.sof
  7. 4 4
      fw/boot.mif
  8. 1 1
      fw/hello.c
  9. 7 12
      fw/sys.h
  10. 11 0
      iodevs.conf
  11. 34 20
      tools/iodevs.pl

+ 17 - 6
fpga/iodevs.vh

@@ -1,7 +1,18 @@
-	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];
+	localparam IODEV_ADDR_BITS         = 'h00000004; // 4
+	localparam IODEV_ADDR_SHIFT        = 'h00000007; // 7
+	localparam SDRAM_ADDR              = 'h40000000; // 1073741824
+	localparam SDRAM_BITS              = 'h00000019; // 25
+	localparam SRAM_ADDR               = 'h00000000; // 0
+	localparam SRAM_BITS               = 'h0000000f; // 15
+	localparam XDEV_ADDR_BITS          = 'h00000002; // 2
+	localparam XDEV_ADDR_SHIFT         = 'h0000001c; // 28
+	localparam _PC_IRQ                 = 'h00000020; // 32
+	localparam _PC_RESET               = 'h00000010; // 16
+
+	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_sys;
 	wire [ 0:0] iodev_valid_sys = iodev_valid[0:0];
@@ -60,9 +71,9 @@
 				4'd5:	 iodev_rdata = iodev_rdata_i2c;
 				4'd6:	 iodev_rdata = iodev_rdata_esp;
 				4'd7:	 iodev_rdata = iodev_rdata_abc;
-				default: iodev_rdata = 32'hffffffff;
+				default: iodev_rdata = 32'hxxxxxxxx;
 			endcase
-			default: iodev_rdata = 32'hffffffff;
+			default: iodev_rdata = 32'hxxxxxxxx;
 		endcase
 
 	tri0 [31:0] sys_irq;

+ 3 - 3
fpga/max80.sv

@@ -396,7 +396,7 @@ module max80 (
    assign gpio    = 6'bzzzzzz;
 
    // Embedded RISC-V CPU
-   parameter cpu_fast_mem_bits = 13; /* 2^[this] * 4 bytes */
+   parameter cpu_fast_mem_bits = SRAM_BITS-2; /* 2^[this] * 4 bytes */
 
    // Edge-triggered IRQs. picorv32 latches interrupts
    // but doesn't edge detect for a slow signal, so do it
@@ -456,8 +456,8 @@ module max80 (
 	.resetn ( rst_n ),
 	.trap ( cpu_trap ),
 
-	.progaddr_reset ( 32'h0000_0010 ),
-	.progaddr_irq   ( 32'h0000_0020 ),
+	.progaddr_reset ( _PC_RESET ),
+	.progaddr_irq   ( _PC_IRQ ),
 
 	.mem_instr ( cpu_mem_instr ),
 	.mem_ready ( cpu_mem_ready ),

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

@@ -5542,10 +5542,10 @@ CONTENT BEGIN
 159F : 6F206465;
 15A0 : 4F203A6E;
 15A1 : 32207463;
-15A2 : 30322033;
-15A3 : 30203132;
-15A4 : 35343A30;
-15A5 : 0A30323A;
+15A2 : 30322037;
+15A3 : 31203132;
+15A4 : 34343A31;
+15A5 : 0A32313A;
 15A6 : 5452000A;
 15A7 : 49203A43;
 15A8 : 53204332;

+ 1 - 1
fw/hello.c

@@ -86,7 +86,7 @@ static void test_sdram(void)
 	       (rdtime() - start_time)/(CPU_HZ/1000));
 
     stride *= 3;
-    stride = (stride & SDRAM_MASK) ^ (stride >> (SDRAM_ADDR_BITS-2));
+    stride = (stride & SDRAM_MASK) ^ (stride >> (SDRAM_BITS-2));
     stride = (stride & ~3) | 4;
 #endif
 }

+ 7 - 12
fw/sys.h

@@ -4,13 +4,14 @@
 /*
  * Various constants that need to match the hardware configuration.
  * This file must be includable from assembly and from a linker script.
- * XXX: generate this the fixed parameters here from iodevs.conf and
- * share with the Verilog code.
+ *
+ * The base constants should be defined in iodevs.conf; this file contains
+ * derived constants.
  */
 
-#define SRAM_ADDR	0
-#define SRAM_ADDR_BITS	15
-#define SRAM_SIZE      (0x1 << SRAM_ADDR_BITS)
+#include "iodevs.h"
+
+#define SRAM_SIZE      (0x1 << SRAM_BITS)
 #define SRAM_MASK      (SRAM_SIZE - 1)
 #define SRAM_END       (SRAM_ADDR + SRAM_SIZE)
 
@@ -18,14 +19,8 @@
 #define STACK_TOP	SRAM_END	/* Initial stack pointer */
 #define STACK_BOTTOM	(STACK_TOP - STACK_SIZE)
 
-#define SDRAM_ADDR      0x40000000
-#define SDRAM_ADDR_BITS 25
-#define SDRAM_SIZE      (0x1 << SDRAM_ADDR_BITS)
+#define SDRAM_SIZE      (0x1 << SDRAM_BITS)
 #define SDRAM_MASK      (SDRAM_SIZE - 1)
 #define SDRAM_END       (SDRAM_ADDR + SDRAM_SIZE)
 
-/* This need to match the corresponding Verilog constants */
-#define _PC_RESET	0x10
-#define _PC_IRQ		0x20
-
 #endif /* SYS_H */

+ 11 - 0
iodevs.conf

@@ -3,6 +3,17 @@
 # I/O device configuration
 #
 
+# Common constants
+our %consts = (
+    '_PC_RESET'  => 0x10,
+    '_PC_IRQ'    => 0x20,
+    'SRAM_ADDR'  => 0,
+    'SRAM_BITS'  => 15,
+    'SDRAM_ADDR' => 0x40000000,
+    'SDRAM_BITS' => 25
+    );
+
+# I/O address definitions
 our $xdev_addr_bits   = 2;
 our $xdev_addr_shift  = 28;
 our $iodev_addr_bits  = 4;

+ 34 - 20
tools/iodevs.pl

@@ -8,6 +8,7 @@ use strict;
 use File::Spec;
 
 # Variables from configuration file
+our %consts;
 our $iodev_addr_bits;
 our $iodev_addr_shift;
 our $xdev_addr_bits;
@@ -28,17 +29,18 @@ sub generate_h($) {
     print $out "#ifndef IODEVS_H\n";
     print $out "#define IODEVS_H\n\n";
 
-    printf $out "#define IODEV_ADDR_BITS %d\n", $iodev_addr_bits;
-    printf $out "#define IODEV_ADDR_SHIFT %d\n", $iodev_addr_shift;
+    foreach my $c (sort(keys(%consts))) {
+	printf $out "#define %-23s 0x%08x /* %d */\n",
+	    $c, $consts{$c}, $consts{$c};
+    }
+    print $out "\n";
 
     my $ndev  = 0;
     my $nxdev = 0;
     my $nirq  = 0;
 
-    print $out "\n";
-
     foreach my $sysirq (@sysirqs) {
-	printf $out "#define %s_IRQ %d\n", uc($sysirq), $nirq++;
+	printf $out "#define %-23s %d\n", "\U$sysirq\E_IRQ", $nirq++;
     }
 
     foreach my $dev (@iodevs) {
@@ -53,17 +55,17 @@ sub generate_h($) {
 	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,
+	    printf $out "\n#define %-23s %d\n", $name.'_XDEV', $nxdev;
+	    printf $out "#define %-23s 0x%08x\n", $name.'_BASE',
 		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,
+	    printf $out "\n#define %-23s %d\n", $name.'_DEV', $ndev;
+	    printf $out "#define %-23s 0x%08x\n", $name.'_BASE',
 		base($ndev, $iodev_addr_bits, $iodev_addr_shift);
 	}
-	printf $out "#define %s_DEV_COUNT %d\n", $name, $dcount;
+	printf $out "#define %-23s %d\n", $name.'_DEV_COUNT', $dcount;
 	if ($icount) {
-	    printf $out "#define %s_IRQ %d\n", $name, $nirq;
+	    printf $out "#define %-23s %d\n", $name.'_IRQ', $nirq;
 	}
 
 	$ndev  += $xdev ? 0 : $dcount;
@@ -71,7 +73,7 @@ sub generate_h($) {
 	$nirq  += $dcount * $icount;
     }
 
-    printf $out "\n#define IRQ_VECTORS %d\n", $nirq;
+    printf $out "\n#define %-23s %d\n", 'IRQ_VECTORS', $nirq;
 
     print $out "\n#endif /* IODEVS_H */\n";
 }
@@ -105,13 +107,13 @@ sub generate_irqtbl($)
 	$nirq += $dcount*$icount;
     }
 
-    print $out "static void irqhandler_spurious(unsigned int vector)\n";
+    print $out "static IRQHANDLER(spurious)\n";
     print $out "{\n";
     print $out "\tmask_irq(vector);\n";
     print $out "}\n\n";
 
     foreach my $irq (@irqtbl) {
-	printf $out "void irqhandler_%s(unsigned int) __attribute__((weak,alias(\"irqhandler_spurious\")));\n", $irq->[0];
+	printf $out "IRQHANDLER(%s) __attribute__((weak,alias(\"irqhandler_spurious\")));\n", $irq->[0];
 
     }
     print $out "\nirqhandler_t __attribute__((section(\".sdata\")))\n";
@@ -129,6 +131,12 @@ sub generate_verilog($)
 {
     my($out) = @_;
 
+    foreach my $c (sort(keys(%consts))) {
+	printf $out "\tlocalparam %-23s = \'h%08x; // %d\n",
+	    $c, $consts{$c}, $consts{$c};
+    }
+    print $out "\n";
+
     my $ndev = 0;
     my $nxdev = 0;
     my $nirq = scalar(@sysirqs);
@@ -140,12 +148,12 @@ sub generate_verilog($)
     my @valid = ();
     my @irqs = ();
 
-    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",
+    print $out "\treg  [31:0] nxdev_rdata;\n";
+    print $out "\treg  [31:0] iodev_rdata;\n";
+    printf $out "\twire [%2d: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",
+    printf $out "\twire [%2d: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;
 
@@ -229,9 +237,9 @@ sub generate_verilog($)
 	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\t\tdefault: iodev_rdata = 32'hxxxxxxxx;\n";
     print $out "\t\t\tendcase\n";
-    print $out "\t\t\tdefault: iodev_rdata = 32'hffffffff;\n";
+    print $out "\t\t\tdefault: iodev_rdata = 32'hxxxxxxxx;\n";
     print $out "\t\tendcase\n";
 
     print $out "\n";
@@ -262,6 +270,12 @@ unless (defined(do File::Spec->rel2abs($infile))) {
     die "$0: $infile: $@\n"
 }
 
+# Export these as constants, too
+$consts{'IODEV_ADDR_BITS'}  = $iodev_addr_bits;
+$consts{'IODEV_ADDR_SHIFT'} = $iodev_addr_shift;
+$consts{'XDEV_ADDR_BITS'}   = $xdev_addr_bits;
+$consts{'XDEV_ADDR_SHIFT'}  = $xdev_addr_shift;
+
 open(my $out, '>', $outfile) or die;
 
 if ($mode eq 'h') {