From 9adc0e5bad01f34f6cf6b6d53019ead30ba49945 Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Mon, 14 Sep 2020 17:21:55 +0200 Subject: add ability to make non-aligned loads/stores and loads/stores of 1 or 2 bytes together with test bench --- design/stack_machine.v | 37 ++++--- tclasm.tcl | 108 +++++++++++++++++++ tests/stack_machine_unaligned/Makefile | 1 + tests/stack_machine_unaligned/instructions.s.tcl | 125 ++++++++++++++++++++++ tests/stack_machine_unaligned/test.v | 1 + tests/stack_machine_unaligned/words_to_verify.mem | 19 ++++ 6 files changed, 279 insertions(+), 12 deletions(-) create mode 120000 tests/stack_machine_unaligned/Makefile create mode 100644 tests/stack_machine_unaligned/instructions.s.tcl create mode 120000 tests/stack_machine_unaligned/test.v create mode 100644 tests/stack_machine_unaligned/words_to_verify.mem diff --git a/design/stack_machine.v b/design/stack_machine.v index b6c2706..54eae5e 100644 --- a/design/stack_machine.v +++ b/design/stack_machine.v @@ -22,7 +22,7 @@ module stack_machine_new output reg [20:0] D_ADR_O, input wire [31:0] D_DAT_I, output reg [31:0] D_DAT_O, - output reg [3:0] D_SEL_O, /* We'll start using it soon */ + output reg [3:0] D_SEL_O, output reg D_STB_O, output reg D_CYC_O, output reg D_WE_O, @@ -37,8 +37,6 @@ module stack_machine_new if (CLK_I || !CLK_I) begin /* avoiding "found no sensitivities" warning */ I_DAT_O = 16'bx; I_WE_O = 1'b0; - - D_SEL_O = 4'hF; /* This one is temporary */ end end @@ -161,16 +159,25 @@ module stack_machine_new wire word_operation; wire dword_operation; wire qword_operation; /* We won't implement these in hw */ + wire [3:0] instruction_select_mask; assign byte_operation = instruction[9:8] == 2'b00; assign word_operation = instruction[9:8] == 2'b01; assign dword_operation = instruction[9:8] == 2'b10; assign qword_operation = instruction[9:8] == 2'b11; + assign instruction_select_mask = byte_operation ? 4'b0001 : + word_operation ? 4'b0011 : + 4'b1111; /* Flag mainly meant for load instructions, but not exclusively */ wire sign_extend; assign sign_extend = instruction[7]; + wire loaded_value_sign; + assign loaded_value_sign = !sign_extend ? 0 : + byte_operation ? D_DAT_I[7] : + word_operation ? D_DAT_I[15] : 1'bx; + /* Instructions other than load and store go here */ /* Instructions, that do not change stack size */ @@ -382,14 +389,14 @@ module stack_machine_new if (load) begin D_ADR_O <= addr_to_use; D_DAT_O <= 32'bx; - /* D_SEL_O <= ????; */ /* We'll later set this one */ + D_SEL_O <= instruction_select_mask; D_STB_O <= 1; D_CYC_O <= 1; D_WE_O <= 0; end else if (store) begin D_ADR_O <= addr_to_use; D_DAT_O <= r1; - /* D_SEL_O <= ????; */ /* We'll later set this one */ + D_SEL_O <= instruction_select_mask; D_STB_O <= 1; D_CYC_O <= 1; D_WE_O <= 1; @@ -397,7 +404,7 @@ module stack_machine_new `SET_SP(sp + 4); D_ADR_O <= sp; D_DAT_O <= 32'bx; - /* D_SEL_O <= 4'hF; */ + D_SEL_O <= 4'b1111; D_STB_O <= 1; D_CYC_O <= 1; D_WE_O <= 0; @@ -405,7 +412,7 @@ module stack_machine_new `SET_SP(sp - 4); D_ADR_O <= sp - 4; D_DAT_O <= r0; - /* D_SEL_O <= 4'hF; */ + D_SEL_O <= 4'b1111; D_STB_O <= 1; D_CYC_O <= 1; D_WE_O <= 1; @@ -433,21 +440,21 @@ module stack_machine_new `SET_SP(sp + 4); D_ADR_O <= sp; D_DAT_O <= 32'bx; - /* D_SEL_O <= 4'hF; */ + D_SEL_O <= 4'b1111; D_STB_O <= 1; D_WE_O <= 0; end else if (stack_grows) begin `SET_SP(sp - 4); D_ADR_O <= sp - 4; D_DAT_O <= stack_put_value; - /* D_SEL_O <= 4'hF; */ + D_SEL_O <= 4'b1111; D_STB_O <= 1; D_WE_O <= 1; end end else begin // if (load_store_unrequested ||... D_ADR_O <= 21'bx; D_DAT_O <= 32'bx; - /* D_SEL_O <= 4'bx; */ + D_SEL_O <= 4'bx; D_STB_O <= 0; D_WE_O <= 0; end // else: !if(load_store_unrequested ||... @@ -475,8 +482,14 @@ module stack_machine_new if (stack_grows && first_execution_tick) r0 <= r1; - if (load && load_store_uncompleted) - r1 <= D_DAT_I; + if (load && load_store_uncompleted) begin + if (byte_operation) + r1 <= {{24{loaded_value_sign}}, D_DAT_I[7:0]}; + else if (word_operation) + r1 <= {{16{loaded_value_sign}}, D_DAT_I[15:0]}; + else + r1 <= D_DAT_I; + end if (!first_execution_tick && use_im) im <= 32'bx; diff --git a/tclasm.tcl b/tclasm.tcl index 5af74c4..f80863d 100755 --- a/tclasm.tcl +++ b/tclasm.tcl @@ -105,6 +105,42 @@ proc store+ {address} { } +proc _storeb {address_part} { + puts 011111000[__to_binary $address_part 7] +} + +proc storeb {address} { + _with_im _storeb $address +} + + +proc _storeb+ {address_part} { + puts 011011000[__to_binary $address_part 7] +} + +proc storeb+ {address} { + _with_im _storeb+ $address +} + + +proc _storew {address_part} { + puts 011111010[__to_binary $address_part 7] +} + +proc storew {address} { + _with_im _storew $address +} + + +proc _storew+ {address_part} { + puts 011011010[__to_binary $address_part 7] +} + +proc storew+ {address} { + _with_im _storew+ $address +} + + proc _load {address_part} { puts 010111100[__to_binary $address_part 7] } @@ -123,6 +159,78 @@ proc load+ {address} { } +proc _loadbzx {address_part} { + puts 010111000[__to_binary $address_part 7] +} + +proc loadbzx {address} { + _with_im _loadbzx $address +} + + +proc _loadbzx+ {address_part} { + puts 010011000[__to_binary $address_part 7] +} + +proc loadbzx+ {address} { + _with_im _loadbzx+ $address +} + + +proc _loadbsx {address_part} { + puts 010111001[__to_binary $address_part 7] +} + +proc loadbsx {address} { + _with_im _loadbsx $address +} + + +proc _loadbsx+ {address_part} { + puts 010011001[__to_binary $address_part 7] +} + +proc loadbsx+ {address} { + _with_im _loadbsx+ $address +} + + +proc _loadwzx {address_part} { + puts 010111010[__to_binary $address_part 7] +} + +proc loadwzx {address} { + _with_im _loadwzx $address +} + + +proc _loadwzx+ {address_part} { + puts 010011010[__to_binary $address_part 7] +} + +proc loadwzx+ {address} { + _with_im _loadwzx+ $address +} + + +proc _loadwsx {address_part} { + puts 010111011[__to_binary $address_part 7] +} + +proc loadwsx {address} { + _with_im _loadwsx $address +} + + +proc _loadwsx+ {address_part} { + puts 010011011[__to_binary $address_part 7] +} + +proc loadwsx+ {address} { + _with_im _loadwsx+ $address +} + + # Instructions, that do not change stack size proc halt {} { diff --git a/tests/stack_machine_unaligned/Makefile b/tests/stack_machine_unaligned/Makefile new file mode 120000 index 0000000..2c3c770 --- /dev/null +++ b/tests/stack_machine_unaligned/Makefile @@ -0,0 +1 @@ +../stack_machine_store/Makefile \ No newline at end of file diff --git a/tests/stack_machine_unaligned/instructions.s.tcl b/tests/stack_machine_unaligned/instructions.s.tcl new file mode 100644 index 0000000..9f2a0a8 --- /dev/null +++ b/tests/stack_machine_unaligned/instructions.s.tcl @@ -0,0 +1,125 @@ +### make memory reads and writes of bytes, words and dwords at both +### aligned and unaligned locations + +## set up stack +set_sp 0 + +## store value h9A785634 at h100 writing 1 byte at a time + +# write first 2 bytes using storeb +const h34 +storeb h000100 + +# try putting some garbage in higher 3 bytes of our constant - it should +# not get written anyway +const h9ABA9E56 +storeb h000101 + +# write another 2 bytes using storeb+ +const 2 +const h78 +storeb+ h100 + +const 3 +const h9A +storeb+ h100 + + +## test single-byte loads + +# sign-extend read value h9A (as hFFFFFF9A) and store it at h104 +loadbsx h00103 +store h00104 + +# sign-extend read value h78 (as h00000078) and store it at h108 +const 2 +loadbsx+ h00100 +store h00108 + +# zero-extend read value h9A (as h0000009A) and store it at h10C +const 3 +loadbzx+ h00100 +store h0010C + +# zero-extend read value h78 (as h00000078) and store it at h110 +loadbzx h00102 +store h00110 + + +## store values hD4C32B1A and h8877FFEE at h200 and h204 +## writing 2 bytes at a time + +# make aligned writes at h200 and h206 +# only byte 1A matters - higher one will be overwritten later +const h481A +storew h00200 + +# only byte 88 matters - lower one will be overwritten later +const 6 +const h8805 +storew+ h00200 + +# make unaligned writes at h203, h201 and h205 +const hEED4 +storew h00203 + +const 1 +const hC32B +storew+ h00200 + +# only bytes 77FF matter - higher ones won't be written anyway +const h71F577FF +storew h00205 + + +## test 2-word loads + +# sign-extend read value h2B1A (as h00002B1A) and store it at h208 +const 0 +loadwsx+ h00200 +store h00208 + +# sign-extend read value hC32B (as hFFFFC32B) and store it at h20C +loadwsx h00201 +store h0020C + +# zero-extend read value hD4C3 (as h0000D4C3) and store it at h210 +loadwzx h00202 +store h00210 + +# zero-extend read value h77FF (as h000077FF) and store it at h214 +const 5 +loadwzx+ h00200 +store h00214 + + +## test unaligned 4-byte memory writes + +# write values h92837400, hBECD0001 and h000044AF at h300, h304 and h308 +const 0 +const 0 +const 0 +storeb h300 +storeb h305 +storew h30A + +const h01928374 +store h301 + +const 6 +const h44AFBECD +store+ h300 + + +## test unaligned 4-byte memory reads + +# read value hCD000192 and write it at h30C +load h303 +store h30C + +# read value h0044AFBE and write it at h310 +const 7 +load+ h300 +store h310 + +halt diff --git a/tests/stack_machine_unaligned/test.v b/tests/stack_machine_unaligned/test.v new file mode 120000 index 0000000..f5b6a59 --- /dev/null +++ b/tests/stack_machine_unaligned/test.v @@ -0,0 +1 @@ +../stack_machine_store/test.v \ No newline at end of file diff --git a/tests/stack_machine_unaligned/words_to_verify.mem b/tests/stack_machine_unaligned/words_to_verify.mem new file mode 100644 index 0000000..a426aa7 --- /dev/null +++ b/tests/stack_machine_unaligned/words_to_verify.mem @@ -0,0 +1,19 @@ +// address value + 100 9A785634 + 104 FFFFFF9A + 108 00000078 + 10C 0000009A + 110 00000078 + + 200 D4C32B1A + 204 8877FFEE + 208 00002B1A + 20C FFFFC32B + 210 0000D4C3 + 214 000077FF + + 300 92837400 + 304 BECD0001 + 308 000044AF + 30C CD000192 + 310 0044AFBE -- cgit v1.2.3