aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-09-16 14:42:32 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-09-16 14:42:32 +0200
commit780f056e61323a41abcaf0dd53a44f99bcac197c (patch)
tree29aed814e2809e9ba258d4f8465a964180803c82
parent196582e9c74cbdc02e66189774ed22f2ca632691 (diff)
downloadAGH-engineering-thesis-780f056e61323a41abcaf0dd53a44f99bcac197c.tar.gz
AGH-engineering-thesis-780f056e61323a41abcaf0dd53a44f99bcac197c.zip
add function calling (call, ret and drop instructions) with a testbench + bugfix in stack machine
-rw-r--r--design/stack_machine.v45
-rwxr-xr-xtclasm.tcl24
l---------tests/stack_machine_function_call/Makefile1
-rw-r--r--tests/stack_machine_function_call/instructions.s.tcl88
l---------tests/stack_machine_function_call/test.v1
-rw-r--r--tests/stack_machine_function_call/words_to_verify.mem3
6 files changed, 155 insertions, 7 deletions
diff --git a/design/stack_machine.v b/design/stack_machine.v
index 54eae5e..91e808b 100644
--- a/design/stack_machine.v
+++ b/design/stack_machine.v
@@ -206,10 +206,18 @@ module stack_machine_new
assign instr_tee = !set_im && !use_im && stack_grows &&
instruction[11:0] == 12'd0;
+ wire instr_get_frame;
+ assign instr_get_frame = !set_im && !use_im && stack_grows &&
+ instruction[11:0] == 12'd1;
+
wire instr_const;
assign instr_const = use_im && stack_grows &&
instruction[11:7] == 5'd0;
+ wire instr_call;
+ assign instr_call = use_im && stack_grows &&
+ instruction[11:7] == 5'd1;
+
/* Instructions, that shrink stack */
wire instr_add;
assign instr_add = !set_im && !use_im && stack_shrinks_by_1 &&
@@ -227,6 +235,14 @@ module stack_machine_new
assign instr_mul = !set_im && !use_im && stack_shrinks_by_1 &&
instruction[11:0] == 12'd3;
+ wire instr_drop;
+ assign instr_drop = !set_im && !use_im && stack_shrinks_by_1 &&
+ instruction[11:0] == 12'd4;
+
+ wire instr_ret;
+ assign instr_ret = !set_im && !use_im && stack_shrinks_by_1 &&
+ instruction[11:0] == 12'b000010000000;
+
wire instr_cond_jump;
assign instr_cond_jump = use_im && stack_shrinks_by_1 &&
instruction[11:7] == 5'd1;
@@ -366,8 +382,6 @@ module stack_machine_new
I_CYC_O <= 1;
D_CYC_O <= 0;
- D_STB_O <= 0;
- D_WE_O <= 0;
end
if (first_execution_tick) begin
@@ -434,8 +448,9 @@ module stack_machine_new
<= {stack_transfer_unrequested[0], 1'b0};
end
- if (load_store_unrequested ||
- stack_transfer_unrequested[0]) begin
+ if (stack_transfer_unrequested[0] ||
+ (load_store_unrequested &&
+ stack_transfer_unrequested[1])) begin
if (stack_shrinks) begin
`SET_SP(sp + 4);
D_ADR_O <= sp;
@@ -443,7 +458,7 @@ module stack_machine_new
D_SEL_O <= 4'b1111;
D_STB_O <= 1;
D_WE_O <= 0;
- end else if (stack_grows) begin
+ end else /* if (stack_grows) */ begin
`SET_SP(sp - 4);
D_ADR_O <= sp - 4;
D_DAT_O <= stack_put_value;
@@ -451,13 +466,13 @@ module stack_machine_new
D_STB_O <= 1;
D_WE_O <= 1;
end
- end else begin // if (load_store_unrequested ||...
+ end else begin // if (stack_transfer_unrequested[0] ||...
D_ADR_O <= 21'bx;
D_DAT_O <= 32'bx;
D_SEL_O <= 4'bx;
D_STB_O <= 0;
D_WE_O <= 0;
- end // else: !if(load_store_unrequested ||...
+ end // else: !if(stack_transfer_unrequested[0] ||...
end // if (data_request_happens)
if (data_command_completes) begin
@@ -521,9 +536,17 @@ module stack_machine_new
if (instr_tee)
r1 <= r1;
+ if (instr_get_frame && first_execution_tick)
+ r1 <= sp;
+
if (instr_const && first_execution_tick)
r1 <= im_effective;
+ if (instr_call && first_execution_tick) begin
+ r1 <= pc;
+ `SET_PC(im_effective);
+ end
+
/* Instructions, that shrink stack */
if (instr_add && arithmetic_uncompleted)
r1 <= r0 + r1;
@@ -537,12 +560,20 @@ module stack_machine_new
if (instr_mul && arithmetic_uncompleted)
r1 <= r0 * r1;
+ if (instr_drop && arithmetic_uncompleted)
+ r1 <= r0;
+
if (instr_cond_jump && arithmetic_uncompleted) begin
r1 <= r0;
if (r1)
`SET_PC(im_effective);
end
+
+ if (instr_ret && arithmetic_uncompleted) begin
+ r1 <= r0;
+ `SET_PC(r1);
+ end
end // case: STEP_EXECUTING
endcase // case (step)
end // else: !if(RST_I)
diff --git a/tclasm.tcl b/tclasm.tcl
index f80863d..0dec4b0 100755
--- a/tclasm.tcl
+++ b/tclasm.tcl
@@ -273,6 +273,11 @@ proc tee {} {
}
+proc get_frame {} {
+ puts 0001000000000001
+}
+
+
proc _const {value_part} {
puts 010100000[__to_binary $value_part 7]
}
@@ -282,6 +287,15 @@ proc const {value} {
}
+proc _call {address_part} {
+ puts 010100001[__to_binary $address_part 7]
+}
+
+proc call {address} {
+ _with_im _call $address
+}
+
+
# Instructions, that shrink stack
proc add {} {
@@ -304,6 +318,16 @@ proc mul {} {
}
+proc drop {} {
+ puts 0011000000000100
+}
+
+
+proc ret {} {
+ puts 0011000010000000
+}
+
+
proc _cond_jump {address_part} {
puts 011100001[__to_binary $address_part 7]
}
diff --git a/tests/stack_machine_function_call/Makefile b/tests/stack_machine_function_call/Makefile
new file mode 120000
index 0000000..2c3c770
--- /dev/null
+++ b/tests/stack_machine_function_call/Makefile
@@ -0,0 +1 @@
+../stack_machine_store/Makefile \ No newline at end of file
diff --git a/tests/stack_machine_function_call/instructions.s.tcl b/tests/stack_machine_function_call/instructions.s.tcl
new file mode 100644
index 0000000..450b669
--- /dev/null
+++ b/tests/stack_machine_function_call/instructions.s.tcl
@@ -0,0 +1,88 @@
+### call a simple function, that sums its 2 arguments
+
+## store sth at h1000 to later check if calee restored it properly
+# 1 16-bit instruction
+const h23
+# 2 16-bit instructions
+store h1000
+
+# function arguments - each loaded with 1 16-bit instruction
+const h32
+const h14
+# also 1 16-bit instruction
+call 18
+
+## this executes after return - store the computed difference at h400
+# this takes 2 16-bit instructions
+store h400
+# and this takes 1 16-bit instruction
+halt
+
+# address 18 here
+
+## function frame will look like this:
+## *****higher addresses*****
+## argument1
+## argument2
+## ...
+## return address
+## local1
+## local2
+## ...
+## previous frame address
+## *****lower addresses*****
+
+## push the arguments out of r0 and r1 to memory (+ claim space for
+## backed stack frame address and backed return address);
+## if we had n local variables, we'd repeat that n more times
+const 0
+const 0
+const 0
+
+## with this we get the address to reference our locals from into r1
+get_frame
+tee
+
+## we get our previous frame and back it up as first local
+load h1000
+store+ h0
+
+## we now store our new function frame
+store h1000
+
+## here the actual function body starts
+
+## fetch the first argument
+load h1000
+load+ hC
+
+## fetch the second one
+load h1000
+load+ h8
+
+sub
+
+## function exit - store the result at the the top of current frame
+load h1000
+swap
+store+ hC
+
+## put the return address just below result
+load h1000
+tee
+tee
+load+ h4
+store+ h8
+
+## restore old frame
+load+ 0
+store h1000
+
+## discard current frame
+drop
+drop
+drop
+drop
+
+## return
+ret
diff --git a/tests/stack_machine_function_call/test.v b/tests/stack_machine_function_call/test.v
new file mode 120000
index 0000000..f5b6a59
--- /dev/null
+++ b/tests/stack_machine_function_call/test.v
@@ -0,0 +1 @@
+../stack_machine_store/test.v \ No newline at end of file
diff --git a/tests/stack_machine_function_call/words_to_verify.mem b/tests/stack_machine_function_call/words_to_verify.mem
new file mode 100644
index 0000000..8048d6f
--- /dev/null
+++ b/tests/stack_machine_function_call/words_to_verify.mem
@@ -0,0 +1,3 @@
+// address value
+ 1000 23
+ 400 1E