-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathopa_isa_base_pkg.vhd
282 lines (254 loc) · 9.73 KB
/
opa_isa_base_pkg.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
-- opa: Open Processor Architecture
-- Copyright (C) 2014-2016 Wesley W. Terpstra
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- To apply the GPL to my VHDL, please follow these definitions:
-- Program - The entire collection of VHDL in this project and any
-- netlist or floorplan derived from it.
-- System Library - Any macro that translates directly to hardware
-- e.g. registers, IO pins, or memory blocks
--
-- My intent is that if you include OPA into your project, all of the HDL
-- and other design files that go into the same physical chip must also
-- be released under the GPL. If this does not cover your usage, then you
-- must consult me directly to receive the code under a different license.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package opa_isa_base_pkg is
type t_opa_isa_info is record
big_endian : boolean;
num_arch : natural;
imm_wide : natural;
op_wide : natural;
page_size : natural;
end record t_opa_isa_info;
-- All processors must fit under these limits. Increase them if needed.
constant c_imm_wide_max : natural := 128;
constant c_log_arch_max : natural := 8; -- log2(num_arch)
-- Fast execute units operate in one of four modes
-- An example of instructions each mode can handle:
-- lut: XORI, ORI, ANDI, XOR, OR, AND, LUI
-- addlu: AUIPC, ADDI, ADD, SUB
-- addhs: BLT, BGE, SLTI, SLT, BLTU, BGEU, SLTIU, SLTU, BEQ, BNE
-- jump: JAL, JALR
constant c_opa_fast_lut : std_logic_vector(1 downto 0) := "00";
constant c_opa_fast_addl : std_logic_vector(1 downto 0) := "01";
constant c_opa_fast_addh : std_logic_vector(1 downto 0) := "10";
constant c_opa_fast_jump : std_logic_vector(1 downto 0) := "11";
type t_opa_adder is record
eq : std_logic;
nota : std_logic;
notb : std_logic;
cin : std_logic;
sign : std_logic;
fault : std_logic;
end record t_opa_adder;
-- Slow execute units operate in one of four modes
-- mul (00)
-- shift (01)
-- load (10)
-- store (11)
-- An example of instructions each mode can handle:
-- mul: MUL, MULH, MULHSU, MULHU [DIV, DIVU, REM, REMU]
-- shift: SLLI, SRLI, SRAI, SLL, SRL, SRA
-- load: LB, LH, LW, LBU, LHU
-- store: SB, SH, SW
constant c_opa_slow_mul : std_logic_vector(1 downto 0) := "00";
constant c_opa_slow_shift : std_logic_vector(1 downto 0) := "01";
constant c_opa_slow_ldst : std_logic_vector(1 downto 0) := "10";
constant c_opa_slow_sext : std_logic_vector(1 downto 0) := "11";
type t_opa_mul is record
sexta : std_logic; -- DIV|DIVU
sextb : std_logic;
high : std_logic; -- MULH|REM vs. MUL|DIV
divide : std_logic;
end record t_opa_mul;
type t_opa_shift is record
right : std_logic;
sext : std_logic;
end record t_opa_shift;
constant c_opa_ldst_byte : std_logic_vector(1 downto 0) := "00";
constant c_opa_ldst_half : std_logic_vector(1 downto 0) := "01";
constant c_opa_ldst_word : std_logic_vector(1 downto 0) := "10";
constant c_opa_ldst_quad : std_logic_vector(1 downto 0) := "11";
type t_opa_ldst is record
store : std_logic;
sext : std_logic;
size : std_logic_vector(1 downto 0); -- 1,2,4,8
end record t_opa_ldst;
type t_opa_sext is record
size : std_logic_vector(1 downto 0);
end record t_opa_sext;
type t_opa_arg is record
fmode : std_logic_vector(1 downto 0);
adder : t_opa_adder;
lut : std_logic_vector(3 downto 0);
smode : std_logic_vector(1 downto 0);
mul : t_opa_mul;
shift : t_opa_shift;
ldst : t_opa_ldst;
sext : t_opa_sext;
end record t_opa_arg;
-- General information every instruction must provide
type t_opa_op is record
-- Information for the rename stage
archa : std_logic_vector(c_log_arch_max-1 downto 0);
archb : std_logic_vector(c_log_arch_max-1 downto 0);
archx : std_logic_vector(c_log_arch_max-1 downto 0);
geta : std_logic; -- 1=rega, 0=PC
getb : std_logic; -- 1=regb, 0=imm
setx : std_logic;
-- Information for the decode stage
bad : std_logic;
jump : std_logic;
take : std_logic; -- true => jump
force : std_logic; -- true => take
pop : std_logic; -- pop return stack; '-' when jump=0
push : std_logic; -- push return stack; '-' when jump=0
immb : std_logic_vector(c_imm_wide_max-1 downto 0); -- branch immediates; less cases than imm.
-- Information for the issue stage
fast : std_logic; -- goes to fast/slow EU
order : std_logic; -- don't issue it unless it is last
-- Information for the execute stage
imm : std_logic_vector(c_imm_wide_max-1 downto 0);
arg : t_opa_arg;
end record t_opa_op;
constant c_opa_op_bad : t_opa_op := (
archa => (others => '-'),
archb => (others => '-'),
archx => (others => '-'),
geta => '-',
getb => '-',
setx => '-',
bad => '1',
jump => '-',
take => '-',
force => '-',
pop => '-',
push => '-',
immb => (others => '-'),
fast => '-',
order => '-',
imm => (others => '-'),
arg => (
fmode => (others => '-'),
adder => (eq => '-', nota => '-', notb => '-', cin => '-', sign => '-', fault => '-'),
lut => (others => '-'),
smode => (others => '-'),
mul => (sexta => '-', sextb => '-', high => '-', divide => '-'),
shift => (right => '-', sext => '-'),
ldst => (store => '-', sext => '-', size => (others => '-')),
sext => (size => (others => '-'))));
constant c_opa_op_undef : t_opa_op := (
archa => (others => 'X'),
archb => (others => 'X'),
archx => (others => 'X'),
geta => 'X',
getb => 'X',
setx => 'X',
bad => 'X',
jump => 'X',
take => 'X',
force => 'X',
pop => 'X',
push => 'X',
immb => (others => 'X'),
fast => 'X',
order => 'X',
imm => (others => 'X'),
arg => (
fmode => (others => 'X'),
adder => (eq => 'X', nota => 'X', notb => 'X', cin => 'X', sign => 'X', fault => 'X'),
lut => (others => 'X'),
smode => (others => 'X'),
mul => (sexta => 'X', sextb => 'X', high => 'X', divide => 'X'),
shift => (right => 'X', sext => 'X'),
ldst => (store => 'X', sext => 'X', size => (others => 'X')),
sext => (size => (others => 'X'))));
-- Even ISAs need this function
function f_opa_log2(x : natural) return natural;
function f_opa_and(x : std_logic_vector) return std_logic;
function f_opa_or(x : std_logic_vector) return std_logic;
-- Define the arguments needed for operations in our execution units
constant c_arg_wide : natural := 26;
function f_opa_vec_from_arg(x : t_opa_arg) return std_logic_vector;
function f_opa_arg_from_vec(x : std_logic_vector(c_arg_wide-1 downto 0)) return t_opa_arg;
end package;
package body opa_isa_base_pkg is
function f_opa_vec_from_arg(x : t_opa_arg) return std_logic_vector is
variable result : std_logic_vector(c_arg_wide-1 downto 0);
begin
result :=
x.fmode &
x.adder.eq & x.adder.nota & x.adder.notb & x.adder.cin & x.adder.sign & x.adder.fault &
x.lut &
x.smode &
x.mul.sexta & x.mul.sextb & x.mul.high & x.mul.high &
x.shift.right & x.shift.sext &
x.ldst.store & x.ldst.sext & x.ldst.size &
x.sext.size;
return result;
end f_opa_vec_from_arg;
function f_opa_arg_from_vec(x : std_logic_vector(c_arg_wide-1 downto 0)) return t_opa_arg is
variable result : t_opa_arg;
begin
result.fmode := x(25 downto 24);
result.adder.eq := x(23);
result.adder.nota := x(22);
result.adder.notb := x(21);
result.adder.cin := x(20);
result.adder.sign := x(19);
result.adder.fault := x(18);
result.lut := x(17 downto 14);
result.smode := x(13 downto 12);
result.mul.sexta := x(11);
result.mul.sextb := x(10);
result.mul.high := x(9);
result.mul.divide := x(8);
result.shift.right := x(7);
result.shift.sext := x(6);
result.ldst.store := x(5);
result.ldst.sext := x(4);
result.ldst.size := x(3 downto 2);
result.sext.size := x(1 downto 0);
return result;
end f_opa_arg_from_vec;
function f_opa_log2(x : natural) return natural is
begin
if x <= 1
then return 0;
else return f_opa_log2((x+1)/2)+1;
end if;
end f_opa_log2;
function f_opa_or(x : std_logic_vector) return std_logic is
alias y : std_logic_vector(x'length-1 downto 0) is x;
constant c_mid : natural := (y'high + y'low) / 2;
begin
if y'length = 0 then return '0'; end if;
if y'length = 1 then return y(y'low); end if;
return f_opa_or(y(y'high downto c_mid+1)) or
f_opa_or(y(c_mid downto y'low));
end f_opa_or;
function f_opa_and(x : std_logic_vector) return std_logic is
alias y : std_logic_vector(x'length-1 downto 0) is x;
constant c_mid : natural := (y'high + y'low) / 2;
begin
if y'length = 0 then return '1'; end if;
if y'length = 1 then return y(y'left); end if;
return f_opa_and(y(y'high downto c_mid+1)) and
f_opa_and(y(c_mid downto y'low));
end f_opa_and;
end opa_isa_base_pkg;