dcache: Implement load-reserve and store-conditional instructions
[microwatt.git] / fetch2.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.wishbone_types.all;
8
9 entity fetch2 is
10 port(
11 clk : in std_ulogic;
12 rst : in std_ulogic;
13
14 stall_in : in std_ulogic;
15 flush_in : in std_ulogic;
16
17 -- Results from icache
18 i_in : in IcacheToFetch2Type;
19
20 -- Output to decode
21 f_out : out Fetch2ToDecode1Type
22 );
23 end entity fetch2;
24
25 architecture behaviour of fetch2 is
26
27 -- The icache cannot stall, so we need to stash a cycle
28 -- of output from it when we stall.
29 type reg_internal_type is record
30 stash : IcacheToFetch2Type;
31 stash_valid : std_ulogic;
32 stopped : std_ulogic;
33 end record;
34
35 signal r_int, rin_int : reg_internal_type;
36 signal r, rin : Fetch2ToDecode1Type;
37
38 begin
39 regs : process(clk)
40 begin
41 if rising_edge(clk) then
42
43 if (r /= rin) then
44 report "fetch2 rst:" & std_ulogic'image(rst) &
45 " S:" & std_ulogic'image(stall_in) &
46 " F:" & std_ulogic'image(flush_in) &
47 " T:" & std_ulogic'image(rin.stop_mark) &
48 " V:" & std_ulogic'image(rin.valid) &
49 " nia:" & to_hstring(rin.nia);
50 end if;
51
52 -- Output state remains unchanged on stall, unless we are flushing
53 if rst = '1' or flush_in = '1' or stall_in = '0' then
54 r <= rin;
55 end if;
56
57 -- Internal state is updated on every clock
58 r_int <= rin_int;
59 end if;
60 end process;
61
62 comb : process(all)
63 variable v : Fetch2ToDecode1Type;
64 variable v_int : reg_internal_type;
65 variable v_i_in : IcacheToFetch2Type;
66 begin
67 v := r;
68 v_int := r_int;
69
70 -- If stalling, stash away the current input from the icache
71 if stall_in = '1' and v_int.stash_valid = '0' then
72 v_int.stash := i_in;
73 v_int.stash_valid := '1';
74 end if;
75
76 -- If unstalling, source input from the stash and invalidate it,
77 -- otherwise source normally from the icache.
78 --
79 v_i_in := i_in;
80 if v_int.stash_valid = '1' and stall_in = '0' then
81 v_i_in := v_int.stash;
82 v_int.stash_valid := '0';
83 end if;
84
85 v.valid := v_i_in.valid;
86 v.stop_mark := v_i_in.stop_mark;
87 v.nia := v_i_in.nia;
88 v.insn := v_i_in.insn;
89
90 -- Clear stash internal valid bit on flush. We still mark
91 -- the stash itself as valid since we still want to override
92 -- whatever comes form icache when unstalling, but we'll
93 -- override it with something invalid.
94 --
95 if flush_in = '1' then
96 v_int.stash.valid := '0';
97 end if;
98
99 -- If we are flushing or the instruction comes with a stop mark
100 -- we tag it as invalid so it doesn't get decoded and executed
101 if flush_in = '1' or v.stop_mark = '1' then
102 v.valid := '0';
103 end if;
104
105 -- Clear stash on reset
106 if rst = '1' then
107 v_int.stash_valid := '0';
108 end if;
109
110 -- Update registers
111 rin <= v;
112 rin_int <= v_int;
113
114 -- Update outputs
115 f_out <= r;
116 end process;
117
118 end architecture behaviour;