multiply: Move selection of result bits into execute1
[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 );
13 port(
14 clk : in std_ulogic;
15 rst : in std_ulogic;
16
17 -- Control inputs:
18 stall_in : in std_ulogic;
19 flush_in : in std_ulogic;
20 stop_in : in std_ulogic;
21 alt_reset_in : in std_ulogic;
22
23 -- redirect from execution unit
24 e_in : in Execute1ToFetch1Type;
25
26 -- Request to icache
27 i_out : out Fetch1ToIcacheType;
28
29 -- outputs to logger
30 log_out : out std_ulogic_vector(42 downto 0)
31 );
32 end entity fetch1;
33
34 architecture behaviour of fetch1 is
35 type stop_state_t is (RUNNING, STOPPED, RESTARTING);
36 type reg_internal_t is record
37 stop_state: stop_state_t;
38 end record;
39 signal r, r_next : Fetch1ToIcacheType;
40 signal r_int, r_next_int : reg_internal_t;
41 signal log_nia : std_ulogic_vector(42 downto 0);
42 begin
43
44 regs : process(clk)
45 begin
46 if rising_edge(clk) then
47 log_nia <= r.nia(63) & r.nia(43 downto 2);
48 if r /= r_next then
49 report "fetch1 rst:" & std_ulogic'image(rst) &
50 " IR:" & std_ulogic'image(e_in.virt_mode) &
51 " P:" & std_ulogic'image(e_in.priv_mode) &
52 " R:" & std_ulogic'image(e_in.redirect) &
53 " S:" & std_ulogic'image(stall_in) &
54 " T:" & std_ulogic'image(stop_in) &
55 " nia:" & to_hstring(r_next.nia) &
56 " SM:" & std_ulogic'image(r_next.stop_mark);
57 end if;
58 r <= r_next;
59 r_int <= r_next_int;
60 end if;
61 end process;
62 log_out <= log_nia;
63
64 comb : process(all)
65 variable v : Fetch1ToIcacheType;
66 variable v_int : reg_internal_t;
67 variable increment : boolean;
68 begin
69 v := r;
70 v_int := r_int;
71
72 if rst = '1' then
73 if alt_reset_in = '1' then
74 v.nia := ALT_RESET_ADDRESS;
75 else
76 v.nia := RESET_ADDRESS;
77 end if;
78 v.virt_mode := '0';
79 v.priv_mode := '1';
80 v_int.stop_state := RUNNING;
81 elsif e_in.redirect = '1' then
82 v.nia := e_in.redirect_nia;
83 v.virt_mode := e_in.virt_mode;
84 v.priv_mode := e_in.priv_mode;
85 elsif stall_in = '0' then
86
87 -- For debug stop/step to work properly we need a little bit of
88 -- trickery here. If we just stop incrementing and send stop marks
89 -- when stop_in is set, then we'll increment on the cycle it clears
90 -- and end up never executing the instruction we were stopped on.
91 --
92 -- Avoid this along with the opposite issue when stepping (stop is
93 -- cleared for only one cycle) is handled by the state machine below
94 --
95 -- By default, increment addresses
96 increment := true;
97 case v_int.stop_state is
98 when RUNNING =>
99 -- If we are running and stop_in is set, then stop incrementing,
100 -- we are now stopped.
101 if stop_in = '1' then
102 increment := false;
103 v_int.stop_state := STOPPED;
104 end if;
105 when STOPPED =>
106 -- When stopped, never increment. If stop is cleared, go to state
107 -- "restarting" but still don't increment that cycle. stop_in is
108 -- now 0 so we'll send the NIA down without a stop mark.
109 increment := false;
110 if stop_in = '0' then
111 v_int.stop_state := RESTARTING;
112 end if;
113 when RESTARTING =>
114 -- We have just sent the NIA down, we can start incrementing again.
115 -- If stop_in is still not set, go back to running normally.
116 -- If stop_in is set again (that was a one-cycle "step"), go
117 -- back to "stopped" state which means we'll stop incrementing
118 -- on the next cycle. This ensures we increment the PC once after
119 -- sending one instruction without a stop mark. Since stop_in is
120 -- now set, the new PC will be sent with a stop mark and thus not
121 -- executed.
122 if stop_in = '0' then
123 v_int.stop_state := RUNNING;
124 else
125 v_int.stop_state := STOPPED;
126 end if;
127 end case;
128
129 if increment then
130 v.nia := std_logic_vector(unsigned(v.nia) + 4);
131 end if;
132 end if;
133
134 v.req := not rst;
135 v.stop_mark := stop_in;
136
137 r_next <= v;
138 r_next_int <= v_int;
139
140 -- Update outputs to the icache
141 i_out <= r;
142
143 end process;
144
145 end architecture behaviour;