core: Restore bypass path from execute1
[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
13 e_in : in Execute1ToWritebackType;
14 l_in : in Loadstore1ToWritebackType;
15 fp_in : in FPUToWritebackType;
16
17 w_out : out WritebackToRegisterFileType;
18 c_out : out WritebackToCrFileType;
19
20 complete_out : out instr_tag_t
21 );
22 end entity writeback;
23
24 architecture behaviour of writeback is
25 begin
26 writeback_0: process(clk)
27 variable x : std_ulogic_vector(0 downto 0);
28 variable y : std_ulogic_vector(0 downto 0);
29 variable w : std_ulogic_vector(0 downto 0);
30 begin
31 if rising_edge(clk) then
32 -- Do consistency checks only on the clock edge
33 x(0) := e_in.valid;
34 y(0) := l_in.valid;
35 w(0) := fp_in.valid;
36 assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) +
37 to_integer(unsigned(w))) <= 1 severity failure;
38
39 x(0) := e_in.write_enable or e_in.exc_write_enable;
40 y(0) := l_in.write_enable;
41 w(0) := fp_in.write_enable;
42 assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) +
43 to_integer(unsigned(w))) <= 1 severity failure;
44
45 w(0) := e_in.write_cr_enable;
46 x(0) := (e_in.write_enable and e_in.rc);
47 y(0) := fp_in.write_cr_enable;
48 assert (to_integer(unsigned(w)) + to_integer(unsigned(x)) +
49 to_integer(unsigned(y))) <= 1 severity failure;
50
51 assert not (e_in.valid = '1' and e_in.instr_tag.valid = '0') severity failure;
52 assert not (l_in.valid = '1' and l_in.instr_tag.valid = '0') severity failure;
53 assert not (fp_in.valid = '1' and fp_in.instr_tag.valid = '0') severity failure;
54 end if;
55 end process;
56
57 writeback_1: process(all)
58 variable cf: std_ulogic_vector(3 downto 0);
59 variable zero : std_ulogic;
60 variable sign : std_ulogic;
61 variable scf : std_ulogic_vector(3 downto 0);
62 begin
63 w_out <= WritebackToRegisterFileInit;
64 c_out <= WritebackToCrFileInit;
65
66 complete_out <= instr_tag_init;
67 if e_in.valid = '1' then
68 complete_out <= e_in.instr_tag;
69 elsif l_in.valid = '1' then
70 complete_out <= l_in.instr_tag;
71 elsif fp_in.valid = '1' then
72 complete_out <= fp_in.instr_tag;
73 end if;
74
75 if e_in.exc_write_enable = '1' then
76 w_out.write_reg <= e_in.exc_write_reg;
77 w_out.write_data <= e_in.exc_write_data;
78 w_out.write_enable <= '1';
79 else
80 if e_in.write_enable = '1' then
81 w_out.write_reg <= e_in.write_reg;
82 w_out.write_data <= e_in.write_data;
83 w_out.write_enable <= '1';
84 end if;
85
86 if e_in.write_cr_enable = '1' then
87 c_out.write_cr_enable <= '1';
88 c_out.write_cr_mask <= e_in.write_cr_mask;
89 c_out.write_cr_data <= e_in.write_cr_data;
90 end if;
91
92 if e_in.write_xerc_enable = '1' then
93 c_out.write_xerc_enable <= '1';
94 c_out.write_xerc_data <= e_in.xerc;
95 end if;
96
97 if fp_in.write_enable = '1' then
98 w_out.write_reg <= fp_in.write_reg;
99 w_out.write_data <= fp_in.write_data;
100 w_out.write_enable <= '1';
101 end if;
102
103 if fp_in.write_cr_enable = '1' then
104 c_out.write_cr_enable <= '1';
105 c_out.write_cr_mask <= fp_in.write_cr_mask;
106 c_out.write_cr_data <= fp_in.write_cr_data;
107 end if;
108
109 if l_in.write_enable = '1' then
110 w_out.write_reg <= l_in.write_reg;
111 w_out.write_data <= l_in.write_data;
112 w_out.write_enable <= '1';
113 end if;
114
115 if l_in.rc = '1' then
116 -- st*cx. instructions
117 scf(3) := '0';
118 scf(2) := '0';
119 scf(1) := l_in.store_done;
120 scf(0) := l_in.xerc.so;
121 c_out.write_cr_enable <= '1';
122 c_out.write_cr_mask <= num_to_fxm(0);
123 c_out.write_cr_data(31 downto 28) <= scf;
124 end if;
125
126 -- Perform CR0 update for RC forms
127 -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data
128 if e_in.rc = '1' and e_in.write_enable = '1' then
129 zero := not (or e_in.write_data(31 downto 0));
130 if e_in.mode_32bit = '0' then
131 sign := e_in.write_data(63);
132 zero := zero and not (or e_in.write_data(63 downto 32));
133 else
134 sign := e_in.write_data(31);
135 end if;
136 c_out.write_cr_enable <= '1';
137 c_out.write_cr_mask <= num_to_fxm(0);
138 cf(3) := sign;
139 cf(2) := not sign and not zero;
140 cf(1) := zero;
141 cf(0) := e_in.xerc.so;
142 c_out.write_cr_data(31 downto 28) <= cf;
143 end if;
144 end if;
145 end process;
146 end;