From f747a526b97b29a0479c62c4ecea285f1f5f2fde Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 13 Mar 2022 16:51:03 -0700 Subject: Change command parser to support bulk download script. --- download.tcl | 28 +++++++++++++ hdl/command_parser.sv | 113 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 23 deletions(-) create mode 100755 download.tcl diff --git a/download.tcl b/download.tcl new file mode 100755 index 0000000..2e64865 --- /dev/null +++ b/download.tcl @@ -0,0 +1,28 @@ +#!/usr/bin/env expect + +set core 0 + +if {$::argc > 0} { + set core [lindex $::argv 0] +} + +spawn nios2-terminal --instance 0 +expect -ex "connected to hardware target" + +send "@[format %x [expr $core * 32768]]\n" + +while {[gets stdin line] >= 0} { + send "$line\n" + expect -ex "$line" +} + +# It's likely we ended with a very large zero-memory operation. We want to see +# two command bytes echoed back to us in order to guarantee that the zero +# operation has completely flushed to memory. +send "?" +expect -ex "?" +send "?" +expect -ex "?" + +send "\004" +expect -ex "exiting due to ^D on remote" diff --git a/hdl/command_parser.sv b/hdl/command_parser.sv index 5c49db9..cf4fe65 100644 --- a/hdl/command_parser.sv +++ b/hdl/command_parser.sv @@ -21,29 +21,32 @@ module command_parser bit input_byte_valid; uart_byte_t input_byte; + bit [`RAM_ADDRESS_BITS:0] zero_count; + (* syn_encoding = "one-hot" *) enum int unsigned - { READ_ADDRESS_OR_COMMAND + { READ_COMMAND + , READ_ADDRESS , READ_DATA + , READ_ZERO_COUNT + , ZERO_MEMORY } state; always @(posedge clock) begin if (reset) begin uart_ready = 0; command_valid = 0; + for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) + command_data.mask[i] = ~0; + command_data.tag = TAG; input_byte_valid = 0; input_byte = 0; + zero_count = 0; state = state.first; end else begin if (echo_ready) echo_valid = 0; if (command_ready && command_valid) begin command_valid = 0; - command_data.address = 0; - command_data.write = 0; - for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) begin - command_data.data[i] = 0; - command_data.mask[i] = ~0; - end - command_data.tag = TAG; + ++command_data.address; end if (uart_ready && uart_valid) begin echo_valid = 1; @@ -52,10 +55,42 @@ module command_parser input_byte = uart_data; end - if (!command_valid && input_byte_valid) begin + if (!command_valid) begin case (state) - READ_ADDRESS_OR_COMMAND: begin + READ_COMMAND: if (input_byte_valid) begin + case (input_byte) + + "@": begin + command_data.address = 0; + state = READ_ADDRESS; + end + + "?": begin + command_valid = 1; + command_data.write = 0; + end + + "=": begin + command_data.write = 1; + for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) + command_data.data[i] = 0; + state = READ_DATA; + end + + "!": begin + command_data.write = 1; + for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) + command_data.data[i] = 0; + zero_count = 0; + state = READ_ZERO_COUNT; + end + + endcase + input_byte_valid = 0; + end + + READ_ADDRESS: if (input_byte_valid) begin if (input_byte >= "0" && input_byte <= "9") begin command_data.address = command_data.address << 4; command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "0"; @@ -65,22 +100,13 @@ module command_parser end else if (input_byte >= "A" && input_byte <= "F") begin command_data.address = command_data.address << 4; command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "A" + 10; - end else if (input_byte == "?") begin - command_valid = 1; - command_data.write = 0; - command_data.data = 0; - end else if (input_byte == "=") begin - command_data.write = 1; - command_data.data = 0; - state = READ_DATA; end else begin - command_data.address = 0; - command_data.write = 0; - command_data.data = 0; + state = state.first; end + input_byte_valid = 0; end - READ_DATA: begin + READ_DATA: if (input_byte_valid) begin automatic bit [$bits(command_data.data)-1:0] flat_data = command_data.data; flat_data = flat_data << 4; if (input_byte >= "0" && input_byte <= "9") begin @@ -96,10 +122,51 @@ module command_parser command_valid = 1; state = state.first; end + input_byte_valid = 0; + end + + READ_ZERO_COUNT: if (input_byte_valid) begin + if (input_byte >= "0" && input_byte <= "9") begin + zero_count = zero_count << 4; + zero_count[3:0] = input_byte - "0"; + end else if (input_byte >= "a" && input_byte <= "f") begin + zero_count = zero_count << 4; + zero_count[3:0] = input_byte - "a" + 10; + end else if (input_byte >= "A" && input_byte <= "F") begin + zero_count = zero_count << 4; + zero_count[3:0] = input_byte - "A" + 10; + end else begin + state = ZERO_MEMORY; + end + input_byte_valid = 0; + end + +`ifdef SLOW_ZEROING + ZERO_MEMORY: if (!echo_valid) begin + if (zero_count == 0) begin + echo_valid = 1; + echo_data = "\n"; + state = state.first; + end else begin + echo_valid = 1; + echo_data = "."; + command_valid = 1; + --zero_count; + end + end +`else + ZERO_MEMORY: begin + if (zero_count == 0) begin + state = state.first; + end else begin + command_valid = 1; + if (--zero_count == 0) + state = state.first; + end end +`endif endcase - input_byte_valid = 0; end uart_ready = !echo_valid && !input_byte_valid; -- cgit v1.2.3