aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-09-14 17:21:55 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-09-14 17:21:55 +0200
commit9adc0e5bad01f34f6cf6b6d53019ead30ba49945 (patch)
tree251934b5b979af9c23153e795fd8e824b1275660
parent76fad4a36b498db9e96e77460cb1f5e721c0f3e9 (diff)
downloadAGH-engineering-thesis-9adc0e5bad01f34f6cf6b6d53019ead30ba49945.tar.gz
AGH-engineering-thesis-9adc0e5bad01f34f6cf6b6d53019ead30ba49945.zip
add ability to make non-aligned loads/stores and loads/stores of 1 or 2 bytes together with test bench
-rw-r--r--design/stack_machine.v37
-rwxr-xr-xtclasm.tcl108
l---------tests/stack_machine_unaligned/Makefile1
-rw-r--r--tests/stack_machine_unaligned/instructions.s.tcl125
l---------tests/stack_machine_unaligned/test.v1
-rw-r--r--tests/stack_machine_unaligned/words_to_verify.mem19
6 files changed, 279 insertions, 12 deletions
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