Add CR hazard detection
[microwatt.git] / control.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 entity control is
5 generic (
6 PIPELINE_DEPTH : natural := 2
7 );
8 port (
9 clk : in std_ulogic;
10 rst : in std_ulogic;
11
12 complete_in : in std_ulogic;
13 valid_in : in std_ulogic;
14 flush_in : in std_ulogic;
15 sgl_pipe_in : in std_ulogic;
16 stop_mark_in : in std_ulogic;
17
18 gpr_write_valid_in : in std_ulogic;
19 gpr_write_in : in std_ulogic_vector(4 downto 0);
20
21 gpr_a_read_valid_in : in std_ulogic;
22 gpr_a_read_in : in std_ulogic_vector(4 downto 0);
23
24 gpr_b_read_valid_in : in std_ulogic;
25 gpr_b_read_in : in std_ulogic_vector(4 downto 0);
26
27 gpr_c_read_valid_in : in std_ulogic;
28 gpr_c_read_in : in std_ulogic_vector(4 downto 0);
29
30 cr_read_in : in std_ulogic;
31 cr_write_in : in std_ulogic;
32
33 valid_out : out std_ulogic;
34 stall_out : out std_ulogic;
35 stopped_out : out std_ulogic
36 );
37 end entity control;
38
39 architecture rtl of control is
40 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
41
42 type reg_internal_type is record
43 state : state_type;
44 outstanding : integer range -1 to PIPELINE_DEPTH+2;
45 end record;
46 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
47
48 signal r_int, rin_int : reg_internal_type := reg_internal_init;
49
50 signal stall_a_out : std_ulogic;
51 signal stall_b_out : std_ulogic;
52 signal stall_c_out : std_ulogic;
53 signal cr_stall_out : std_ulogic;
54
55 signal gpr_write_valid : std_ulogic := '0';
56 signal cr_write_valid : std_ulogic := '0';
57 begin
58 gpr_hazard0: entity work.gpr_hazard
59 generic map (
60 PIPELINE_DEPTH => 2
61 )
62 port map (
63 clk => clk,
64
65 gpr_write_valid_in => gpr_write_valid,
66 gpr_write_in => gpr_write_in,
67 gpr_read_valid_in => gpr_a_read_valid_in,
68 gpr_read_in => gpr_a_read_in,
69
70 stall_out => stall_a_out
71 );
72
73 gpr_hazard1: entity work.gpr_hazard
74 generic map (
75 PIPELINE_DEPTH => 2
76 )
77 port map (
78 clk => clk,
79
80 gpr_write_valid_in => gpr_write_valid,
81 gpr_write_in => gpr_write_in,
82 gpr_read_valid_in => gpr_b_read_valid_in,
83 gpr_read_in => gpr_b_read_in,
84
85 stall_out => stall_b_out
86 );
87
88 gpr_hazard2: entity work.gpr_hazard
89 generic map (
90 PIPELINE_DEPTH => 2
91 )
92 port map (
93 clk => clk,
94
95 gpr_write_valid_in => gpr_write_valid,
96 gpr_write_in => gpr_write_in,
97 gpr_read_valid_in => gpr_c_read_valid_in,
98 gpr_read_in => gpr_c_read_in,
99
100 stall_out => stall_c_out
101 );
102
103 cr_hazard0: entity work.cr_hazard
104 generic map (
105 PIPELINE_DEPTH => 2
106 )
107 port map (
108 clk => clk,
109
110 cr_read_in => cr_read_in,
111 cr_write_in => cr_write_valid,
112
113 stall_out => cr_stall_out
114 );
115
116 control0: process(clk)
117 begin
118 if rising_edge(clk) then
119 assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
120 r_int <= rin_int;
121 end if;
122 end process;
123
124 control1 : process(all)
125 variable v_int : reg_internal_type;
126 variable valid_tmp : std_ulogic;
127 variable stall_tmp : std_ulogic;
128 begin
129 v_int := r_int;
130
131 -- asynchronous
132 valid_tmp := valid_in and not flush_in;
133 stall_tmp := '0';
134
135 if complete_in = '1' then
136 v_int.outstanding := r_int.outstanding - 1;
137 end if;
138
139 -- Handle debugger stop
140 stopped_out <= '0';
141 if stop_mark_in = '1' and v_int.outstanding = 0 then
142 stopped_out <= '1';
143 end if;
144
145 -- state machine to handle instructions that must be single
146 -- through the pipeline.
147 case r_int.state is
148 when IDLE =>
149 if valid_tmp = '1' then
150 if (sgl_pipe_in = '1') then
151 if v_int.outstanding /= 0 then
152 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
153 stall_tmp := '1';
154 else
155 -- send insn out and wait on it to complete
156 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
157 end if;
158 else
159 -- let it go out if there are no GPR hazards
160 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
161 end if;
162 end if;
163
164 when WAIT_FOR_PREV_TO_COMPLETE =>
165 if v_int.outstanding = 0 then
166 -- send insn out and wait on it to complete
167 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
168 else
169 stall_tmp := '1';
170 end if;
171
172 when WAIT_FOR_CURR_TO_COMPLETE =>
173 if v_int.outstanding = 0 then
174 v_int.state := IDLE;
175 -- XXX Don't replicate this
176 if valid_tmp = '1' then
177 if (sgl_pipe_in = '1') then
178 if v_int.outstanding /= 0 then
179 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
180 stall_tmp := '1';
181 else
182 -- send insn out and wait on it to complete
183 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
184 end if;
185 else
186 -- let it go out if there are no GPR hazards
187 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
188 end if;
189 end if;
190 else
191 stall_tmp := '1';
192 end if;
193 end case;
194
195 if stall_tmp = '1' then
196 valid_tmp := '0';
197 end if;
198
199 if valid_tmp = '1' then
200 v_int.outstanding := v_int.outstanding + 1;
201 gpr_write_valid <= gpr_write_valid_in;
202 cr_write_valid <= cr_write_in;
203 else
204 gpr_write_valid <= '0';
205 cr_write_valid <= '0';
206 end if;
207
208 if rst = '1' then
209 v_int.state := IDLE;
210 v_int.outstanding := 0;
211 stall_tmp := '0';
212 end if;
213
214 -- update outputs
215 valid_out <= valid_tmp;
216 stall_out <= stall_tmp;
217
218 -- update registers
219 rin_int <= v_int;
220 end process;
221 end;