Skip to content
Snippets Groups Projects
Commit 4e6cafac authored by Alban Gruin's avatar Alban Gruin
Browse files

frontend: add a segmented RAS, based on the original RAS


Signed-off-by: default avatarAlban Gruin <alban.gruin@irit.fr>
parent 1f23dc8e
No related branches found
No related tags found
No related merge requests found
//Copyright (C) 2018 to present,
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 08.02.2018
// Migrated: Luis Vitorio Cargnini, IEEE
// Date: 09.06.2018
// segmented return address stack
module sras #(
parameter int unsigned DEPTH = 2,
parameter int unsigned SpecDepth = 16
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic push_i,
input logic pop_i,
input logic [riscv::VLEN-1:0] data_i,
input logic begin_spec_i,
input logic valid_spec_i,
input logic bad_spec_i,
output ariane_pkg::ras_t data_o
);
logic [$clog2(SpecDepth)-1:0] ptr_spec_d, ptr_spec_q;
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;
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;
always_comb begin
stack_d = stack_q;
tos_d = tos_q;
if (!bad_spec_i && begin_spec_i) begin
stack_d[ptr_spec_d] = stack_q[ptr_spec_q];
tos_d[ptr_spec_d] = tos_q[ptr_spec_q];
end
data_o = stack_d[ptr_spec_d][tos_d[ptr_spec_d]];
// leave everything untouched and just push the latest value to the
// top of the stack
if (pop_i && push_i) begin
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = data_i;
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b1;
end else begin
// push on the stack
if (push_i) begin
tos_d[ptr_spec_d] = tos_d[ptr_spec_d] + 1'b1;
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = data_i;
// mark the new return address as valid
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b1;
if (begin_spec_i) begin
tos_d[ptr_spec_q] = tos_d[ptr_spec_q] + 1'b1;
stack_d[ptr_spec_q][tos_d[ptr_spec_q]] = stack_d[ptr_spec_d][tos_d[ptr_spec_d]];
end
end
if (pop_i) begin
// we popped the value so invalidate the end of the stack
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = '0;
stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b0;
tos_d[ptr_spec_d] = tos_d[ptr_spec_d] - 1'b1;
end
end
if (flush_i) begin
stack_d = '0;
tos_d = '0;
end
end
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;
end else begin
stack_q <= stack_d;
ptr_spec_q <= ptr_spec_d;
ptr_backup_q <= ptr_backup_d;
tos_q <= tos_d;
end
end
endmodule
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment