/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd. Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software 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. */ // `include "../cpu/environment.h" // * if gpr write back and pc retire happen at the same time,there is need to // * use gpr buffer, if gpr write back is one cycle after pc retire, there is // * no need to use gpr buffer. // // * for CK803 USE_GPR_BUFFER // * interface with Smart SoC testbench. // common interface `define mcause tb.x_soc.x_cpu_sub_system_ahb.x_e906_top.cp0_pad_mcause[31:0] // single issue cpu interface `define retire tb.x_soc.x_cpu_sub_system_ahb.biu_pad_retire `define retire_pc tb.x_soc.x_cpu_sub_system_ahb.biu_pad_retire_pc `define wb_gpr_data tb.x_soc.x_cpu_sub_system_ahb.biu_pad_wb_gpr_data `define wb_gpr_index tb.x_soc.x_cpu_sub_system_ahb.biu_pad_wb_gpr_index `define wb_gpr_en tb.x_soc.x_cpu_sub_system_ahb.biu_pad_wb_gpr_en module mnt(); // * reg definition for PC buffer // * these buffered signals are one cycle delay and used to print logfile reg retire_latch; reg [31:0] retire_pc_latch; // * reg definition for GPR buffer // * these buffered signals are one cycle delay reg wb_gpr_en_delay1; reg [ 4:0] wb_gpr_index_delay1; reg [31:0] wb_gpr_data_delay1; // * reg definition for GPR, these registers hold the old value of GPR reg [31:0] GPR [31:0]; // * wire definition for GPR signal // * these signals used to print logfile and is connected to wb_gpr directly // * or wb_gpr_delay1 signal according to definition USE_GPR_BUFFER wire wb_gpr_en_latch; wire [ 4:0] wb_gpr_index_latch; wire [31:0] wb_gpr_data_latch; // * PC Buffer always @(posedge `clk or negedge `rst_b) begin if(!`rst_b) retire_latch <= 1'b0; else retire_latch <= `retire; end always @(posedge `clk) begin retire_pc_latch[31:0] <= `retire_pc[31:0]; end // * GPR Buffer always @(posedge `clk or negedge `rst_b) begin if(!`rst_b) wb_gpr_en_delay1 <= 1'b0; else wb_gpr_en_delay1 <= `wb_gpr_en; end always @(posedge `clk) begin wb_gpr_index_delay1[4:0] <= `wb_gpr_index[4:0]; wb_gpr_data_delay1[31:0] <= `wb_gpr_data[31:0]; end // * wires connecttion // * if USE_GPR_BUFFER, use delayed signal, else use signal directly assign wb_gpr_en_latch = `wb_gpr_en; assign wb_gpr_index_latch[4:0] = `wb_gpr_index[4:0]; assign wb_gpr_data_latch[31:0] = `wb_gpr_data[31:0]; // * GPR has three write ports. port 1 is for single issue cpu, port 2 and port 3 are // * for dual issue cpu. port 1 and port 2 or 3 cannot be valid at the same time. // * if port 2 and 3 are valid at the same time, they cannot write the same reigster. // * this is assured by cpu inner logical wire gpr_we; assign gpr_we = wb_gpr_en_latch; integer i; always @(posedge `clk or negedge `rst_b) begin if(!`rst_b) begin for(i = 0; i < 32; i = i+1) begin GPR[i] <= 32'b0; end end else if(gpr_we) begin GPR[wb_gpr_index_latch] <= wb_gpr_data_latch; end end // * logfile is new in current directory. The name of the file is GPR.log // * there are 3 write ports. the first is for single issue cpu. the second and // * the third is for dual issue cpu. port for single issue and port for dual // * issue cannot be valied at the same time. integer GPR_FH; initial begin GPR_FH = $fopen("GPR.log"); if(GPR_FH == 0) begin $display("can't open log file GPR.log in mnt.v!"); $finish; end end // * for single issue cpu, there is only one print function is valid at one time // * when PC retire, print PC, PSR and GPR information wire retire_pc_print; assign retire_pc_print = retire_latch; always @(posedge `clk) begin if(retire_pc_print) begin $fwrite(GPR_FH, "PC : %8h |", retire_pc_latch[31:0]); $fwrite(GPR_FH, "MCAUSE: %8h\n", `mcause); for(i = 0; i < 32; i = i+1) begin if(wb_gpr_en_latch && (i == wb_gpr_index_latch[4:0])) begin $fwrite(GPR_FH, "gr%2d:%8h |",i,wb_gpr_data_latch[31:0]); end else begin $fwrite(GPR_FH, "gr%2d:%8h |",i,GPR[i]); end if(i % 4 == 3) begin $fwrite(GPR_FH, "\n"); end end $fwrite(GPR_FH, "\n"); end end endmodule