mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
We now have a record that represents the actions taken in executing an instruction, and a process that computes that for the incoming instruction. We no longer have 'current' or 'r.cur_instr', instead things like the destination register are put into r.e in the first cycle of an instruction and not reinitialized in subsequent busy cycles. For mfspr and mtspr, we now decode "slow" SPR numbers (those SPRs that are not stored in the register file) to a new "spr_selector" record in decode1 (excluding those in the loadstore unit). With this, the result for mfspr is determined in the data path. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
124 lines
3.7 KiB
VHDL
124 lines
3.7 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
library work;
|
|
use work.common.all;
|
|
|
|
entity cr_file is
|
|
generic (
|
|
SIM : boolean := false;
|
|
-- Non-zero to enable log data collection
|
|
LOG_LENGTH : natural := 0
|
|
);
|
|
port(
|
|
clk : in std_logic;
|
|
|
|
d_in : in Decode2ToCrFileType;
|
|
d_out : out CrFileToDecode2Type;
|
|
|
|
w_in : in WritebackToCrFileType;
|
|
ctrl : in ctrl_t;
|
|
|
|
-- debug
|
|
sim_dump : in std_ulogic;
|
|
|
|
log_out : out std_ulogic_vector(12 downto 0)
|
|
);
|
|
end entity cr_file;
|
|
|
|
architecture behaviour of cr_file is
|
|
signal crs : std_ulogic_vector(31 downto 0) := (others => '0');
|
|
signal crs_updated : std_ulogic_vector(31 downto 0);
|
|
signal xerc : xer_common_t := xerc_init;
|
|
signal xerc_updated : xer_common_t;
|
|
begin
|
|
cr_create_0: process(all)
|
|
variable hi, lo : integer := 0;
|
|
variable cr_tmp : std_ulogic_vector(31 downto 0) := (others => '0');
|
|
begin
|
|
cr_tmp := crs;
|
|
|
|
for i in 0 to 7 loop
|
|
if w_in.write_cr_mask(i) = '1' then
|
|
lo := i*4;
|
|
hi := lo + 3;
|
|
cr_tmp(hi downto lo) := w_in.write_cr_data(hi downto lo);
|
|
end if;
|
|
end loop;
|
|
|
|
crs_updated <= cr_tmp;
|
|
|
|
if w_in.write_xerc_enable = '1' then
|
|
xerc_updated <= w_in.write_xerc_data;
|
|
else
|
|
xerc_updated <= xerc;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
-- synchronous writes
|
|
cr_write_0: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if w_in.write_cr_enable = '1' then
|
|
report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask);
|
|
crs <= crs_updated;
|
|
end if;
|
|
if w_in.write_xerc_enable = '1' then
|
|
report "Writing XERC SO=" & std_ulogic'image(xerc_updated.so) &
|
|
" OV=" & std_ulogic'image(xerc_updated.ov) &
|
|
" CA=" & std_ulogic'image(xerc_updated.ca) &
|
|
" OV32=" & std_ulogic'image(xerc_updated.ov32) &
|
|
" CA32=" & std_ulogic'image(xerc_updated.ca32);
|
|
xerc <= xerc_updated;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- asynchronous reads
|
|
cr_read_0: process(all)
|
|
begin
|
|
-- just return the entire CR to make mfcrf easier for now
|
|
if d_in.read = '1' then
|
|
report "Reading CR " & to_hstring(crs_updated);
|
|
end if;
|
|
d_out.read_cr_data <= crs_updated;
|
|
d_out.read_xerc_data <= xerc_updated;
|
|
end process;
|
|
|
|
sim_dump_test: if SIM generate
|
|
dump_cr: process(all)
|
|
variable xer : std_ulogic_vector(31 downto 0);
|
|
begin
|
|
if sim_dump = '1' then
|
|
report "CR 00000000" & to_hstring(crs);
|
|
xer := (others => '0');
|
|
xer(31) := xerc.so;
|
|
xer(30) := xerc.ov;
|
|
xer(29) := xerc.ca;
|
|
xer(19) := xerc.ov32;
|
|
xer(18) := xerc.ca32;
|
|
xer(17 downto 0) := ctrl.xer_low;
|
|
report "XER 00000000" & to_hstring(xer);
|
|
assert false report "end of test" severity failure;
|
|
end if;
|
|
end process;
|
|
end generate;
|
|
|
|
cf_log: if LOG_LENGTH > 0 generate
|
|
signal log_data : std_ulogic_vector(12 downto 0);
|
|
begin
|
|
cr_log: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
log_data <= w_in.write_cr_enable &
|
|
w_in.write_cr_data(31 downto 28) &
|
|
w_in.write_cr_mask;
|
|
end if;
|
|
end process;
|
|
log_out <= log_data;
|
|
end generate;
|
|
|
|
end architecture behaviour;
|