2021-03-04 23:31:12 +00:00
|
|
|
///////////////////////////////////////////
|
2023-02-17 03:40:27 +00:00
|
|
|
// functionName.sv
|
2021-03-04 23:31:12 +00:00
|
|
|
//
|
2024-10-15 15:27:53 +00:00
|
|
|
// Written: Rose Thompson rose@rosethompson.net
|
2023-06-14 22:02:49 +00:00
|
|
|
//
|
2023-02-17 03:40:27 +00:00
|
|
|
// Purpose: decode name of function
|
2021-03-04 23:31:12 +00:00
|
|
|
//
|
|
|
|
// A component of the Wally configurable RISC-V project.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
|
|
|
//
|
2023-02-17 03:40:27 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
|
|
|
//
|
|
|
|
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
|
|
|
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
|
|
|
// may obtain a copy of the License at
|
2021-03-04 23:31:12 +00:00
|
|
|
//
|
2023-02-17 03:40:27 +00:00
|
|
|
// https://solderpad.org/licenses/SHL-2.1/
|
2021-03-04 23:31:12 +00:00
|
|
|
//
|
2023-02-17 03:40:27 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, any work distributed under the
|
|
|
|
// 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.
|
2022-01-07 12:58:40 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
2021-03-04 23:31:12 +00:00
|
|
|
|
2023-06-14 21:35:55 +00:00
|
|
|
module FunctionName import cvw::*; #(parameter cvw_t P) (
|
|
|
|
input logic reset,
|
|
|
|
input logic clk,
|
|
|
|
input string ProgramAddrMapFile,
|
|
|
|
input string ProgramLabelMapFile
|
|
|
|
);
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2023-12-18 22:38:56 +00:00
|
|
|
logic [P.XLEN-1:0] ProgramAddrMapMemory [logic [P.XLEN-1:0]];
|
|
|
|
string ProgramLabelMapMemory [logic [P.XLEN-1:0]];
|
2021-03-11 23:12:21 +00:00
|
|
|
string FunctionName;
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2021-03-11 23:12:21 +00:00
|
|
|
|
2023-06-14 21:35:55 +00:00
|
|
|
logic [P.XLEN-1:0] PCF, PCD, PCE, PCM, FunctionAddr, PCM_temp, PCMOld;
|
2023-03-03 23:49:44 +00:00
|
|
|
logic StallD, StallE, StallM, FlushD, FlushE, FlushM;
|
|
|
|
logic InstrValidM;
|
2023-12-18 22:37:26 +00:00
|
|
|
logic [P.XLEN-1:0] ProgramAddrIndex, ProgramAddrIndexQ;
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2023-01-30 17:47:51 +00:00
|
|
|
assign PCF = testbench.dut.core.ifu.PCF;
|
2022-01-20 16:02:08 +00:00
|
|
|
assign StallD = testbench.dut.core.StallD;
|
|
|
|
assign StallE = testbench.dut.core.StallE;
|
2023-03-03 23:49:44 +00:00
|
|
|
assign StallM = testbench.dut.core.StallM;
|
2022-01-20 16:02:08 +00:00
|
|
|
assign FlushD = testbench.dut.core.FlushD;
|
|
|
|
assign FlushE = testbench.dut.core.FlushE;
|
2023-03-03 23:49:44 +00:00
|
|
|
assign FlushM = testbench.dut.core.FlushM;
|
|
|
|
assign InstrValidM = testbench.dut.core.InstrValidM;
|
2021-03-24 18:03:43 +00:00
|
|
|
|
|
|
|
// copy from ifu
|
|
|
|
// when the F and D stages are flushed we need to ensure the PCE is held so that the function name does not
|
|
|
|
// erroneously change.
|
2023-03-03 23:49:44 +00:00
|
|
|
// also need to hold the old value not an erroneously fetched PC.
|
2023-06-14 21:35:55 +00:00
|
|
|
flopenr #(P.XLEN) PCDReg(clk, reset, ~StallD, FlushD ? PCE : PCF, PCD);
|
|
|
|
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, FlushD & FlushE ? PCF : FlushE ? PCE : PCD, PCE);
|
|
|
|
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, FlushD & FlushE & FlushM ? PCF : FlushE & FlushM ? PCE : FlushM ? PCM : PCE, PCM_temp);
|
|
|
|
flopenr #(P.XLEN) PCMOldReg(clk, reset, InstrValidM, PCM_temp, PCMOld);
|
2023-03-03 23:49:44 +00:00
|
|
|
assign PCM = InstrValidM ? PCM_temp : PCMOld;
|
2021-03-10 17:00:51 +00:00
|
|
|
|
|
|
|
task automatic bin_search_min;
|
2023-06-14 21:35:55 +00:00
|
|
|
input logic [P.XLEN-1:0] pc;
|
|
|
|
input logic [P.XLEN-1:0] length;
|
2023-12-18 22:38:56 +00:00
|
|
|
ref logic [P.XLEN-1:0] array [logic [P.XLEN-1:0]];
|
2023-06-14 21:35:55 +00:00
|
|
|
output logic [P.XLEN-1:0] minval;
|
|
|
|
output logic [P.XLEN-1:0] mid;
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2023-06-14 21:35:55 +00:00
|
|
|
logic [P.XLEN-1:0] left, right;
|
2021-03-10 17:00:51 +00:00
|
|
|
|
|
|
|
begin
|
2021-03-11 23:12:21 +00:00
|
|
|
if ( pc == 0 ) begin
|
2024-11-20 15:23:51 +00:00
|
|
|
// want to keep the old value for mid and minval
|
2021-03-11 23:12:21 +00:00
|
|
|
mid = 0;
|
|
|
|
return;
|
|
|
|
end
|
2021-03-10 17:00:51 +00:00
|
|
|
left = 0;
|
|
|
|
right = length;
|
|
|
|
while (left <= right) begin
|
|
|
|
mid = left + ((right - left) / 2);
|
|
|
|
if (array[mid] == pc) begin
|
|
|
|
minval = array[mid];
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
if (array[mid] < pc) begin
|
|
|
|
left = mid + 1;
|
|
|
|
end else if( array[mid] > pc) begin
|
|
|
|
right = mid -1;
|
|
|
|
end else begin
|
2021-08-24 16:08:46 +00:00
|
|
|
//$display("Critical Error in FunctionName. PC, %x not found.", pc);
|
2021-03-10 17:00:51 +00:00
|
|
|
return;
|
|
|
|
//$stop();
|
|
|
|
end
|
|
|
|
end // while (left <= right)
|
|
|
|
// if the element pc is now found, right and left will be equal at this point.
|
|
|
|
// we need to check if pc is less than the array at left or greather.
|
|
|
|
// if it is less than pc, then we select left as the index.
|
|
|
|
// if it is greather we want 1 less than left.
|
|
|
|
if (array[left] < pc) begin
|
|
|
|
minval = array[left];
|
2021-03-17 16:06:32 +00:00
|
|
|
mid = left;
|
2021-03-10 17:00:51 +00:00
|
|
|
return;
|
2021-02-27 01:43:40 +00:00
|
|
|
end else begin
|
2021-03-10 17:00:51 +00:00
|
|
|
minval = array[left-1];
|
2021-03-17 16:06:32 +00:00
|
|
|
mid = left - 1;
|
2021-03-10 17:00:51 +00:00
|
|
|
return;
|
2021-02-27 01:43:40 +00:00
|
|
|
end
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
|
|
|
endtask // bin_search_min
|
|
|
|
|
2021-03-11 23:12:21 +00:00
|
|
|
integer ProgramAddrMapFP, ProgramLabelMapFP;
|
2023-12-18 22:38:56 +00:00
|
|
|
logic [P.XLEN-1:0] ProgramAddrMapLineCount;
|
|
|
|
logic [P.XLEN-1:0] ProgramLabelMapLineCount;
|
|
|
|
logic [P.XLEN-1:0] ProgramAddrMapLine;
|
2021-03-11 23:12:21 +00:00
|
|
|
string ProgramLabelMapLine;
|
2021-04-29 22:36:46 +00:00
|
|
|
integer status;
|
|
|
|
|
2021-03-10 17:00:51 +00:00
|
|
|
|
|
|
|
// preload
|
2021-03-11 23:12:21 +00:00
|
|
|
// initial begin
|
2023-03-03 23:49:44 +00:00
|
|
|
always @ (negedge reset) begin
|
2023-12-18 22:26:56 +00:00
|
|
|
|
|
|
|
// cannot readmemh directoy to a dynmaic array. Sad times :(
|
|
|
|
// Let's initialize a static array with FFFF_FFFF for all addresses.
|
|
|
|
// Then we can readmemh and finally copy to the dynamic array.
|
|
|
|
|
2023-03-03 23:49:44 +00:00
|
|
|
// clear out the old mapping between programs.
|
2023-07-11 15:51:17 +00:00
|
|
|
ProgramAddrMapMemory.delete();
|
|
|
|
ProgramLabelMapMemory.delete();
|
2023-03-03 23:49:44 +00:00
|
|
|
|
2023-12-18 22:26:56 +00:00
|
|
|
// Unfortunately verilator version 5.011 readmemh does not support dynamic arrays
|
|
|
|
//$readmemh(ProgramAddrMapFile, ProgramAddrMapMemory);
|
2021-03-10 21:17:02 +00:00
|
|
|
// we need to count the number of lines in the file so we can set FunctionRadixLineCount.
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2021-03-11 23:12:21 +00:00
|
|
|
ProgramAddrMapLineCount = 0;
|
|
|
|
ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r");
|
2021-03-10 17:00:51 +00:00
|
|
|
|
|
|
|
// read line by line to count lines
|
2024-03-06 13:48:17 +00:00
|
|
|
if (ProgramAddrMapFP != 0) begin
|
2021-03-11 23:12:21 +00:00
|
|
|
while (! $feof(ProgramAddrMapFP)) begin
|
2023-12-18 22:26:56 +00:00
|
|
|
status = $fscanf(ProgramAddrMapFP, "%h\n", ProgramAddrMapLine);
|
|
|
|
ProgramAddrMapMemory[ProgramAddrMapLineCount] = ProgramAddrMapLine;
|
|
|
|
ProgramAddrMapLineCount = ProgramAddrMapLineCount + 1;
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
|
|
|
end else begin
|
2021-03-11 23:12:21 +00:00
|
|
|
$display("Cannot open file %s for reading.", ProgramAddrMapFile);
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
2021-03-11 23:12:21 +00:00
|
|
|
$fclose(ProgramAddrMapFP);
|
2021-03-10 20:43:44 +00:00
|
|
|
|
|
|
|
// ProgramIndexFile maps the program name to the compile index.
|
|
|
|
// The compile index is then used to inditify the application
|
|
|
|
// in the custom radix.
|
|
|
|
// Build an associative array to convert the name to an index.
|
2021-03-11 23:12:21 +00:00
|
|
|
ProgramLabelMapLineCount = 0;
|
|
|
|
ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r");
|
2021-03-10 17:00:51 +00:00
|
|
|
|
2024-03-06 13:48:17 +00:00
|
|
|
if (ProgramLabelMapFP != 0) begin
|
2021-03-11 23:12:21 +00:00
|
|
|
while (! $feof(ProgramLabelMapFP)) begin
|
2021-04-29 22:36:46 +00:00
|
|
|
status = $fscanf(ProgramLabelMapFP, "%s\n", ProgramLabelMapLine);
|
2021-03-11 23:12:21 +00:00
|
|
|
ProgramLabelMapMemory[ProgramLabelMapLineCount] = ProgramLabelMapLine;
|
|
|
|
ProgramLabelMapLineCount = ProgramLabelMapLineCount + 1;
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
|
|
|
end else begin
|
2021-03-11 23:12:21 +00:00
|
|
|
$display("Cannot open file %s for reading.", ProgramLabelMapFile);
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
2021-03-11 23:12:21 +00:00
|
|
|
$fclose(ProgramLabelMapFP);
|
2023-03-03 23:49:44 +00:00
|
|
|
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
|
|
|
|
2023-03-03 23:49:44 +00:00
|
|
|
always @(PCM) begin
|
|
|
|
bin_search_min(PCM, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex);
|
2021-03-10 17:00:51 +00:00
|
|
|
end
|
2021-02-27 01:43:40 +00:00
|
|
|
|
2022-02-02 00:03:09 +00:00
|
|
|
logic OrReducedAdr, AnyUnknown;
|
|
|
|
assign OrReducedAdr = |ProgramAddrIndex;
|
|
|
|
assign AnyUnknown = (OrReducedAdr === 1'bx) ? 1'b1 : 1'b0;
|
2024-03-06 13:48:17 +00:00
|
|
|
initial ProgramAddrIndex = 0;
|
2022-02-02 00:03:09 +00:00
|
|
|
|
2023-07-07 23:22:28 +00:00
|
|
|
always @(*) FunctionName = AnyUnknown ? "Unknown!" : ProgramLabelMapMemory[ProgramAddrIndex];
|
2021-02-27 01:43:40 +00:00
|
|
|
|
|
|
|
endmodule // function_radix
|
|
|
|
|