abstractaccelerator/opene906/smart_run/logical/tb/mnt.v

169 lines
4.7 KiB
Verilog

/*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