Add Tercel PHY reset synchronization
[microwatt.git] / logical.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.decode_types.all;
7 use work.ppc_fx_insns.all;
8
9 entity logical is
10 port (
11 rs : in std_ulogic_vector(63 downto 0);
12 rb : in std_ulogic_vector(63 downto 0);
13 op : in insn_type_t;
14 invert_in : in std_ulogic;
15 invert_out : in std_ulogic;
16 result : out std_ulogic_vector(63 downto 0);
17 datalen : in std_logic_vector(3 downto 0)
18 );
19 end entity logical;
20
21 architecture behaviour of logical is
22
23 subtype twobit is unsigned(1 downto 0);
24 type twobit32 is array(0 to 31) of twobit;
25 signal pc2 : twobit32;
26 subtype threebit is unsigned(2 downto 0);
27 type threebit16 is array(0 to 15) of threebit;
28 signal pc4 : threebit16;
29 subtype fourbit is unsigned(3 downto 0);
30 type fourbit8 is array(0 to 7) of fourbit;
31 signal pc8 : fourbit8;
32 subtype sixbit is unsigned(5 downto 0);
33 type sixbit2 is array(0 to 1) of sixbit;
34 signal pc32 : sixbit2;
35 signal par0, par1 : std_ulogic;
36 signal popcnt : std_ulogic_vector(63 downto 0);
37 signal parity : std_ulogic_vector(63 downto 0);
38 signal permute : std_ulogic_vector(7 downto 0);
39
40 function bcd_to_dpd(bcd: std_ulogic_vector(11 downto 0)) return std_ulogic_vector is
41 variable dpd: std_ulogic_vector(9 downto 0);
42 variable a, b, c, d, e, f, g, h, i, j, k, m: std_ulogic;
43 begin
44 -- The following equations are copied from PowerISA v3.0B Book 1 appendix B
45 a := bcd(11);
46 b := bcd(10);
47 c := bcd(9);
48 d := bcd(8);
49 e := bcd(7);
50 f := bcd(6);
51 g := bcd(5);
52 h := bcd(4);
53 i := bcd(3);
54 j := bcd(2);
55 k := bcd(1);
56 m := bcd(0);
57 dpd(9) := (f and a and i and not e) or (j and a and not i) or (b and not a);
58 dpd(8) := (g and a and i and not e) or (k and a and not i) or (c and not a);
59 dpd(7) := d;
60 dpd(6) := (j and not a and e and not i) or (f and not i and not e) or
61 (f and not a and not e) or (e and i);
62 dpd(5) := (k and not a and e and not i) or (g and not i and not e) or
63 (g and not a and not e) or (a and i);
64 dpd(4) := h;
65 dpd(3) := a or e or i;
66 dpd(2) := (not e and j and not i) or (e and i) or a;
67 dpd(1) := (not a and k and not i) or (a and i) or e;
68 dpd(0) := m;
69 return dpd;
70 end;
71
72 function dpd_to_bcd(dpd: std_ulogic_vector(9 downto 0)) return std_ulogic_vector is
73 variable bcd: std_ulogic_vector(11 downto 0);
74 variable p, q, r, s, t, u, v, w, x, y: std_ulogic;
75 begin
76 -- The following equations are copied from PowerISA v3.0B Book 1 appendix B
77 p := dpd(9);
78 q := dpd(8);
79 r := dpd(7);
80 s := dpd(6);
81 t := dpd(5);
82 u := dpd(4);
83 v := dpd(3);
84 w := dpd(2);
85 x := dpd(1);
86 y := dpd(0);
87 bcd(11) := (not s and v and w) or (t and v and w and s) or (v and w and not x);
88 bcd(10) := (p and s and x and not t) or (p and not w) or (p and not v);
89 bcd(9) := (q and s and x and not t) or (q and not w) or (q and not v);
90 bcd(8) := r;
91 bcd(7) := (v and not w and x) or (s and v and w and x) or (not t and v and w and x);
92 bcd(6) := (p and t and v and w and x and not s) or (s and not x and v) or
93 (s and not v);
94 bcd(5) := (q and t and w and v and x and not s) or (t and not x and v) or
95 (t and not v);
96 bcd(4) := u;
97 bcd(3) := (t and v and w and x) or (s and v and w and x) or (v and not w and not x);
98 bcd(2) := (p and not s and not t and w and v) or (s and v and not w and x) or
99 (p and w and not x and v) or (w and not v);
100 bcd(1) := (q and not s and not t and v and w) or (t and v and not w and x) or
101 (q and v and w and not x) or (x and not v);
102 bcd(0) := y;
103 return bcd;
104 end;
105
106 begin
107 logical_0: process(all)
108 variable rb_adj, tmp : std_ulogic_vector(63 downto 0);
109 variable negative : std_ulogic;
110 variable j : integer;
111 begin
112 -- population counts
113 for i in 0 to 31 loop
114 pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
115 end loop;
116 for i in 0 to 15 loop
117 pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));
118 end loop;
119 for i in 0 to 7 loop
120 pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));
121 end loop;
122 for i in 0 to 1 loop
123 pc32(i) <= ("00" & pc8(i * 4)) + ("00" & pc8(i * 4 + 1)) +
124 ("00" & pc8(i * 4 + 2)) + ("00" & pc8(i * 4 + 3));
125 end loop;
126 popcnt <= (others => '0');
127 if datalen(3 downto 2) = "00" then
128 -- popcntb
129 for i in 0 to 7 loop
130 popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8(i));
131 end loop;
132 elsif datalen(3) = '0' then
133 -- popcntw
134 for i in 0 to 1 loop
135 popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));
136 end loop;
137 else
138 popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));
139 end if;
140
141 -- parity calculations
142 par0 <= rs(0) xor rs(8) xor rs(16) xor rs(24);
143 par1 <= rs(32) xor rs(40) xor rs(48) xor rs(56);
144 parity <= (others => '0');
145 if datalen(3) = '1' then
146 parity(0) <= par0 xor par1;
147 else
148 parity(0) <= par0;
149 parity(32) <= par1;
150 end if;
151
152 -- bit permutation
153 for i in 0 to 7 loop
154 j := i * 8;
155 if rs(j+7 downto j+6) = "00" then
156 permute(i) <= rb(to_integer(unsigned(rs(j+5 downto j))));
157 else
158 permute(i) <= '0';
159 end if;
160 end loop;
161
162 rb_adj := rb;
163 if invert_in = '1' then
164 rb_adj := not rb;
165 end if;
166
167 case op is
168 when OP_AND | OP_OR | OP_XOR =>
169 case op is
170 when OP_AND =>
171 tmp := rs and rb_adj;
172 when OP_OR =>
173 tmp := rs or rb_adj;
174 when others =>
175 tmp := rs xor rb_adj;
176 end case;
177 if invert_out = '1' then
178 tmp := not tmp;
179 end if;
180
181 when OP_POPCNT =>
182 tmp := popcnt;
183 when OP_PRTY =>
184 tmp := parity;
185 when OP_CMPB =>
186 tmp := ppc_cmpb(rs, rb);
187 when OP_BPERM =>
188 tmp := std_ulogic_vector(resize(unsigned(permute), 64));
189 when OP_BCD =>
190 -- invert_in is abused to indicate direction of conversion
191 if invert_in = '0' then
192 -- cbcdtd
193 tmp := x"000" & bcd_to_dpd(rs(55 downto 44)) & bcd_to_dpd(rs(43 downto 32)) &
194 x"000" & bcd_to_dpd(rs(23 downto 12)) & bcd_to_dpd(rs(11 downto 0));
195 else
196 -- cdtbcd
197 tmp := x"00" & dpd_to_bcd(rs(51 downto 42)) & dpd_to_bcd(rs(41 downto 32)) &
198 x"00" & dpd_to_bcd(rs(19 downto 10)) & dpd_to_bcd(rs(9 downto 0));
199 end if;
200 when OP_EXTS =>
201 -- note datalen is a 1-hot encoding
202 negative := (datalen(0) and rs(7)) or
203 (datalen(1) and rs(15)) or
204 (datalen(2) and rs(31));
205 tmp := (others => negative);
206 if datalen(2) = '1' then
207 tmp(31 downto 16) := rs(31 downto 16);
208 end if;
209 if datalen(2) = '1' or datalen(1) = '1' then
210 tmp(15 downto 8) := rs(15 downto 8);
211 end if;
212 tmp(7 downto 0) := rs(7 downto 0);
213 when others =>
214 -- e.g. OP_MTSPR
215 tmp := rs;
216 end case;
217
218 result <= tmp;
219
220 end process;
221 end behaviour;