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

Subversion Repositories ion

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

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 96 ja_rd
    present_data_wr_addr :  t_word;
65 60 ja_rd
    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 84 ja_rd
 
86
    -- Log trigger --------------------------------------------------
87
    -- Enable logging after fetching from a given address -----------
88
    log_trigger_address :   t_word;
89
    log_triggered :         boolean;
90 60 ja_rd
end record t_log_info;
91
 
92
procedure log_cpu_activity(
93
                signal clk :    in std_logic;
94
                signal reset :  in std_logic;
95
                signal done :   in std_logic;
96
                entity_name :   string;
97
                signal info :   inout t_log_info;
98
                signal_name :   string;
99 84 ja_rd
                trigger_addr :  in t_word;
100 60 ja_rd
                file l_file :   TEXT);
101
 
102
 
103
end package;
104
 
105
package body mips_tb_pkg is
106
 
107
procedure log_cpu_status(
108 84 ja_rd
                signal info :   inout t_log_info;
109 60 ja_rd
                file l_file :   TEXT) is
110
variable i : integer;
111
variable ri : std_logic_vector(7 downto 0);
112
variable full_pc, temp, temp2 : t_word;
113
variable k : integer := 2;
114
begin
115
 
116 84 ja_rd
    -- Trigger logging if the CPU fetches from trigger address
117
    if (info.log_trigger_address(31 downto 2) = info.present_code_rd_addr) and
118
       info.code_rd_vma='1' then
119
        info.log_triggered <= true;
120
 
121
        assert 1=0
122
        report "Log triggered by fetch from address 0x"& hstr(info.log_trigger_address)
123
        severity note;
124
    end if;
125
 
126 60 ja_rd
    -- This is the address of the opcode that triggered the changed we're
127
    -- about to log
128
    full_pc := info.pc_m(k);
129
 
130
 
131
    -- Log activity only at the 1st cycle of each instruction
132
    if info.code_rd_vma='1' then
133
 
134
        -- Log register changes -------------------------------------
135
        ri := X"00";
136
        for i in 0 to 31 loop
137
            if info.prev_rbank(i)/=info.rbank(i)
138 84 ja_rd
               and info.prev_rbank(i)(0)/='U' then
139
                if info.log_triggered then
140
                    print(l_file, "("& hstr(full_pc)& ") "&
141
                        "["& hstr(ri)& "]="& hstr(info.rbank(i)));
142
                end if;
143 60 ja_rd
            end if;
144
            ri := ri + 1;
145
        end loop;
146
 
147
        -- Log memory writes ----------------------------------------
148
        if info.write_pending then
149
 
150
            ri := X"0" & info.pending_data_wr_we;
151
            temp := info.pending_data_wr;
152
            if info.pending_data_wr_we(3)='0' then
153
                temp := temp and X"00ffffff";
154
            end if;
155
            if info.pending_data_wr_we(2)='0' then
156
                temp := temp and X"ff00ffff";
157
            end if;
158
            if info.pending_data_wr_we(1)='0' then
159
                temp := temp and X"ffff00ff";
160
            end if;
161
            if info.pending_data_wr_we(0)='0' then
162
                temp := temp and X"ffffff00";
163
            end if;
164 84 ja_rd
            if info.log_triggered then
165
                print(l_file, "("& hstr(info.pending_data_wr_pc) &") ["&
166
                    hstr(info.pending_data_wr_addr) &"] |"&
167
                    hstr(ri)& "|="&
168
                    hstr(temp)& " WR" );
169
            end if;
170 60 ja_rd
            info.write_pending <= false;
171
        end if;
172
 
173
 
174
        -- Log memory reads ------------------------------------------
175
        if info.read_pending and info.load='1' then
176 84 ja_rd
            if info.log_triggered then
177
                print(l_file, "("& hstr(info.pc_m(1)) &") ["&
178
                      hstr(info.pending_data_rd_addr) &"] <"&
179
                      "**"& ">="&
180
                      hstr(info.word_loaded)& " RD" ); -- FIXME
181
            end if;
182 60 ja_rd
            info.read_pending <= false;
183
        end if;
184
 
185
        -- Log aux register changes ---------------------------------
186
        if info.prev_lo /= info.reg_lo and info.prev_lo(0)/='U' then
187
            -- Adjust opcode PC when LO came from the mul module
188
            if info.mdiv_pending then
189
                temp2 := info.mdiv_address;
190
                info.mdiv_pending <= false;
191
            else
192
                temp2 := info.pc_m(k-1);
193
            end if;
194
 
195
            -- we're observing the value of reg_lo, but the mult core
196
            -- will output the negated value in some cases. We
197
            -- have to mimic that behavior.
198
            if info.negate_reg_lo='1' then
199
                -- negate reg_lo before displaying
200
                temp := not info.reg_lo;
201
                temp := temp + 1;
202 84 ja_rd
                if info.log_triggered then
203
                    print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(temp));
204
                end if;
205 60 ja_rd
            else
206 84 ja_rd
                if info.log_triggered then
207
                    print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(info.reg_lo));
208
                end if;
209 60 ja_rd
            end if;
210
        end if;
211
        if info.prev_hi /= info.reg_hi and info.prev_hi(0)/='U' then
212
            -- Adjust opcode PC when HI came from the mul module
213
            if info.mdiv_pending then
214
                temp2 := info.mdiv_address;
215
                info.mdiv_pending <= false;
216
            else
217
                temp2 := info.pc_m(k-1);
218
            end if;
219 84 ja_rd
 
220
            if info.log_triggered then
221
                print(l_file, "("& hstr(temp2)& ") [HI]="& hstr(info.reg_hi));
222
            end if;
223 60 ja_rd
        end if;
224
 
225
        if info.prev_epc /= info.cp0_epc and info.cp0_epc(31)/='U'  then
226
            temp := info.cp0_epc & "00";
227 84 ja_rd
            if info.log_triggered then
228
                print(l_file, "("& hstr(info.pc_m(k-1))& ") [EP]="& hstr(temp));
229
            end if;
230 60 ja_rd
            info.prev_epc <= info.cp0_epc;
231
        end if;
232
 
233
 
234
        -- Save present cycle info to compare the next cycle --------
235
        info.prev_rbank <= info.rbank;
236
        info.prev_hi <= info.reg_hi;
237
        info.prev_lo <= info.reg_lo;
238
 
239
        info.pc_m(3) <= info.pc_m(2);
240
        info.pc_m(2) <= info.pc_m(1);
241
        info.pc_m(1) <= info.pc_m(0);
242
        info.pc_m(0) <= info.present_code_rd_addr & "00";
243
 
244
    end if;
245
 
246
    if info.data_byte_we/="0000" then
247
        info.write_pending <= true;
248
        info.pending_data_wr_we <= info.data_byte_we;
249 96 ja_rd
        info.pending_data_wr_addr <= info.present_data_wr_addr;
250 60 ja_rd
        info.pending_data_wr_pc <= info.pc_m(k-1);
251
        info.pending_data_wr <= info.present_data_wr;
252
    end if;
253
 
254
    if info.data_rd_vma='1' then
255
        info.read_pending <= true;
256
        info.pending_data_rd_addr <= info.present_data_rd_addr;
257
    end if;
258
 
259
    if info.mdiv_count_reg="100000" then
260
        info.mdiv_address <= info.pc_m(1);
261
        info.mdiv_pending <= true;
262
    end if;
263
 
264
    info.prev_count_reg <= info.mdiv_count_reg;
265
 
266
end procedure log_cpu_status;
267
 
268
procedure log_cpu_activity(
269
                signal clk :    in std_logic;
270
                signal reset :  in std_logic;
271
                signal done :   in std_logic;
272
                entity_name :   string;
273
                signal info :   inout t_log_info;
274
                signal_name :   string;
275 84 ja_rd
                trigger_addr :  in t_word;
276 60 ja_rd
                file l_file :   TEXT) is
277
begin
278
    init_signal_spy("/"&entity_name&"/p1_rbank", signal_name&".rbank", 0, -1);
279
    init_signal_spy("/"&entity_name&"/code_rd_addr", signal_name&".present_code_rd_addr", 0, -1);
280
    init_signal_spy("/"&entity_name&"/mult_div/upper_reg", signal_name&".reg_hi", 0, -1);
281
    init_signal_spy("/"&entity_name&"/mult_div/lower_reg", signal_name&".reg_lo", 0, -1);
282
    init_signal_spy("/"&entity_name&"/mult_div/negate_reg", signal_name&".negate_reg_lo", 0, -1);
283
    init_signal_spy("/"&entity_name&"/mult_div/count_reg", signal_name&".mdiv_count_reg", 0, -1);
284
    init_signal_spy("/"&entity_name&"/cp0_epc", signal_name&".cp0_epc", 0, -1);
285
    init_signal_spy("/"&entity_name&"/data_rd_vma", signal_name&".data_rd_vma", 0, -1);
286
    init_signal_spy("/"&entity_name&"/code_rd_vma", signal_name&".code_rd_vma", 0, -1);
287
    init_signal_spy("/"&entity_name&"/p2_do_load", signal_name&".load", 0, -1);
288 96 ja_rd
    init_signal_spy("/"&entity_name&"/data_addr", signal_name&".present_data_wr_addr", 0, -1);
289 60 ja_rd
    init_signal_spy("/"&entity_name&"/data_wr", signal_name&".present_data_wr", 0, -1);
290
    init_signal_spy("/"&entity_name&"/byte_we", signal_name&".data_byte_we", 0, -1);
291
    init_signal_spy("/"&entity_name&"/p2_data_word_rd", signal_name&".word_loaded", 0, -1);
292 96 ja_rd
    init_signal_spy("/"&entity_name&"/data_addr", signal_name&".present_data_rd_addr", 0, -1);
293 60 ja_rd
 
294
    while done='0' loop
295
        wait until clk'event and clk='1';
296
        if reset='1' then
297
            -- FIXME should use real reset vector here
298
            info.pc_m <= (others => X"00000000");
299 84 ja_rd
 
300
            -- By default logging is DISABLED by triggering with an impossible
301
            -- fetch address. Logging must be enabled from outside by 
302
            -- setting log_trigger_address to a suitable value.
303
            info.log_trigger_address <= trigger_addr;
304
            info.log_triggered <= false;
305 60 ja_rd
        else
306
            log_cpu_status(info, l_file);
307
        end if;
308
    end loop;
309
 
310
 
311
end procedure log_cpu_activity;
312
 
313
 
314
 
315
end package body;

powered by: WebSVN 2.1.0

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