ignore /abc.history
[microwatt.git] / fetch1.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.common.all;
7
8 entity fetch1 is
9 generic(
10 RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
11 ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
12 HAS_BTC : boolean := true
13 );
14 port(
15 clk : in std_ulogic;
16 rst : in std_ulogic;
17
18 -- Control inputs:
19 stall_in : in std_ulogic;
20 flush_in : in std_ulogic;
21 inval_btc : in std_ulogic;
22 stop_in : in std_ulogic;
23 alt_reset_in : in std_ulogic;
24
25 -- redirect from writeback unit
26 w_in : in WritebackToFetch1Type;
27
28 -- redirect from decode1
29 d_in : in Decode1ToFetch1Type;
30
31 -- Request to icache
32 i_out : out Fetch1ToIcacheType;
33
34 -- outputs to logger
35 log_out : out std_ulogic_vector(42 downto 0)
36 );
37 end entity fetch1;
38
39 architecture behaviour of fetch1 is
40 type reg_internal_t is record
41 mode_32bit: std_ulogic;
42 rd_is_niap4: std_ulogic;
43 predicted_taken: std_ulogic;
44 predicted_nia: std_ulogic_vector(63 downto 0);
45 end record;
46 signal r, r_next : Fetch1ToIcacheType;
47 signal r_int, r_next_int : reg_internal_t;
48 signal advance_nia : std_ulogic;
49 signal log_nia : std_ulogic_vector(42 downto 0);
50
51 constant BTC_ADDR_BITS : integer := 10;
52 constant BTC_TAG_BITS : integer := 62 - BTC_ADDR_BITS;
53 constant BTC_TARGET_BITS : integer := 62;
54 constant BTC_SIZE : integer := 2 ** BTC_ADDR_BITS;
55 constant BTC_WIDTH : integer := BTC_TAG_BITS + BTC_TARGET_BITS + 2;
56 type btc_mem_type is array (0 to BTC_SIZE - 1) of std_ulogic_vector(BTC_WIDTH - 1 downto 0);
57
58 signal btc_rd_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0) := (others => '0');
59 signal btc_rd_valid : std_ulogic := '0';
60
61 begin
62
63 regs : process(clk)
64 begin
65 if rising_edge(clk) then
66 log_nia <= r.nia(63) & r.nia(43 downto 2);
67 if r /= r_next then
68 report "fetch1 rst:" & std_ulogic'image(rst) &
69 " IR:" & std_ulogic'image(r_next.virt_mode) &
70 " P:" & std_ulogic'image(r_next.priv_mode) &
71 " E:" & std_ulogic'image(r_next.big_endian) &
72 " 32:" & std_ulogic'image(r_next_int.mode_32bit) &
73 " R:" & std_ulogic'image(w_in.redirect) & std_ulogic'image(d_in.redirect) &
74 " S:" & std_ulogic'image(stall_in) &
75 " T:" & std_ulogic'image(stop_in) &
76 " nia:" & to_hstring(r_next.nia);
77 end if;
78 if rst = '1' or w_in.redirect = '1' or d_in.redirect = '1' or stall_in = '0' then
79 r.virt_mode <= r_next.virt_mode;
80 r.priv_mode <= r_next.priv_mode;
81 r.big_endian <= r_next.big_endian;
82 r_int.mode_32bit <= r_next_int.mode_32bit;
83 end if;
84 if advance_nia = '1' then
85 r.predicted <= r_next.predicted;
86 r.pred_ntaken <= r_next.pred_ntaken;
87 r.nia <= r_next.nia;
88 r_int.predicted_taken <= r_next_int.predicted_taken;
89 r_int.predicted_nia <= r_next_int.predicted_nia;
90 r_int.rd_is_niap4 <= r_next_int.rd_is_niap4;
91 end if;
92 -- always send the up-to-date stop mark and req
93 r.stop_mark <= stop_in;
94 r.req <= not rst and not stop_in;
95 end if;
96 end process;
97 log_out <= log_nia;
98
99 btc : if HAS_BTC generate
100 signal btc_memory : btc_mem_type;
101 attribute ram_style : string;
102 attribute ram_style of btc_memory : signal is "block";
103
104 signal btc_valids : std_ulogic_vector(BTC_SIZE - 1 downto 0);
105 attribute ram_style of btc_valids : signal is "distributed";
106
107 signal btc_wr : std_ulogic;
108 signal btc_wr_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0);
109 signal btc_wr_addr : std_ulogic_vector(BTC_ADDR_BITS - 1 downto 0);
110 begin
111 btc_wr_data <= w_in.br_taken &
112 r.virt_mode &
113 w_in.br_nia(63 downto BTC_ADDR_BITS + 2) &
114 w_in.redirect_nia(63 downto 2);
115 btc_wr_addr <= w_in.br_nia(BTC_ADDR_BITS + 1 downto 2);
116 btc_wr <= w_in.br_last;
117
118 btc_ram : process(clk)
119 variable raddr : unsigned(BTC_ADDR_BITS - 1 downto 0);
120 begin
121 if rising_edge(clk) then
122 raddr := unsigned(r.nia(BTC_ADDR_BITS + 1 downto 2)) +
123 to_unsigned(2, BTC_ADDR_BITS);
124 if advance_nia = '1' then
125 if is_X(raddr) then
126 btc_rd_data <= (others => 'X');
127 btc_rd_valid <= 'X';
128 else
129 btc_rd_data <= btc_memory(to_integer(raddr));
130 btc_rd_valid <= btc_valids(to_integer(raddr));
131 end if;
132 end if;
133 if btc_wr = '1' then
134 assert not is_X(btc_wr_addr) report "Writing to unknown address" severity FAILURE;
135 btc_memory(to_integer(unsigned(btc_wr_addr))) <= btc_wr_data;
136 end if;
137 if inval_btc = '1' or rst = '1' then
138 btc_valids <= (others => '0');
139 elsif btc_wr = '1' then
140 assert not is_X(btc_wr_addr) report "Writing to unknown address" severity FAILURE;
141 btc_valids(to_integer(unsigned(btc_wr_addr))) <= '1';
142 end if;
143 end if;
144 end process;
145 end generate;
146
147 comb : process(all)
148 variable v : Fetch1ToIcacheType;
149 variable v_int : reg_internal_t;
150 begin
151 v := r;
152 v_int := r_int;
153 v.predicted := '0';
154 v.pred_ntaken := '0';
155 v_int.predicted_taken := '0';
156 v_int.rd_is_niap4 := '0';
157
158 if rst = '1' then
159 if alt_reset_in = '1' then
160 v.nia := ALT_RESET_ADDRESS;
161 else
162 v.nia := RESET_ADDRESS;
163 end if;
164 v.virt_mode := '0';
165 v.priv_mode := '1';
166 v.big_endian := '0';
167 v_int.mode_32bit := '0';
168 v_int.predicted_nia := (others => '0');
169 elsif w_in.redirect = '1' then
170 v.nia := w_in.redirect_nia(63 downto 2) & "00";
171 if w_in.mode_32bit = '1' then
172 v.nia(63 downto 32) := (others => '0');
173 end if;
174 v.virt_mode := w_in.virt_mode;
175 v.priv_mode := w_in.priv_mode;
176 v.big_endian := w_in.big_endian;
177 v_int.mode_32bit := w_in.mode_32bit;
178 elsif d_in.redirect = '1' then
179 v.nia := d_in.redirect_nia(63 downto 2) & "00";
180 if r_int.mode_32bit = '1' then
181 v.nia(63 downto 32) := (others => '0');
182 end if;
183 elsif r_int.predicted_taken = '1' then
184 v.nia := r_int.predicted_nia;
185 elsif r.req = '1' then
186 v_int.rd_is_niap4 := '1';
187 v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
188 if r_int.mode_32bit = '1' then
189 v.nia(63 downto 32) := x"00000000";
190 end if;
191 if btc_rd_valid = '1' and r_int.rd_is_niap4 = '1' and
192 btc_rd_data(BTC_WIDTH - 2) = r.virt_mode and
193 btc_rd_data(BTC_WIDTH - 3 downto BTC_TARGET_BITS)
194 = v.nia(BTC_TAG_BITS + BTC_ADDR_BITS + 1 downto BTC_ADDR_BITS + 2) then
195 v_int.predicted_taken := btc_rd_data(BTC_WIDTH - 1);
196 v.predicted := btc_rd_data(BTC_WIDTH - 1);
197 v.pred_ntaken := not btc_rd_data(BTC_WIDTH - 1);
198 end if;
199 end if;
200 v_int.predicted_nia := btc_rd_data(BTC_TARGET_BITS - 1 downto 0) & "00";
201
202 -- If the last NIA value went down with a stop mark, it didn't get
203 -- executed, and hence we shouldn't increment NIA.
204 advance_nia <= rst or w_in.redirect or d_in.redirect or (not r.stop_mark and not stall_in);
205
206 r_next <= v;
207 r_next_int <= v_int;
208
209 -- Update outputs to the icache
210 i_out <= r;
211
212 end process;
213
214 end architecture behaviour;