2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
7 use work.crhelpers.all;
14 e_in : in Execute1ToWritebackType;
15 l_in : in Loadstore1ToWritebackType;
16 fp_in : in FPUToWritebackType;
18 w_out : out WritebackToRegisterFileType;
19 c_out : out WritebackToCrFileType;
20 f_out : out WritebackToFetch1Type;
23 events : out WritebackEventType;
25 flush_out : out std_ulogic;
26 interrupt_out: out std_ulogic;
27 complete_out : out instr_tag_t
31 architecture behaviour of writeback is
32 type irq_state_t is (WRITE_SRR0, WRITE_SRR1);
34 type reg_type is record
36 srr1 : std_ulogic_vector(63 downto 0);
39 signal r, rin : reg_type;
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);
47 if rising_edge(clk) then
49 r.state <= WRITE_SRR0;
50 r.srr1 <= (others => '0');
55 -- Do consistency checks only on the clock edge
59 assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) +
60 to_integer(unsigned(w))) <= 1 severity failure;
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;
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;
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;
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;
91 w_out <= WritebackToRegisterFileInit;
92 c_out <= WritebackToCrFileInit;
93 f := WritebackToFetch1Init;
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;
106 events.instr_complete <= complete_out.valid;
107 events.fp_complete <= fp_in.valid;
109 intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt;
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;
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;
127 elsif l_in.interrupt = '1' then
128 vec := l_in.intr_vec;
129 w_out.write_data <= l_in.srr0;
131 elsif fp_in.interrupt = '1' then
132 vec := fp_in.intr_vec;
133 w_out.write_data <= fp_in.srr0;
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);
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';
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;
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;
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';
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;
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';
178 if l_in.rc = '1' then
179 -- st*cx. instructions
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;
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));
197 sign := e_in.write_data(31);
199 c_out.write_cr_enable <= '1';
200 c_out.write_cr_mask <= num_to_fxm(0);
202 cf(2) := not sign and not zero;
204 cf(0) := e_in.xerc.so;
205 c_out.write_cr_data(31 downto 28) <= cf;
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;
217 f.redirect_nia := std_ulogic_vector(to_unsigned(vec, 64));
220 -- XXX need an interrupt LE bit here, e.g. from LPCR
224 if e_in.abs_br = '1' then
225 f.redirect_nia := e_in.br_offset;
227 f.redirect_nia := std_ulogic_vector(unsigned(e_in.last_nia) + unsigned(e_in.br_offset));
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);
237 flush_out <= f_out.redirect;