ignore /abc.history
[microwatt.git] / register_file.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 register_file is
9 generic (
10 SIM : boolean := false;
11 HAS_FPU : boolean := true;
12 -- Non-zero to enable log data collection
13 LOG_LENGTH : natural := 0
14 );
15 port(
16 clk : in std_logic;
17 stall : in std_ulogic;
18
19 d1_in : in Decode1ToRegisterFileType;
20 d_in : in Decode2ToRegisterFileType;
21 d_out : out RegisterFileToDecode2Type;
22
23 w_in : in WritebackToRegisterFileType;
24
25 dbg_gpr_req : in std_ulogic;
26 dbg_gpr_ack : out std_ulogic;
27 dbg_gpr_addr : in gspr_index_t;
28 dbg_gpr_data : out std_ulogic_vector(63 downto 0);
29
30 -- debug
31 sim_dump : in std_ulogic;
32 sim_dump_done : out std_ulogic;
33
34 log_out : out std_ulogic_vector(71 downto 0)
35 );
36 end entity register_file;
37
38 architecture behaviour of register_file is
39 type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0);
40 signal registers : regfile := (others => (others => '0'));
41 signal dbg_data : std_ulogic_vector(63 downto 0);
42 signal dbg_ack : std_ulogic;
43 signal dbg_gpr_done : std_ulogic;
44 signal addr_1_reg : gspr_index_t;
45 signal addr_2_reg : gspr_index_t;
46 signal addr_3_reg : gspr_index_t;
47 signal rd_2 : std_ulogic;
48 signal fwd_1 : std_ulogic;
49 signal fwd_2 : std_ulogic;
50 signal fwd_3 : std_ulogic;
51 signal data_1 : std_ulogic_vector(63 downto 0);
52 signal data_2 : std_ulogic_vector(63 downto 0);
53 signal data_3 : std_ulogic_vector(63 downto 0);
54 signal prev_write_data : std_ulogic_vector(63 downto 0);
55
56 begin
57 -- synchronous reads and writes
58 register_write_0: process(clk)
59 variable a_addr, b_addr, c_addr : gspr_index_t;
60 variable w_addr : gspr_index_t;
61 variable b_enable : std_ulogic;
62 begin
63 if rising_edge(clk) then
64 if w_in.write_enable = '1' then
65 w_addr := w_in.write_reg;
66 if HAS_FPU and w_addr(5) = '1' then
67 report "Writing FPR " & to_hstring(w_addr(4 downto 0)) & " " & to_hstring(w_in.write_data);
68 else
69 w_addr(5) := '0';
70 report "Writing GPR " & to_hstring(w_addr) & " " & to_hstring(w_in.write_data);
71 end if;
72 assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure;
73 registers(to_integer(unsigned(w_addr))) <= w_in.write_data;
74 end if;
75
76 a_addr := d1_in.reg_1_addr;
77 b_addr := d1_in.reg_2_addr;
78 c_addr := d1_in.reg_3_addr;
79 b_enable := d1_in.read_2_enable;
80 if stall = '1' then
81 a_addr := addr_1_reg;
82 b_addr := addr_2_reg;
83 c_addr := addr_3_reg;
84 b_enable := rd_2;
85 else
86 addr_1_reg <= a_addr;
87 addr_2_reg <= b_addr;
88 addr_3_reg <= c_addr;
89 rd_2 <= b_enable;
90 end if;
91
92 fwd_1 <= '0';
93 fwd_2 <= '0';
94 fwd_3 <= '0';
95 if w_in.write_enable = '1' then
96 if w_addr = a_addr then
97 fwd_1 <= '1';
98 end if;
99 if w_addr = b_addr then
100 fwd_2 <= '1';
101 end if;
102 if w_addr = c_addr then
103 fwd_3 <= '1';
104 end if;
105 end if;
106
107 -- Do debug reads to GPRs and FPRs using the B port when it is not in use
108 if dbg_gpr_req = '1' then
109 if b_enable = '0' then
110 b_addr := dbg_gpr_addr(5 downto 0);
111 dbg_gpr_done <= '1';
112 end if;
113 else
114 dbg_gpr_done <= '0';
115 end if;
116
117 if not HAS_FPU then
118 -- Make it obvious that we only want 32 GSPRs for a no-FPU implementation
119 a_addr(5) := '0';
120 b_addr(5) := '0';
121 c_addr(5) := '0';
122 end if;
123 if is_X(a_addr) then
124 data_1 <= (others => 'X');
125 else
126 data_1 <= registers(to_integer(unsigned(a_addr)));
127 end if;
128 if is_X(b_addr) then
129 data_2 <= (others => 'X');
130 else
131 data_2 <= registers(to_integer(unsigned(b_addr)));
132 end if;
133 if is_X(c_addr) then
134 data_3 <= (others => 'X');
135 else
136 data_3 <= registers(to_integer(unsigned(c_addr)));
137 end if;
138
139 prev_write_data <= w_in.write_data;
140 end if;
141 end process register_write_0;
142
143 -- asynchronous forwarding of write data
144 register_read_0: process(all)
145 variable out_data_1 : std_ulogic_vector(63 downto 0);
146 variable out_data_2 : std_ulogic_vector(63 downto 0);
147 variable out_data_3 : std_ulogic_vector(63 downto 0);
148 begin
149 out_data_1 := data_1;
150 out_data_2 := data_2;
151 out_data_3 := data_3;
152 if fwd_1 = '1' then
153 out_data_1 := prev_write_data;
154 end if;
155 if fwd_2 = '1' then
156 out_data_2 := prev_write_data;
157 end if;
158 if fwd_3 = '1' then
159 out_data_3 := prev_write_data;
160 end if;
161
162 if d_in.read1_enable = '1' then
163 report "Reading GPR " & to_hstring(addr_1_reg) & " " & to_hstring(out_data_1);
164 end if;
165 if d_in.read2_enable = '1' then
166 report "Reading GPR " & to_hstring(addr_2_reg) & " " & to_hstring(out_data_2);
167 end if;
168 if d_in.read3_enable = '1' then
169 report "Reading GPR " & to_hstring(addr_3_reg) & " " & to_hstring(out_data_3);
170 end if;
171
172 d_out.read1_data <= out_data_1;
173 d_out.read2_data <= out_data_2;
174 d_out.read3_data <= out_data_3;
175 end process register_read_0;
176
177 -- Latch read data and ack if dbg read requested and B port not busy
178 dbg_register_read: process(clk)
179 begin
180 if rising_edge(clk) then
181 if dbg_gpr_req = '1' then
182 if dbg_ack = '0' and dbg_gpr_done = '1' then
183 dbg_data <= data_2;
184 dbg_ack <= '1';
185 end if;
186 else
187 dbg_ack <= '0';
188 end if;
189 end if;
190 end process;
191
192 dbg_gpr_ack <= dbg_ack;
193 dbg_gpr_data <= dbg_data;
194
195 -- Dump registers if core terminates
196 sim_dump_test: if SIM generate
197 dump_registers: process(all)
198 begin
199 if sim_dump = '1' then
200 loop_0: for i in 0 to 31 loop
201 report "GPR" & integer'image(i) & " " & to_hstring(registers(i));
202 end loop loop_0;
203 sim_dump_done <= '1';
204 else
205 sim_dump_done <= '0';
206 end if;
207 end process;
208 end generate;
209
210 -- Keep GHDL synthesis happy
211 sim_dump_test_synth: if not SIM generate
212 sim_dump_done <= '0';
213 end generate;
214
215 rf_log: if LOG_LENGTH > 0 generate
216 signal log_data : std_ulogic_vector(71 downto 0);
217 begin
218 reg_log: process(clk)
219 begin
220 if rising_edge(clk) then
221 log_data <= w_in.write_data &
222 w_in.write_enable &
223 '0' & w_in.write_reg;
224 end if;
225 end process;
226 log_out <= log_data;
227 end generate;
228
229 end architecture behaviour;