OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [vhdl/] [tb/] [mips_tb_pkg.vhdl] - Blame information for rev 60

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 ja_rd
--------------------------------------------------------------------------------
2
-- mips_tb_pkg.vhdl -- Functions and data for the simulation test benches.
3
--------------------------------------------------------------------------------
4
-- Most of this file deals with the 'simulation log': the CPU execution history
5
-- is logged to a text file for easy comparison to a similaro log written by the
6
-- software simulator. This is meant as a debugging tool and is explained to 
7
-- some detail in the project doc.
8
-- It is used as a verification tool at least while no better verification test
9
-- bench exists.
10
--------------------------------------------------------------------------------
11
-- FIXME Console logging code should be here too
12
--------------------------------------------------------------------------------
13
-- WARNING: 
14
-- This package contains arguably the worst code of the project; in order
15
-- to expedite things, a number of trial-and-error hacks have been performed on
16
-- the code below. Mostly, the adjustment of the displayed PC.
17
-- This is just the kind of hdl you don't want prospective employers to see :)
18
-- 
19
-- The problem is: each change in the CPU state is logged in a text line, in 
20
-- which the address of the instruction that caused the change is included. 
21
-- From outside the CPU it is not always trivial to find out what instruction
22
-- caused what change (pipeline delays, cache stalls, etc.). 
23
-- I think the logging rules should be pretty stable now but I might have to
24
-- tweak them again as the cache implementation changes. Eventually I aim to
25
-- make this code fully independent of the cache implementation; it should
26
-- only depend on the cpu. I will do this step by step, as I do all the rest.
27
--------------------------------------------------------------------------------
28
 
29
library ieee,modelsim_lib;
30
use ieee.std_logic_1164.all;
31
use ieee.std_logic_arith.all;
32
use ieee.std_logic_unsigned.all;
33
 
34
use work.mips_pkg.all;
35
 
36
use modelsim_lib.util.all;
37
use std.textio.all;
38
use work.txt_util.all;
39
 
40
 
41
package mips_tb_pkg is
42
 
43
type t_pc_queue is array(0 to 3) of t_word;
44
 
45
type t_log_info is record
46
    rbank :                 t_rbank;
47
    prev_rbank :            t_rbank;
48
 
49
    cp0_epc :               t_pc;
50
    prev_epc :              t_pc;
51
 
52
    pc_m :                  t_pc_queue;
53
 
54
    reg_hi, reg_lo :        t_word;
55
    prev_hi, prev_lo :      t_word;
56
    negate_reg_lo :         std_logic;
57
    mdiv_count_reg :        std_logic_vector(5 downto 0);
58
    prev_count_reg :        std_logic_vector(5 downto 0);
59
 
60
    data_rd_vma :           std_logic;
61
    code_rd_vma :           std_logic;
62
    data_byte_we :          std_logic_vector(3 downto 0);
63
 
64
    present_data_wr_addr :  t_pc;
65
    present_data_wr :       t_word;
66
    present_data_rd_addr :  t_word;
67
    present_code_rd_addr :  t_pc;
68
 
69
    pending_data_rd_addr :  t_word;
70
    pending_data_wr_addr :  t_word;
71
    pending_data_wr_pc :    t_word;
72
    pending_data_wr :       t_word;
73
    pending_data_wr_we :    std_logic_vector(3 downto 0);
74
 
75
    word_loaded :           t_word;
76
 
77
    mdiv_address :          t_word;
78
    mdiv_pending :          boolean;
79
 
80
    data_rd_address :       t_word;
81
    load :                  std_logic;
82
 
83
    read_pending :          boolean;
84
    write_pending :         boolean;
85
end record t_log_info;
86
 
87
procedure log_cpu_activity(
88
                signal clk :    in std_logic;
89
                signal reset :  in std_logic;
90
                signal done :   in std_logic;
91
                entity_name :   string;
92
                signal info :   inout t_log_info;
93
                signal_name :   string;
94
                file l_file :   TEXT);
95
 
96
 
97
end package;
98
 
99
package body mips_tb_pkg is
100
 
101
procedure log_cpu_status(
102
                signal info :   inout t_log_info;
103
                file l_file :   TEXT) is
104
variable i : integer;
105
variable ri : std_logic_vector(7 downto 0);
106
variable full_pc, temp, temp2 : t_word;
107
variable k : integer := 2;
108
begin
109
 
110
    -- This is the address of the opcode that triggered the changed we're
111
    -- about to log
112
    full_pc := info.pc_m(k);
113
 
114
 
115
    -- Log activity only at the 1st cycle of each instruction
116
    if info.code_rd_vma='1' then
117
 
118
        -- Log register changes -------------------------------------
119
        ri := X"00";
120
        for i in 0 to 31 loop
121
            if info.prev_rbank(i)/=info.rbank(i)
122
               and info.prev_rbank(i)(0)/='U' then
123
                print(l_file, "("& hstr(full_pc)& ") "&
124
                      "["& hstr(ri)& "]="& hstr(info.rbank(i)));
125
            end if;
126
            ri := ri + 1;
127
        end loop;
128
 
129
        -- Log memory writes ----------------------------------------
130
        if info.write_pending then
131
 
132
            ri := X"0" & info.pending_data_wr_we;
133
            temp := info.pending_data_wr;
134
            if info.pending_data_wr_we(3)='0' then
135
                temp := temp and X"00ffffff";
136
            end if;
137
            if info.pending_data_wr_we(2)='0' then
138
                temp := temp and X"ff00ffff";
139
            end if;
140
            if info.pending_data_wr_we(1)='0' then
141
                temp := temp and X"ffff00ff";
142
            end if;
143
            if info.pending_data_wr_we(0)='0' then
144
                temp := temp and X"ffffff00";
145
            end if;
146
            print(l_file, "("& hstr(info.pending_data_wr_pc) &") ["&
147
                  hstr(info.pending_data_wr_addr) &"] |"&
148
                  hstr(ri)& "|="&
149
                  hstr(temp)& " WR" );
150
            info.write_pending <= false;
151
        end if;
152
 
153
 
154
        -- Log memory reads ------------------------------------------
155
        if info.read_pending and info.load='1' then
156
            print(l_file, "("& hstr(info.pc_m(1)) &") ["&
157
                  hstr(info.pending_data_rd_addr) &"] <"&
158
                  "**"& ">="&
159
                  hstr(info.word_loaded)& " RD" ); -- FIXME
160
            info.read_pending <= false;
161
        end if;
162
 
163
        -- Log aux register changes ---------------------------------
164
        if info.prev_lo /= info.reg_lo and info.prev_lo(0)/='U' then
165
            -- Adjust opcode PC when LO came from the mul module
166
            if info.mdiv_pending then
167
                temp2 := info.mdiv_address;
168
                info.mdiv_pending <= false;
169
            else
170
                temp2 := info.pc_m(k-1);
171
            end if;
172
 
173
            -- we're observing the value of reg_lo, but the mult core
174
            -- will output the negated value in some cases. We
175
            -- have to mimic that behavior.
176
            if info.negate_reg_lo='1' then
177
                -- negate reg_lo before displaying
178
                temp := not info.reg_lo;
179
                temp := temp + 1;
180
                print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(temp));
181
            else
182
                print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(info.reg_lo));
183
            end if;
184
        end if;
185
        if info.prev_hi /= info.reg_hi and info.prev_hi(0)/='U' then
186
            -- Adjust opcode PC when HI came from the mul module
187
            if info.mdiv_pending then
188
                temp2 := info.mdiv_address;
189
                info.mdiv_pending <= false;
190
            else
191
                temp2 := info.pc_m(k-1);
192
            end if;
193
 
194
            print(l_file, "("& hstr(temp2)& ") [HI]="& hstr(info.reg_hi));
195
        end if;
196
 
197
        if info.prev_epc /= info.cp0_epc and info.cp0_epc(31)/='U'  then
198
            temp := info.cp0_epc & "00";
199
            print(l_file, "("& hstr(info.pc_m(k-1))& ") [EP]="& hstr(temp));
200
            info.prev_epc <= info.cp0_epc;
201
        end if;
202
 
203
 
204
        -- Save present cycle info to compare the next cycle --------
205
        info.prev_rbank <= info.rbank;
206
        info.prev_hi <= info.reg_hi;
207
        info.prev_lo <= info.reg_lo;
208
 
209
        info.pc_m(3) <= info.pc_m(2);
210
        info.pc_m(2) <= info.pc_m(1);
211
        info.pc_m(1) <= info.pc_m(0);
212
        info.pc_m(0) <= info.present_code_rd_addr & "00";
213
 
214
    end if;
215
 
216
    if info.data_byte_we/="0000" then
217
        info.write_pending <= true;
218
        info.pending_data_wr_we <= info.data_byte_we;
219
        info.pending_data_wr_addr <= info.present_data_wr_addr & "00";
220
        info.pending_data_wr_pc <= info.pc_m(k-1);
221
        info.pending_data_wr <= info.present_data_wr;
222
    end if;
223
 
224
    if info.data_rd_vma='1' then
225
        info.read_pending <= true;
226
        info.pending_data_rd_addr <= info.present_data_rd_addr;
227
    end if;
228
 
229
    if info.mdiv_count_reg="100000" then
230
        info.mdiv_address <= info.pc_m(1);
231
        info.mdiv_pending <= true;
232
    end if;
233
 
234
    info.prev_count_reg <= info.mdiv_count_reg;
235
 
236
end procedure log_cpu_status;
237
 
238
procedure log_cpu_activity(
239
                signal clk :    in std_logic;
240
                signal reset :  in std_logic;
241
                signal done :   in std_logic;
242
                entity_name :   string;
243
                signal info :   inout t_log_info;
244
                signal_name :   string;
245
                file l_file :   TEXT) is
246
begin
247
    init_signal_spy("/"&entity_name&"/p1_rbank", signal_name&".rbank", 0, -1);
248
    init_signal_spy("/"&entity_name&"/code_rd_addr", signal_name&".present_code_rd_addr", 0, -1);
249
    init_signal_spy("/"&entity_name&"/mult_div/upper_reg", signal_name&".reg_hi", 0, -1);
250
    init_signal_spy("/"&entity_name&"/mult_div/lower_reg", signal_name&".reg_lo", 0, -1);
251
    init_signal_spy("/"&entity_name&"/mult_div/negate_reg", signal_name&".negate_reg_lo", 0, -1);
252
    init_signal_spy("/"&entity_name&"/mult_div/count_reg", signal_name&".mdiv_count_reg", 0, -1);
253
    init_signal_spy("/"&entity_name&"/cp0_epc", signal_name&".cp0_epc", 0, -1);
254
    init_signal_spy("/"&entity_name&"/data_rd_vma", signal_name&".data_rd_vma", 0, -1);
255
    init_signal_spy("/"&entity_name&"/code_rd_vma", signal_name&".code_rd_vma", 0, -1);
256
    init_signal_spy("/"&entity_name&"/p2_do_load", signal_name&".load", 0, -1);
257
    init_signal_spy("/"&entity_name&"/data_wr_addr", signal_name&".present_data_wr_addr", 0, -1);
258
    init_signal_spy("/"&entity_name&"/data_wr", signal_name&".present_data_wr", 0, -1);
259
    init_signal_spy("/"&entity_name&"/byte_we", signal_name&".data_byte_we", 0, -1);
260
    init_signal_spy("/"&entity_name&"/p2_data_word_rd", signal_name&".word_loaded", 0, -1);
261
    init_signal_spy("/"&entity_name&"/data_rd_addr", signal_name&".present_data_rd_addr", 0, -1);
262
 
263
    while done='0' loop
264
        wait until clk'event and clk='1';
265
        if reset='1' then
266
            -- FIXME should use real reset vector here
267
            info.pc_m <= (others => X"00000000");
268
        else
269
            log_cpu_status(info, l_file);
270
        end if;
271
    end loop;
272
 
273
 
274
end procedure log_cpu_activity;
275
 
276
 
277
 
278
end package body;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.