diff --git a/src/frontend/sras.sv b/src/frontend/sras.sv index 053f13ff62b6de2047a110c92d77bacdb1bc7ee9..4f1aea3ad10cdba17415af8cfebd14ac040abc37 100644 --- a/src/frontend/sras.sv +++ b/src/frontend/sras.sv @@ -16,7 +16,8 @@ // segmented return address stack module sras #( parameter int unsigned DEPTH = 2, - parameter int unsigned SpecDepth = 16 + parameter int unsigned SpecDepth = 16, + parameter int unsigned SZ_OVF = 16 )( input logic clk_i, input logic rst_ni, @@ -34,6 +35,7 @@ module sras #( logic [$clog2(SpecDepth)-1:0] ptr_backup_d, ptr_backup_q; logic [SpecDepth-1:0][$clog2(DEPTH)-1:0] tos_d, tos_q; ariane_pkg::ras_t [SpecDepth-1:0][DEPTH-1:0] stack_d, stack_q; + logic [SpecDepth-1:0][SZ_OVF-1:0] ovf_counter_d, ovf_counter_q; assign ptr_spec_d = (bad_spec_i) ? ptr_backup_q : (begin_spec_i) ? ptr_spec_q + 1'b1 : ptr_spec_q; assign ptr_backup_d = (valid_spec_i) ? ptr_backup_q + 1'b1 : ptr_backup_q; @@ -48,26 +50,51 @@ module sras #( assign pp_plus_one = tos_q[ptr_spec_q] + 1'b1; assign prev_minus_one = previous_tos - 1'b1; + logic overflow; + assign overflow = |ovf_counter_q[ptr_spec_q]; + always_comb begin tos_d = tos_q; + ovf_counter_d = ovf_counter_q; if (flush_i) begin tos_d = '0; - end else if (push_i && !pop_i) begin - tos_d[ptr_spec_d] = prev_plus_one; - tos_d[ptr_spec_q] = pp_plus_one; - end else if (!push_i && pop_i) begin - tos_d[ptr_spec_d] = prev_minus_one; - end else if (!bad_spec_i && begin_spec_i) begin - tos_d[ptr_spec_d] = tos_q[ptr_spec_q]; + ovf_counter_d = '0; + end else if (!bad_spec_i) begin + if (push_i && !pop_i) begin + if (overflow) begin + ovf_counter_d[ptr_spec_d] = ovf_counter_q[ptr_spec_q] + 1'b1; + end else begin + if (prev_plus_one == '0 || pp_plus_one == '0) begin + ovf_counter_d[ptr_spec_d] = ovf_counter_q[ptr_spec_q] + 1'b1; + ovf_counter_d[ptr_spec_q] = ovf_counter_q[ptr_spec_q] + 1'b1; + end else begin + tos_d[ptr_spec_d] = prev_plus_one; + tos_d[ptr_spec_q] = pp_plus_one; + end + end + end else if (!push_i && pop_i) begin + if (ovf_counter_q[ptr_spec_q] != '0) begin + ovf_counter_d[ptr_spec_d] = ovf_counter_q[ptr_spec_q] - 1'b1; + end else begin + tos_d[ptr_spec_d] = prev_minus_one; + end + end else if (!bad_spec_i && begin_spec_i) begin + tos_d[ptr_spec_d] = tos_q[ptr_spec_q]; + ovf_counter_d[ptr_spec_d] = ovf_counter_q[ptr_spec_q]; + end end end + logic can_pop, can_push; + assign can_pop = pop_i && ovf_counter_d[ptr_spec_q][SZ_OVF-1:1] == '0 && !bad_spec_i; + assign can_push = push_i && ovf_counter_d[ptr_spec_q] == '0 && !bad_spec_i; + assign data_o = stack_q[previous_tos_addr][previous_tos]; ariane_pkg::ras_t to_push; - assign to_push.ra = (push_i) ? data_i : 0; - assign to_push.valid = push_i; + assign to_push.ra = (can_push) ? data_i : 0; + assign to_push.valid = can_push; ariane_pkg::ras_t [DEPTH-1:0] new_stack, prev_stack; @@ -78,11 +105,11 @@ module sras #( new_stack = stack_q[ptr_spec_q]; end - if (pop_i) begin + if (can_pop) begin new_stack[previous_tos] = to_push; end - if (push_i) begin + if (can_push) begin new_stack[prev_plus_one] = to_push; end end @@ -90,7 +117,7 @@ module sras #( always_comb begin prev_stack = stack_q[ptr_spec_q]; - if (push_i) begin + if (can_push) begin prev_stack[pp_plus_one] = to_push; end end @@ -104,15 +131,17 @@ module sras #( always_ff @(posedge clk_i or negedge rst_ni) begin if (~rst_ni) begin - stack_q <= '0; - ptr_spec_q <= '0; - ptr_backup_q <= '0; - tos_q <= '0; + stack_q <= '0; + ptr_spec_q <= '0; + ptr_backup_q <= '0; + tos_q <= '0; + ovf_counter_q <= '0; end else begin - stack_q <= stack_d; - ptr_spec_q <= ptr_spec_d; - ptr_backup_q <= ptr_backup_d; - tos_q <= tos_d; + stack_q <= stack_d; + ptr_spec_q <= ptr_spec_d; + ptr_backup_q <= ptr_backup_d; + tos_q <= tos_d; + ovf_counter_q <= ovf_counter_d; end end