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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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