Browse Source

clocks: centralize strobes; rng: shut down when not in use

Centralize clock strobes. They can be used by the SDRAM for refresh
and init timing as well.

The random number generator ring oscillators can be fairly expensive
in terms of power, so shut them down when enough entropy has been
collected and there does not appear to be further demand.
H. Peter Anvin 3 years ago
parent
commit
de1566292f
15 changed files with 7389 additions and 7250 deletions
  1. 10 2
      fpga/iodevs.vh
  2. 74 38
      fpga/max80.sv
  3. BIN
      fpga/output_files/max80.jbc
  4. BIN
      fpga/output_files/max80.jic
  5. 1 1
      fpga/output_files/max80.pin
  6. BIN
      fpga/output_files/max80.pof
  7. BIN
      fpga/output_files/max80.sof
  8. 115 19
      fpga/rng.sv
  9. 29 39
      fpga/sdram.sv
  10. 1 0
      iodevs.conf
  11. 7143 7143
      rv32/boot.mif
  12. 4 4
      rv32/io.h
  13. 5 1
      rv32/ioregs.h
  14. 6 2
      rv32/system.c
  15. 1 1
      rv32/test/main.c

+ 10 - 2
fpga/iodevs.vh

@@ -59,6 +59,11 @@
 	wire [ 0:0] iodev_valid_abcmemmap = xdev_valid[0:0];
 	tri1 [ 0:0] iodev_wait_n_abcmemmap;
 
+	wire [31:0] iodev_rdata_random;
+	wire [ 0:0] iodev_irq_random;
+	wire [ 0:0] iodev_valid_random = iodev_valid[8:8];
+	tri1 [ 0:0] iodev_wait_n_random;
+
 	// I/O input MUX
 	always_comb
 		case (cpu_mem_addr[29:28])
@@ -73,6 +78,7 @@
 				4'd5:	 iodev_rdata = iodev_rdata_i2c;
 				4'd6:	 iodev_rdata = iodev_rdata_esp;
 				4'd7:	 iodev_rdata = iodev_rdata_abc;
+				4'd8:	 iodev_rdata = iodev_rdata_random;
 				default: iodev_rdata = 32'hxxxxxxxx;
 			endcase
 			default: iodev_rdata = 32'hxxxxxxxx;
@@ -86,9 +92,10 @@
 	assign sys_irq[ 7] = iodev_irq_i2c[0];
 	assign sys_irq[ 8] = iodev_irq_esp[0];
 	assign sys_irq[ 9] = iodev_irq_abc[0];
+	assign sys_irq[10] = iodev_irq_random[0];
 
 	localparam [31:0] irq_edge_mask =  32'h00000008;
-	localparam [31:0] irq_masked    = ~32'h000003ff;
+	localparam [31:0] irq_masked    = ~32'h000007ff;
 
 	wire iodev_wait_n = (&iodev_wait_n_sys) & 
 		(&iodev_wait_n_sysclock) & 
@@ -98,4 +105,5 @@
 		(&iodev_wait_n_i2c) & 
 		(&iodev_wait_n_esp) & 
 		(&iodev_wait_n_abc) & 
-		(&iodev_wait_n_abcmemmap);
+		(&iodev_wait_n_abcmemmap) & 
+		(&iodev_wait_n_random);

+ 74 - 38
fpga/max80.sv

@@ -72,7 +72,7 @@ module max80 (
 
 	      // USB serial (naming is FPGA as DCE)
 	      input	    tty_txd,
-	      output	    tty_rxd,
+	      inout	    tty_rxd,
 	      input	    tty_rts,
 	      output	    tty_cts,
 	      input	    tty_dtr,
@@ -120,9 +120,6 @@ module max80 (
    //   PLLs and reset
    // -----------------------------------------------------------------------
 
-   // Assert internal reset for 4096 cycles after PLL lock
-   parameter reset_pow2 = 12;
-
    reg			    rst_n      = 1'b0;	// Internal system reset
    reg			    hard_rst_n = 1'b0;	// Strict POR reset only
 
@@ -143,9 +140,10 @@ module max80 (
    //  sdram_clk, sys_clk    - 2:1 ratio
    //  vid_hdmiclk, vid_clk  - 5:1 ratio
    //
+   wire     reset_plls;
    wire     master_clk;		// 336 MHz internal master clock
    pll2 pll2 (
-	      .areset ( 1'b0 ),
+	      .areset ( reset_plls ),
 	      .locked ( pll_locked[2] ),
 
 	      .inclk0 ( clock_48 ),
@@ -181,32 +179,47 @@ module max80 (
 
    wire all_plls_locked = &pll_locked;
 
-   // sys_clk pulse generation of various powers of two
-   // Also used to generate rst_n
-   reg [23:1] sys_clk_ctr;
-   reg [23:1] sys_clk_ctr_q;
-   reg [23:1] sys_clk_stb;
+   //
+   // sys_clk pulse generation of various powers of two; allows us to
+   // reuse the same counter for a lot of things that require periodic
+   // timing events without strong requirements on the specific timing.
+   // The first strobe is asserted 2^n cycles after rst_n goes high.
+   //
+   // The same counter is used to hold rst_n and hard_rst_n low for
+   // 2^reset_pow2 cycles.
+   //
+   // XXX: reuse this counter for the CPU cycle counter.
+   //
+   parameter reset_pow2 = 12;
 
-   reg [1:0]  reset_cmd_q;
-   wire       reset_cmd;
+   reg [31:0] sys_clk_ctr;
+   reg [31:0] sys_clk_ctr_q;
+   reg [31:1] sys_clk_stb;
+
+   // 3 types of reset: system, hard, and reconfig
+   reg  [3:1] reset_cmd_q;
+   wire [3:1] reset_cmd;
+   reg	      soft_reset_q;
 
    always @(negedge all_plls_locked or posedge sys_clk)
      if (~all_plls_locked)
        begin
-	  hard_rst_n    <= 1'b0;
-	  rst_n         <= 1'b0;
-	  reset_cmd_q   <= 2'b0;
-	  sys_clk_ctr   <= 1'b0;
-	  sys_clk_ctr_q <= 1'b0;
-	  sys_clk_stb   <= 1'b0;
+	  hard_rst_n     <= 1'b0;
+	  rst_n          <= 1'b0;
+	  reset_cmd_q    <= 3'b0;
+	  soft_reset_q   <= 1'b0;
+	  sys_clk_ctr    <= (-'sb1) << reset_pow2;
+	  sys_clk_ctr_q  <= 'b0;
+	  sys_clk_stb    <= 'b0;
        end
      else
        begin
-	  reset_cmd_q <= { reset_cmd_q[0], reset_cmd };
+	  reset_cmd_q    <= reset_cmd;
+	  soft_reset_q   <= reset_cmd_q[1]; // Edge detect for soft reset
 
-	  if (reset_cmd_q == 2'b01)
+	  if (reset_cmd_q[1] & ~soft_reset_q)
 	    begin
-	       sys_clk_ctr   <= 1'b0;
+	       sys_clk_ctr   <= (-'sb1) << reset_pow2;
 	       sys_clk_ctr_q <= 1'b0;
 	       sys_clk_stb   <= 1'b0;
 	       rst_n         <= 1'b0;
@@ -214,10 +227,10 @@ module max80 (
 	  else
 	    begin
 	       sys_clk_ctr   <= sys_clk_ctr + 1'b1;
-	       sys_clk_ctr_q <= sys_clk_ctr;
+	       sys_clk_ctr_q <= ~rst_n ? 'b0 : sys_clk_ctr;
 	       sys_clk_stb   <= ~sys_clk_ctr & sys_clk_ctr_q;
-	       rst_n         <= rst_n      | sys_clk_stb[reset_pow2];
-	       hard_rst_n    <= hard_rst_n | sys_clk_stb[reset_pow2];
+	       rst_n         <= rst_n      | ~sys_clk_ctr[reset_pow2];
+	       hard_rst_n    <= hard_rst_n | ~sys_clk_ctr[reset_pow2];
 	    end
        end
 
@@ -324,7 +337,9 @@ module max80 (
    sdram #(.port1_count(dram_port_count))
    sdram (
 	  .rst_n    ( rst_n ),
-	  .clk      ( sdram_clk ), // Internal clock
+	  .clk      ( sdram_clk ),       // Internal memory clock
+	  .init_tmr ( sys_clk_stb[14] ), // > 100 μs (tP) after reset
+	  .rfsh_tmr ( sys_clk_stb[8] ),  // < 3.9 μs (tREFI/2)
 
 	  .sr_cke   ( sr_cke ),
 	  .sr_cs_n  ( sr_cs_n ),
@@ -581,15 +596,32 @@ module max80 (
 	  usb_rxd_break_rst <= usb_rxd_break & ~usb_rxd_break_q;
        end
 
-   assign reset_cmd =
-		     // Explicit reset command
-		     (sysreg[3] & cpu_mem_wstrb[0] & cpu_mem_wdata[0]) |
-		     // CPU hung
-		     cpu_trap |
-		     // BREAK received on USB tty
-		     usb_rxd_break_rst;
+   // Reset control. Note that CPU reset command 0 is intentionally ignored.
+   wire [3:0] cpu_reset_cmd =
+	      (sysreg[3] & cpu_mem_wstrb[0]) << cpu_mem_wdata[1:0];
+
+   //
+   // Soft system reset: FPGA not reloaded, PLLs not reset,
+   // USB and console are not reset
+   //
+   // Triggered by:
+   //  - CPU reset command 1
+   //  - CPU entering TRAP state (irrecoverable error)
+   //  - BREAK received on USB console
+   //
+   assign reset_cmd[1] = cpu_reset_cmd[1] | cpu_trap | usb_rxd_break_rst;
+
+   //
+   // Hard system reset: FPGA not reloaded, PLLs reset, all hw units reset
+   //
+   assign reset_cmd[2] = cpu_reset_cmd[2];
+
+   //
+   // FPGA reload reset
+   //
+   assign reset_cmd[3] = cpu_reset_cmd[3];
 
-  // LED indication from the CPU
+   // LED indication from the CPU
    reg [2:0]   led_q;
    always @(negedge rst_n or posedge sys_clk)
      if (~rst_n)
@@ -605,10 +637,14 @@ module max80 (
    wire        rtc_clk_s;
    rng #(.nclocks(2), .width(32)) rng
      (
-      .sys_clk ( sys_clk ),
-      .q       ( sysreg_rdata[4] ),
-      .clocks  ( { rtc_clk_s, abc_clk_s } ),
-      .rngio   ( rngio )
+      .rst_n     ( rst_n ),
+      .sys_clk   ( sys_clk ),
+      .read_stb  ( iodev_valid_random ),
+      .latch_stb ( sys_clk_stb[16] ),
+      .ready     ( iodev_irq_random ),
+      .q         ( iodev_rdata_random ),
+      .clocks    ( { rtc_clk_s, abc_clk_s } ),
+      .rngio     ( rngio )
       );
 
    //
@@ -685,7 +721,7 @@ module max80 (
 		  );
 
    assign tty_data_in      = tty_txd;
-   assign tty_rxd          = tty_data_out;
+   assign tty_rxd          = tty_dtr ? 1'bz : tty_data_out;
    assign tty_rts_in       = tty_rts;
    assign tty_cts          = tty_cts_out;
 

BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


+ 1 - 1
fpga/output_files/max80.pin

@@ -161,7 +161,7 @@ sr_we_n                      : F9        : output : 3.3-V LVTTL       :
 GND                          : F10       : gnd    :                   :         :           :                
 VCCINT                       : F11       : power  :                   : 1.2V    :           :                
 VCCA2                        : F12       : power  :                   : 2.5V    :           :                
-tty_rxd                      : F13       : output : 3.3-V LVTTL       :         : 6         : Y              
+tty_rxd                      : F13       : bidir  : 3.3-V LVTTL       :         : 6         : Y              
 sd_dat[2]                    : F14       : bidir  : 3.3-V LVTTL       :         : 6         : Y              
 sd_dat[0]                    : F15       : bidir  : 3.3-V LVTTL       :         : 6         : Y              
 sd_dat[3]                    : F16       : bidir  : 3.3-V LVTTL       :         : 6         : Y              

BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 115 - 19
fpga/rng.sv

@@ -8,39 +8,132 @@ module rng
   width = 32	// Output bus width
   )
    (
-    // System clock
-    input	       sys_clk,
+    // System reset and clock
+    input		   rst_n,
+    input		   sys_clk,
 
-     // Output data
-    output [width-1:0] q,
+    input		   read_stb,
+    input		   latch_stb,
+    output		   ready,
+    output reg [width-1:0] q,
 
      // Randomness inputs
-    input [nclocks-1:0] clocks,		// Random input synchronized to sys_clk
+    input [nclocks-1:0]    clocks, // Random input synchronized to sys_clk
     (* keep = 1 *) inout [2:0] rngio	// Unconnected pins with pullups
     );
 
-   wire		 int_clock;	// Internal oscillator clock
+   // Number of internal oscillators
+   localparam n_osc = 2;
+   wire [n_osc:1]	   osc;
+   wire [n_osc:1]	   osc_s;
+
+   //
+   // Latch control and enable logic
+   //
+   reg [n_osc:1]	   osc_q;
+   reg [n_osc:1]	   osc_e; // Edge detected
+
+   typedef enum logic [2:0] {
+	st_starting,		// Powering up oscillators
+	st_started,		// Oscillators running
+	st_strobed,		// Starting strobe received
+	st_latch,		// Ending strobe received, latch output data
+	st_ready,		// Output data available
+	st_stopped		// Data available, powered down due to idle
+   } state_t;
+   state_t state = st_starting;
+
+   // Number of ticks before shutting down
+   localparam shutdown_ticks_lg2 = 1;
+   reg [shutdown_ticks_lg2-1:0] shutdown_tmr;
+
+   assign ready   = (state == st_ready) | (state == st_stopped);
+   wire   running = (state != st_stopped);
+
+   wire [width-1:0] random_data;
+
+   always @(posedge sys_clk or negedge rst_n)
+     if (~rst_n)
+       begin
+	  state <= st_starting;
+	  osc_q <= 'b0;
+	  osc_e <= 'b0;
+       end
+     else
+       begin
+	  osc_q        <= ~osc_s;
+	  osc_e        <= 'b0;
+	  shutdown_tmr <= 'b0;
+
+	  case (state)
+	    st_starting: begin
+	       osc_e <= osc_e | (osc_s & osc_q);
+	       if (&osc_e)
+		 state <= st_started;
+	    end
+	    st_started: begin
+	       if (latch_stb)
+		 state <= st_strobed;
+	    end
+	    st_strobed: begin
+	       if (latch_stb)
+		 state <= st_latch;
+	    end
+	    st_latch: begin
+	       // Wait here if read_stb is still active from previous read
+	       if (~read_stb)
+		 begin
+		    q <= random_data;
+		    state <= st_ready;
+		 end
+	    end
+	    st_ready: begin
+	       shutdown_tmr <= shutdown_tmr + latch_stb;
+
+	       // If shutdown_tmr is nonzero, then we have had at least
+	       // one latch_stb already while waiting here, and so we
+	       // can use that data immediately.
+	       if (read_stb)
+		 state <= |shutdown_tmr ? st_latch :
+			  latch_stb ? st_strobed : st_started;
+	       else if (latch_stb & &shutdown_tmr)
+		 state <= st_stopped;
+	    end
+	    st_stopped: begin
+	       // Data is available, but haven't been consumed for
+	       // a long time, so we have shut down the ring oscillators.
+	       // When a read happens, start them up again.
+	       if (read_stb)
+		 state <= st_starting;
+	    end
+	  endcase // case (state)
+       end // else: !if(~rst_n)
+
+   //
+   // Internal oscillators: allow them to be stopped to save power
+   // if we have had multiple ticks with no data accesses.
+   //
 
    // Internal on-chip oscillator
    int_osc int_osc
      (
-      .clkout ( int_clock ),
-      .oscena ( 1'b1 )
+      .clkout ( osc[1] ),
+      .oscena ( running )
       );
 
    // Ring oscillator using the rngio pins
-   assign rngio[0] = ~rngio[2];
-   assign rngio[1] = ~rngio[0];
-   assign rngio[2] = ~rngio[1];
+   assign rngio[0] = ~rngio[2] & running;
+   assign rngio[1] = ~rngio[0] & running;
+   assign rngio[2] = ~rngio[1] & running;
 
-   wire [1:0] sclocks;		// Internally generated clocks
+   assign osc[2] = rngio[0];
 
-   synchronizer #(.width(2)) synchro
+   synchronizer #(.width(n_osc)) synchro
      (
       .rst_n ( 1'b1 ),
       .clk ( sys_clk ),
-      .d ( { rngio[0], int_clock } ),
-      .q ( sclocks )
+      .d ( osc ),
+      .q ( osc_s )
       );
 
    // LFSR randomness accumulator
@@ -53,11 +146,14 @@ module rng
 
    localparam lsfr_max = width > poly_width ? width-1 : poly_width-1;
 
-   reg [lsfr_max:0] lsfr;
+   wire			lsfr_input = ^{osc_s, clocks};
+
+   reg [lsfr_max:0]	lsfr;
 
    always @(posedge sys_clk)
-     lsfr <= {lsfr[lsfr_max-1:0], ^{sclocks, clocks}} ^
-	     {{(lsfr_max+1){lsfr[poly_width-1]}} & poly};
+     lsfr <= ({lsfr[lsfr_max-1:0], lsfr_input} ^
+	      {{(lsfr_max+1){lsfr[poly_width-1]}} & poly});
+
+   assign random_data = lsfr[width-1:0];
 
-   assign q = lsfr[width-1:0];
 endmodule // rng

+ 29 - 39
fpga/sdram.sv

@@ -277,28 +277,30 @@ module sdram
 )
 (
 	      // Reset and clock
-	      input		rst_n,
-	      input		clk,
+	      input	    rst_n,
+	      input	    clk,
+	      input	    init_tmr, // tRP timer
+	      input	    rfsh_tmr, // tREFI/2 timer
 
 	      // SDRAM hardware interface
-	      output		sr_cke, // SDRAM clock enable
-	      output		sr_cs_n, // SDRAM CS#
-	      output		sr_ras_n, // SDRAM RAS#
-	      output		sr_cas_n, // SDRAM CAS#
-	      output		sr_we_n, // SDRAM WE#
-	      output [1:0]	sr_dqm, // SDRAM DQM (per byte)
-	      output [1:0]	sr_ba, // SDRAM bank selects
-	      output [12:0]	sr_a, // SDRAM address bus
-	      inout [15:0]	sr_dq, // SDRAM data bus
-
-	      // Port 1
-              dram_bus.ustr     port1 [1:port1_count],
+	      output	    sr_cke, // SDRAM clock enable
+	      output	    sr_cs_n, // SDRAM CS#
+	      output	    sr_ras_n, // SDRAM RAS#
+	      output	    sr_cas_n, // SDRAM CAS#
+	      output	    sr_we_n, // SDRAM WE#
+	      output [1:0]  sr_dqm, // SDRAM DQM (per byte)
+	      output [1:0]  sr_ba, // SDRAM bank selects
+	      output [12:0] sr_a, // SDRAM address bus
+	      inout [15:0]  sr_dq, // SDRAM data bus
+
+			    // Port 1
+			    dram_bus.ustr port1 [1:port1_count],
 
 	      // Port 2
-	      input [24:1]	a2,
-	      input [15:0]	wd2,
-	      input [1:0]	wrq2,
-	      output reg	wacc2 // Data accepted, advance data & addr
+	      input [24:1]  a2,
+	      input [15:0]  wd2,
+	      input [1:0]   wrq2,
+	      output reg    wacc2 // Data accepted, advance data & addr
 	      );
 
 `include "functions.sv"		// For modelsim
@@ -357,13 +359,9 @@ module sdram
    reg			    dram_d_en; // Drive data out
    assign		    sr_dq = dram_d_en ? dram_d : 16'hzzzz;
 
-   // State machine and counters
-   reg [t_refi_lg2-2:0]	      rfsh_ctr;  // Refresh timer
-   wire			      rfsh_ctr_msb = rfsh_ctr[t_refi_lg2-2];
-   reg			      rfsh_ctr_last_msb;
-   wire			      rfsh_tick = rfsh_ctr_last_msb & ~rfsh_ctr_msb;
-   reg [t_p_lg2:t_refi_lg2-1] init_ctr;  // Reset to init counter
-   reg [1:0]		      rfsh_prio; // Refresh priority (0-3)
+   // Refresh timer logic
+   reg			    rfsh_tmr_q;
+   reg [1:0]		    rfsh_prio; // Refresh priority (0-3)
 
    // Port1 and refresh arbiter
    dram_bus                   p1 ();
@@ -398,26 +396,18 @@ module sdram
    always @(posedge clk or negedge rst_n)
      if (~rst_n)
        begin
-	  rfsh_ctr  <= 1'b0;
-	  rfsh_prio <= 2'b00;
-	  init_ctr  <= 1'b0;
+	  rfsh_tmr_q <= 1'b0;
+	  rfsh_prio  <= 2'b00;
        end
      else
        begin
-	  rfsh_ctr           <= rfsh_ctr + 1'b1;
-	  rfsh_ctr_last_msb  <= rfsh_ctr_msb;
+	  rfsh_tmr_q         <= rfsh_tmr; // Edge detect
 
 	  // Refresh priority management: saturating 2-bit counter
 	  if (is_rfsh)
 	    rfsh_prio <= 2'b00; // This is a refresh cycle
-	  else
-	    rfsh_prio <= rfsh_prio + (rfsh_tick & ~&rfsh_prio);
-
-	  // The refresh counter is also used as a prescaler
-	  // for the initialization counter.
-	  // Note that means init_ctr is two cycles "behind"
-	  // rfsh_ctr; this is totally fine.
-	  init_ctr <= init_ctr + rfsh_tick;
+	  else if (rfsh_tmr & ~rfsh_tmr_q)
+	    rfsh_prio <= rfsh_prio + (~&rfsh_prio);
        end // else: !if(~rst_n)
 
    reg  [5:0] op_ctr;		// Cycle into the current state
@@ -500,7 +490,7 @@ module sdram
 		 dram_a[10] <= 1'b1; // Precharge all banks
 
 		 dram_cmd  <= cmd_nop;
-		 if (init_ctr[t_p_lg2])
+		 if (init_tmr)
 		   begin
 		      dram_cmd <= cmd_pre;
 		      state    <= st_init_rfsh;

+ 1 - 0
iodevs.conf

@@ -36,4 +36,5 @@ our @iodevs = (
     { -name => 'esp',       -irq => 'l' },
     { -name => 'abc',       -irq => 'l' },
     { -name => 'abcmemmap', -xdev => 1 },
+    { -name => 'random',    -irq => 'l' }
 );

File diff suppressed because it is too large
+ 7143 - 7143
rv32/boot.mif


+ 4 - 4
rv32/io.h

@@ -34,11 +34,11 @@ enum leds {
     LED_ABCBUS
 };
 
-static inline void __attribute__((noreturn)) reset(void)
+static inline void __attribute__((noreturn)) reset(unsigned int type)
 {
     p_maskirq(~0, 0);		/* Block all interrupts */
     for (;;)
-	SYS_RESET = 1;
+	SYS_RESET = type;
 }
 
 extern const uint32_t time_zero;
@@ -84,8 +84,8 @@ static inline void wait_romcopy_done(void)
 /* Read a random 32-bit number */
 static inline uint32_t rdrand(void)
 {
-    udelay(256);		/* Allow the RNG to do its job */
-    return SYS_RANDOM;
+    waitfor(RANDOM_IRQ);
+    return RANDOM_DATA;
 }
 
 #endif /* IO_H */

+ 5 - 1
rv32/ioregs.h

@@ -61,7 +61,9 @@
 #define SYS_BOARDMAJOR		IODEVRB3(SYS,1)
 #define SYS_LED			IODEVL(SYS,2)
 #define SYS_RESET		IODEVL(SYS,3)
-#define SYS_RANDOM		IODEVRL(SYS,4)
+#define SYS_RESET_SOFT		1
+#define SYS_RESET_HARD		2
+#define SYS_RESET_RECONFIG	3
 
 #define ROMCOPY_RAMADDR		IODEVL(ROMCOPY,0)
 #define ROMCOPY_ROMCMD		IODEVL(ROMCOPY,1)
@@ -157,4 +159,6 @@
 #define ABCMEMMAP_CLR0WEMP	0x200
 #define ABCMEMMAP_CLR0REMP	0x100
 
+#define RANDOM_DATA		IODEVRL(RANDOM,0)
+
 #endif /* IODEV_H */

+ 6 - 2
rv32/system.c

@@ -12,8 +12,12 @@ IRQHANDLER(sysclock)
 
     count++;
     timer_irq_count = count;
-    if (!(count & ((1U << TIMER_SHIFT)-1)))
+    if (!(count & ((1U << TIMER_SHIFT)-1))) {
+	register size_t oldpc asm("s10");
 	CON_DATA = '.';		/* Console heartbeat */
+	con_printf("\n<%08x>\r", oldpc);
+	con_flush();
+    }
 }
 
 static no_return killed(const char *how, size_t pc)
@@ -22,7 +26,7 @@ static no_return killed(const char *how, size_t pc)
 
     con_flush();
     udelay(5000000);
-    reset();
+    reset(SYS_RESET_SOFT);
 }
 
 IRQHANDLER(buserr)

+ 1 - 1
rv32/test/main.c

@@ -261,5 +261,5 @@ void main(void)
     con_puts("*** Doing reset ***\n");
     con_flush();
 
-    reset();
+    reset(SYS_RESET_SOFT);
 }

Some files were not shown because too many files changed in this diff