begin working on linux verilator simulation
[microwatt.git] / writeback.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 use work.crhelpers.all;
8
9 entity writeback is
10 port (
11 clk : in std_ulogic;
12 rst : in std_ulogic;
13
14 e_in : in Execute1ToWritebackType;
15 l_in : in Loadstore1ToWritebackType;
16 fp_in : in FPUToWritebackType;
17
18 w_out : out WritebackToRegisterFileType;
19 c_out : out WritebackToCrFileType;
20 f_out : out WritebackToFetch1Type;
21
22 -- PMU event bus
23 events : out WritebackEventType;
24
25 flush_out : out std_ulogic;
26 interrupt_out: out std_ulogic;
27 complete_out : out instr_tag_t
28 );
29 end entity writeback;
30
31 architecture behaviour of writeback is
32 type irq_state_t is (WRITE_SRR0, WRITE_SRR1);
33
34 type reg_type is record
35 state : irq_state_t;
36 srr1 : std_ulogic_vector(63 downto 0);
37 end record;
38
39 signal r, rin : reg_type;
40
41 begin
42 writeback_0: process(clk)
43 variable x : std_ulogic_vector(0 downto 0);
44 variable y : std_ulogic_vector(0 downto 0);
45 variable w : std_ulogic_vector(0 downto 0);
46 begin
47 if rising_edge(clk) then
48 if rst = '1' then
49 r.state <= WRITE_SRR0;
50 r.srr1 <= (others => '0');
51 else
52 r <= rin;
53 end if;
54
55 -- Do consistency checks only on the clock edge
56 x(0) := e_in.valid;
57 y(0) := l_in.valid;
58 w(0) := fp_in.valid;
59 assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) +
60 to_integer(unsigned(w))) <= 1 severity failure;
61
62 x(0) := e_in.write_enable;
63 y(0) := l_in.write_enable;
64 w(0) := fp_in.write_enable;
65 assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) +
66 to_integer(unsigned(w))) <= 1 severity failure;
67
68 w(0) := e_in.write_cr_enable;
69 x(0) := (e_in.write_enable and e_in.rc);
70 y(0) := fp_in.write_cr_enable;
71 assert (to_integer(unsigned(w)) + to_integer(unsigned(x)) +
72 to_integer(unsigned(y))) <= 1 severity failure;
73
74 assert not (e_in.valid = '1' and e_in.instr_tag.valid = '0') severity failure;
75 assert not (l_in.valid = '1' and l_in.instr_tag.valid = '0') severity failure;
76 assert not (fp_in.valid = '1' and fp_in.instr_tag.valid = '0') severity failure;
77 end if;
78 end process;
79
80 writeback_1: process(all)
81 variable v : reg_type;
82 variable f : WritebackToFetch1Type;
83 variable cf: std_ulogic_vector(3 downto 0);
84 variable zero : std_ulogic;
85 variable sign : std_ulogic;
86 variable scf : std_ulogic_vector(3 downto 0);
87 variable vec : integer range 0 to 16#fff#;
88 variable srr1 : std_ulogic_vector(15 downto 0);
89 variable intr : std_ulogic;
90 begin
91 w_out <= WritebackToRegisterFileInit;
92 c_out <= WritebackToCrFileInit;
93 f := WritebackToFetch1Init;
94 interrupt_out <= '0';
95 vec := 0;
96 v := r;
97
98 complete_out <= instr_tag_init;
99 if e_in.valid = '1' then
100 complete_out <= e_in.instr_tag;
101 elsif l_in.valid = '1' then
102 complete_out <= l_in.instr_tag;
103 elsif fp_in.valid = '1' then
104 complete_out <= fp_in.instr_tag;
105 end if;
106 events.instr_complete <= complete_out.valid;
107 events.fp_complete <= fp_in.valid;
108
109 intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt;
110
111 if r.state = WRITE_SRR1 then
112 w_out.write_reg <= fast_spr_num(SPR_SRR1);
113 w_out.write_data <= r.srr1;
114 w_out.write_enable <= '1';
115 interrupt_out <= '1';
116 v.state := WRITE_SRR0;
117
118 elsif intr = '1' then
119 w_out.write_reg <= fast_spr_num(SPR_SRR0);
120 w_out.write_enable <= '1';
121 v.state := WRITE_SRR1;
122 srr1 := (others => '0');
123 if e_in.interrupt = '1' then
124 vec := e_in.intr_vec;
125 w_out.write_data <= e_in.last_nia;
126 srr1 := e_in.srr1;
127 elsif l_in.interrupt = '1' then
128 vec := l_in.intr_vec;
129 w_out.write_data <= l_in.srr0;
130 srr1 := l_in.srr1;
131 elsif fp_in.interrupt = '1' then
132 vec := fp_in.intr_vec;
133 w_out.write_data <= fp_in.srr0;
134 srr1 := fp_in.srr1;
135 end if;
136 v.srr1(63 downto 31) := e_in.msr(63 downto 31);
137 v.srr1(30 downto 27) := srr1(14 downto 11);
138 v.srr1(26 downto 22) := e_in.msr(26 downto 22);
139 v.srr1(21 downto 16) := srr1(5 downto 0);
140 v.srr1(15 downto 0) := e_in.msr(15 downto 0);
141
142 else
143 if e_in.write_enable = '1' then
144 w_out.write_reg <= e_in.write_reg;
145 w_out.write_data <= e_in.write_data;
146 w_out.write_enable <= '1';
147 end if;
148
149 if e_in.write_cr_enable = '1' then
150 c_out.write_cr_enable <= '1';
151 c_out.write_cr_mask <= e_in.write_cr_mask;
152 c_out.write_cr_data <= e_in.write_cr_data;
153 end if;
154
155 if e_in.write_xerc_enable = '1' then
156 c_out.write_xerc_enable <= '1';
157 c_out.write_xerc_data <= e_in.xerc;
158 end if;
159
160 if fp_in.write_enable = '1' then
161 w_out.write_reg <= fp_in.write_reg;
162 w_out.write_data <= fp_in.write_data;
163 w_out.write_enable <= '1';
164 end if;
165
166 if fp_in.write_cr_enable = '1' then
167 c_out.write_cr_enable <= '1';
168 c_out.write_cr_mask <= fp_in.write_cr_mask;
169 c_out.write_cr_data <= fp_in.write_cr_data;
170 end if;
171
172 if l_in.write_enable = '1' then
173 w_out.write_reg <= l_in.write_reg;
174 w_out.write_data <= l_in.write_data;
175 w_out.write_enable <= '1';
176 end if;
177
178 if l_in.rc = '1' then
179 -- st*cx. instructions
180 scf(3) := '0';
181 scf(2) := '0';
182 scf(1) := l_in.store_done;
183 scf(0) := l_in.xerc.so;
184 c_out.write_cr_enable <= '1';
185 c_out.write_cr_mask <= num_to_fxm(0);
186 c_out.write_cr_data(31 downto 28) <= scf;
187 end if;
188
189 -- Perform CR0 update for RC forms
190 -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data
191 if e_in.rc = '1' and e_in.write_enable = '1' then
192 zero := not (or e_in.write_data(31 downto 0));
193 if e_in.mode_32bit = '0' then
194 sign := e_in.write_data(63);
195 zero := zero and not (or e_in.write_data(63 downto 32));
196 else
197 sign := e_in.write_data(31);
198 end if;
199 c_out.write_cr_enable <= '1';
200 c_out.write_cr_mask <= num_to_fxm(0);
201 cf(3) := sign;
202 cf(2) := not sign and not zero;
203 cf(1) := zero;
204 cf(0) := e_in.xerc.so;
205 c_out.write_cr_data(31 downto 28) <= cf;
206 end if;
207 end if;
208
209 -- Outputs to fetch1
210 f.redirect := e_in.redirect;
211 f.br_nia := e_in.last_nia;
212 f.br_last := e_in.br_last;
213 f.br_taken := e_in.br_taken;
214 if intr = '1' then
215 f.redirect := '1';
216 f.br_last := '0';
217 f.redirect_nia := std_ulogic_vector(to_unsigned(vec, 64));
218 f.virt_mode := '0';
219 f.priv_mode := '1';
220 -- XXX need an interrupt LE bit here, e.g. from LPCR
221 f.big_endian := '0';
222 f.mode_32bit := '0';
223 else
224 if e_in.abs_br = '1' then
225 f.redirect_nia := e_in.br_offset;
226 else
227 f.redirect_nia := std_ulogic_vector(unsigned(e_in.last_nia) + unsigned(e_in.br_offset));
228 end if;
229 -- send MSR[IR], ~MSR[PR], ~MSR[LE] and ~MSR[SF] up to fetch1
230 f.virt_mode := e_in.redir_mode(3);
231 f.priv_mode := e_in.redir_mode(2);
232 f.big_endian := e_in.redir_mode(1);
233 f.mode_32bit := e_in.redir_mode(0);
234 end if;
235
236 f_out <= f;
237 flush_out <= f_out.redirect;
238
239 rin <= v;
240 end process;
241 end;