Line 80... |
Line 80... |
data_rd_address : t_word;
|
data_rd_address : t_word;
|
load : std_logic;
|
load : std_logic;
|
|
|
read_pending : boolean;
|
read_pending : boolean;
|
write_pending : boolean;
|
write_pending : boolean;
|
|
|
|
-- Log trigger --------------------------------------------------
|
|
-- Enable logging after fetching from a given address -----------
|
|
log_trigger_address : t_word;
|
|
log_triggered : boolean;
|
end record t_log_info;
|
end record t_log_info;
|
|
|
procedure log_cpu_activity(
|
procedure log_cpu_activity(
|
signal clk : in std_logic;
|
signal clk : in std_logic;
|
signal reset : in std_logic;
|
signal reset : in std_logic;
|
signal done : in std_logic;
|
signal done : in std_logic;
|
entity_name : string;
|
entity_name : string;
|
signal info : inout t_log_info;
|
signal info : inout t_log_info;
|
signal_name : string;
|
signal_name : string;
|
|
trigger_addr : in t_word;
|
file l_file : TEXT);
|
file l_file : TEXT);
|
|
|
|
|
end package;
|
end package;
|
|
|
Line 105... |
Line 111... |
variable ri : std_logic_vector(7 downto 0);
|
variable ri : std_logic_vector(7 downto 0);
|
variable full_pc, temp, temp2 : t_word;
|
variable full_pc, temp, temp2 : t_word;
|
variable k : integer := 2;
|
variable k : integer := 2;
|
begin
|
begin
|
|
|
|
-- Trigger logging if the CPU fetches from trigger address
|
|
if (info.log_trigger_address(31 downto 2) = info.present_code_rd_addr) and
|
|
info.code_rd_vma='1' then
|
|
info.log_triggered <= true;
|
|
|
|
assert 1=0
|
|
report "Log triggered by fetch from address 0x"& hstr(info.log_trigger_address)
|
|
severity note;
|
|
end if;
|
|
|
-- This is the address of the opcode that triggered the changed we're
|
-- This is the address of the opcode that triggered the changed we're
|
-- about to log
|
-- about to log
|
full_pc := info.pc_m(k);
|
full_pc := info.pc_m(k);
|
|
|
|
|
Line 118... |
Line 134... |
-- Log register changes -------------------------------------
|
-- Log register changes -------------------------------------
|
ri := X"00";
|
ri := X"00";
|
for i in 0 to 31 loop
|
for i in 0 to 31 loop
|
if info.prev_rbank(i)/=info.rbank(i)
|
if info.prev_rbank(i)/=info.rbank(i)
|
and info.prev_rbank(i)(0)/='U' then
|
and info.prev_rbank(i)(0)/='U' then
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(full_pc)& ") "&
|
print(l_file, "("& hstr(full_pc)& ") "&
|
"["& hstr(ri)& "]="& hstr(info.rbank(i)));
|
"["& hstr(ri)& "]="& hstr(info.rbank(i)));
|
end if;
|
end if;
|
|
end if;
|
ri := ri + 1;
|
ri := ri + 1;
|
end loop;
|
end loop;
|
|
|
-- Log memory writes ----------------------------------------
|
-- Log memory writes ----------------------------------------
|
if info.write_pending then
|
if info.write_pending then
|
Line 141... |
Line 159... |
temp := temp and X"ffff00ff";
|
temp := temp and X"ffff00ff";
|
end if;
|
end if;
|
if info.pending_data_wr_we(0)='0' then
|
if info.pending_data_wr_we(0)='0' then
|
temp := temp and X"ffffff00";
|
temp := temp and X"ffffff00";
|
end if;
|
end if;
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(info.pending_data_wr_pc) &") ["&
|
print(l_file, "("& hstr(info.pending_data_wr_pc) &") ["&
|
hstr(info.pending_data_wr_addr) &"] |"&
|
hstr(info.pending_data_wr_addr) &"] |"&
|
hstr(ri)& "|="&
|
hstr(ri)& "|="&
|
hstr(temp)& " WR" );
|
hstr(temp)& " WR" );
|
|
end if;
|
info.write_pending <= false;
|
info.write_pending <= false;
|
end if;
|
end if;
|
|
|
|
|
-- Log memory reads ------------------------------------------
|
-- Log memory reads ------------------------------------------
|
if info.read_pending and info.load='1' then
|
if info.read_pending and info.load='1' then
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(info.pc_m(1)) &") ["&
|
print(l_file, "("& hstr(info.pc_m(1)) &") ["&
|
hstr(info.pending_data_rd_addr) &"] <"&
|
hstr(info.pending_data_rd_addr) &"] <"&
|
"**"& ">="&
|
"**"& ">="&
|
hstr(info.word_loaded)& " RD" ); -- FIXME
|
hstr(info.word_loaded)& " RD" ); -- FIXME
|
|
end if;
|
info.read_pending <= false;
|
info.read_pending <= false;
|
end if;
|
end if;
|
|
|
-- Log aux register changes ---------------------------------
|
-- Log aux register changes ---------------------------------
|
if info.prev_lo /= info.reg_lo and info.prev_lo(0)/='U' then
|
if info.prev_lo /= info.reg_lo and info.prev_lo(0)/='U' then
|
Line 175... |
Line 197... |
-- have to mimic that behavior.
|
-- have to mimic that behavior.
|
if info.negate_reg_lo='1' then
|
if info.negate_reg_lo='1' then
|
-- negate reg_lo before displaying
|
-- negate reg_lo before displaying
|
temp := not info.reg_lo;
|
temp := not info.reg_lo;
|
temp := temp + 1;
|
temp := temp + 1;
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(temp));
|
print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(temp));
|
|
end if;
|
else
|
else
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(info.reg_lo));
|
print(l_file, "("& hstr(temp2)& ") [LO]="& hstr(info.reg_lo));
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end if;
|
if info.prev_hi /= info.reg_hi and info.prev_hi(0)/='U' then
|
if info.prev_hi /= info.reg_hi and info.prev_hi(0)/='U' then
|
-- Adjust opcode PC when HI came from the mul module
|
-- Adjust opcode PC when HI came from the mul module
|
if info.mdiv_pending then
|
if info.mdiv_pending then
|
temp2 := info.mdiv_address;
|
temp2 := info.mdiv_address;
|
info.mdiv_pending <= false;
|
info.mdiv_pending <= false;
|
else
|
else
|
temp2 := info.pc_m(k-1);
|
temp2 := info.pc_m(k-1);
|
end if;
|
end if;
|
|
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(temp2)& ") [HI]="& hstr(info.reg_hi));
|
print(l_file, "("& hstr(temp2)& ") [HI]="& hstr(info.reg_hi));
|
end if;
|
end if;
|
|
end if;
|
|
|
if info.prev_epc /= info.cp0_epc and info.cp0_epc(31)/='U' then
|
if info.prev_epc /= info.cp0_epc and info.cp0_epc(31)/='U' then
|
temp := info.cp0_epc & "00";
|
temp := info.cp0_epc & "00";
|
|
if info.log_triggered then
|
print(l_file, "("& hstr(info.pc_m(k-1))& ") [EP]="& hstr(temp));
|
print(l_file, "("& hstr(info.pc_m(k-1))& ") [EP]="& hstr(temp));
|
|
end if;
|
info.prev_epc <= info.cp0_epc;
|
info.prev_epc <= info.cp0_epc;
|
end if;
|
end if;
|
|
|
|
|
-- Save present cycle info to compare the next cycle --------
|
-- Save present cycle info to compare the next cycle --------
|
Line 240... |
Line 270... |
signal reset : in std_logic;
|
signal reset : in std_logic;
|
signal done : in std_logic;
|
signal done : in std_logic;
|
entity_name : string;
|
entity_name : string;
|
signal info : inout t_log_info;
|
signal info : inout t_log_info;
|
signal_name : string;
|
signal_name : string;
|
|
trigger_addr : in t_word;
|
file l_file : TEXT) is
|
file l_file : TEXT) is
|
begin
|
begin
|
init_signal_spy("/"&entity_name&"/p1_rbank", signal_name&".rbank", 0, -1);
|
init_signal_spy("/"&entity_name&"/p1_rbank", signal_name&".rbank", 0, -1);
|
init_signal_spy("/"&entity_name&"/code_rd_addr", signal_name&".present_code_rd_addr", 0, -1);
|
init_signal_spy("/"&entity_name&"/code_rd_addr", signal_name&".present_code_rd_addr", 0, -1);
|
init_signal_spy("/"&entity_name&"/mult_div/upper_reg", signal_name&".reg_hi", 0, -1);
|
init_signal_spy("/"&entity_name&"/mult_div/upper_reg", signal_name&".reg_hi", 0, -1);
|
Line 263... |
Line 294... |
while done='0' loop
|
while done='0' loop
|
wait until clk'event and clk='1';
|
wait until clk'event and clk='1';
|
if reset='1' then
|
if reset='1' then
|
-- FIXME should use real reset vector here
|
-- FIXME should use real reset vector here
|
info.pc_m <= (others => X"00000000");
|
info.pc_m <= (others => X"00000000");
|
|
|
|
-- By default logging is DISABLED by triggering with an impossible
|
|
-- fetch address. Logging must be enabled from outside by
|
|
-- setting log_trigger_address to a suitable value.
|
|
info.log_trigger_address <= trigger_addr;
|
|
info.log_triggered <= false;
|
else
|
else
|
log_cpu_status(info, l_file);
|
log_cpu_status(info, l_file);
|
end if;
|
end if;
|
end loop;
|
end loop;
|
|
|