| 1 |
2 |
tarookumic |
|
| 2 |
|
|
|
| 3 |
|
|
|
| 4 |
|
|
|
| 5 |
|
|
----------------------------------------------------------------------------
|
| 6 |
|
|
-- This file is a part of the LEON VHDL model
|
| 7 |
|
|
-- Copyright (C) 1999 European Space Agency (ESA)
|
| 8 |
|
|
--
|
| 9 |
|
|
-- This library is free software; you can redistribute it and/or
|
| 10 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
| 11 |
|
|
-- License as published by the Free Software Foundation; either
|
| 12 |
|
|
-- version 2 of the License, or (at your option) any later version.
|
| 13 |
|
|
--
|
| 14 |
|
|
-- See the file COPYING.LGPL for the full details of the license.
|
| 15 |
|
|
|
| 16 |
|
|
|
| 17 |
|
|
-----------------------------------------------------------------------------
|
| 18 |
|
|
-- Entity: iu
|
| 19 |
|
|
-- File: iu.vhd
|
| 20 |
|
|
-- Author: Jiri Gaisler - ESA/ESTEC
|
| 21 |
|
|
-- Description: LEON integer unit. Consists of 5 pipline stages: fetch,
|
| 22 |
|
|
-- decode, execute, memory and write-back. Each stage is
|
| 23 |
|
|
-- implemented in a separate process.
|
| 24 |
|
|
------------------------------------------------------------------------------
|
| 25 |
|
|
|
| 26 |
|
|
library IEEE;
|
| 27 |
|
|
use IEEE.std_logic_1164.all;
|
| 28 |
|
|
use IEEE.std_logic_arith.all;
|
| 29 |
|
|
use IEEE.std_logic_unsigned."+";
|
| 30 |
|
|
use IEEE.std_logic_unsigned."-";
|
| 31 |
|
|
use IEEE.std_logic_unsigned.conv_integer;
|
| 32 |
|
|
use work.leon_target.all;
|
| 33 |
|
|
use work.leon_config.all;
|
| 34 |
|
|
use work.mmuconfig.all;
|
| 35 |
|
|
use work.sparcv8.all;
|
| 36 |
|
|
use work.leon_iface.all;
|
| 37 |
|
|
use work.macro.all;
|
| 38 |
|
|
use work.tech_map.all;
|
| 39 |
|
|
use work.multlib.all;
|
| 40 |
|
|
|
| 41 |
|
|
entity iu is
|
| 42 |
|
|
port (
|
| 43 |
|
|
rst : in std_logic;
|
| 44 |
|
|
clk : in clk_type;
|
| 45 |
|
|
holdn : in std_logic;
|
| 46 |
|
|
ici : out icache_in_type; -- icache input
|
| 47 |
|
|
ico : in icache_out_type; -- icache output
|
| 48 |
|
|
dci : out dcache_in_type; -- dcache input
|
| 49 |
|
|
dco : in dcache_out_type; -- dcache output
|
| 50 |
|
|
fpui : out fpu_in_type; -- FPU input
|
| 51 |
|
|
fpuo : in fpu_out_type; -- FPU output
|
| 52 |
|
|
iui : in iu_in_type; -- system input
|
| 53 |
|
|
iuo : out iu_out_type; -- system output
|
| 54 |
|
|
rfi : out rf_in_type; -- register-file input
|
| 55 |
|
|
rfo : in rf_out_type; -- register-file output
|
| 56 |
|
|
cpi : out cp_in_type; -- CP input
|
| 57 |
|
|
cpo : in cp_out_type; -- CP output
|
| 58 |
|
|
fpi : out cp_in_type; -- FP input
|
| 59 |
|
|
fpo : in cp_out_type -- FP output
|
| 60 |
|
|
);
|
| 61 |
|
|
end;
|
| 62 |
|
|
|
| 63 |
|
|
architecture rtl of iu is
|
| 64 |
|
|
|
| 65 |
|
|
-- pipeline_control type is defined in package iface
|
| 66 |
|
|
|
| 67 |
|
|
type fetch_stage_inputs is record
|
| 68 |
|
|
branch : std_logic; -- select branch address
|
| 69 |
|
|
jump : std_logic; -- select jump address
|
| 70 |
|
|
exception : std_logic; -- select exception address
|
| 71 |
|
|
hold_pc : std_logic; -- hold PC (multi-cycle inst.)
|
| 72 |
|
|
branch_address : std_logic_vector(31 downto PCLOW); -- branch address
|
| 73 |
|
|
jump_address : std_logic_vector(31 downto PCLOW); -- jump address
|
| 74 |
|
|
trap_address : std_logic_vector(31 downto PCLOW); -- trap address
|
| 75 |
|
|
end record;
|
| 76 |
|
|
|
| 77 |
|
|
type fetch_stage_registers is record
|
| 78 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
| 79 |
|
|
branch : std_logic; -- branch indicator
|
| 80 |
|
|
end record;
|
| 81 |
|
|
|
| 82 |
|
|
type decode_stage_type is record
|
| 83 |
|
|
inst : std_logic_vector(31 downto 0); -- instruction
|
| 84 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
| 85 |
|
|
mexc : std_logic; -- memory exception (fetch)
|
| 86 |
|
|
annul : std_logic; -- instruction annul bit
|
| 87 |
|
|
cnt : std_logic_vector(1 downto 0); -- cycle number (multi-cycle inst)
|
| 88 |
|
|
mulcnt : std_logic_vector(4 downto 0); -- cycle number (multiplier)
|
| 89 |
|
|
pv : std_logic; -- PC valid flag
|
| 90 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
| 91 |
|
|
step : std_logic; -- single step
|
| 92 |
|
|
end record;
|
| 93 |
|
|
|
| 94 |
|
|
type execute_stage_type is record
|
| 95 |
|
|
write_cwp, write_icc, write_reg, write_y, rst_mey : std_logic;
|
| 96 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
| 97 |
|
|
icc : std_logic_vector(3 downto 0); -- integer condition codes
|
| 98 |
|
|
alu_cin : std_logic; -- ALU carry-in
|
| 99 |
|
|
ymsb : std_logic; -- MULSCC Y(msb)
|
| 100 |
|
|
rs1data : std_logic_vector(31 downto 0); -- source operand 1
|
| 101 |
|
|
rs2data : std_logic_vector(31 downto 0); -- source operand 2
|
| 102 |
|
|
aluop : std_logic_vector(2 downto 0); -- Alu operation
|
| 103 |
|
|
alusel : std_logic_vector(1 downto 0); -- Alu result select
|
| 104 |
|
|
aluadd : std_logic; -- add/sub select
|
| 105 |
|
|
mulstep : std_logic; -- MULSCC
|
| 106 |
|
|
mulinsn : std_logic; -- SMUL/UMUL
|
| 107 |
|
|
ldbp1, ldbp2 : std_logic; -- load bypass enable
|
| 108 |
|
|
ctrl : pipeline_control_type;
|
| 109 |
|
|
result : std_logic_vector(31 downto 0); -- data forward from execute stage
|
| 110 |
|
|
micc : std_logic_vector(3 downto 0); -- icc for multiply insn
|
| 111 |
|
|
licc : std_logic_vector(3 downto 0); -- icc to me stage
|
| 112 |
|
|
end record;
|
| 113 |
|
|
|
| 114 |
|
|
type memory_stage_type is record
|
| 115 |
|
|
inull : std_logic;
|
| 116 |
|
|
signed : std_logic; -- signed load
|
| 117 |
|
|
addr_misal : std_logic; -- misaligned address
|
| 118 |
|
|
write_cwp, write_icc, write_reg, write_y : std_logic;
|
| 119 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
| 120 |
|
|
icc : std_logic_vector(3 downto 0);
|
| 121 |
|
|
result : std_logic_vector(31 downto 0);
|
| 122 |
|
|
bpresult : std_logic_vector(31 downto 0); -- result for bypass to de & me
|
| 123 |
|
|
y : std_logic_vector(31 downto 0); -- pipeline Y register
|
| 124 |
|
|
my : std_logic_vector(31 downto 0); -- me stage Y feedback
|
| 125 |
|
|
memory_load : std_logic;
|
| 126 |
|
|
mulinsn : std_logic; -- SMUL/UMUL
|
| 127 |
|
|
ld_size : std_logic_vector(1 downto 0); -- memory load size
|
| 128 |
|
|
ctrl : pipeline_control_type;
|
| 129 |
|
|
jmpl_rett : std_logic;
|
| 130 |
|
|
irqen : std_logic;
|
| 131 |
|
|
ipend : std_logic;
|
| 132 |
|
|
werr : std_logic; -- store error
|
| 133 |
|
|
su : std_logic; -- supervisor mode
|
| 134 |
|
|
end record;
|
| 135 |
|
|
|
| 136 |
|
|
type write_stage_type is record
|
| 137 |
|
|
write_cwp, write_icc, write_reg : std_logic;
|
| 138 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
| 139 |
|
|
icc : std_logic_vector(3 downto 0);
|
| 140 |
|
|
result : std_logic_vector(31 downto 0);
|
| 141 |
|
|
y : std_logic_vector(31 downto 0);
|
| 142 |
|
|
asr18 : std_logic_vector(31 downto 0);
|
| 143 |
|
|
annul_all : std_logic;
|
| 144 |
|
|
trapping : std_logic;
|
| 145 |
|
|
error : std_logic;
|
| 146 |
|
|
nerror : std_logic;
|
| 147 |
|
|
mexc : std_logic;
|
| 148 |
|
|
intack : std_logic;
|
| 149 |
|
|
tpcsel : std_logic_vector(1 downto 0); -- Trap pc select
|
| 150 |
|
|
dsutrap : std_logic; -- debug unit trap (optional)
|
| 151 |
|
|
ctrl : pipeline_control_type;
|
| 152 |
|
|
|
| 153 |
|
|
end record;
|
| 154 |
|
|
|
| 155 |
|
|
type special_register_type is record
|
| 156 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
| 157 |
|
|
icc : std_logic_vector(3 downto 0); -- integer condition codes
|
| 158 |
|
|
tt : std_logic_vector(7 downto 0); -- trap type
|
| 159 |
|
|
tba : std_logic_vector(19 downto 0); -- trap base address
|
| 160 |
|
|
wim : std_logic_vector(NWINDOWS-1 downto 0); -- window invalid mask
|
| 161 |
|
|
pil : std_logic_vector(3 downto 0); -- processor interrupt level
|
| 162 |
|
|
ec : std_logic; -- enable CP
|
| 163 |
|
|
ef : std_logic; -- enable FP
|
| 164 |
|
|
ps : std_logic; -- previous supervisor flag
|
| 165 |
|
|
s : std_logic; -- supervisor flag
|
| 166 |
|
|
et : std_logic; -- enable traps
|
| 167 |
|
|
end record;
|
| 168 |
|
|
|
| 169 |
|
|
type fsr_type is record
|
| 170 |
|
|
cexc : std_logic_vector(4 downto 0); -- current exceptions
|
| 171 |
|
|
aexc : std_logic_vector(4 downto 0); -- accrued exceptions
|
| 172 |
|
|
fcc : std_logic_vector(1 downto 0); -- FPU condition codes
|
| 173 |
|
|
ftt : std_logic_vector(2 downto 0); -- FPU trap type
|
| 174 |
|
|
tem : std_logic_vector(4 downto 0); -- trap enable mask
|
| 175 |
|
|
rd : std_logic_vector(1 downto 0); -- rounding mode
|
| 176 |
|
|
end record;
|
| 177 |
|
|
|
| 178 |
|
|
type fpu_ctrl1_type is record
|
| 179 |
|
|
fpop : std_logic_vector(1 downto 0); -- FPOP type
|
| 180 |
|
|
dsz : std_logic; -- destination size (0=single, 1=double)
|
| 181 |
|
|
ldfsr : std_logic; -- LDFSR in progress
|
| 182 |
|
|
end record;
|
| 183 |
|
|
|
| 184 |
|
|
type fpu_ctrl2_type is record
|
| 185 |
|
|
fpop : std_logic_vector(1 downto 0);
|
| 186 |
|
|
dsz : std_logic;
|
| 187 |
|
|
fcc : std_logic_vector(1 downto 0);
|
| 188 |
|
|
cexc : std_logic_vector(4 downto 0); -- current FPU excetion bits
|
| 189 |
|
|
ldfsr : std_logic;
|
| 190 |
|
|
end record;
|
| 191 |
|
|
|
| 192 |
|
|
type fpu_reg_type is record
|
| 193 |
|
|
fsr : fsr_type;
|
| 194 |
|
|
fpop : std_logic;
|
| 195 |
|
|
reset : std_logic;
|
| 196 |
|
|
rstdel : std_logic_vector(1 downto 0);
|
| 197 |
|
|
fpbusy : std_logic;
|
| 198 |
|
|
fpld : std_logic;
|
| 199 |
|
|
fpexc : std_logic;
|
| 200 |
|
|
op1h : std_logic_vector(31 downto 0);
|
| 201 |
|
|
ex : fpu_ctrl1_type;
|
| 202 |
|
|
me, wr : fpu_ctrl2_type;
|
| 203 |
|
|
end record;
|
| 204 |
|
|
|
| 205 |
|
|
constant WPALEN : integer := 30;
|
| 206 |
|
|
type watchpoint_register is record
|
| 207 |
|
|
addr : std_logic_vector(WPALEN+1 downto 2); -- watchpoint address
|
| 208 |
|
|
mask : std_logic_vector(WPALEN+1 downto 2); -- watchpoint mask
|
| 209 |
|
|
exec : std_logic; -- trap on instruction
|
| 210 |
|
|
load : std_logic; -- trap on load
|
| 211 |
|
|
store : std_logic; -- trap on store
|
| 212 |
|
|
end record;
|
| 213 |
|
|
|
| 214 |
|
|
type watchpoint_registers is array (0 to 3) of watchpoint_register;
|
| 215 |
|
|
|
| 216 |
|
|
type dsu_registers is record
|
| 217 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
| 218 |
|
|
dmode : std_logic; -- debug mode active
|
| 219 |
|
|
dmode2 : std_logic; -- debug mode active (delayed)
|
| 220 |
|
|
dstate : std_logic; -- debug state
|
| 221 |
|
|
tt : std_logic_vector(7 downto 0); -- trap type
|
| 222 |
|
|
error : std_logic; -- trap would cause error
|
| 223 |
|
|
dsuen : std_logic;
|
| 224 |
|
|
end record;
|
| 225 |
|
|
|
| 226 |
|
|
component div
|
| 227 |
|
|
port (
|
| 228 |
|
|
rst : in std_logic;
|
| 229 |
|
|
clk : in clk_type;
|
| 230 |
|
|
holdn : in std_logic;
|
| 231 |
|
|
divi : in div_in_type;
|
| 232 |
|
|
divo : out div_out_type
|
| 233 |
|
|
);
|
| 234 |
|
|
end component;
|
| 235 |
|
|
|
| 236 |
|
|
component mul
|
| 237 |
|
|
port (
|
| 238 |
|
|
rst : in std_logic;
|
| 239 |
|
|
clk : in clk_type;
|
| 240 |
|
|
holdn : in std_logic;
|
| 241 |
|
|
muli : in mul_in_type;
|
| 242 |
|
|
mulo : out mul_out_type
|
| 243 |
|
|
);
|
| 244 |
|
|
end component;
|
| 245 |
|
|
|
| 246 |
|
|
-- registers
|
| 247 |
|
|
|
| 248 |
|
|
constant FASTADD : boolean := false;
|
| 249 |
|
|
constant PILOPT : boolean := FASTDECODE;
|
| 250 |
|
|
constant Zero32: std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
|
| 251 |
|
|
signal fecomb : fetch_stage_inputs;
|
| 252 |
|
|
signal fe, fein : fetch_stage_registers;
|
| 253 |
|
|
signal de, dein : decode_stage_type;
|
| 254 |
|
|
signal ex, exin : execute_stage_type;
|
| 255 |
|
|
signal me, mein : memory_stage_type;
|
| 256 |
|
|
signal wr, wrin : write_stage_type;
|
| 257 |
|
|
signal sregsin, sregs : special_register_type;
|
| 258 |
|
|
signal dciin : dcache_in_type;
|
| 259 |
|
|
signal fpu_reg, fpu_regin : fpu_reg_type;
|
| 260 |
|
|
signal tr, trin : watchpoint_registers;
|
| 261 |
|
|
signal dsur, dsurin : dsu_registers;
|
| 262 |
|
|
signal muli : mul_in_type; -- multiplier input
|
| 263 |
|
|
signal mulo : mul_out_type; -- muliplier output
|
| 264 |
|
|
signal divi : div_in_type; -- divider input
|
| 265 |
|
|
signal divo : div_out_type; -- divider output
|
| 266 |
|
|
signal sum32, add32in1, add32in2 : std_logic_vector(31 downto 0);
|
| 267 |
|
|
signal add32cin : std_logic;
|
| 268 |
|
|
|
| 269 |
|
|
begin
|
| 270 |
|
|
|
| 271 |
|
|
-------------------------------------------------------------------------------
|
| 272 |
|
|
-- Instruction fetch stage
|
| 273 |
|
|
-------------------------------------------------------------------------------
|
| 274 |
|
|
|
| 275 |
|
|
fetch_stage : process(fecomb, fe, rst, de, mein)
|
| 276 |
|
|
variable v : fetch_stage_registers;
|
| 277 |
|
|
variable npc : std_logic_vector(31 downto PCLOW);
|
| 278 |
|
|
begin
|
| 279 |
|
|
|
| 280 |
|
|
v := fe;
|
| 281 |
|
|
|
| 282 |
|
|
-- pc generation
|
| 283 |
|
|
|
| 284 |
|
|
npc := fe.pc;
|
| 285 |
|
|
if (rst = '0') then
|
| 286 |
|
|
v.pc := (others => '0'); v.branch := '0';
|
| 287 |
|
|
elsif fecomb.exception = '1' then -- exception
|
| 288 |
|
|
v.branch := '1'; v.pc := fecomb.trap_address;
|
| 289 |
|
|
npc := v.pc;
|
| 290 |
|
|
elsif (not mein.inull and fecomb.hold_pc) = '1' then
|
| 291 |
|
|
v.pc := fe.pc; v.branch := fe.branch;
|
| 292 |
|
|
elsif fecomb.jump = '1' then
|
| 293 |
|
|
v.pc := fecomb.jump_address; v.branch := '1';
|
| 294 |
|
|
npc := v.pc;
|
| 295 |
|
|
elsif fecomb.branch = '1' then
|
| 296 |
|
|
v.pc := fecomb.branch_address; v.branch := '1';
|
| 297 |
|
|
npc := v.pc;
|
| 298 |
|
|
else
|
| 299 |
|
|
v.branch := '0';
|
| 300 |
|
|
-- pragma translate_off
|
| 301 |
|
|
if not is_x(fe.pc) then
|
| 302 |
|
|
-- pragma translate_on
|
| 303 |
|
|
v.pc(31 downto 2) := fe.pc(31 downto 2) + 1; -- Address incrementer
|
| 304 |
|
|
-- pragma translate_off
|
| 305 |
|
|
else
|
| 306 |
|
|
v.pc := (others => 'X');
|
| 307 |
|
|
end if;
|
| 308 |
|
|
-- pragma translate_on
|
| 309 |
|
|
npc := v.pc;
|
| 310 |
|
|
end if;
|
| 311 |
|
|
|
| 312 |
|
|
-- drive register inputs
|
| 313 |
|
|
|
| 314 |
|
|
fein <= v;
|
| 315 |
|
|
|
| 316 |
|
|
-- drive some icache inputs
|
| 317 |
|
|
|
| 318 |
|
|
-- ici.rpc(31 downto PCLOW) <= v.pc(31 downto PCLOW);
|
| 319 |
|
|
ici.rpc(31 downto PCLOW) <= npc;
|
| 320 |
|
|
ici.fpc(31 downto PCLOW) <= fe.pc(31 downto PCLOW);
|
| 321 |
|
|
ici.dpc(31 downto PCLOW) <= de.pc(31 downto PCLOW);
|
| 322 |
|
|
ici.fbranch <= fe.branch;
|
| 323 |
|
|
ici.rbranch <= v.branch;
|
| 324 |
|
|
|
| 325 |
|
|
end process;
|
| 326 |
|
|
|
| 327 |
|
|
-------------------------------------------------------------------------------
|
| 328 |
|
|
-- Instruction decode stage
|
| 329 |
|
|
-------------------------------------------------------------------------------
|
| 330 |
|
|
|
| 331 |
|
|
|
| 332 |
|
|
decode_stage : process(rst, fe, de, ex, me, mein, wrin, wr, sregs, ico, rfo,
|
| 333 |
|
|
sregsin, fpo, cpo, dco, holdn, fpu_reg, mulo, divo, tr,
|
| 334 |
|
|
iui, dsur)
|
| 335 |
|
|
|
| 336 |
|
|
variable rfenable1, rfenable2 : std_logic; -- regfile enable strobes
|
| 337 |
|
|
variable op : std_logic_vector(1 downto 0);
|
| 338 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
| 339 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
| 340 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
| 341 |
|
|
variable cond : std_logic_vector(3 downto 0);
|
| 342 |
|
|
variable rs1, rs2, rd : std_logic_vector(4 downto 0);
|
| 343 |
|
|
variable write_cwp, write_icc, write_reg, write_y : std_logic;
|
| 344 |
|
|
variable cnt : std_logic_vector(1 downto 0); -- cycle number
|
| 345 |
|
|
variable cwp_new : std_logic_vector(NWINLOG2-1 downto 0);
|
| 346 |
|
|
variable icc, br_icc : std_logic_vector(3 downto 0);
|
| 347 |
|
|
variable alu_cin : std_logic;
|
| 348 |
|
|
variable immediate_data : std_logic_vector(31 downto 0);
|
| 349 |
|
|
variable n, z, v, c : std_logic; -- temporary condition codes
|
| 350 |
|
|
variable i : std_logic; -- immidiate data bit
|
| 351 |
|
|
variable su : std_logic; -- local supervisor bit;
|
| 352 |
|
|
variable et : std_logic; -- local enable trap bit
|
| 353 |
|
|
variable inull, annul, annul_current : std_logic;
|
| 354 |
|
|
variable branch, annul_next, bres, branch_true: std_logic;
|
| 355 |
|
|
variable aluop : std_logic_vector(2 downto 0);
|
| 356 |
|
|
variable alusel : std_logic_vector(1 downto 0);
|
| 357 |
|
|
variable aluadd : std_logic;
|
| 358 |
|
|
variable mulstep : std_logic;
|
| 359 |
|
|
variable mulinsn : std_logic;
|
| 360 |
|
|
variable y0 : std_logic;
|
| 361 |
|
|
variable branch_address : std_logic_vector(31 downto PCLOW);
|
| 362 |
|
|
variable rs1data, rs2data : std_logic_vector(31 downto 0);
|
| 363 |
|
|
variable operand2_select : std_logic;
|
| 364 |
|
|
variable read_addr1, read_addr2, chkrd : std_logic_vector(RABITS-1 downto 0);
|
| 365 |
|
|
variable hold_pc : std_logic; -- Hold PC during multi-cycle ops
|
| 366 |
|
|
variable pv : std_logic; -- PC valid
|
| 367 |
|
|
variable ldlock, ldcheck1, ldcheck2, ldcheck3 : std_logic; -- load interlock
|
| 368 |
|
|
variable ldchkex, ldchkme : std_logic; -- load interlock for ex and me
|
| 369 |
|
|
variable illegal_inst : std_logic; -- illegal instruction
|
| 370 |
|
|
variable privileged_inst : std_logic; -- privileged instruction trap
|
| 371 |
|
|
variable cp_disabled : std_logic; -- CP disable trap
|
| 372 |
|
|
variable fp_disabled : std_logic; -- FP disable trap
|
| 373 |
|
|
variable watchpoint_exc : std_logic; -- watchpoint trap
|
| 374 |
|
|
variable winovf_exception : std_logic; -- window overflow trap
|
| 375 |
|
|
variable winunf_exception : std_logic; -- window underflow trap
|
| 376 |
|
|
variable ticc_exception : std_logic; -- TICC trap
|
| 377 |
|
|
variable fp_exception : std_logic; -- STDFQ trap
|
| 378 |
|
|
variable ctrl : pipeline_control_type;
|
| 379 |
|
|
variable ldbp1, ldbp2 : std_logic; -- load bypass enable
|
| 380 |
|
|
variable mulcnt : std_logic_vector(4 downto 0); -- multiply cycle number
|
| 381 |
|
|
variable ymsb : std_logic; -- next msb of Y during MUL
|
| 382 |
|
|
variable rst_mey : std_logic; -- reset me stage Y register
|
| 383 |
|
|
variable fpld, fpst, fpop : std_logic; -- FPU instructions
|
| 384 |
|
|
variable fpmov : std_logic; -- FPU instructions
|
| 385 |
|
|
variable fbres, fbranch_true : std_logic; -- FBCC branch result
|
| 386 |
|
|
variable cbres, cbranch_true : std_logic; -- CBCC branch result
|
| 387 |
|
|
variable fcc : std_logic_vector(1 downto 0); -- FPU condition codes
|
| 388 |
|
|
variable ccc : std_logic_vector(1 downto 0); -- CP condition codes
|
| 389 |
|
|
variable cwpmax : std_logic_vector(4 downto 0);
|
| 390 |
|
|
variable bicc_hold, icc_check : std_logic;
|
| 391 |
|
|
variable fsr_ld, fsr_ld_check, fsr_check, fsr_lock : std_logic;
|
| 392 |
|
|
variable fpexin : fpu_ctrl1_type;
|
| 393 |
|
|
variable rs1mod : std_logic;
|
| 394 |
|
|
variable step : std_logic;
|
| 395 |
|
|
variable divstart,mulstart : std_logic; -- start multiply or divide
|
| 396 |
|
|
variable cpldlock, fpldlock, annul_current_cp : std_logic;
|
| 397 |
|
|
constant RDOPT : boolean := FASTDECODE;-- optimise dest reg address generation
|
| 398 |
|
|
constant RS1OPT : boolean := FASTDECODE;-- optimise src1 reg address generation
|
| 399 |
|
|
|
| 400 |
|
|
function regdec(cwp, regin : std_logic_vector; fp : std_logic)
|
| 401 |
|
|
return std_logic_vector is
|
| 402 |
|
|
variable reg : std_logic_vector(4 downto 0);
|
| 403 |
|
|
variable ra : std_logic_vector(RABITS -1 downto 0);
|
| 404 |
|
|
begin
|
| 405 |
|
|
reg := regin; ra(4 downto 0) := reg;
|
| 406 |
|
|
if (FPIFTYPE = serial) and (fp = '1') then
|
| 407 |
|
|
ra(RABITS -1 downto 5) := F0ADDR(RABITS-5 downto 1);
|
| 408 |
|
|
elsif reg(4 downto 3) = "00" then ra(RABITS -1 downto 4) := R0ADDR;
|
| 409 |
|
|
else
|
| 410 |
|
|
-- pragma translate_off
|
| 411 |
|
|
if not (is_x(cwp & ra(4))) then
|
| 412 |
|
|
-- pragma translate_on
|
| 413 |
|
|
ra(NWINLOG2+3 downto 4) := (cwp + ra(4));
|
| 414 |
|
|
if CWPOPT then ra(RABITS-1) := '0';
|
| 415 |
|
|
elsif ra(RABITS-1 downto 4) = R0ADDR then
|
| 416 |
|
|
ra(RABITS-1 downto 4) := (others => '0');
|
| 417 |
|
|
end if;
|
| 418 |
|
|
-- pragma translate_off
|
| 419 |
|
|
end if;
|
| 420 |
|
|
-- pragma translate_on
|
| 421 |
|
|
end if;
|
| 422 |
|
|
return(ra);
|
| 423 |
|
|
end;
|
| 424 |
|
|
|
| 425 |
|
|
begin
|
| 426 |
|
|
|
| 427 |
|
|
-- instruction bit-field decoding
|
| 428 |
|
|
|
| 429 |
|
|
op := de.inst(31 downto 30);
|
| 430 |
|
|
op2 := de.inst(24 downto 22);
|
| 431 |
|
|
op3 := de.inst(24 downto 19);
|
| 432 |
|
|
opf := de.inst(13 downto 5);
|
| 433 |
|
|
cond := de.inst(28 downto 25);
|
| 434 |
|
|
annul := de.inst(29);
|
| 435 |
|
|
rs1 := de.inst(18 downto 14);
|
| 436 |
|
|
rs2 := de.inst(4 downto 0);
|
| 437 |
|
|
rd := de.inst(29 downto 25);
|
| 438 |
|
|
i := de.inst(13);
|
| 439 |
|
|
|
| 440 |
|
|
-- common initialisation
|
| 441 |
|
|
|
| 442 |
|
|
ctrl.annul := de.annul; ctrl.cnt := de.cnt; ctrl.pv := de.pv; pv := '1';
|
| 443 |
|
|
cnt := "00"; ctrl.tt := "000000"; ctrl.ld := '0'; ctrl.rett := '0';
|
| 444 |
|
|
ctrl.pc := de.pc; ctrl.inst := de.inst; mulcnt := de.mulcnt;
|
| 445 |
|
|
write_y := '0'; fpld := '0'; fpst := '0'; fpop := '0';
|
| 446 |
|
|
fp_exception := '0'; fpmov := '0'; step := '0';
|
| 447 |
|
|
fpexin.fpop := "00"; fpexin.dsz := '0'; fpexin.ldfsr := '0';
|
| 448 |
|
|
|
| 449 |
|
|
winovf_exception := '0'; winunf_exception := '0';
|
| 450 |
|
|
write_cwp := '0'; cwp_new := de.cwp; rs1mod := '0';
|
| 451 |
|
|
rfenable1 := '0'; rfenable2 := '0';
|
| 452 |
|
|
|
| 453 |
|
|
-- detect RETT instruction in the pipeline and set the local psr.su and psr.et
|
| 454 |
|
|
|
| 455 |
|
|
if ((ex.ctrl.rett and not ex.ctrl.annul) or (me.ctrl.rett and not me.ctrl.annul) or
|
| 456 |
|
|
(wr.ctrl.rett and not wr.ctrl.annul)) = '1'
|
| 457 |
|
|
then
|
| 458 |
|
|
su := sregs.ps; et := '1';
|
| 459 |
|
|
else
|
| 460 |
|
|
su := sregs.s; et := sregs.et;
|
| 461 |
|
|
end if;
|
| 462 |
|
|
|
| 463 |
|
|
-- Check for illegal and privileged instructions
|
| 464 |
|
|
|
| 465 |
|
|
illegal_inst := '0'; privileged_inst := '0'; cp_disabled := '0';
|
| 466 |
|
|
fp_disabled := '0';
|
| 467 |
|
|
case op is
|
| 468 |
|
|
when CALL => null;
|
| 469 |
|
|
when FMT2 =>
|
| 470 |
|
|
case op2 is
|
| 471 |
|
|
when SETHI | BICC => null;
|
| 472 |
|
|
when FBFCC =>
|
| 473 |
|
|
if FPEN then fp_disabled := not sregs.ef;
|
| 474 |
|
|
else fp_disabled := '1'; end if;
|
| 475 |
|
|
when CBCCC =>
|
| 476 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
| 477 |
|
|
when others => illegal_inst := '1';
|
| 478 |
|
|
end case;
|
| 479 |
|
|
when FMT3 =>
|
| 480 |
|
|
case op3 is
|
| 481 |
|
|
when IAND | ANDCC | ANDN | ANDNCC | IOR | ORCC | ORN | ORNCC | IXOR |
|
| 482 |
|
|
XORCC | IXNOR | XNORCC | ISLL | ISRL | ISRA | MULSCC | IADD | ADDX |
|
| 483 |
|
|
ADDCC | ADDXCC | TADDCC | TADDCCTV | ISUB | SUBX | SUBCC | SUBXCC |
|
| 484 |
|
|
TSUBCC | TSUBCCTV | FLUSH | JMPL | TICC | SAVE | RESTORE | RDY => null;
|
| 485 |
|
|
when UMAC | SMAC =>
|
| 486 |
|
|
if not MACEN then illegal_inst := '1'; end if;
|
| 487 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 488 |
|
|
if MULTIPLIER = none then illegal_inst := '1'; end if;
|
| 489 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
| 490 |
|
|
if DIVIDER = none then illegal_inst := '1'; end if;
|
| 491 |
|
|
when RETT => illegal_inst := et; privileged_inst := not su;
|
| 492 |
|
|
when RDPSR | RDTBR | RDWIM => privileged_inst := not su;
|
| 493 |
|
|
when WRY =>
|
| 494 |
|
|
|
| 495 |
|
|
if not ((rd = "00000") or ((rd = "10010") and MACEN) or
|
| 496 |
|
|
((rd(4 downto 3) = "11") and (WATCHPOINTS > 0)))
|
| 497 |
|
|
then
|
| 498 |
|
|
|
| 499 |
|
|
illegal_inst := '1';
|
| 500 |
|
|
end if;
|
| 501 |
|
|
when WRPSR =>
|
| 502 |
|
|
privileged_inst := not su;
|
| 503 |
|
|
when WRWIM | WRTBR => privileged_inst := not su;
|
| 504 |
|
|
when FPOP1 | FPOP2 =>
|
| 505 |
|
|
if FPEN then fp_disabled := not sregs.ef; fpop := '1';
|
| 506 |
|
|
else fp_disabled := '1'; fpop := '0'; end if;
|
| 507 |
|
|
when CPOP1 | CPOP2 =>
|
| 508 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
| 509 |
|
|
when others => illegal_inst := '1';
|
| 510 |
|
|
end case;
|
| 511 |
|
|
when others => -- LDST
|
| 512 |
|
|
case op3 is
|
| 513 |
|
|
when LDD | ISTD => illegal_inst := rd(0); -- trap if odd destination register
|
| 514 |
|
|
when LD | LDUB | LDSTUB | LDUH | LDSB | LDSH | ST | STB | STH | SWAP =>
|
| 515 |
|
|
null;
|
| 516 |
|
|
when LDDA | STDA =>
|
| 517 |
|
|
illegal_inst := i or rd(0); privileged_inst := not su;
|
| 518 |
|
|
when LDA | LDUBA| LDSTUBA | LDUHA | LDSBA | LDSHA | STA | STBA | STHA |
|
| 519 |
|
|
SWAPA =>
|
| 520 |
|
|
illegal_inst := i; privileged_inst := not su;
|
| 521 |
|
|
when LDDF | STDF | LDF | LDFSR | STF | STFSR =>
|
| 522 |
|
|
if FPEN then fp_disabled := not sregs.ef;
|
| 523 |
|
|
else fp_disabled := '1'; end if;
|
| 524 |
|
|
when STDFQ =>
|
| 525 |
|
|
privileged_inst := not su;
|
| 526 |
|
|
if (not FPEN) or (sregs.ef = '0') then fp_disabled := '1'; end if;
|
| 527 |
|
|
when STDCQ =>
|
| 528 |
|
|
privileged_inst := not su;
|
| 529 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
| 530 |
|
|
when LDC | LDCSR | LDDC | STC | STCSR | STDC =>
|
| 531 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
| 532 |
|
|
when others => illegal_inst := '1';
|
| 533 |
|
|
end case;
|
| 534 |
|
|
end case;
|
| 535 |
|
|
|
| 536 |
|
|
-- branch address adder
|
| 537 |
|
|
|
| 538 |
|
|
branch_address := (others => '0');
|
| 539 |
|
|
if op = CALL then branch_address(31 downto 2) := de.inst(29 downto 0);
|
| 540 |
|
|
else branch_address(31 downto 2) := de.inst(21) & de.inst(21) & de.inst(21) &
|
| 541 |
|
|
de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) &
|
| 542 |
|
|
de.inst(21) & de.inst(21 downto 0);
|
| 543 |
|
|
end if;
|
| 544 |
|
|
|
| 545 |
|
|
-- pragma translate_off
|
| 546 |
|
|
if not (is_x(branch_address) or is_x(de.pc)) then
|
| 547 |
|
|
-- pragma translate_on
|
| 548 |
|
|
branch_address := branch_address + de.pc; -- address adder (branch)
|
| 549 |
|
|
-- pragma translate_off
|
| 550 |
|
|
else
|
| 551 |
|
|
branch_address := (others => 'X');
|
| 552 |
|
|
end if;
|
| 553 |
|
|
-- pragma translate_on
|
| 554 |
|
|
|
| 555 |
|
|
fecomb.branch_address <= branch_address;
|
| 556 |
|
|
|
| 557 |
|
|
-- ICC pipeline and forwarding
|
| 558 |
|
|
|
| 559 |
|
|
if (me.write_icc and not me.ctrl.annul) = '1' then icc := wrin.icc;
|
| 560 |
|
|
elsif (wr.write_icc and not wr.ctrl.annul) = '1' then icc := wr.icc;
|
| 561 |
|
|
else icc := sregs.icc; end if;
|
| 562 |
|
|
|
| 563 |
|
|
br_icc := icc;
|
| 564 |
|
|
|
| 565 |
|
|
if ((ex.write_icc and not ex.ctrl.annul) = '1') then
|
| 566 |
|
|
icc := ex.icc;
|
| 567 |
|
|
if not ICC_HOLD then br_icc := icc; end if;
|
| 568 |
|
|
end if;
|
| 569 |
|
|
|
| 570 |
|
|
write_icc := '0'; alu_cin := '0';
|
| 571 |
|
|
|
| 572 |
|
|
case op is
|
| 573 |
|
|
when FMT3 =>
|
| 574 |
|
|
case op3 is
|
| 575 |
|
|
when SUBCC | TSUBCC | TSUBCCTV =>
|
| 576 |
|
|
write_icc := '1';
|
| 577 |
|
|
when ADDCC | ANDCC | ORCC | XORCC | ANDNCC | ORNCC | XNORCC | MULSCC |
|
| 578 |
|
|
TADDCC | TADDCCTV =>
|
| 579 |
|
|
write_icc := '1';
|
| 580 |
|
|
when UMULCC | SMULCC =>
|
| 581 |
|
|
if MULTIPLIER = iterative then
|
| 582 |
|
|
if de.cnt /= "11" then write_icc := '1'; end if;
|
| 583 |
|
|
end if;
|
| 584 |
|
|
if MULTIPLIER = m32x32 then write_icc := '1'; end if;
|
| 585 |
|
|
when ADDX | SUBX =>
|
| 586 |
|
|
alu_cin := icc(0);
|
| 587 |
|
|
when ADDXCC | SUBXCC =>
|
| 588 |
|
|
write_icc := '1'; alu_cin := icc(0);
|
| 589 |
|
|
when others => null;
|
| 590 |
|
|
end case;
|
| 591 |
|
|
when others => null;
|
| 592 |
|
|
end case;
|
| 593 |
|
|
|
| 594 |
|
|
exin.write_icc <= write_icc; exin.alu_cin <= alu_cin;
|
| 595 |
|
|
|
| 596 |
|
|
-- BICC/TICC evaluation
|
| 597 |
|
|
|
| 598 |
|
|
n := br_icc(3); z := br_icc(2); v := br_icc(1); c := br_icc(0);
|
| 599 |
|
|
case cond(2 downto 0) is
|
| 600 |
|
|
when "000" => bres := '0'; -- bn, ba
|
| 601 |
|
|
when "001" => bres := z; -- be, bne
|
| 602 |
|
|
when "010" => bres := z or (n xor v); -- ble, bg
|
| 603 |
|
|
when "011" => bres := n xor v; -- bl, bge
|
| 604 |
|
|
when "100" => bres := c or z; -- blue, bgu
|
| 605 |
|
|
when "101" => bres := c; -- bcs, bcc
|
| 606 |
|
|
when "110" => bres := n; -- bneg, bpos
|
| 607 |
|
|
when others => bres := v; -- bvs. bvc
|
| 608 |
|
|
end case;
|
| 609 |
|
|
branch_true := cond(3) xor bres;
|
| 610 |
|
|
|
| 611 |
|
|
-- FBFCC evaluation
|
| 612 |
|
|
|
| 613 |
|
|
if FPEN then
|
| 614 |
|
|
if FPIFTYPE = serial then
|
| 615 |
|
|
if (fpu_reg.me.fpop = "10") and (me.ctrl.annul = '0') then
|
| 616 |
|
|
fcc := fpu_reg.me.fcc;
|
| 617 |
|
|
elsif (fpu_reg.wr.fpop = "10") and (wr.ctrl.annul = '0') then
|
| 618 |
|
|
fcc := fpu_reg.wr.fcc;
|
| 619 |
|
|
else fcc := fpu_reg.fsr.fcc; end if;
|
| 620 |
|
|
else fcc := fpo.cc; end if;
|
| 621 |
|
|
case cond(2 downto 0) is
|
| 622 |
|
|
when "000" => fbres := '0'; -- fba, fbn
|
| 623 |
|
|
when "001" => fbres := fcc(1) or fcc(0);
|
| 624 |
|
|
when "010" => fbres := fcc(1) xor fcc(0);
|
| 625 |
|
|
when "011" => fbres := fcc(0);
|
| 626 |
|
|
when "100" => fbres := (not fcc(1)) and fcc(0);
|
| 627 |
|
|
when "101" => fbres := fcc(1);
|
| 628 |
|
|
when "110" => fbres := fcc(1) and not fcc(0);
|
| 629 |
|
|
when others => fbres := fcc(1) and fcc(0);
|
| 630 |
|
|
end case;
|
| 631 |
|
|
fbranch_true := cond(3) xor fbres;
|
| 632 |
|
|
|
| 633 |
|
|
-- decode some FPU instruction types
|
| 634 |
|
|
case opf is
|
| 635 |
|
|
when FMOVS | FABSS | FNEGS => fpmov := '1';
|
| 636 |
|
|
when FITOD | FSTOD | FSQRTD | FADDD | FSUBD | FMULD | FDIVD =>
|
| 637 |
|
|
fpexin.dsz := '1';
|
| 638 |
|
|
when others => null;
|
| 639 |
|
|
end case;
|
| 640 |
|
|
end if;
|
| 641 |
|
|
|
| 642 |
|
|
-- CBCCC evaluation
|
| 643 |
|
|
|
| 644 |
|
|
if CPEN then
|
| 645 |
|
|
ccc := cpo.cc;
|
| 646 |
|
|
case cond(2 downto 0) is
|
| 647 |
|
|
when "000" => cbres := '0';
|
| 648 |
|
|
when "001" => cbres := ccc(1) or ccc(0);
|
| 649 |
|
|
when "010" => cbres := ccc(1) xor ccc(0);
|
| 650 |
|
|
when "011" => cbres := ccc(0);
|
| 651 |
|
|
when "100" => cbres := (not ccc(1)) and ccc(0);
|
| 652 |
|
|
when "101" => cbres := ccc(1);
|
| 653 |
|
|
when "110" => cbres := ccc(1) and not ccc(0);
|
| 654 |
|
|
when others => cbres := ccc(1) and ccc(0);
|
| 655 |
|
|
end case;
|
| 656 |
|
|
cbranch_true := cond(3) xor cbres;
|
| 657 |
|
|
end if;
|
| 658 |
|
|
|
| 659 |
|
|
-- Alu operation generation
|
| 660 |
|
|
|
| 661 |
|
|
aluop := ALU_NOP; alusel := ALU_RES_MISC; aluadd := '1';
|
| 662 |
|
|
mulstep := '0'; mulinsn := '0';
|
| 663 |
|
|
case op is
|
| 664 |
|
|
when FMT2 =>
|
| 665 |
|
|
case op2 is
|
| 666 |
|
|
when SETHI => aluop := ALU_PASS2;
|
| 667 |
|
|
when others =>
|
| 668 |
|
|
end case;
|
| 669 |
|
|
when FMT3 =>
|
| 670 |
|
|
case op3 is
|
| 671 |
|
|
when IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | SAVE | RESTORE |
|
| 672 |
|
|
TICC | JMPL | RETT => alusel := ALU_RES_ADD;
|
| 673 |
|
|
when ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV =>
|
| 674 |
|
|
alusel := ALU_RES_ADD; aluadd := '0';
|
| 675 |
|
|
when MULSCC => alusel := ALU_RES_ADD; mulstep := '1';
|
| 676 |
|
|
when UMUL | UMULCC =>
|
| 677 |
|
|
if MULTIPLIER = iterative then
|
| 678 |
|
|
case de.cnt is
|
| 679 |
|
|
when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
|
| 680 |
|
|
when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
|
| 681 |
|
|
when others => alusel := ALU_RES_ADD;
|
| 682 |
|
|
end case;
|
| 683 |
|
|
end if;
|
| 684 |
|
|
if MULTIPLIER > iterative then mulinsn := '1'; end if;
|
| 685 |
|
|
when SMUL | SMULCC =>
|
| 686 |
|
|
if MULTIPLIER = iterative then
|
| 687 |
|
|
case de.cnt is
|
| 688 |
|
|
when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
|
| 689 |
|
|
when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
|
| 690 |
|
|
when others => alusel := ALU_RES_ADD; aluadd := '0';
|
| 691 |
|
|
end case;
|
| 692 |
|
|
end if;
|
| 693 |
|
|
if MULTIPLIER > iterative then mulinsn := '1'; end if;
|
| 694 |
|
|
when UMAC | SMAC =>
|
| 695 |
|
|
if MACEN then mulinsn := '1'; end if;
|
| 696 |
|
|
when UDIV | UDIVCC | SDIV | SDIVCC =>
|
| 697 |
|
|
if DIVIDER /= none then aluop := ALU_DIV; alusel := ALU_RES_LOGIC; end if;
|
| 698 |
|
|
when IAND | ANDCC => aluop := ALU_AND; alusel := ALU_RES_LOGIC;
|
| 699 |
|
|
when ANDN | ANDNCC => aluop := ALU_ANDN; alusel := ALU_RES_LOGIC;
|
| 700 |
|
|
when IOR | ORCC => aluop := ALU_OR; alusel := ALU_RES_LOGIC;
|
| 701 |
|
|
when ORN | ORNCC => aluop := ALU_ORN; alusel := ALU_RES_LOGIC;
|
| 702 |
|
|
when IXNOR | XNORCC => aluop := ALU_XNOR; alusel := ALU_RES_LOGIC;
|
| 703 |
|
|
when XORCC | IXOR | WRPSR | WRWIM | WRTBR | WRY =>
|
| 704 |
|
|
aluop := ALU_XOR; alusel := ALU_RES_LOGIC;
|
| 705 |
|
|
when RDPSR | RDTBR | RDWIM => aluop := ALU_PASS2;
|
| 706 |
|
|
when RDY => aluop := ALU_RDY;
|
| 707 |
|
|
when ISLL => aluop := ALU_SLL; alusel := ALU_RES_SHIFT;
|
| 708 |
|
|
when ISRL => aluop := ALU_SRL; alusel := ALU_RES_SHIFT;
|
| 709 |
|
|
when ISRA => aluop := ALU_SRA; alusel := ALU_RES_SHIFT;
|
| 710 |
|
|
when FPOP1 | FPOP2 =>
|
| 711 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 712 |
|
|
if de.cnt /= "00" then
|
| 713 |
|
|
if opf(1) = '1' then rs1(0) := '1'; rs2(0) := '1'; end if;
|
| 714 |
|
|
if fpexin.dsz = '1' then rd(0) := '1'; end if;
|
| 715 |
|
|
end if;
|
| 716 |
|
|
if op3 = FPOP1 then fpexin.fpop := "01"; else fpexin.fpop := "10"; end if;
|
| 717 |
|
|
if fpmov = '1' then aluop := ALU_FOP; fpexin.fpop := "11";
|
| 718 |
|
|
else aluop := ALU_PASS2; end if;
|
| 719 |
|
|
end if;
|
| 720 |
|
|
when others =>
|
| 721 |
|
|
end case;
|
| 722 |
|
|
when others => -- LDST
|
| 723 |
|
|
case de.cnt is
|
| 724 |
|
|
when "00" =>
|
| 725 |
|
|
alusel := ALU_RES_ADD;
|
| 726 |
|
|
if FPEN then fpld := (op3(5) and not op3(2));
|
| 727 |
|
|
else fpld := '0'; end if;
|
| 728 |
|
|
when "01" =>
|
| 729 |
|
|
if (op3(2) and not op3(3)) = '1' then -- ST
|
| 730 |
|
|
rs1 := rd; rs1mod := '1';
|
| 731 |
|
|
end if;
|
| 732 |
|
|
case op3 is
|
| 733 |
|
|
when LDD | LDDA | LDDC =>
|
| 734 |
|
|
rd(0) := '1'; alusel := ALU_RES_ADD;
|
| 735 |
|
|
when LDDF =>
|
| 736 |
|
|
rd(0) := '1'; alusel := ALU_RES_ADD;
|
| 737 |
|
|
if FPEN then fpld := '1'; end if;
|
| 738 |
|
|
when STFSR => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_FSR; end if;
|
| 739 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
|
| 740 |
|
|
alusel := ALU_RES_ADD;
|
| 741 |
|
|
when STF | STDF =>
|
| 742 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 743 |
|
|
aluop := ALU_PASS1; fpst := '1';
|
| 744 |
|
|
end if;
|
| 745 |
|
|
when others =>
|
| 746 |
|
|
aluop := ALU_PASS1;
|
| 747 |
|
|
if op3(2) = '1' then -- ST
|
| 748 |
|
|
if op3(1 downto 0) = "01" then -- store byte
|
| 749 |
|
|
aluop := ALU_STB;
|
| 750 |
|
|
elsif op3(1 downto 0) = "10" then -- store halfword
|
| 751 |
|
|
aluop := ALU_STH;
|
| 752 |
|
|
end if;
|
| 753 |
|
|
end if;
|
| 754 |
|
|
end case;
|
| 755 |
|
|
when "10" =>
|
| 756 |
|
|
aluop := ALU_PASS1;
|
| 757 |
|
|
rs1 := rd; rs1mod := '1';
|
| 758 |
|
|
if op3(2) = '1' then -- ST
|
| 759 |
|
|
if (op3(3) and not op3(1))= '1' then aluop := ALU_ONES; -- LDSTUB/A
|
| 760 |
|
|
elsif op3(3 downto 0) = "0111" then
|
| 761 |
|
|
rs1(0) := '1'; -- STD/F/A
|
| 762 |
|
|
if ((FPIFTYPE = serial) and FPEN) and (op3(5) = '1') then fpst := '1'; end if;
|
| 763 |
|
|
end if;
|
| 764 |
|
|
end if;
|
| 765 |
|
|
when others =>
|
| 766 |
|
|
end case;
|
| 767 |
|
|
|
| 768 |
|
|
end case;
|
| 769 |
|
|
|
| 770 |
|
|
exin.aluop <= aluop; exin.alusel <= alusel; exin.aluadd <= aluadd;
|
| 771 |
|
|
exin.mulstep <= mulstep; exin.mulinsn <= mulinsn;
|
| 772 |
|
|
|
| 773 |
|
|
-- Alu operand select
|
| 774 |
|
|
|
| 775 |
|
|
operand2_select := ALU_SIMM;
|
| 776 |
|
|
|
| 777 |
|
|
case op is
|
| 778 |
|
|
when FMT2 =>
|
| 779 |
|
|
case op2 is
|
| 780 |
|
|
when SETHI => operand2_select := ALU_SIMM;
|
| 781 |
|
|
when others => operand2_select := ALU_RS2;
|
| 782 |
|
|
end case;
|
| 783 |
|
|
when FMT3 =>
|
| 784 |
|
|
case op3 is
|
| 785 |
|
|
when RDWIM | RDPSR | RDTBR => operand2_select := ALU_SIMM;
|
| 786 |
|
|
when FPOP1 | FPOP2 => if ((FPIFTYPE = serial) and FPEN) then operand2_select := ALU_RS2; end if;
|
| 787 |
|
|
when others =>
|
| 788 |
|
|
if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
|
| 789 |
|
|
else operand2_select := ALU_RS2; end if;
|
| 790 |
|
|
end case;
|
| 791 |
|
|
when LDST =>
|
| 792 |
|
|
if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
|
| 793 |
|
|
else operand2_select := ALU_RS2; end if;
|
| 794 |
|
|
when others => operand2_select := ALU_RS2;
|
| 795 |
|
|
end case;
|
| 796 |
|
|
|
| 797 |
|
|
|
| 798 |
|
|
-- CWP generation, pipelinig and forwarding
|
| 799 |
|
|
-- Also check for window underflow/overflow conditions
|
| 800 |
|
|
|
| 801 |
|
|
if (op = FMT3) and ((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE)) then
|
| 802 |
|
|
write_cwp := '1';
|
| 803 |
|
|
if (op3 = SAVE) then
|
| 804 |
|
|
-- pragma translate_off
|
| 805 |
|
|
if not is_x(de.cwp) then
|
| 806 |
|
|
-- pragma translate_on
|
| 807 |
|
|
if (not CWPOPT) and (de.cwp = CWPMIN) then cwp_new := CWPMAX;
|
| 808 |
|
|
else cwp_new := de.cwp - 1 ; end if;
|
| 809 |
|
|
-- pragma translate_off
|
| 810 |
|
|
end if;
|
| 811 |
|
|
-- pragma translate_on
|
| 812 |
|
|
else
|
| 813 |
|
|
-- pragma translate_off
|
| 814 |
|
|
if not is_x(de.cwp) then
|
| 815 |
|
|
-- pragma translate_on
|
| 816 |
|
|
if (not CWPOPT) and (de.cwp = CWPMAX) then cwp_new := CWPMIN;
|
| 817 |
|
|
else cwp_new := de.cwp + 1; end if;
|
| 818 |
|
|
-- pragma translate_off
|
| 819 |
|
|
end if;
|
| 820 |
|
|
-- pragma translate_on
|
| 821 |
|
|
end if;
|
| 822 |
|
|
|
| 823 |
|
|
if sregs.wim(conv_integer('0' & cwp_new)) = '1' then
|
| 824 |
|
|
if op3 = SAVE then winovf_exception := '1';
|
| 825 |
|
|
else winunf_exception := '1'; end if;
|
| 826 |
|
|
end if;
|
| 827 |
|
|
end if;
|
| 828 |
|
|
|
| 829 |
|
|
exin.write_cwp <= write_cwp;
|
| 830 |
|
|
exin.cwp <= cwp_new;
|
| 831 |
|
|
|
| 832 |
|
|
-- Immediate data generation
|
| 833 |
|
|
|
| 834 |
|
|
immediate_data := (others => '0');
|
| 835 |
|
|
case op is
|
| 836 |
|
|
when FMT2 =>
|
| 837 |
|
|
immediate_data := de.inst(21 downto 0) & "0000000000";
|
| 838 |
|
|
when FMT3 =>
|
| 839 |
|
|
case op3 is
|
| 840 |
|
|
when RDPSR => immediate_data(31 downto 5) := std_logic_vector(IMPL) &
|
| 841 |
|
|
std_logic_vector(VER) & icc & "000000" & sregs.ec & sregs.ef &
|
| 842 |
|
|
sregs.pil & su & sregs.ps & et;
|
| 843 |
|
|
immediate_data(NWINLOG2-1 downto 0) := de.cwp;
|
| 844 |
|
|
when RDTBR => immediate_data(31 downto 4) := sregs.tba & sregs.tt;
|
| 845 |
|
|
when RDWIM => immediate_data(NWINDOWS-1 downto 0) := sregs.wim;
|
| 846 |
|
|
when others =>
|
| 847 |
|
|
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 848 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 849 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 850 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 851 |
|
|
de.inst(12 downto 0);
|
| 852 |
|
|
end case;
|
| 853 |
|
|
when others => -- LDST
|
| 854 |
|
|
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 855 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 856 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 857 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
| 858 |
|
|
de.inst(12 downto 0);
|
| 859 |
|
|
end case;
|
| 860 |
|
|
|
| 861 |
|
|
-- register read address generation
|
| 862 |
|
|
|
| 863 |
|
|
if RS1OPT then
|
| 864 |
|
|
if rs1mod = '1' then
|
| 865 |
|
|
read_addr1 := regdec(de.cwp, de.inst(29 downto 26) & rs1(0), (fpst or fpop));
|
| 866 |
|
|
else
|
| 867 |
|
|
read_addr1 := regdec(de.cwp, de.inst(18 downto 15) & rs1(0), (fpst or fpop));
|
| 868 |
|
|
end if;
|
| 869 |
|
|
else
|
| 870 |
|
|
read_addr1 := regdec(de.cwp, rs1, (fpst or fpop));
|
| 871 |
|
|
end if;
|
| 872 |
|
|
read_addr2 := regdec(de.cwp, rs2, fpop);
|
| 873 |
|
|
|
| 874 |
|
|
|
| 875 |
|
|
-- register write address generation
|
| 876 |
|
|
|
| 877 |
|
|
write_reg := '0'; fsr_ld := '0';
|
| 878 |
|
|
|
| 879 |
|
|
case op is
|
| 880 |
|
|
when CALL =>
|
| 881 |
|
|
write_reg := '1'; rd := "01111"; -- CALL saves PC in r[15] (%o7)
|
| 882 |
|
|
when FMT2 =>
|
| 883 |
|
|
if (op2 = SETHI) then write_reg := '1'; end if;
|
| 884 |
|
|
when FMT3 =>
|
| 885 |
|
|
case op3 is
|
| 886 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 887 |
|
|
if MULTIPLIER = none then write_reg := '1'; end if;
|
| 888 |
|
|
if MULTIPLIER = m32x32 then write_reg := '1'; end if;
|
| 889 |
|
|
if MULTIPLIER = iterative then
|
| 890 |
|
|
if de.cnt = "10" then write_reg := '1'; end if;
|
| 891 |
|
|
end if;
|
| 892 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
| 893 |
|
|
if DIVIDER /= none then write_reg := '0'; else write_reg := '1'; end if;
|
| 894 |
|
|
when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
|
| 895 |
|
|
when FPOP1 | FPOP2 => null;
|
| 896 |
|
|
when CPOP1 | CPOP2 => null;
|
| 897 |
|
|
when others => write_reg := '1';
|
| 898 |
|
|
end case;
|
| 899 |
|
|
when LDST =>
|
| 900 |
|
|
ctrl.ld := not op3(2);
|
| 901 |
|
|
if (op3(2) = '0') and
|
| 902 |
|
|
not ((CPEN or (FPIFTYPE = parallel)) and (op3(5) = '1'))
|
| 903 |
|
|
then write_reg := '1'; end if;
|
| 904 |
|
|
case op3 is
|
| 905 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
|
| 906 |
|
|
if de.cnt = "00" then write_reg := '1'; end if;
|
| 907 |
|
|
when LDFSR => if ((FPIFTYPE = serial) and FPEN) then write_reg := '0'; fsr_ld := '1'; end if;
|
| 908 |
|
|
when others => null;
|
| 909 |
|
|
end case;
|
| 910 |
|
|
when others => null;
|
| 911 |
|
|
end case;
|
| 912 |
|
|
|
| 913 |
|
|
if (rd = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpld = '1')) then
|
| 914 |
|
|
write_reg := '0';
|
| 915 |
|
|
end if;
|
| 916 |
|
|
|
| 917 |
|
|
ctrl.rd := regdec(cwp_new, rd, (fpld or fpop));
|
| 918 |
|
|
if RDOPT then chkrd := regdec(de.cwp, rd, (fpld or fpop));
|
| 919 |
|
|
else chkrd := ctrl.rd; end if;
|
| 920 |
|
|
|
| 921 |
|
|
-- LD/BICC/TICC delay interlock generation
|
| 922 |
|
|
|
| 923 |
|
|
ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0';
|
| 924 |
|
|
ldchkex := '1'; ldchkme := '1'; bicc_hold := '0'; icc_check := '0';
|
| 925 |
|
|
fsr_check := '0'; fsr_ld_check := '0'; fsr_lock := '0';
|
| 926 |
|
|
|
| 927 |
|
|
if (de.annul = '0') then
|
| 928 |
|
|
case op is
|
| 929 |
|
|
when FMT2 =>
|
| 930 |
|
|
if (op2 = BICC) and (cond(2 downto 0) /= "000") then
|
| 931 |
|
|
icc_check := '1';
|
| 932 |
|
|
end if;
|
| 933 |
|
|
when FMT3 =>
|
| 934 |
|
|
ldcheck1 := '1'; ldcheck2 := not i;
|
| 935 |
|
|
case op3 is
|
| 936 |
|
|
when TICC =>
|
| 937 |
|
|
if (cond(2 downto 0) /= "000") then icc_check := '1'; end if;
|
| 938 |
|
|
when RDY | RDWIM | RDTBR =>
|
| 939 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
| 940 |
|
|
when RDPSR =>
|
| 941 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
| 942 |
|
|
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
|
| 943 |
|
|
when ADDX | ADDXCC | SUBX | SUBXCC =>
|
| 944 |
|
|
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
|
| 945 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 946 |
|
|
if MULTIPLIER = iterative then
|
| 947 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
| 948 |
|
|
if (de.cnt = "00") then ldcheck1 := '1'; end if;
|
| 949 |
|
|
if (de.cnt = "01") then ldcheck2 := not i; end if;
|
| 950 |
|
|
end if;
|
| 951 |
|
|
when FPOP1 | FPOP2 =>
|
| 952 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 953 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
| 954 |
|
|
case opf is
|
| 955 |
|
|
when FITOS | FITOD | FSTOI | FDTOI | FSTOD | FDTOS | FMOVS |
|
| 956 |
|
|
FNEGS | FABSS | FSQRTS | FSQRTD =>
|
| 957 |
|
|
ldcheck2 := '1';
|
| 958 |
|
|
when others => ldcheck1 := '1'; ldcheck2 := '1';
|
| 959 |
|
|
end case;
|
| 960 |
|
|
if de.cnt /= "00" then ldchkex := '0'; end if;
|
| 961 |
|
|
fsr_ld_check := '1';
|
| 962 |
|
|
end if;
|
| 963 |
|
|
when others =>
|
| 964 |
|
|
end case;
|
| 965 |
|
|
when LDST =>
|
| 966 |
|
|
ldcheck1 := '1'; ldchkex := '0';
|
| 967 |
|
|
case de.cnt is
|
| 968 |
|
|
when "00" => -- check store data dependency if 2-cycle load delay
|
| 969 |
|
|
if (LDDELAY = 2) and (op3(2) = '1') and not (((FPIFTYPE = serial) and FPEN) and (op3 = STFSR))
|
| 970 |
|
|
then ldcheck3 := '1'; end if;
|
| 971 |
|
|
ldcheck2 := not i; ldchkex := '1';
|
| 972 |
|
|
when "01" => ldcheck2 := not i;
|
| 973 |
|
|
when others => ldchkme := '0';
|
| 974 |
|
|
end case;
|
| 975 |
|
|
if ((FPIFTYPE = serial) and FPEN) and ((op3 = LDFSR) or (op3 = STFSR)) then
|
| 976 |
|
|
fsr_check := '1';
|
| 977 |
|
|
if (op3 = STFSR) then fsr_ld_check := '1'; end if;
|
| 978 |
|
|
end if;
|
| 979 |
|
|
when others => null;
|
| 980 |
|
|
end case;
|
| 981 |
|
|
end if;
|
| 982 |
|
|
|
| 983 |
|
|
-- MAC has two-cycle latency, check for data-dependecies
|
| 984 |
|
|
if MACEN then
|
| 985 |
|
|
if ((ex.mulinsn and ex.ctrl.inst(24) and ldchkex and not ex.ctrl.annul) = '1') and
|
| 986 |
|
|
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
|
| 987 |
|
|
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
|
| 988 |
|
|
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
|
| 989 |
|
|
then ldlock := '1'; end if;
|
| 990 |
|
|
end if;
|
| 991 |
|
|
|
| 992 |
|
|
if MACEN or (MULTIPLIER = m32x32) then
|
| 993 |
|
|
bicc_hold := icc_check and ex.write_icc and ex.mulinsn and not ex.ctrl.annul;
|
| 994 |
|
|
end if;
|
| 995 |
|
|
if ICC_HOLD then
|
| 996 |
|
|
bicc_hold := bicc_hold or (icc_check and ex.write_icc and not ex.ctrl.annul);
|
| 997 |
|
|
end if;
|
| 998 |
|
|
|
| 999 |
|
|
if ((ex.ctrl.ld and ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
|
| 1000 |
|
|
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
|
| 1001 |
|
|
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
|
| 1002 |
|
|
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
|
| 1003 |
|
|
then ldlock := '1'; end if;
|
| 1004 |
|
|
|
| 1005 |
|
|
if ((me.ctrl.ld and me.write_reg and ldchkme and not me.ctrl.annul) = '1') and
|
| 1006 |
|
|
((LDDELAY = 2) or ((fsr_ld_check and not fsr_check) = '1')) and
|
| 1007 |
|
|
(((ldcheck1 = '1') and (me.ctrl.rd = read_addr1)) or
|
| 1008 |
|
|
((ldcheck2 = '1') and (me.ctrl.rd = read_addr2)))
|
| 1009 |
|
|
then ldlock := '1'; end if;
|
| 1010 |
|
|
|
| 1011 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 1012 |
|
|
if (fsr_check = '1') then
|
| 1013 |
|
|
fsr_lock := ((xorv(fpu_reg.ex.fpop) and not ex.ctrl.annul) or
|
| 1014 |
|
|
(xorv(fpu_reg.me.fpop) and not me.ctrl.annul) or
|
| 1015 |
|
|
(xorv(fpu_reg.wr.fpop) and not wr.ctrl.annul));
|
| 1016 |
|
|
end if;
|
| 1017 |
|
|
if fsr_ld_check = '1' then
|
| 1018 |
|
|
fsr_lock := fsr_lock or (fpu_reg.ex.ldfsr and not ex.ctrl.annul)
|
| 1019 |
|
|
or (fpu_reg.me.ldfsr and not me.ctrl.annul)
|
| 1020 |
|
|
or (fpu_reg.wr.ldfsr and not wr.ctrl.annul);
|
| 1021 |
|
|
end if;
|
| 1022 |
|
|
end if;
|
| 1023 |
|
|
|
| 1024 |
|
|
ldlock := ldlock or bicc_hold or fsr_lock;
|
| 1025 |
|
|
cpldlock := ldlock; fpldlock := ldlock;
|
| 1026 |
|
|
if CPEN then
|
| 1027 |
|
|
if FPIFTYPE = parallel then cpldlock := cpldlock or fpo.ldlock; end if;
|
| 1028 |
|
|
ldlock := ldlock or cpo.ldlock;
|
| 1029 |
|
|
end if;
|
| 1030 |
|
|
if FPIFTYPE = parallel then
|
| 1031 |
|
|
if CPEN then fpldlock := fpldlock or cpo.ldlock; end if;
|
| 1032 |
|
|
ldlock := ldlock or fpo.ldlock;
|
| 1033 |
|
|
end if;
|
| 1034 |
|
|
|
| 1035 |
|
|
-- data forwarding detection. Forward data if destination and source
|
| 1036 |
|
|
-- registers are equal and destination register will be written.
|
| 1037 |
|
|
|
| 1038 |
|
|
rs1data := rfo.data1(31 downto 0); ldbp1 := '0';
|
| 1039 |
|
|
if (rs1 = "00000") and not (((FPIFTYPE = serial) and FPEN) and ((fpop or fpst) = '1')) then
|
| 1040 |
|
|
rs1data := (others => '0');
|
| 1041 |
|
|
elsif ldcheck1 = '1' then
|
| 1042 |
|
|
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
|
| 1043 |
|
|
(read_addr1 = ex.ctrl.rd)
|
| 1044 |
|
|
then
|
| 1045 |
|
|
rs1data := ex.result;
|
| 1046 |
|
|
else
|
| 1047 |
|
|
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
|
| 1048 |
|
|
rs1data := mein.bpresult;
|
| 1049 |
|
|
if LDDELAY = 1 then ldbp1 := me.ctrl.ld; end if;
|
| 1050 |
|
|
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr1 = wr.ctrl.rd) then
|
| 1051 |
|
|
rs1data := wr.result;
|
| 1052 |
|
|
else rfenable1 := '1'; end if;
|
| 1053 |
|
|
end if;
|
| 1054 |
|
|
end if;
|
| 1055 |
|
|
|
| 1056 |
|
|
rs2data := rfo.data2(31 downto 0); ldbp2 := '0';
|
| 1057 |
|
|
if (operand2_select = ALU_SIMM) then
|
| 1058 |
|
|
rs2data := immediate_data;
|
| 1059 |
|
|
elsif (rs2 = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpop = '1')) then
|
| 1060 |
|
|
rs2data := (others => '0');
|
| 1061 |
|
|
elsif ldcheck2 = '1' then
|
| 1062 |
|
|
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and (read_addr2 = ex.ctrl.rd) then
|
| 1063 |
|
|
rs2data := ex.result;
|
| 1064 |
|
|
else
|
| 1065 |
|
|
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
|
| 1066 |
|
|
rs2data := mein.bpresult;
|
| 1067 |
|
|
if LDDELAY = 1 then ldbp2 := me.ctrl.ld; end if;
|
| 1068 |
|
|
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr2 = wr.ctrl.rd) then
|
| 1069 |
|
|
rs2data := wr.result;
|
| 1070 |
|
|
else rfenable2 := '1'; end if;
|
| 1071 |
|
|
end if;
|
| 1072 |
|
|
end if;
|
| 1073 |
|
|
|
| 1074 |
|
|
-- multiply operand generation
|
| 1075 |
|
|
|
| 1076 |
|
|
if (ex.write_y and not ex.ctrl.annul) = '1' then
|
| 1077 |
|
|
y0 := mein.y(0);
|
| 1078 |
|
|
elsif (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1' then
|
| 1079 |
|
|
y0 := me.my(0);
|
| 1080 |
|
|
else
|
| 1081 |
|
|
y0 := wr.y(0);
|
| 1082 |
|
|
end if;
|
| 1083 |
|
|
|
| 1084 |
|
|
ymsb := '-';
|
| 1085 |
|
|
|
| 1086 |
|
|
-- mul/div unit
|
| 1087 |
|
|
|
| 1088 |
|
|
divi.y <= (wr.y(31) and op3(0)) & wr.y;
|
| 1089 |
|
|
divstart := '0'; mulstart := '0';
|
| 1090 |
|
|
case op is
|
| 1091 |
|
|
when FMT3 =>
|
| 1092 |
|
|
case op3 is
|
| 1093 |
|
|
when MULSCC =>
|
| 1094 |
|
|
ymsb := rs1data(0); rs1data := (icc(3) xor icc(1)) & rs1data(31 downto 1);
|
| 1095 |
|
|
if y0 = '0' then
|
| 1096 |
|
|
rs2data := (others => '0'); rfenable2 := '0'; ldbp2 := '0';
|
| 1097 |
|
|
end if;
|
| 1098 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 1099 |
|
|
if MULTIPLIER = iterative then
|
| 1100 |
|
|
case de.cnt is
|
| 1101 |
|
|
when "00" =>
|
| 1102 |
|
|
rs2data := (others => '0'); ymsb := rs1data(0); rfenable2 := '0';
|
| 1103 |
|
|
when "01" | "10" =>
|
| 1104 |
|
|
ymsb := ex.result(0);
|
| 1105 |
|
|
rs1data := (ex.micc(3) xor ex.micc(1)) & ex.result(31 downto 1);
|
| 1106 |
|
|
if (mein.y(0) = '0') or (de.cnt = "10") then
|
| 1107 |
|
|
rs2data := (others => '0'); ldbp2 := '0'; rfenable2 := '0';
|
| 1108 |
|
|
end if;
|
| 1109 |
|
|
when others =>
|
| 1110 |
|
|
if (op3 = UMUL) or (op3 = UMULCC) then
|
| 1111 |
|
|
rs2data := ex.result; rfenable2 := '1';
|
| 1112 |
|
|
if rfo.data2(31) = '0' then
|
| 1113 |
|
|
rs1data := (others => '0');
|
| 1114 |
|
|
end if;
|
| 1115 |
|
|
else
|
| 1116 |
|
|
rs1data := ex.result; rfenable1 := '1';
|
| 1117 |
|
|
if rfo.data1(31) = '0' then
|
| 1118 |
|
|
rs2data := (others => '0'); rfenable2 := '0';
|
| 1119 |
|
|
end if;
|
| 1120 |
|
|
end if;
|
| 1121 |
|
|
end case;
|
| 1122 |
|
|
end if;
|
| 1123 |
|
|
when others => null;
|
| 1124 |
|
|
end case;
|
| 1125 |
|
|
when others => null;
|
| 1126 |
|
|
end case;
|
| 1127 |
|
|
|
| 1128 |
|
|
exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;
|
| 1129 |
|
|
|
| 1130 |
|
|
-- PC generation
|
| 1131 |
|
|
|
| 1132 |
|
|
branch := '0'; annul_next := '0'; annul_current := '0';
|
| 1133 |
|
|
inull := not Rst; hold_pc := '0'; ticc_exception := '0';
|
| 1134 |
|
|
fpop := '0'; fpld := '0';
|
| 1135 |
|
|
if ((ldlock or de.annul) = '0') then
|
| 1136 |
|
|
case op is
|
| 1137 |
|
|
when CALL =>
|
| 1138 |
|
|
branch := '1';
|
| 1139 |
|
|
if mein.inull = '1' then
|
| 1140 |
|
|
hold_pc := '1'; annul_current := '1';
|
| 1141 |
|
|
end if;
|
| 1142 |
|
|
when FMT2 =>
|
| 1143 |
|
|
if (op2 = BICC) or (FPEN and (op2 = FBFCC)) or (CPEN and (op2 = CBCCC)) then
|
| 1144 |
|
|
if (FPEN and (op2 = FBFCC)) then
|
| 1145 |
|
|
branch := fbranch_true;
|
| 1146 |
|
|
if (FPIFTYPE = parallel) and (fpo.ccv /= '1') then
|
| 1147 |
|
|
hold_pc := '1'; annul_current := '1';
|
| 1148 |
|
|
end if;
|
| 1149 |
|
|
elsif (CPEN and (op2 = CBCCC)) then
|
| 1150 |
|
|
branch := cbranch_true;
|
| 1151 |
|
|
if cpo.ccv /= '1' then hold_pc := '1'; annul_current := '1'; end if;
|
| 1152 |
|
|
else branch := branch_true; end if;
|
| 1153 |
|
|
if hold_pc = '0' then
|
| 1154 |
|
|
if (branch = '1') then
|
| 1155 |
|
|
if (cond = BA) and (annul = '1') then annul_next := '1'; end if;
|
| 1156 |
|
|
else annul_next := annul; end if;
|
| 1157 |
|
|
if mein.inull = '1' then -- contention with JMPL
|
| 1158 |
|
|
hold_pc := '1'; annul_current := '1'; annul_next := '0';
|
| 1159 |
|
|
end if;
|
| 1160 |
|
|
end if;
|
| 1161 |
|
|
end if;
|
| 1162 |
|
|
when FMT3 =>
|
| 1163 |
|
|
case op3 is
|
| 1164 |
|
|
when FPOP1 | FPOP2 =>
|
| 1165 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 1166 |
|
|
case de.cnt is
|
| 1167 |
|
|
when "00" =>
|
| 1168 |
|
|
if (opf(1) or fpexin.dsz) = '1' then
|
| 1169 |
|
|
hold_pc := '1'; pv := '0'; cnt := "01";
|
| 1170 |
|
|
end if;
|
| 1171 |
|
|
if (opf(1) or fpmov) = '0' then fpop := holdn; end if;
|
| 1172 |
|
|
if op3 = FPOP1 then write_reg := not (opf(1) and not fpexin.dsz); end if;
|
| 1173 |
|
|
when others =>
|
| 1174 |
|
|
if op3 = FPOP1 then write_reg := '1'; end if;
|
| 1175 |
|
|
fpop := opf(1) and holdn; cnt := "00";
|
| 1176 |
|
|
end case;
|
| 1177 |
|
|
end if;
|
| 1178 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 1179 |
|
|
if MULTIPLIER = iterative then
|
| 1180 |
|
|
case de.cnt is
|
| 1181 |
|
|
when "00" =>
|
| 1182 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
| 1183 |
|
|
when "01" =>
|
| 1184 |
|
|
hold_pc := '1'; pv := '0'; cnt := "01"; mulcnt := mulcnt + 1;
|
| 1185 |
|
|
if (de.mulcnt = "11111") then cnt := "10"; end if;
|
| 1186 |
|
|
when "10" =>
|
| 1187 |
|
|
cnt := "11"; pv := '0'; hold_pc := '1';
|
| 1188 |
|
|
when "11" =>
|
| 1189 |
|
|
cnt := "00";
|
| 1190 |
|
|
when others => null;
|
| 1191 |
|
|
end case;
|
| 1192 |
|
|
end if;
|
| 1193 |
|
|
if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then
|
| 1194 |
|
|
case de.cnt is
|
| 1195 |
|
|
when "00" =>
|
| 1196 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
| 1197 |
|
|
mulstart := '1';
|
| 1198 |
|
|
when "01" =>
|
| 1199 |
|
|
if mulo.ready = '1' then cnt := "00";
|
| 1200 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
| 1201 |
|
|
when others => null;
|
| 1202 |
|
|
end case;
|
| 1203 |
|
|
end if;
|
| 1204 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
| 1205 |
|
|
if DIVIDER /= none then
|
| 1206 |
|
|
case de.cnt is
|
| 1207 |
|
|
when "00" =>
|
| 1208 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
| 1209 |
|
|
divstart := '1';
|
| 1210 |
|
|
when "01" =>
|
| 1211 |
|
|
if divo.ready = '1' then cnt := "00";
|
| 1212 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
| 1213 |
|
|
when others => null;
|
| 1214 |
|
|
end case;
|
| 1215 |
|
|
end if;
|
| 1216 |
|
|
when TICC =>
|
| 1217 |
|
|
if branch_true = '1' then ticc_exception := '1'; end if;
|
| 1218 |
|
|
when RETT =>
|
| 1219 |
|
|
ctrl.rett := '1'; su := sregs.ps;
|
| 1220 |
|
|
when others => null;
|
| 1221 |
|
|
end case;
|
| 1222 |
|
|
when LDST =>
|
| 1223 |
|
|
case de.cnt is
|
| 1224 |
|
|
when "00" =>
|
| 1225 |
|
|
if (op3(2) = '1') or (op3(1 downto 0) = "11") then -- ST/LDST/SWAP/LDD
|
| 1226 |
|
|
cnt := "01"; hold_pc := '1'; pv := '0';
|
| 1227 |
|
|
end if;
|
| 1228 |
|
|
when "01" =>
|
| 1229 |
|
|
if (op3(2 downto 0) = "111") or (op3(3 downto 0) = "1101") or
|
| 1230 |
|
|
((CPEN or FPEN) and ((op3(5) & op3(2 downto 0)) = "1110"))
|
| 1231 |
|
|
then -- LDD/STD/LDSTUB/SWAP
|
| 1232 |
|
|
cnt := "10"; pv := '0'; hold_pc := '1';
|
| 1233 |
|
|
else
|
| 1234 |
|
|
cnt := "00";
|
| 1235 |
|
|
end if;
|
| 1236 |
|
|
when "10" =>
|
| 1237 |
|
|
cnt := "00";
|
| 1238 |
|
|
when others => null;
|
| 1239 |
|
|
end case;
|
| 1240 |
|
|
when others => null;
|
| 1241 |
|
|
end case;
|
| 1242 |
|
|
end if;
|
| 1243 |
|
|
|
| 1244 |
|
|
muli.start <= mulstart;
|
| 1245 |
|
|
divi.start <= divstart;
|
| 1246 |
|
|
|
| 1247 |
|
|
-- instruction watchpoints
|
| 1248 |
|
|
|
| 1249 |
|
|
watchpoint_exc := '0';
|
| 1250 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
| 1251 |
|
|
if ((tr(i).exec and not de.annul) = '1') then
|
| 1252 |
|
|
if (((tr(i).addr xor de.pc(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)) then
|
| 1253 |
|
|
watchpoint_exc := '1';
|
| 1254 |
|
|
end if;
|
| 1255 |
|
|
end if;
|
| 1256 |
|
|
end loop;
|
| 1257 |
|
|
|
| 1258 |
|
|
if DEBUG_UNIT then
|
| 1259 |
|
|
if ((iui.debug.dsuen and iui.debug.bwatch and not de.annul) = '1') then
|
| 1260 |
|
|
watchpoint_exc := de.pv and (watchpoint_exc or iui.debug.dbreak or de.step);
|
| 1261 |
|
|
end if;
|
| 1262 |
|
|
end if;
|
| 1263 |
|
|
|
| 1264 |
|
|
-- prioritise traps
|
| 1265 |
|
|
|
| 1266 |
|
|
ctrl.trap := de.mexc or privileged_inst or illegal_inst or fp_disabled or
|
| 1267 |
|
|
cp_disabled or ticc_exception or winunf_exception or
|
| 1268 |
|
|
winovf_exception or fp_exception or watchpoint_exc;
|
| 1269 |
|
|
|
| 1270 |
|
|
if de.mexc = '1' then ctrl.tt := IAEX_TT;
|
| 1271 |
|
|
elsif privileged_inst = '1' then ctrl.tt := PRIV_TT;
|
| 1272 |
|
|
elsif illegal_inst = '1' then ctrl.tt := IINST_TT;
|
| 1273 |
|
|
elsif fp_disabled = '1' then ctrl.tt := FPDIS_TT;
|
| 1274 |
|
|
elsif cp_disabled = '1' then ctrl.tt := CPDIS_TT;
|
| 1275 |
|
|
elsif watchpoint_exc = '1' then ctrl.tt := WATCH_TT;
|
| 1276 |
|
|
elsif winovf_exception = '1' then ctrl.tt := WINOF_TT;
|
| 1277 |
|
|
elsif winunf_exception = '1' then ctrl.tt := WINUF_TT;
|
| 1278 |
|
|
elsif fp_exception = '1' then ctrl.tt := FPEXC_TT;
|
| 1279 |
|
|
elsif ticc_exception = '1' then ctrl.tt := TICC_TT;
|
| 1280 |
|
|
end if;
|
| 1281 |
|
|
|
| 1282 |
|
|
|
| 1283 |
|
|
hold_pc := (hold_pc or ldlock) and not wr.annul_all;
|
| 1284 |
|
|
|
| 1285 |
|
|
if hold_pc = '1' then dein.pc <= de.pc;
|
| 1286 |
|
|
else dein.pc <= fe.pc; end if;
|
| 1287 |
|
|
|
| 1288 |
|
|
annul_current_cp := annul_current;
|
| 1289 |
|
|
annul_current := (annul_current or ldlock or wr.annul_all);
|
| 1290 |
|
|
ctrl.annul := de.annul or wr.annul_all or annul_current;
|
| 1291 |
|
|
pv := pv and not ((mein.inull and not hold_pc) or wr.annul_all);
|
| 1292 |
|
|
annul_next := (mein.inull and not hold_pc) or annul_next or wr.annul_all
|
| 1293 |
|
|
or (ldlock and de.annul);
|
| 1294 |
|
|
if (annul_next = '1') or (rst = '0') then
|
| 1295 |
|
|
cnt := (others => '0'); mulcnt := (others => '0');
|
| 1296 |
|
|
end if;
|
| 1297 |
|
|
|
| 1298 |
|
|
if DEBUG_UNIT then
|
| 1299 |
|
|
step := iui.debug.step and pv and not de.annul;
|
| 1300 |
|
|
end if;
|
| 1301 |
|
|
fecomb.hold_pc <= hold_pc;
|
| 1302 |
|
|
fecomb.branch <= branch;
|
| 1303 |
|
|
dein.annul <= annul_next;
|
| 1304 |
|
|
dein.cnt <= cnt;
|
| 1305 |
|
|
dein.mulcnt <= mulcnt;
|
| 1306 |
|
|
dein.step <= step;
|
| 1307 |
|
|
dein.pv <= pv;
|
| 1308 |
|
|
-- pv means that the corresponding pc can be save on a trap
|
| 1309 |
|
|
ctrl.pv := de.pv and
|
| 1310 |
|
|
not ((de.annul and not de.pv) or wr.annul_all or annul_current);
|
| 1311 |
|
|
inull := inull or mein.inull or hold_pc or wr.annul_all;
|
| 1312 |
|
|
|
| 1313 |
|
|
ici.nullify <= inull;
|
| 1314 |
|
|
ici.su <= su;
|
| 1315 |
|
|
exin.ctrl <= ctrl;
|
| 1316 |
|
|
exin.write_reg <= write_reg;
|
| 1317 |
|
|
|
| 1318 |
|
|
-- latch next cwp
|
| 1319 |
|
|
|
| 1320 |
|
|
if wr.trapping = '1' then
|
| 1321 |
|
|
dein.cwp <= sregsin.cwp;
|
| 1322 |
|
|
elsif (write_cwp and not ctrl.annul) = '1' then
|
| 1323 |
|
|
dein.cwp <= cwp_new;
|
| 1324 |
|
|
elsif (ex.write_cwp and not ex.ctrl.annul) = '1' then
|
| 1325 |
|
|
dein.cwp <= ex.cwp;
|
| 1326 |
|
|
elsif (me.write_cwp and not me.ctrl.annul) = '1' then
|
| 1327 |
|
|
dein.cwp <= me.cwp;
|
| 1328 |
|
|
elsif (wr.write_cwp and not wr.ctrl.annul) = '1' then
|
| 1329 |
|
|
dein.cwp <= wr.cwp;
|
| 1330 |
|
|
else
|
| 1331 |
|
|
dein.cwp <= sregs.cwp;
|
| 1332 |
|
|
end if;
|
| 1333 |
|
|
|
| 1334 |
|
|
|
| 1335 |
|
|
-- y-register write select and forwarding
|
| 1336 |
|
|
|
| 1337 |
|
|
rst_mey := '0';
|
| 1338 |
|
|
|
| 1339 |
|
|
case op is
|
| 1340 |
|
|
when FMT3 =>
|
| 1341 |
|
|
case op3 is
|
| 1342 |
|
|
when MULSCC => write_y := '1';
|
| 1343 |
|
|
when WRY => if rd = "00000" then write_y := '1'; end if;
|
| 1344 |
|
|
when UMAC | SMAC =>
|
| 1345 |
|
|
if MACEN then write_y := '1'; end if;
|
| 1346 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
| 1347 |
|
|
if MULTIPLIER = iterative then
|
| 1348 |
|
|
if de.cnt = "00" then rst_mey := '1'; end if;
|
| 1349 |
|
|
if de.cnt = "11" then write_y := '1'; end if;
|
| 1350 |
|
|
end if;
|
| 1351 |
|
|
if MULTIPLIER = m32x32 then write_y := '1'; end if;
|
| 1352 |
|
|
when others => null;
|
| 1353 |
|
|
end case;
|
| 1354 |
|
|
when others => null;
|
| 1355 |
|
|
end case;
|
| 1356 |
|
|
|
| 1357 |
|
|
-- debug unit diagnostic regfile read
|
| 1358 |
|
|
if DEBUG_UNIT and (dsur.dmode and iui.debug.denable) = '1' then
|
| 1359 |
|
|
read_addr1 := iui.debug.daddr(RABITS+1 downto 2); rfenable1 := '1';
|
| 1360 |
|
|
end if;
|
| 1361 |
|
|
|
| 1362 |
|
|
exin.write_y <= write_y;
|
| 1363 |
|
|
exin.rst_mey <= rst_mey;
|
| 1364 |
|
|
exin.rs1data <= rs1data;
|
| 1365 |
|
|
exin.rs2data <= rs2data;
|
| 1366 |
|
|
exin.ymsb <= ymsb;
|
| 1367 |
|
|
rfi.rd1addr <= read_addr1; rfi.rd2addr <= read_addr2;
|
| 1368 |
|
|
|
| 1369 |
|
|
-- CP/FPU interface
|
| 1370 |
|
|
|
| 1371 |
|
|
if (FPIFTYPE = serial) then
|
| 1372 |
|
|
fpu_regin.fpop <= fpop and (not fpu_reg.fpld) and not ctrl.annul;
|
| 1373 |
|
|
fpexin.ldfsr := fsr_ld;
|
| 1374 |
|
|
fpu_regin.ex <= fpexin;
|
| 1375 |
|
|
end if;
|
| 1376 |
|
|
|
| 1377 |
|
|
if CPEN then
|
| 1378 |
|
|
cpi.dannul <= annul_current_cp or cpldlock or wr.annul_all or de.annul;
|
| 1379 |
|
|
cpi.dtrap <= ctrl.trap;
|
| 1380 |
|
|
end if;
|
| 1381 |
|
|
|
| 1382 |
|
|
if FPIFTYPE = parallel then
|
| 1383 |
|
|
fpi.dannul <= annul_current_cp or fpldlock or wr.annul_all or de.annul;
|
| 1384 |
|
|
fpi.dtrap <= ctrl.trap;
|
| 1385 |
|
|
fpi.fdata <= ico.data;
|
| 1386 |
|
|
fpi.frdy <= (not ico.mds) or (holdn and not hold_pc);
|
| 1387 |
|
|
end if;
|
| 1388 |
|
|
|
| 1389 |
|
|
|
| 1390 |
|
|
if RF_LOWPOW = false then rfenable1 := '1'; rfenable2 := '1'; end if;
|
| 1391 |
|
|
rfi.ren1 <= rfenable1; rfi.ren2 <= rfenable2;
|
| 1392 |
|
|
|
| 1393 |
|
|
end process;
|
| 1394 |
|
|
|
| 1395 |
|
|
-------------------------------------------------------------------------------
|
| 1396 |
|
|
-- execute stage
|
| 1397 |
|
|
-------------------------------------------------------------------------------
|
| 1398 |
|
|
|
| 1399 |
|
|
|
| 1400 |
|
|
execute_stage : process(rst, de, ex, me, wr, wrin, sregs, fpu_reg, fpu_regin,
|
| 1401 |
|
|
fpo, cpo, fpuo, mulo, divo, tr, iui, dsur, sum32)
|
| 1402 |
|
|
|
| 1403 |
|
|
variable op : std_logic_vector(1 downto 0);
|
| 1404 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
| 1405 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
| 1406 |
|
|
variable rs1 : std_logic_vector(4 downto 0);
|
| 1407 |
|
|
variable inull, jump, link_pc : std_logic;
|
| 1408 |
|
|
variable dcache_write : std_logic; -- Load or store cycle
|
| 1409 |
|
|
variable memory_load : std_logic;
|
| 1410 |
|
|
variable signed : std_logic;
|
| 1411 |
|
|
variable enaddr : std_logic;
|
| 1412 |
|
|
variable force_a2 : std_logic; -- force A(2) in second LDD cycle
|
| 1413 |
|
|
variable addr_misal : std_logic; -- misaligned address (JMPL/RETT)
|
| 1414 |
|
|
variable ld_size : std_logic_vector(1 downto 0); -- Load size
|
| 1415 |
|
|
variable read : std_logic;
|
| 1416 |
|
|
variable su : std_logic; -- Local supervisor bit
|
| 1417 |
|
|
variable asi : std_logic_vector(7 downto 0); -- Local ASI
|
| 1418 |
|
|
variable ctrl : pipeline_control_type;
|
| 1419 |
|
|
variable res, y : std_logic_vector(31 downto 0);
|
| 1420 |
|
|
variable icc, licc, micc : std_logic_vector(3 downto 0);
|
| 1421 |
|
|
variable addout : std_logic_vector(31 downto 0);
|
| 1422 |
|
|
variable shiftout : std_logic_vector(31 downto 0);
|
| 1423 |
|
|
variable logicout : std_logic_vector(31 downto 0);
|
| 1424 |
|
|
variable miscout : std_logic_vector(31 downto 0);
|
| 1425 |
|
|
variable edata : std_logic_vector(31 downto 0);
|
| 1426 |
|
|
variable aluresult : std_logic_vector(31 downto 0);
|
| 1427 |
|
|
variable eaddress : std_logic_vector(31 downto 0);
|
| 1428 |
|
|
variable nexty : std_logic_vector(31 downto 0);
|
| 1429 |
|
|
variable aluin1, aluin2 : std_logic_vector(31 downto 0);
|
| 1430 |
|
|
variable shiftin : std_logic_vector(63 downto 0);
|
| 1431 |
|
|
variable shiftcnt : std_logic_vector(4 downto 0);
|
| 1432 |
|
|
variable ymsb : std_logic; -- next msb of Y during MUL
|
| 1433 |
|
|
variable write_reg, write_icc, write_y : std_logic;
|
| 1434 |
|
|
variable lock : std_logic;
|
| 1435 |
|
|
variable dsu_cache : std_logic;
|
| 1436 |
|
|
variable fpmein : fpu_ctrl2_type;
|
| 1437 |
|
|
variable mulop1, mulop2 : std_logic_vector(32 downto 0);
|
| 1438 |
|
|
variable wpi : integer range 0 to 3; -- watchpoint index
|
| 1439 |
|
|
variable addin2 : std_logic_vector(31 downto 0);
|
| 1440 |
|
|
variable cin : std_logic;
|
| 1441 |
|
|
|
| 1442 |
|
|
begin
|
| 1443 |
|
|
|
| 1444 |
|
|
-- op-code decoding
|
| 1445 |
|
|
|
| 1446 |
|
|
op := ex.ctrl.inst(31 downto 30);
|
| 1447 |
|
|
op3 := ex.ctrl.inst(24 downto 19);
|
| 1448 |
|
|
opf := ex.ctrl.inst(13 downto 5);
|
| 1449 |
|
|
rs1 := ex.ctrl.inst(18 downto 14);
|
| 1450 |
|
|
|
| 1451 |
|
|
-- common initialisation
|
| 1452 |
|
|
|
| 1453 |
|
|
ctrl := ex.ctrl; memory_load := '0';
|
| 1454 |
|
|
ctrl.annul := ctrl.annul or wr.annul_all;
|
| 1455 |
|
|
read := not op3(2);
|
| 1456 |
|
|
dcache_write := '0'; enaddr := '0'; wpi := 0;
|
| 1457 |
|
|
ld_size := LDWORD; signed := '0'; addr_misal := '0'; lock := '0';
|
| 1458 |
|
|
write_reg := ex.write_reg;
|
| 1459 |
|
|
write_icc := ex.write_icc;
|
| 1460 |
|
|
write_y := ex.write_y;
|
| 1461 |
|
|
fpmein.fpop := fpu_reg.ex.fpop;
|
| 1462 |
|
|
fpmein.dsz := fpu_reg.ex.dsz;
|
| 1463 |
|
|
fpmein.ldfsr := fpu_reg.ex.ldfsr;
|
| 1464 |
|
|
fpmein.cexc := fpuo.excep(4 downto 0);
|
| 1465 |
|
|
fpmein.fcc := fpuo.ConditionCodes;
|
| 1466 |
|
|
muli.mac <= op3(5);
|
| 1467 |
|
|
dsu_cache := '0';
|
| 1468 |
|
|
|
| 1469 |
|
|
-- load/store size decoding
|
| 1470 |
|
|
|
| 1471 |
|
|
case op is
|
| 1472 |
|
|
when LDST =>
|
| 1473 |
|
|
case op3 is
|
| 1474 |
|
|
when LDUB | LDUBA => ld_size := LDBYTE;
|
| 1475 |
|
|
when LDSTUB | LDSTUBA => ld_size := LDBYTE; lock := '1';
|
| 1476 |
|
|
when LDUH | LDUHA => ld_size := LDHALF;
|
| 1477 |
|
|
when LDSB | LDSBA => ld_size := LDBYTE; signed := '1';
|
| 1478 |
|
|
when LDSH | LDSHA => ld_size := LDHALF; signed := '1';
|
| 1479 |
|
|
when LD | LDA | LDF | LDC => ld_size := LDWORD;
|
| 1480 |
|
|
when SWAP | SWAPA => ld_size := LDWORD; lock := '1';
|
| 1481 |
|
|
when LDD | LDDA | LDDF | LDDC => ld_size := LDDBL;
|
| 1482 |
|
|
when STB | STBA => ld_size := LDBYTE;
|
| 1483 |
|
|
when STH | STHA => ld_size := LDHALF;
|
| 1484 |
|
|
when ST | STA | STF => ld_size := LDWORD;
|
| 1485 |
|
|
when ISTD | STDA => ld_size := LDDBL;
|
| 1486 |
|
|
when STDF | STDFQ => if FPEN then ld_size := LDDBL; end if;
|
| 1487 |
|
|
when STDC | STDCQ => if CPEN then ld_size := LDDBL; end if;
|
| 1488 |
|
|
when others => null;
|
| 1489 |
|
|
end case;
|
| 1490 |
|
|
when others => null;
|
| 1491 |
|
|
end case;
|
| 1492 |
|
|
|
| 1493 |
|
|
link_pc := '0'; jump:= '0'; inull :='0'; force_a2 := '0';
|
| 1494 |
|
|
|
| 1495 |
|
|
-- load/store control decoding
|
| 1496 |
|
|
|
| 1497 |
|
|
if (ctrl.annul = '0') then
|
| 1498 |
|
|
case op is
|
| 1499 |
|
|
when CALL =>
|
| 1500 |
|
|
link_pc := '1';
|
| 1501 |
|
|
when FMT3 =>
|
| 1502 |
|
|
case op3 is
|
| 1503 |
|
|
when JMPL =>
|
| 1504 |
|
|
jump := '1'; link_pc := '1';
|
| 1505 |
|
|
inull := me.ctrl.annul or not me.jmpl_rett;
|
| 1506 |
|
|
when RETT =>
|
| 1507 |
|
|
jump := '1'; inull := me.ctrl.annul or not me.jmpl_rett;
|
| 1508 |
|
|
when others => null;
|
| 1509 |
|
|
end case;
|
| 1510 |
|
|
when LDST =>
|
| 1511 |
|
|
if (ctrl.trap or (wrin.ctrl.trap and not wrin.ctrl.annul)) = '0' then
|
| 1512 |
|
|
case ex.ctrl.cnt is
|
| 1513 |
|
|
when "00" =>
|
| 1514 |
|
|
memory_load := op3(3) or not op3(2); -- LD/LDST/SWAP
|
| 1515 |
|
|
read := memory_load; enaddr := '1';
|
| 1516 |
|
|
when "01" =>
|
| 1517 |
|
|
memory_load := not op3(2); -- LDD
|
| 1518 |
|
|
enaddr := memory_load;
|
| 1519 |
|
|
force_a2 := memory_load;
|
| 1520 |
|
|
if op3(3 downto 2) = "01" then -- ST/STD
|
| 1521 |
|
|
dcache_write := '1';
|
| 1522 |
|
|
end if;
|
| 1523 |
|
|
if op3(3 downto 2) = "11" then -- LDST/SWAP
|
| 1524 |
|
|
enaddr := '1';
|
| 1525 |
|
|
end if;
|
| 1526 |
|
|
when "10" => -- STD/LDST/SWAP
|
| 1527 |
|
|
dcache_write := '1';
|
| 1528 |
|
|
when others => null;
|
| 1529 |
|
|
end case;
|
| 1530 |
|
|
end if;
|
| 1531 |
|
|
when others => null;
|
| 1532 |
|
|
end case;
|
| 1533 |
|
|
end if;
|
| 1534 |
|
|
|
| 1535 |
|
|
-- supervisor bit generation
|
| 1536 |
|
|
|
| 1537 |
|
|
if ((wr.ctrl.rett and not wr.ctrl.annul) = '1') then su := sregs.ps;
|
| 1538 |
|
|
else su := sregs.s; end if;
|
| 1539 |
|
|
if su = '1' then asi := "00001011"; else asi := "00001010"; end if;
|
| 1540 |
|
|
if (op3(4) = '1') and ((op3(5) = '0') or not CPEN) then
|
| 1541 |
|
|
asi := ex.ctrl.inst(12 downto 5);
|
| 1542 |
|
|
end if;
|
| 1543 |
|
|
|
| 1544 |
|
|
|
| 1545 |
|
|
-- load data bypass in case (LDDELAY = 1)
|
| 1546 |
|
|
|
| 1547 |
|
|
aluin1 := ex.rs1data; aluin2 := ex.rs2data; ymsb := ex.ymsb;
|
| 1548 |
|
|
|
| 1549 |
|
|
if LDDELAY = 1 then
|
| 1550 |
|
|
if ex.ldbp1 = '1' then aluin1 := wr.result; ymsb := wr.result(0); end if;
|
| 1551 |
|
|
if ex.ldbp2 = '1' then aluin2 := wr.result; end if;
|
| 1552 |
|
|
end if;
|
| 1553 |
|
|
|
| 1554 |
|
|
-- bypassed operands to multiplier
|
| 1555 |
|
|
|
| 1556 |
|
|
muli.signed <= op3(0); divi.signed <= op3(0);
|
| 1557 |
|
|
mulop1 := (aluin1(31) and op3(0)) & aluin1;
|
| 1558 |
|
|
mulop2 := (aluin2(31) and op3(0)) & aluin2;
|
| 1559 |
|
|
if (ex.mulinsn = '0') and not INFER_MULT then -- try to minimise power
|
| 1560 |
|
|
mulop1 := (others => '0'); mulop2 := (others => '0');
|
| 1561 |
|
|
end if;
|
| 1562 |
|
|
muli.op1 <= mulop1; muli.op2 <= mulop2;
|
| 1563 |
|
|
|
| 1564 |
|
|
divi.op1 <= (aluin1(31) and op3(0)) & aluin1;
|
| 1565 |
|
|
divi.op2 <= (aluin2(31) and op3(0)) & aluin2;
|
| 1566 |
|
|
|
| 1567 |
|
|
-- ALU add/sub
|
| 1568 |
|
|
|
| 1569 |
|
|
icc := "0000";
|
| 1570 |
|
|
|
| 1571 |
|
|
-- pragma translate_off
|
| 1572 |
|
|
if not (is_x(aluin1) or is_x(aluin2)) then
|
| 1573 |
|
|
-- pragma translate_on
|
| 1574 |
|
|
cin := ex.alu_cin; addin2 := aluin2;
|
| 1575 |
|
|
if ex.aluadd = '0' then
|
| 1576 |
|
|
addin2 := not aluin2; cin := not cin;
|
| 1577 |
|
|
end if;
|
| 1578 |
|
|
-- addout := aluin1 + addin2 + cin;
|
| 1579 |
|
|
if FASTADD then addout := sum32;
|
| 1580 |
|
|
else
|
| 1581 |
|
|
if ex.aluadd = '0' then addout := aluin1 - aluin2 - ex.alu_cin;
|
| 1582 |
|
|
else addout := aluin1 + aluin2 + ex.alu_cin; end if;
|
| 1583 |
|
|
end if;
|
| 1584 |
|
|
-- pragma translate_off
|
| 1585 |
|
|
end if;
|
| 1586 |
|
|
-- pragma translate_on
|
| 1587 |
|
|
|
| 1588 |
|
|
add32in1 <= aluin1;
|
| 1589 |
|
|
add32in2 <= addin2;
|
| 1590 |
|
|
add32cin <= cin;
|
| 1591 |
|
|
|
| 1592 |
|
|
-- fast address adders if enabled
|
| 1593 |
|
|
|
| 1594 |
|
|
if FASTJUMP then
|
| 1595 |
|
|
-- pragma translate_off
|
| 1596 |
|
|
if not (is_x(aluin1) or is_x(aluin2)) then
|
| 1597 |
|
|
-- pragma translate_on
|
| 1598 |
|
|
fecomb.jump_address <= aluin1(31 downto PCLOW) + aluin2(31 downto PCLOW);
|
| 1599 |
|
|
if (aluin1(1 downto 0) + aluin2(1 downto 0)) = "00" then
|
| 1600 |
|
|
addr_misal := '0';
|
| 1601 |
|
|
else
|
| 1602 |
|
|
addr_misal := '1';
|
| 1603 |
|
|
end if;
|
| 1604 |
|
|
-- pragma translate_off
|
| 1605 |
|
|
else
|
| 1606 |
|
|
fecomb.jump_address <= (others => 'X');
|
| 1607 |
|
|
end if;
|
| 1608 |
|
|
-- pragma translate_on
|
| 1609 |
|
|
else
|
| 1610 |
|
|
fecomb.jump_address(31 downto PCLOW) <= addout(31 downto PCLOW);
|
| 1611 |
|
|
if addout(1 downto 0) = "00" then
|
| 1612 |
|
|
addr_misal := '0';
|
| 1613 |
|
|
else
|
| 1614 |
|
|
addr_misal := '1';
|
| 1615 |
|
|
end if;
|
| 1616 |
|
|
end if;
|
| 1617 |
|
|
|
| 1618 |
|
|
res := (others => '-');
|
| 1619 |
|
|
|
| 1620 |
|
|
-- alu ops which set icc
|
| 1621 |
|
|
|
| 1622 |
|
|
case ex.aluop is
|
| 1623 |
|
|
when ALU_OR => logicout := aluin1 or aluin2;
|
| 1624 |
|
|
when ALU_ORN => logicout := aluin1 or not aluin2;
|
| 1625 |
|
|
when ALU_AND => logicout := aluin1 and aluin2;
|
| 1626 |
|
|
when ALU_ANDN => logicout := aluin1 and not aluin2;
|
| 1627 |
|
|
when ALU_XOR => logicout := aluin1 xor aluin2;
|
| 1628 |
|
|
when ALU_XNOR => logicout := aluin1 xor not aluin2;
|
| 1629 |
|
|
when ALU_DIV =>
|
| 1630 |
|
|
if DIVIDER /= none then logicout := aluin2;
|
| 1631 |
|
|
else logicout := (others => '-'); end if;
|
| 1632 |
|
|
when others => logicout := (others => '-');
|
| 1633 |
|
|
end case;
|
| 1634 |
|
|
|
| 1635 |
|
|
-- generate condition codes
|
| 1636 |
|
|
|
| 1637 |
|
|
if (ex.alusel(1) = '0') then
|
| 1638 |
|
|
res := addout;
|
| 1639 |
|
|
if ex.aluadd = '0' then
|
| 1640 |
|
|
icc(0) := ((not aluin1(31)) and aluin2(31)) or -- Carry
|
| 1641 |
|
|
(addout(31) and ((not aluin1(31)) or aluin2(31)));
|
| 1642 |
|
|
icc(1) := (aluin1(31) and (not aluin2(31)) and not addout(31)) or -- Overflow
|
| 1643 |
|
|
(addout(31) and (not aluin1(31)) and aluin2(31));
|
| 1644 |
|
|
else
|
| 1645 |
|
|
icc(0) := (aluin1(31) and aluin2(31)) or -- Carry
|
| 1646 |
|
|
((not addout(31)) and (aluin1(31) or aluin2(31)));
|
| 1647 |
|
|
icc(1) := (aluin1(31) and aluin2(31) and not addout(31)) or -- Overflow
|
| 1648 |
|
|
(addout(31) and (not aluin1(31)) and (not aluin2(31)));
|
| 1649 |
|
|
end if;
|
| 1650 |
|
|
else
|
| 1651 |
|
|
res := logicout;
|
| 1652 |
|
|
icc(1 downto 0) := "00";
|
| 1653 |
|
|
end if;
|
| 1654 |
|
|
|
| 1655 |
|
|
if res = zero32 then -- Zero
|
| 1656 |
|
|
icc(2) := '1';
|
| 1657 |
|
|
else
|
| 1658 |
|
|
icc(2) := '0';
|
| 1659 |
|
|
end if;
|
| 1660 |
|
|
icc(3) := res(31); -- Negative
|
| 1661 |
|
|
|
| 1662 |
|
|
-- select Y
|
| 1663 |
|
|
|
| 1664 |
|
|
if (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1'
|
| 1665 |
|
|
then y := me.my; else y := wr.y; end if;
|
| 1666 |
|
|
|
| 1667 |
|
|
-- alu ops which dont set icc
|
| 1668 |
|
|
|
| 1669 |
|
|
miscout := (others => '-'); edata := (others => '-');
|
| 1670 |
|
|
case ex.aluop is
|
| 1671 |
|
|
when ALU_STB => edata := aluin1(7 downto 0) & aluin1(7 downto 0) &
|
| 1672 |
|
|
aluin1(7 downto 0) & aluin1(7 downto 0);
|
| 1673 |
|
|
miscout := edata;
|
| 1674 |
|
|
when ALU_STH => edata := aluin1(15 downto 0) & aluin1(15 downto 0);
|
| 1675 |
|
|
miscout := edata;
|
| 1676 |
|
|
when ALU_PASS1 => miscout := aluin1; edata := aluin1;
|
| 1677 |
|
|
when ALU_PASS2 => miscout := aluin2;
|
| 1678 |
|
|
when ALU_ONES => miscout := (others => '1'); edata := (others => '1');
|
| 1679 |
|
|
when ALU_RDY =>
|
| 1680 |
|
|
miscout := y;
|
| 1681 |
|
|
|
| 1682 |
|
|
if (WATCHPOINTS > 0) and (rs1(4 downto 3) = "11") then
|
| 1683 |
|
|
wpi := conv_integer(unsigned(rs1(2 downto 1)));
|
| 1684 |
|
|
if rs1(0) = '0' then miscout := tr(wpi).addr & '0' & tr(wpi).exec;
|
| 1685 |
|
|
else miscout := tr(wpi).mask & tr(wpi).load & tr(wpi).store; end if;
|
| 1686 |
|
|
end if;
|
| 1687 |
|
|
when ALU_FSR =>
|
| 1688 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 1689 |
|
|
edata := fpu_reg.fsr.rd & "00" & fpu_reg.fsr.tem & "000" &
|
| 1690 |
|
|
std_logic_vector(FPUVER) & fpu_reg.fsr.ftt & "00" & fpu_reg.fsr.fcc &
|
| 1691 |
|
|
fpu_reg.fsr.aexc & fpu_reg.fsr.cexc;
|
| 1692 |
|
|
miscout := edata;
|
| 1693 |
|
|
end if;
|
| 1694 |
|
|
when ALU_FOP =>
|
| 1695 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 1696 |
|
|
miscout := aluin2;
|
| 1697 |
|
|
case opf(3 downto 2) is
|
| 1698 |
|
|
when "01" => miscout(31) := not miscout(31);
|
| 1699 |
|
|
when "10" => miscout(31) := '0';
|
| 1700 |
|
|
when others => null;
|
| 1701 |
|
|
end case;
|
| 1702 |
|
|
end if;
|
| 1703 |
|
|
when others => null;
|
| 1704 |
|
|
end case;
|
| 1705 |
|
|
|
| 1706 |
|
|
-- shifter
|
| 1707 |
|
|
|
| 1708 |
|
|
shiftin := zero32 & aluin1;
|
| 1709 |
|
|
shiftcnt := aluin2(4 downto 0);
|
| 1710 |
|
|
|
| 1711 |
|
|
if ex.aluop = ALU_SLL then
|
| 1712 |
|
|
shiftin(31 downto 0) := zero32;
|
| 1713 |
|
|
shiftin(63 downto 31) := '0' & aluin1;
|
| 1714 |
|
|
shiftcnt := not shiftcnt;
|
| 1715 |
|
|
elsif ex.aluop = ALU_SRA then
|
| 1716 |
|
|
if aluin1(31) = '1' then
|
| 1717 |
|
|
shiftin(63 downto 32) := (others => '1');
|
| 1718 |
|
|
else
|
| 1719 |
|
|
shiftin(63 downto 32) := zero32;
|
| 1720 |
|
|
end if;
|
| 1721 |
|
|
end if;
|
| 1722 |
|
|
if shiftcnt (4) = '1' then
|
| 1723 |
|
|
shiftin(47 downto 0) := shiftin(63 downto 16);
|
| 1724 |
|
|
end if;
|
| 1725 |
|
|
if shiftcnt (3) = '1' then
|
| 1726 |
|
|
shiftin(39 downto 0) := shiftin(47 downto 8);
|
| 1727 |
|
|
end if;
|
| 1728 |
|
|
if shiftcnt (2) = '1' then
|
| 1729 |
|
|
shiftin(35 downto 0) := shiftin(39 downto 4);
|
| 1730 |
|
|
end if;
|
| 1731 |
|
|
if shiftcnt (1) = '1' then
|
| 1732 |
|
|
shiftin(33 downto 0) := shiftin(35 downto 2);
|
| 1733 |
|
|
end if;
|
| 1734 |
|
|
if shiftcnt (0) = '1' then
|
| 1735 |
|
|
shiftin(31 downto 0) := shiftin(32 downto 1);
|
| 1736 |
|
|
end if;
|
| 1737 |
|
|
shiftout := shiftin(31 downto 0);
|
| 1738 |
|
|
|
| 1739 |
|
|
-- generate overflow for tagged add/sub
|
| 1740 |
|
|
|
| 1741 |
|
|
case op is
|
| 1742 |
|
|
when FMT3 =>
|
| 1743 |
|
|
case op3 is
|
| 1744 |
|
|
when TADDCC | TADDCCTV | TSUBCC | TSUBCCTV =>
|
| 1745 |
|
|
icc(1) := aluin1(0) or aluin1(1) or aluin2(0) or aluin2(1) or icc(1);
|
| 1746 |
|
|
when others => null;
|
| 1747 |
|
|
end case;
|
| 1748 |
|
|
when others => null;
|
| 1749 |
|
|
end case;
|
| 1750 |
|
|
|
| 1751 |
|
|
-- select alu output
|
| 1752 |
|
|
|
| 1753 |
|
|
aluresult := (others => '0');
|
| 1754 |
|
|
if link_pc = '1' then
|
| 1755 |
|
|
aluresult := ex.ctrl.pc(31 downto 2) & "00"; -- save PC during jmpl
|
| 1756 |
|
|
else
|
| 1757 |
|
|
case ex.alusel is
|
| 1758 |
|
|
when ALU_RES_ADD => aluresult := addout;
|
| 1759 |
|
|
when ALU_RES_SHIFT => aluresult := shiftout;
|
| 1760 |
|
|
when ALU_RES_LOGIC => aluresult := logicout;
|
| 1761 |
|
|
when others => aluresult := miscout;
|
| 1762 |
|
|
end case;
|
| 1763 |
|
|
end if;
|
| 1764 |
|
|
|
| 1765 |
|
|
ex.icc <= icc;
|
| 1766 |
|
|
|
| 1767 |
|
|
-- FPU interface
|
| 1768 |
|
|
|
| 1769 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 1770 |
|
|
-- pragma translate_off
|
| 1771 |
|
|
if is_x(aluin1) then aluin1 := (others => '0'); end if;
|
| 1772 |
|
|
if is_x(aluin2) then aluin2 := (others => '0'); end if;
|
| 1773 |
|
|
if is_x(de.inst(19) & de.inst(13 downto 5)) then
|
| 1774 |
|
|
fpui.FpInst <= (others => '0');
|
| 1775 |
|
|
else
|
| 1776 |
|
|
-- pragma translate_on
|
| 1777 |
|
|
fpui.FpInst <= de.inst(19) & de.inst(13 downto 5);
|
| 1778 |
|
|
-- pragma translate_off
|
| 1779 |
|
|
end if;
|
| 1780 |
|
|
if is_x(fpu_reg.fsr.rd) then fpui.RoundingMode <= (others => '0');
|
| 1781 |
|
|
else
|
| 1782 |
|
|
-- pragma translate_on
|
| 1783 |
|
|
fpui.RoundingMode <= fpu_reg.fsr.rd;
|
| 1784 |
|
|
-- pragma translate_off
|
| 1785 |
|
|
end if;
|
| 1786 |
|
|
-- pragma translate_on
|
| 1787 |
|
|
if (ex.ctrl.cnt = "00") or (opf(1) = '0') then
|
| 1788 |
|
|
fpui.fprf_dout1 <= aluin1 & aluin1;
|
| 1789 |
|
|
fpui.fprf_dout2 <= aluin2 & aluin2;
|
| 1790 |
|
|
else
|
| 1791 |
|
|
fpui.fprf_dout1 <= fpu_reg.op1h & aluin1;
|
| 1792 |
|
|
fpui.fprf_dout2 <= me.result & aluin2;
|
| 1793 |
|
|
end if;
|
| 1794 |
|
|
fpu_regin.op1h <= aluin1;
|
| 1795 |
|
|
if fpu_reg.ex.fpop = "01" and (ex.write_reg = '1') then
|
| 1796 |
|
|
if fpu_reg.ex.dsz = '1' then
|
| 1797 |
|
|
if (ex.ctrl.cnt /= "00") then
|
| 1798 |
|
|
aluresult := fpuo.FracResult(34 downto 3);
|
| 1799 |
|
|
end if;
|
| 1800 |
|
|
else
|
| 1801 |
|
|
aluresult := fpuo.SignResult & fpuo.ExpResult(7 downto 0) &
|
| 1802 |
|
|
fpuo.FracResult(54 downto 32);
|
| 1803 |
|
|
end if;
|
| 1804 |
|
|
end if;
|
| 1805 |
|
|
fpu_regin.me <= fpmein;
|
| 1806 |
|
|
end if;
|
| 1807 |
|
|
|
| 1808 |
|
|
if (MULTIPLIER = m32x32) and (ex.mulinsn = '1') then
|
| 1809 |
|
|
aluresult := mulo.result(31 downto 0);
|
| 1810 |
|
|
end if;
|
| 1811 |
|
|
if MACEN then
|
| 1812 |
|
|
if ex.aluop = ALU_RDY then
|
| 1813 |
|
|
if rs1 = "10010" then
|
| 1814 |
|
|
if ((me.mulinsn and me.ctrl.inst(24)) = '1') then
|
| 1815 |
|
|
aluresult := mulo.result(31 downto 0);
|
| 1816 |
|
|
else aluresult := wr.asr18; end if;
|
| 1817 |
|
|
else
|
| 1818 |
|
|
if ((me.mulinsn and me.ctrl.inst(24)) = '1') then
|
| 1819 |
|
|
aluresult := mulo.result(63 downto 32);
|
| 1820 |
|
|
end if;
|
| 1821 |
|
|
end if;
|
| 1822 |
|
|
end if;
|
| 1823 |
|
|
end if;
|
| 1824 |
|
|
|
| 1825 |
|
|
ex.result <= aluresult;
|
| 1826 |
|
|
|
| 1827 |
|
|
-- generate Y
|
| 1828 |
|
|
|
| 1829 |
|
|
micc := icc;
|
| 1830 |
|
|
licc := icc;
|
| 1831 |
|
|
|
| 1832 |
|
|
nexty := y;
|
| 1833 |
|
|
if ex.mulstep = '1' then
|
| 1834 |
|
|
nexty := ymsb & y(31 downto 1);
|
| 1835 |
|
|
elsif (ex.mulinsn = '1') and (MULTIPLIER = iterative) then
|
| 1836 |
|
|
case ex.ctrl.cnt is
|
| 1837 |
|
|
when "00" => nexty := y;
|
| 1838 |
|
|
when "01" => nexty := ymsb & me.y(31 downto 1);
|
| 1839 |
|
|
when "10" =>
|
| 1840 |
|
|
aluresult := ymsb & me.y(31 downto 1);
|
| 1841 |
|
|
licc(3) := ymsb; licc(1 downto 0) := "00";
|
| 1842 |
|
|
if aluresult = zero32 then
|
| 1843 |
|
|
licc(2) := '1'; else licc(2) := '0';
|
| 1844 |
|
|
end if;
|
| 1845 |
|
|
nexty := me.y;
|
| 1846 |
|
|
when others => null;
|
| 1847 |
|
|
end case;
|
| 1848 |
|
|
elsif ((ex.rst_mey or ex.write_y) = '1') and (MULTIPLIER = iterative) then
|
| 1849 |
|
|
if ex.ctrl.cnt = "11" then nexty := addout;
|
| 1850 |
|
|
else nexty := logicout; end if;
|
| 1851 |
|
|
elsif ex.write_y = '1' then
|
| 1852 |
|
|
nexty := logicout;
|
| 1853 |
|
|
end if;
|
| 1854 |
|
|
|
| 1855 |
|
|
if (MULTIPLIER = iterative) then
|
| 1856 |
|
|
micc(3) := icc(3) and not ex.rst_mey;
|
| 1857 |
|
|
micc(1) := icc(1) and not ex.rst_mey;
|
| 1858 |
|
|
end if;
|
| 1859 |
|
|
|
| 1860 |
|
|
-- data address generation
|
| 1861 |
|
|
|
| 1862 |
|
|
eaddress := miscout;
|
| 1863 |
|
|
if ex.alusel = ALU_RES_ADD then
|
| 1864 |
|
|
addout(2) := addout(2) or force_a2; eaddress := addout;
|
| 1865 |
|
|
end if;
|
| 1866 |
|
|
|
| 1867 |
|
|
if CPEN and (op = LDST) and ((op3(5 downto 4) & op3(2)) = "111") and
|
| 1868 |
|
|
(ex.ctrl.cnt /= "00")
|
| 1869 |
|
|
then
|
| 1870 |
|
|
dci.edata <= cpo.data; -- store co-processor
|
| 1871 |
|
|
aluresult := cpo.data;
|
| 1872 |
|
|
elsif (FPIFTYPE = parallel) and (op = LDST) and
|
| 1873 |
|
|
((op3(5 downto 4) & op3(2)) = "101") and (ex.ctrl.cnt /= "00")
|
| 1874 |
|
|
then
|
| 1875 |
|
|
dci.edata <= fpo.data; -- store fpu co-processor
|
| 1876 |
|
|
aluresult := fpo.data;
|
| 1877 |
|
|
else
|
| 1878 |
|
|
dci.edata <= edata;
|
| 1879 |
|
|
aluresult(2) := aluresult(2) or force_a2;
|
| 1880 |
|
|
end if;
|
| 1881 |
|
|
|
| 1882 |
|
|
if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then
|
| 1883 |
|
|
write_reg := write_reg or mulo.ready;
|
| 1884 |
|
|
write_y := write_y or mulo.ready;
|
| 1885 |
|
|
write_icc := write_icc or (mulo.ready and op3(4));
|
| 1886 |
|
|
end if;
|
| 1887 |
|
|
if DIVIDER /= none then
|
| 1888 |
|
|
write_reg := write_reg or divo.ready;
|
| 1889 |
|
|
write_icc := write_icc or (divo.ready and op3(4));
|
| 1890 |
|
|
end if;
|
| 1891 |
|
|
|
| 1892 |
|
|
-- debug unit cache access
|
| 1893 |
|
|
if DEBUG_UNIT then
|
| 1894 |
|
|
if dsur.dmode = '1' then
|
| 1895 |
|
|
dcache_write := '0'; read := '1'; dsu_cache := '0';
|
| 1896 |
|
|
if (iui.debug.denable and iui.debug.daddr(20)) = '1' then
|
| 1897 |
|
|
enaddr := '1';
|
| 1898 |
|
|
asi(4 downto 0) := iui.debug.daddr(17) & "11" & iui.debug.daddr(19 downto 18);
|
| 1899 |
|
|
if M_EN and iui.debug.daddr(21) = '1' then
|
| 1900 |
|
|
-- ASI_ICTX "10101" 0x90300000-0x90340000
|
| 1901 |
|
|
-- ASI_DCTX "10100" 0x90380000-0x903c0000
|
| 1902 |
|
|
asi(4 downto 0) := "1010" & not (iui.debug.daddr(19));
|
| 1903 |
|
|
end if;
|
| 1904 |
|
|
dsu_cache := '1'; ld_size := LDWORD;
|
| 1905 |
|
|
if iui.debug.dwrite = '1' then
|
| 1906 |
|
|
dcache_write := '1'; read := '0';
|
| 1907 |
|
|
end if;
|
| 1908 |
|
|
if (dsur.dsuen and iui.debug.dwrite) = '1' then aluresult := iui.debug.ddata;
|
| 1909 |
|
|
else aluresult(21 downto 2) := iui.debug.daddr; end if;
|
| 1910 |
|
|
end if;
|
| 1911 |
|
|
end if;
|
| 1912 |
|
|
end if;
|
| 1913 |
|
|
|
| 1914 |
|
|
mein.y <= nexty;
|
| 1915 |
|
|
dciin.enaddr <= enaddr;
|
| 1916 |
|
|
dciin.read <= read;
|
| 1917 |
|
|
dciin.write <= dcache_write;
|
| 1918 |
|
|
dciin.asi <= asi;
|
| 1919 |
|
|
dciin.lock <= lock;
|
| 1920 |
|
|
dci.eenaddr <= enaddr;
|
| 1921 |
|
|
dci.eaddress <= eaddress;
|
| 1922 |
|
|
dci.dsuen <= dsur.dsuen;
|
| 1923 |
|
|
dci.esu <= su;
|
| 1924 |
|
|
|
| 1925 |
|
|
fecomb.jump <= jump;
|
| 1926 |
|
|
|
| 1927 |
|
|
ex.micc <= micc;
|
| 1928 |
|
|
mein.inull <= inull;
|
| 1929 |
|
|
mein.icc <= licc;
|
| 1930 |
|
|
mein.memory_load <= memory_load;
|
| 1931 |
|
|
mein.ld_size <= ld_size;
|
| 1932 |
|
|
mein.signed <= signed;
|
| 1933 |
|
|
mein.addr_misal <= addr_misal;
|
| 1934 |
|
|
|
| 1935 |
|
|
mein.result <= aluresult;
|
| 1936 |
|
|
mein.write_reg <= write_reg;
|
| 1937 |
|
|
mein.write_icc <= write_icc;
|
| 1938 |
|
|
mein.write_y <= write_y;
|
| 1939 |
|
|
mein.ctrl <= ctrl;
|
| 1940 |
|
|
mein.su <= su;
|
| 1941 |
|
|
|
| 1942 |
|
|
end process;
|
| 1943 |
|
|
|
| 1944 |
|
|
-------------------------------------------------------------------------------
|
| 1945 |
|
|
-- memory stage
|
| 1946 |
|
|
-------------------------------------------------------------------------------
|
| 1947 |
|
|
|
| 1948 |
|
|
|
| 1949 |
|
|
memory_stage : process(ex, me, wr, sregs, sregsin, iui, dco, fpuo, fpu_reg,
|
| 1950 |
|
|
cpo, fpo, rst, holdn, mulo, divo, tr, dsur)
|
| 1951 |
|
|
|
| 1952 |
|
|
variable op : std_logic_vector(1 downto 0);
|
| 1953 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
| 1954 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
| 1955 |
|
|
variable rd,rs1: std_logic_vector(4 downto 0);
|
| 1956 |
|
|
variable ctrl : pipeline_control_type;
|
| 1957 |
|
|
variable nullify : std_logic;
|
| 1958 |
|
|
variable iflush : std_logic;
|
| 1959 |
|
|
variable ipend : std_logic;
|
| 1960 |
|
|
variable write_cwp : std_logic;
|
| 1961 |
|
|
variable cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
| 1962 |
|
|
variable cwpx : std_logic_vector(5 downto NWINLOG2);
|
| 1963 |
|
|
variable result : std_logic_vector(31 downto 0);
|
| 1964 |
|
|
variable write_reg : std_logic;
|
| 1965 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
| 1966 |
|
|
variable werr : std_logic;
|
| 1967 |
|
|
variable fpexc : std_logic;
|
| 1968 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
| 1969 |
|
|
variable fpwrin : fpu_ctrl2_type;
|
| 1970 |
|
|
variable jmpl_rett : std_logic;
|
| 1971 |
|
|
variable pil : std_logic_vector(3 downto 0);
|
| 1972 |
|
|
variable irqen : std_logic;
|
| 1973 |
|
|
variable dsutrap : std_logic;
|
| 1974 |
|
|
variable y, asr18 : std_logic_vector(31 downto 0);
|
| 1975 |
|
|
variable trv : watchpoint_registers;
|
| 1976 |
|
|
variable wpi : integer range 0 to 3; -- watchpoint index
|
| 1977 |
|
|
|
| 1978 |
|
|
begin
|
| 1979 |
|
|
|
| 1980 |
|
|
-- common initialisation
|
| 1981 |
|
|
|
| 1982 |
|
|
op := me.ctrl.inst(31 downto 30);
|
| 1983 |
|
|
op2 := me.ctrl.inst(24 downto 22);
|
| 1984 |
|
|
op3 := me.ctrl.inst(24 downto 19);
|
| 1985 |
|
|
opf := me.ctrl.inst(13 downto 5);
|
| 1986 |
|
|
rd := me.ctrl.inst(29 downto 25);
|
| 1987 |
|
|
rs1 := me.ctrl.inst(18 downto 14);
|
| 1988 |
|
|
ctrl := me.ctrl;
|
| 1989 |
|
|
ctrl.annul := ctrl.annul or wr.annul_all;
|
| 1990 |
|
|
nullify := ctrl.annul;
|
| 1991 |
|
|
iflush := '0';
|
| 1992 |
|
|
cwp := me.cwp; write_cwp := me.write_cwp;
|
| 1993 |
|
|
result := me.result;
|
| 1994 |
|
|
write_reg := me.write_reg;
|
| 1995 |
|
|
icc := me.icc;
|
| 1996 |
|
|
fpwrin := fpu_reg.me;
|
| 1997 |
|
|
jmpl_rett := '0';
|
| 1998 |
|
|
werr := (me.werr or dco.werr) and rst;
|
| 1999 |
|
|
y := me.y; asr18 := wr.asr18;
|
| 2000 |
|
|
trv := tr; wpi := 0; dsutrap := '0';
|
| 2001 |
|
|
cwpx := me.result(5 downto NWINLOG2); cwpx(5) := '0';
|
| 2002 |
|
|
|
| 2003 |
|
|
-- external interrupt handling
|
| 2004 |
|
|
|
| 2005 |
|
|
-- disable interrupts for one clock after a WRPSR, since a
|
| 2006 |
|
|
-- WRPSR should affect ET and PIL without delay (SPARC V8 ISP, p.183)
|
| 2007 |
|
|
irqen := me.irqen and sregs.et; pil := sregs.pil;
|
| 2008 |
|
|
if (iui.irl = "1111") or (iui.irl > pil) then ipend := irqen;
|
| 2009 |
|
|
else ipend := '0'; end if;
|
| 2010 |
|
|
if (ctrl.annul = '0') and (ctrl.pv = '1') then
|
| 2011 |
|
|
if (werr and holdn) = '1' then
|
| 2012 |
|
|
ctrl.trap := '1'; ctrl.tt := DSEX_TT; werr := '0';
|
| 2013 |
|
|
if op = LDST then nullify := '1'; end if;
|
| 2014 |
|
|
elsif (irqen and not me.ctrl.trap) = '1' then
|
| 2015 |
|
|
|
| 2016 |
|
|
if ipend = '1' then
|
| 2017 |
|
|
|
| 2018 |
|
|
ctrl.trap := '1'; ctrl.tt := "01" & iui.irl;
|
| 2019 |
|
|
if op = LDST then nullify := '1'; end if;
|
| 2020 |
|
|
end if;
|
| 2021 |
|
|
end if;
|
| 2022 |
|
|
end if;
|
| 2023 |
|
|
|
| 2024 |
|
|
iuo.ipend <= me.ipend;
|
| 2025 |
|
|
|
| 2026 |
|
|
-- some trap generation
|
| 2027 |
|
|
|
| 2028 |
|
|
irqen := '1';
|
| 2029 |
|
|
if ((ctrl.annul or ctrl.trap) /= '1') then
|
| 2030 |
|
|
case op is
|
| 2031 |
|
|
when FMT2 =>
|
| 2032 |
|
|
case op2 is
|
| 2033 |
|
|
when FBFCC =>
|
| 2034 |
|
|
if (FPIFTYPE = parallel) and (fpo.exc = '1')
|
| 2035 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if;
|
| 2036 |
|
|
when CBCCC =>
|
| 2037 |
|
|
if CPEN and (cpo.exc = '1')
|
| 2038 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if;
|
| 2039 |
|
|
when others => null;
|
| 2040 |
|
|
end case;
|
| 2041 |
|
|
when FMT3 =>
|
| 2042 |
|
|
case op3 is
|
| 2043 |
|
|
when WRY =>
|
| 2044 |
|
|
if MACEN and (rd = "10010") then asr18 := me.result; end if;
|
| 2045 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
| 2046 |
|
|
if rd(4 downto 1) = std_logic_vector(conv_unsigned(12+i, 4)) then
|
| 2047 |
|
|
if rd(0) = '0' then
|
| 2048 |
|
|
trv(i).addr := me.result(31 downto 2);
|
| 2049 |
|
|
trv(i).exec := me.result(0);
|
| 2050 |
|
|
else
|
| 2051 |
|
|
trv(i).mask := me.result(31 downto 2);
|
| 2052 |
|
|
trv(i).load := me.result(1); trv(i).store := me.result(0);
|
| 2053 |
|
|
end if;
|
| 2054 |
|
|
end if;
|
| 2055 |
|
|
end loop;
|
| 2056 |
|
|
when WRPSR =>
|
| 2057 |
|
|
if (orv(cwpx) = '1') then
|
| 2058 |
|
|
ctrl.trap := '1'; ctrl.tt := IINST_TT;
|
| 2059 |
|
|
else cwp := me.result(NWINLOG2-1 downto 0); write_cwp := '1'; end if;
|
| 2060 |
|
|
when UDIV | SDIV =>
|
| 2061 |
|
|
if (DIVIDER /= none) then
|
| 2062 |
|
|
if icc(2) = '1' then ctrl.trap := '1'; ctrl.tt := DIV_TT; end if;
|
| 2063 |
|
|
end if;
|
| 2064 |
|
|
when UDIVCC | SDIVCC =>
|
| 2065 |
|
|
if (DIVIDER /= none) then
|
| 2066 |
|
|
if icc(2) = '1' then ctrl.trap := '1'; ctrl.tt := DIV_TT; end if;
|
| 2067 |
|
|
end if;
|
| 2068 |
|
|
when JMPL | RETT =>
|
| 2069 |
|
|
-- jmpl_rett := '1';
|
| 2070 |
|
|
if me.addr_misal = '1' then
|
| 2071 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT;
|
| 2072 |
|
|
end if;
|
| 2073 |
|
|
when TADDCCTV | TSUBCCTV =>
|
| 2074 |
|
|
if me.icc(1) = '1' then ctrl.trap := '1'; ctrl.tt := TAG_TT; end if;
|
| 2075 |
|
|
when FLUSH => iflush := '1';
|
| 2076 |
|
|
when FPOP1 | FPOP2 =>
|
| 2077 |
|
|
if (FPIFTYPE = parallel) and (fpo.exc = '1')
|
| 2078 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if;
|
| 2079 |
|
|
when CPOP1 | CPOP2 =>
|
| 2080 |
|
|
if CPEN and (cpo.exc = '1')
|
| 2081 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if;
|
| 2082 |
|
|
when others => null;
|
| 2083 |
|
|
end case;
|
| 2084 |
|
|
when LDST =>
|
| 2085 |
|
|
if ctrl.cnt = "00" then
|
| 2086 |
|
|
case op3 is
|
| 2087 |
|
|
when LDDF | STDF | STDFQ =>
|
| 2088 |
|
|
if FPEN then
|
| 2089 |
|
|
if FPEN and (me.result(2 downto 0) /= "000") then
|
| 2090 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2091 |
|
|
elsif ((FPIFTYPE = parallel) and ((fpo.exc and ctrl.pv) = '1'))
|
| 2092 |
|
|
or ((FPIFTYPE = serial) and (op3 = STDFQ) and (ctrl.pv = '1'))
|
| 2093 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if;
|
| 2094 |
|
|
end if;
|
| 2095 |
|
|
when LDDC | STDC | STDCQ =>
|
| 2096 |
|
|
if CPEN and (me.result(2 downto 0) /= "000") then
|
| 2097 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2098 |
|
|
elsif CPEN and ((cpo.exc and ctrl.pv) = '1')
|
| 2099 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if;
|
| 2100 |
|
|
when LDD | ISTD | LDDA | STDA =>
|
| 2101 |
|
|
if me.result(2 downto 0) /= "000" then
|
| 2102 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2103 |
|
|
end if;
|
| 2104 |
|
|
when LDF | LDFSR | STFSR | STF =>
|
| 2105 |
|
|
if FPEN and (me.result(1 downto 0) /= "00") then
|
| 2106 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2107 |
|
|
elsif (FPIFTYPE = parallel) and ((fpo.exc and ctrl.pv) = '1')
|
| 2108 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if;
|
| 2109 |
|
|
when LDC | LDCSR | STCSR | STC =>
|
| 2110 |
|
|
if CPEN and (me.result(1 downto 0) /= "00") then
|
| 2111 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2112 |
|
|
elsif CPEN and ((cpo.exc and ctrl.pv) = '1')
|
| 2113 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if;
|
| 2114 |
|
|
when LD | LDA | ST | STA | SWAP | SWAPA =>
|
| 2115 |
|
|
if me.result(1 downto 0) /= "00" then
|
| 2116 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2117 |
|
|
end if;
|
| 2118 |
|
|
when LDUH | LDUHA | LDSH | LDSHA | STH | STHA =>
|
| 2119 |
|
|
if me.result(0) /= '0' then
|
| 2120 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
| 2121 |
|
|
end if;
|
| 2122 |
|
|
when others => null;
|
| 2123 |
|
|
end case;
|
| 2124 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
| 2125 |
|
|
if ((((tr(i).load and not op3(2)) or (tr(i).store and op3(2))) = '1') and
|
| 2126 |
|
|
(((tr(i).addr xor me.result(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)))
|
| 2127 |
|
|
or (DEBUG_UNIT and ((iui.debug.dsuen and iui.debug.bwatch and iui.debug.dbreak) = '1'))
|
| 2128 |
|
|
then
|
| 2129 |
|
|
ctrl.trap := '1'; ctrl.tt := WATCH_TT; nullify := '1';
|
| 2130 |
|
|
end if;
|
| 2131 |
|
|
end loop;
|
| 2132 |
|
|
end if;
|
| 2133 |
|
|
when others => null;
|
| 2134 |
|
|
end case;
|
| 2135 |
|
|
end if;
|
| 2136 |
|
|
|
| 2137 |
|
|
-- get result from multiplier and divider
|
| 2138 |
|
|
|
| 2139 |
|
|
case op is
|
| 2140 |
|
|
when FMT3 =>
|
| 2141 |
|
|
case op3 is
|
| 2142 |
|
|
when JMPL | RETT =>
|
| 2143 |
|
|
jmpl_rett := '1';
|
| 2144 |
|
|
when UMUL | SMUL =>
|
| 2145 |
|
|
if (MULTIPLIER > iterative) then
|
| 2146 |
|
|
if (MULTIPLIER /= m32x32) then
|
| 2147 |
|
|
result := mulo.result(31 downto 0);
|
| 2148 |
|
|
end if;
|
| 2149 |
|
|
y := mulo.result(63 downto 32);
|
| 2150 |
|
|
end if;
|
| 2151 |
|
|
when UMULCC | SMULCC =>
|
| 2152 |
|
|
if (MULTIPLIER > iterative) then
|
| 2153 |
|
|
if (MULTIPLIER /= m32x32) then
|
| 2154 |
|
|
result := mulo.result(31 downto 0); icc := mulo.icc;
|
| 2155 |
|
|
else
|
| 2156 |
|
|
icc := me.result(31) & "000";
|
| 2157 |
|
|
if me.result = Zero32 then icc(2) := '1'; end if;
|
| 2158 |
|
|
end if;
|
| 2159 |
|
|
y := mulo.result(63 downto 32);
|
| 2160 |
|
|
end if;
|
| 2161 |
|
|
when UMAC | SMAC =>
|
| 2162 |
|
|
if MACEN then
|
| 2163 |
|
|
result := mulo.result(31 downto 0);
|
| 2164 |
|
|
asr18 := mulo.result(31 downto 0);
|
| 2165 |
|
|
y := mulo.result(63 downto 32);
|
| 2166 |
|
|
end if;
|
| 2167 |
|
|
when UDIV | SDIV =>
|
| 2168 |
|
|
if (DIVIDER /= none) then
|
| 2169 |
|
|
result := divo.result(31 downto 0);
|
| 2170 |
|
|
end if;
|
| 2171 |
|
|
when UDIVCC | SDIVCC =>
|
| 2172 |
|
|
if (DIVIDER /= none) then
|
| 2173 |
|
|
result := divo.result(31 downto 0); icc := divo.icc;
|
| 2174 |
|
|
end if;
|
| 2175 |
|
|
when WRPSR => irqen := '0';
|
| 2176 |
|
|
when others => null;
|
| 2177 |
|
|
end case;
|
| 2178 |
|
|
when others => null;
|
| 2179 |
|
|
end case;
|
| 2180 |
|
|
|
| 2181 |
|
|
mein.irqen <= irqen;
|
| 2182 |
|
|
|
| 2183 |
|
|
-- FPU MSW data store
|
| 2184 |
|
|
|
| 2185 |
|
|
fpexc := '0';
|
| 2186 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 2187 |
|
|
if (xorv(fpu_reg.me.fpop) = '1') then
|
| 2188 |
|
|
if (me.ctrl.cnt = "00") and
|
| 2189 |
|
|
((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1')
|
| 2190 |
|
|
then
|
| 2191 |
|
|
fpwrin.fcc := fpuo.ConditionCodes;
|
| 2192 |
|
|
fpwrin.cexc := fpuo.Excep(4 downto 0);
|
| 2193 |
|
|
end if;
|
| 2194 |
|
|
if ((ctrl.annul or ctrl.trap) /= '1') then
|
| 2195 |
|
|
if ((fpu_reg.me.dsz and me.write_reg) = '1') and
|
| 2196 |
|
|
(me.ctrl.cnt = "00")
|
| 2197 |
|
|
then
|
| 2198 |
|
|
result := fpuo.SignResult & fpuo.ExpResult &
|
| 2199 |
|
|
fpuo.FracResult(54 downto 35);
|
| 2200 |
|
|
end if;
|
| 2201 |
|
|
if ((fpu_reg.fsr.tem and fpwrin.cexc) /= "00000" ) then
|
| 2202 |
|
|
fpexc := '1';
|
| 2203 |
|
|
if ((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1') and
|
| 2204 |
|
|
(me.ctrl.cnt = "00")
|
| 2205 |
|
|
then fpexc := '0'; write_reg := '0';
|
| 2206 |
|
|
else ctrl.trap := '1'; end if;
|
| 2207 |
|
|
end if;
|
| 2208 |
|
|
end if;
|
| 2209 |
|
|
end if;
|
| 2210 |
|
|
fpu_regin.fpexc <= fpexc;
|
| 2211 |
|
|
fpu_regin.wr <= fpwrin;
|
| 2212 |
|
|
end if;
|
| 2213 |
|
|
|
| 2214 |
|
|
mein.bpresult <= result; -- FPU bypass
|
| 2215 |
|
|
|
| 2216 |
|
|
-- load data from cache
|
| 2217 |
|
|
|
| 2218 |
|
|
if (me.memory_load or not dco.mds) = '1' then result := dco.data; end if;
|
| 2219 |
|
|
|
| 2220 |
|
|
-- Y register
|
| 2221 |
|
|
|
| 2222 |
|
|
if (me.write_y = '0') or (me.ctrl.annul = '1') then y := wr.y; end if;
|
| 2223 |
|
|
me.my <= y; -- fast Y feedback
|
| 2224 |
|
|
if ((ctrl.annul or ctrl.trap) = '1') then y := wr.y; end if;
|
| 2225 |
|
|
|
| 2226 |
|
|
if MACEN and ((ctrl.annul or ctrl.trap) = '1') then
|
| 2227 |
|
|
asr18 := wr.asr18;
|
| 2228 |
|
|
end if;
|
| 2229 |
|
|
|
| 2230 |
|
|
if DEBUG_UNIT then
|
| 2231 |
|
|
if (iui.debug.dwrite and iui.debug.denable) = '1' then
|
| 2232 |
|
|
if iui.debug.daddr(20 downto 19) = "01" then
|
| 2233 |
|
|
if iui.debug.daddr(7 downto 2) = "000000" then
|
| 2234 |
|
|
y := iui.debug.ddata;
|
| 2235 |
|
|
end if;
|
| 2236 |
|
|
end if;
|
| 2237 |
|
|
end if;
|
| 2238 |
|
|
end if;
|
| 2239 |
|
|
|
| 2240 |
|
|
wrin.y <= y;
|
| 2241 |
|
|
|
| 2242 |
|
|
|
| 2243 |
|
|
|
| 2244 |
|
|
-- debug unit ASR write access
|
| 2245 |
|
|
|
| 2246 |
|
|
if DEBUG_UNIT and
|
| 2247 |
|
|
((dsur.dmode and iui.debug.dwrite and iui.debug.denable) = '1') and
|
| 2248 |
|
|
(iui.debug.daddr(20 downto 19) = "01")
|
| 2249 |
|
|
then
|
| 2250 |
|
|
case iui.debug.daddr(7 downto 2) is
|
| 2251 |
|
|
when "010010" => -- %ASR18
|
| 2252 |
|
|
asr18 := iui.debug.ddata;
|
| 2253 |
|
|
when others => -- %ASR24 - 31
|
| 2254 |
|
|
if (WATCHPOINTS > 0) and (iui.debug.daddr(7 downto 5) = "011") then
|
| 2255 |
|
|
wpi := conv_integer(unsigned(iui.debug.daddr(4 downto 3)));
|
| 2256 |
|
|
if iui.debug.daddr(2) = '0' then
|
| 2257 |
|
|
trv(wpi).addr := iui.debug.ddata(31 downto 2);
|
| 2258 |
|
|
trv(wpi).exec := iui.debug.ddata(0);
|
| 2259 |
|
|
else
|
| 2260 |
|
|
trv(wpi).mask := iui.debug.ddata(31 downto 2);
|
| 2261 |
|
|
trv(wpi).load := iui.debug.ddata(1);
|
| 2262 |
|
|
trv(wpi).store := iui.debug.ddata(0);
|
| 2263 |
|
|
end if;
|
| 2264 |
|
|
end if;
|
| 2265 |
|
|
end case;
|
| 2266 |
|
|
end if;
|
| 2267 |
|
|
|
| 2268 |
|
|
-- debug unit trap generation + diagnostic write data
|
| 2269 |
|
|
if DEBUG_UNIT and (iui.debug.dsuen = '1') and
|
| 2270 |
|
|
(ctrl.annul = '0') and (ctrl.pv = '1') and (ctrl.trap = '1') and
|
| 2271 |
|
|
((iui.debug.btrapa = '1') or
|
| 2272 |
|
|
((iui.debug.btrape = '1') and not ((ctrl.tt = PRIV_TT) or
|
| 2273 |
|
|
(ctrl.tt = FPDIS_TT) or (ctrl.tt = WINOF_TT) or
|
| 2274 |
|
|
(ctrl.tt = WINUF_TT) or (ctrl.tt(5 downto 4) = "01") or
|
| 2275 |
|
|
(ctrl.tt = TICC_TT))) or
|
| 2276 |
|
|
((iui.debug.bwatch = '1') and (ctrl.tt = WATCH_TT)) or
|
| 2277 |
|
|
((iui.debug.bsoft = '1') and (ctrl.tt = TICC_TT) and
|
| 2278 |
|
|
(me.result(6 downto 0) = "0000001")))
|
| 2279 |
|
|
then dsutrap := '1'; end if;
|
| 2280 |
|
|
if DEBUG_UNIT and (dsur.dmode = '1') then result := iui.debug.ddata; end if;
|
| 2281 |
|
|
|
| 2282 |
|
|
if rst = '0' then
|
| 2283 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
| 2284 |
|
|
trv(i).exec := '0'; trv(i).load := '0'; trv(i).store := '0';
|
| 2285 |
|
|
end loop;
|
| 2286 |
|
|
end if;
|
| 2287 |
|
|
|
| 2288 |
|
|
mein.werr <= werr;
|
| 2289 |
|
|
mein.ipend <= ipend;
|
| 2290 |
|
|
wrin.result <= result;
|
| 2291 |
|
|
wrin.icc <= icc;
|
| 2292 |
|
|
me.jmpl_rett <= jmpl_rett;
|
| 2293 |
|
|
|
| 2294 |
|
|
wrin.cwp <= cwp; wrin.write_cwp <= write_cwp;
|
| 2295 |
|
|
wrin.ctrl <= ctrl;
|
| 2296 |
|
|
wrin.write_reg <= write_reg;
|
| 2297 |
|
|
wrin.asr18 <= asr18;
|
| 2298 |
|
|
ici.flush <= iflush;
|
| 2299 |
|
|
dci.flush <= iflush;
|
| 2300 |
|
|
dci.nullify <= nullify;
|
| 2301 |
|
|
dci.maddress <= me.result;
|
| 2302 |
|
|
dci.msu <= me.su;
|
| 2303 |
|
|
trin <= trv;
|
| 2304 |
|
|
wrin.dsutrap <= dsutrap;
|
| 2305 |
|
|
|
| 2306 |
|
|
end process;
|
| 2307 |
|
|
|
| 2308 |
|
|
-------------------------------------------------------------------------------
|
| 2309 |
|
|
-- write stage
|
| 2310 |
|
|
-------------------------------------------------------------------------------
|
| 2311 |
|
|
|
| 2312 |
|
|
|
| 2313 |
|
|
write_stage : process(rst, holdn, wr, sregs, fe, de, ex, me, fpu_reg, iui, dsur)
|
| 2314 |
|
|
|
| 2315 |
|
|
variable op : std_logic_vector(1 downto 0);
|
| 2316 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
| 2317 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
| 2318 |
|
|
variable rd_address : std_logic_vector(RABITS-1 downto 0);
|
| 2319 |
|
|
variable write_reg : std_logic;
|
| 2320 |
|
|
variable annul_all : std_logic;
|
| 2321 |
|
|
variable cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
| 2322 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
| 2323 |
|
|
variable tt : std_logic_vector(7 downto 0);
|
| 2324 |
|
|
variable tba : std_logic_vector(19 downto 0);
|
| 2325 |
|
|
variable wim : std_logic_vector(NWINDOWS-1 downto 0);
|
| 2326 |
|
|
variable pil : std_logic_vector(3 downto 0);
|
| 2327 |
|
|
variable ec, ef, ps, s, et : std_logic;
|
| 2328 |
|
|
variable exception : std_logic;
|
| 2329 |
|
|
variable trapping : std_logic;
|
| 2330 |
|
|
variable save_pc : std_logic;
|
| 2331 |
|
|
variable error : std_logic;
|
| 2332 |
|
|
variable intack : std_logic;
|
| 2333 |
|
|
variable tpcsel : std_logic_vector(1 downto 0);
|
| 2334 |
|
|
variable npc : std_logic_vector(31 downto PCLOW);
|
| 2335 |
|
|
variable trap_address : std_logic_vector(31 downto PCLOW); -- trap address
|
| 2336 |
|
|
variable wrdata : std_logic_vector(RDBITS-1 downto 0);
|
| 2337 |
|
|
variable newtt, vectt : std_logic_vector(7 downto 0);
|
| 2338 |
|
|
variable vfsr : fsr_type;
|
| 2339 |
|
|
variable write_icc : std_logic;
|
| 2340 |
|
|
variable cpexack : std_logic;
|
| 2341 |
|
|
variable fpexack : std_logic;
|
| 2342 |
|
|
variable dsutrap : std_logic;
|
| 2343 |
|
|
variable vdsu : dsu_registers;
|
| 2344 |
|
|
variable fp_dwrite, fp_dwrite_fsr : std_logic;
|
| 2345 |
|
|
|
| 2346 |
|
|
|
| 2347 |
|
|
begin
|
| 2348 |
|
|
|
| 2349 |
|
|
-- common initialisation
|
| 2350 |
|
|
|
| 2351 |
|
|
op := wr.ctrl.inst(31 downto 30);
|
| 2352 |
|
|
op3 := wr.ctrl.inst(24 downto 19);
|
| 2353 |
|
|
rd := wr.ctrl.inst(29 downto 25);
|
| 2354 |
|
|
|
| 2355 |
|
|
rd_address := wr.ctrl.rd; write_reg := '0'; write_icc := wr.write_icc;
|
| 2356 |
|
|
|
| 2357 |
|
|
annul_all := '0'; exception := '0';
|
| 2358 |
|
|
trapping := wr.trapping; tpcsel := "00";
|
| 2359 |
|
|
save_pc := '0'; error := wr.error; intack := '0';
|
| 2360 |
|
|
newtt := (others => '-'); vectt := (others => '-'); vdsu := dsur;
|
| 2361 |
|
|
vdsu.dsuen := iui.debug.denable; cpexack := '0'; fpexack := '0';
|
| 2362 |
|
|
vdsu.dmode2 := dsur.dmode2 and wr.ctrl.annul; dsutrap := '0';
|
| 2363 |
|
|
vfsr := fpu_reg.fsr;
|
| 2364 |
|
|
fp_dwrite := '0'; fp_dwrite_fsr := '0';
|
| 2365 |
|
|
|
| 2366 |
|
|
|
| 2367 |
|
|
-- special registers write handling
|
| 2368 |
|
|
|
| 2369 |
|
|
icc := sregs.icc; cwp := sregs.cwp; ef := sregs.ef; ec := sregs.ec;
|
| 2370 |
|
|
pil := sregs.pil; s := sregs.s; ps := sregs.ps; et := sregs.et;
|
| 2371 |
|
|
tba := sregs.tba; tt := sregs.tt; wim := sregs.wim;
|
| 2372 |
|
|
|
| 2373 |
|
|
if (wr.ctrl.annul or wr.ctrl.trap) /= '1' then
|
| 2374 |
|
|
if wr.write_cwp = '1' then
|
| 2375 |
|
|
cwp := wr.cwp;
|
| 2376 |
|
|
end if;
|
| 2377 |
|
|
write_reg := wr.write_reg;
|
| 2378 |
|
|
case op is
|
| 2379 |
|
|
when FMT3 =>
|
| 2380 |
|
|
case op3 is
|
| 2381 |
|
|
when WRY =>
|
| 2382 |
|
|
|
| 2383 |
|
|
when WRPSR =>
|
| 2384 |
|
|
cwp := wr.result(NWINLOG2-1 downto 0);
|
| 2385 |
|
|
icc := wr.result(23 downto 20);
|
| 2386 |
|
|
ec := wr.result(13);
|
| 2387 |
|
|
ef := wr.result(12);
|
| 2388 |
|
|
pil := wr.result(11 downto 8);
|
| 2389 |
|
|
s := wr.result(7);
|
| 2390 |
|
|
ps := wr.result(6);
|
| 2391 |
|
|
et := wr.result(5);
|
| 2392 |
|
|
when WRWIM =>
|
| 2393 |
|
|
wim := wr.result(NWINDOWS-1 downto 0);
|
| 2394 |
|
|
when WRTBR =>
|
| 2395 |
|
|
tba := wr.result(31 downto 12);
|
| 2396 |
|
|
when RETT =>
|
| 2397 |
|
|
s := ps;
|
| 2398 |
|
|
et := '1';
|
| 2399 |
|
|
|
| 2400 |
|
|
when FPOP1 | FPOP2 =>
|
| 2401 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 2402 |
|
|
|
| 2403 |
|
|
if (wr.write_reg = '1') and ((wr.ctrl.cnt = "00") or
|
| 2404 |
|
|
((wr.ctrl.cnt = "01") and (fpu_reg.wr.dsz = '0')))
|
| 2405 |
|
|
then
|
| 2406 |
|
|
vfsr.ftt := (others => '0');
|
| 2407 |
|
|
vfsr.cexc := fpu_reg.wr.cexc;
|
| 2408 |
|
|
vfsr.aexc := fpu_reg.wr.cexc or fpu_reg.fsr.aexc;
|
| 2409 |
|
|
end if;
|
| 2410 |
|
|
if (op3 = FPOP2) and
|
| 2411 |
|
|
not ((wr.ctrl.inst(6) = '1') and (wr.ctrl.cnt = "00")) then
|
| 2412 |
|
|
vfsr.fcc := fpu_reg.wr.fcc;
|
| 2413 |
|
|
vfsr.ftt := (others => '0');
|
| 2414 |
|
|
vfsr.cexc := fpu_reg.wr.cexc;
|
| 2415 |
|
|
vfsr.aexc := fpu_reg.wr.cexc or fpu_reg.fsr.aexc;
|
| 2416 |
|
|
end if;
|
| 2417 |
|
|
|
| 2418 |
|
|
end if;
|
| 2419 |
|
|
when others => null;
|
| 2420 |
|
|
end case;
|
| 2421 |
|
|
when LDST =>
|
| 2422 |
|
|
case op3 is
|
| 2423 |
|
|
when STFSR =>
|
| 2424 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 2425 |
|
|
vfsr.ftt := (others => '0');
|
| 2426 |
|
|
end if;
|
| 2427 |
|
|
when LDFSR =>
|
| 2428 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 2429 |
|
|
vfsr.cexc := wr.result(4 downto 0);
|
| 2430 |
|
|
vfsr.aexc := wr.result(9 downto 5);
|
| 2431 |
|
|
vfsr.fcc := wr.result(11 downto 10);
|
| 2432 |
|
|
vfsr.tem := wr.result(27 downto 23);
|
| 2433 |
|
|
vfsr.rd := wr.result(31 downto 30);
|
| 2434 |
|
|
end if;
|
| 2435 |
|
|
|
| 2436 |
|
|
when others => null;
|
| 2437 |
|
|
end case;
|
| 2438 |
|
|
when others => null;
|
| 2439 |
|
|
end case;
|
| 2440 |
|
|
if write_icc = '1' then icc := wr.icc; end if;
|
| 2441 |
|
|
end if;
|
| 2442 |
|
|
|
| 2443 |
|
|
-- trap handling
|
| 2444 |
|
|
|
| 2445 |
|
|
-- nPC selection
|
| 2446 |
|
|
if me.ctrl.pv = '1' then tpcsel := "00";
|
| 2447 |
|
|
elsif ex.ctrl.pv = '1' then tpcsel := "01";
|
| 2448 |
|
|
elsif de.pv = '1' then tpcsel := "10";
|
| 2449 |
|
|
else tpcsel := "11"; end if;
|
| 2450 |
|
|
case wr.tpcsel is
|
| 2451 |
|
|
when "00" => npc := wr.ctrl.pc(31 downto PCLOW);
|
| 2452 |
|
|
when "01" => npc := me.ctrl.pc(31 downto PCLOW);
|
| 2453 |
|
|
when "10" => npc := ex.ctrl.pc(31 downto PCLOW);
|
| 2454 |
|
|
when others => npc := de.pc(31 downto PCLOW);
|
| 2455 |
|
|
end case;
|
| 2456 |
|
|
|
| 2457 |
|
|
-- standard trap handling
|
| 2458 |
|
|
if DEBUG_UNIT and
|
| 2459 |
|
|
((wr.mexc and (iui.debug.btrape or iui.debug.btrapa)) = '1')
|
| 2460 |
|
|
then dsutrap := '1'; end if;
|
| 2461 |
|
|
if wr.mexc = '1' then newtt := "00" & DAEX_TT;
|
| 2462 |
|
|
elsif ((FPIFTYPE = serial) and FPEN) and (fpu_reg.fpexc = '1') then
|
| 2463 |
|
|
newtt := "00" & FPEXC_TT; vfsr.ftt := FPIEEE_ERR;
|
| 2464 |
|
|
elsif ((FPIFTYPE = serial) and FPEN) and (wr.ctrl.tt = FPEXC_TT) then
|
| 2465 |
|
|
newtt := "00" & FPEXC_TT; vfsr.ftt := FPSEQ_ERR;
|
| 2466 |
|
|
elsif wr.ctrl.tt = TICC_TT then newtt := '1' & wr.result(6 downto 0);
|
| 2467 |
|
|
else newtt := "00" & wr.ctrl.tt; end if;
|
| 2468 |
|
|
|
| 2469 |
|
|
if ((wr.ctrl.trap and not wr.ctrl.annul) = '1')
|
| 2470 |
|
|
or ((wr.mexc or trapping) = '1')
|
| 2471 |
|
|
then
|
| 2472 |
|
|
|
| 2473 |
|
|
vdsu.pc := wr.ctrl.pc;
|
| 2474 |
|
|
if DEBUG_UNIT and
|
| 2475 |
|
|
(iui.debug.dsuen = '1') and ((wr.ctrl.annul or dsur.dmode) = '0') and
|
| 2476 |
|
|
(((wr.dsutrap or dsutrap) = '1') or ((iui.debug.berror and not sregs.et) = '1'))
|
| 2477 |
|
|
then
|
| 2478 |
|
|
annul_all := '1'; vdsu.tt := newtt; vdsu.dmode := '1';
|
| 2479 |
|
|
write_reg := '0';
|
| 2480 |
|
|
if (sregs.et = '0') and not
|
| 2481 |
|
|
(((iui.debug.dbreak = '1') and (newtt = ("00" & WATCH_TT))) or
|
| 2482 |
|
|
((iui.debug.bsoft = '1') and (newtt = ("10000001"))))
|
| 2483 |
|
|
then vdsu.error := '1'; else vdsu.error := '0'; end if;
|
| 2484 |
|
|
elsif trapping = '0' then -- first trap cycle
|
| 2485 |
|
|
annul_all := '1'; trapping := '1'; ps := s; s := '1';
|
| 2486 |
|
|
exception := '1'; et := '0';
|
| 2487 |
|
|
if sregs.et = '0' then
|
| 2488 |
|
|
if not NOHALT then error := '1'; end if;
|
| 2489 |
|
|
if ((op = FMT3) and (op3 = RETT)) then tt := newtt; end if;
|
| 2490 |
|
|
vectt := (others => '0');
|
| 2491 |
|
|
else
|
| 2492 |
|
|
write_reg := '1'; save_pc := '1'; tt := newtt; vectt := newtt;
|
| 2493 |
|
|
end if;
|
| 2494 |
|
|
if CPEN and (tt = ("00" & CPEXC_TT)) then cpexack := '1'; end if;
|
| 2495 |
|
|
if (FPIFTYPE = parallel) and (tt = ("00" & FPEXC_TT)) then fpexack := '1'; end if;
|
| 2496 |
|
|
-- pragma translate_off
|
| 2497 |
|
|
if not is_x(cwp) then
|
| 2498 |
|
|
-- pragma translate_on
|
| 2499 |
|
|
rd_address := (others => '0');
|
| 2500 |
|
|
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0001";
|
| 2501 |
|
|
-- pragma translate_off
|
| 2502 |
|
|
end if;
|
| 2503 |
|
|
-- pragma translate_on
|
| 2504 |
|
|
|
| 2505 |
|
|
elsif trapping = '1' then -- second trap cycle
|
| 2506 |
|
|
if error = '1' then
|
| 2507 |
|
|
annul_all := '1'; trapping := '1';
|
| 2508 |
|
|
if DEBUG_UNIT and (iui.debug.dbreak = '1') then
|
| 2509 |
|
|
vdsu.dmode := '1';
|
| 2510 |
|
|
end if;
|
| 2511 |
|
|
else
|
| 2512 |
|
|
trapping := '0';
|
| 2513 |
|
|
if sregs.tt(5 downto 4) = "01" then intack := '1'; end if;
|
| 2514 |
|
|
write_reg := '1'; save_pc := '1';
|
| 2515 |
|
|
-- pragma translate_off
|
| 2516 |
|
|
if not is_x(cwp) then
|
| 2517 |
|
|
-- pragma translate_on
|
| 2518 |
|
|
rd_address := (others => '0');
|
| 2519 |
|
|
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0010";
|
| 2520 |
|
|
-- pragma translate_off
|
| 2521 |
|
|
end if;
|
| 2522 |
|
|
-- pragma translate_on
|
| 2523 |
|
|
-- pragma translate_off
|
| 2524 |
|
|
if not is_x(cwp) then
|
| 2525 |
|
|
-- pragma translate_on
|
| 2526 |
|
|
if (not CWPOPT) and (cwp = CWPMIN) then cwp := CWPMAX;
|
| 2527 |
|
|
else cwp := cwp - 1; end if;
|
| 2528 |
|
|
-- pragma translate_off
|
| 2529 |
|
|
end if;
|
| 2530 |
|
|
-- pragma translate_on
|
| 2531 |
|
|
end if;
|
| 2532 |
|
|
end if;
|
| 2533 |
|
|
end if;
|
| 2534 |
|
|
|
| 2535 |
|
|
trap_address(31 downto 4) := sregs.tba & vectt;
|
| 2536 |
|
|
trap_address(3 downto PCLOW) := (others => '0');
|
| 2537 |
|
|
|
| 2538 |
|
|
-- debug mode
|
| 2539 |
|
|
|
| 2540 |
|
|
if DEBUG_UNIT then
|
| 2541 |
|
|
iuo.debug.dbreak <= iui.debug.dbreak;
|
| 2542 |
|
|
-- iuo.debug.dbreak <= iui.debug.dsuen and iui.debug.dbreak;
|
| 2543 |
|
|
if iui.debug.rerror = '1' then trapping := '0'; error := '0'; end if;
|
| 2544 |
|
|
if (dsur.dmode = '1') then
|
| 2545 |
|
|
if dsur.dstate = '0' then
|
| 2546 |
|
|
annul_all := '1'; trap_address := dsur.pc; exception := '1';
|
| 2547 |
|
|
vdsu.pc := npc; vdsu.dstate := '1';
|
| 2548 |
|
|
else
|
| 2549 |
|
|
annul_all := '1'; trap_address := fe.pc; exception := '1';
|
| 2550 |
|
|
if (iui.debug.dsuen and iui.debug.dbreak) = '0' then
|
| 2551 |
|
|
annul_all := '0'; vdsu.dmode := '0'; vdsu.dstate := '0';
|
| 2552 |
|
|
trap_address := dsur.pc;
|
| 2553 |
|
|
end if;
|
| 2554 |
|
|
if (iui.debug.dwrite and iui.debug.denable) = '1' then
|
| 2555 |
|
|
if iui.debug.daddr(20 downto 19) = "00" then -- write regfile
|
| 2556 |
|
|
write_reg := dsur.dsuen;
|
| 2557 |
|
|
rd_address := iui.debug.daddr(RABITS+1 downto 2);
|
| 2558 |
|
|
if (FPIFTYPE = parallel) and FPEN then
|
| 2559 |
|
|
if iui.debug.daddr(17 downto 16) = "11" then
|
| 2560 |
|
|
fp_dwrite := dsur.dsuen;
|
| 2561 |
|
|
write_reg := '0';
|
| 2562 |
|
|
end if;
|
| 2563 |
|
|
end if;
|
| 2564 |
|
|
elsif iui.debug.daddr(20 downto 19) = "01" then -- write special registers
|
| 2565 |
|
|
case iui.debug.daddr(7 downto 2) is
|
| 2566 |
|
|
when "000001" => -- PSR
|
| 2567 |
|
|
cwp := iui.debug.ddata(NWINLOG2-1 downto 0);
|
| 2568 |
|
|
icc := iui.debug.ddata(23 downto 20);
|
| 2569 |
|
|
ec := iui.debug.ddata(13);
|
| 2570 |
|
|
ef := iui.debug.ddata(12);
|
| 2571 |
|
|
pil := iui.debug.ddata(11 downto 8);
|
| 2572 |
|
|
s := iui.debug.ddata(7);
|
| 2573 |
|
|
ps := iui.debug.ddata(6);
|
| 2574 |
|
|
et := iui.debug.ddata(5);
|
| 2575 |
|
|
when "000010" => -- WIM
|
| 2576 |
|
|
wim := iui.debug.ddata(NWINDOWS-1 downto 0);
|
| 2577 |
|
|
when "000011" => tba := iui.debug.ddata(31 downto 12); -- TBR
|
| 2578 |
|
|
when "000100" => trap_address := iui.debug.ddata(31 downto PCLOW); -- PC
|
| 2579 |
|
|
when "000101" => vdsu.pc := iui.debug.ddata(31 downto PCLOW); -- NPC
|
| 2580 |
|
|
when "000110" => -- FSR
|
| 2581 |
|
|
if (FPIFTYPE = serial) and FPEN then
|
| 2582 |
|
|
vfsr.cexc := iui.debug.ddata(4 downto 0);
|
| 2583 |
|
|
vfsr.aexc := iui.debug.ddata(9 downto 5);
|
| 2584 |
|
|
vfsr.fcc := iui.debug.ddata(11 downto 10);
|
| 2585 |
|
|
vfsr.tem := iui.debug.ddata(27 downto 23);
|
| 2586 |
|
|
vfsr.rd := iui.debug.ddata(31 downto 30);
|
| 2587 |
|
|
elsif (FPIFTYPE = parallel) and FPEN then
|
| 2588 |
|
|
fp_dwrite_fsr := '1';
|
| 2589 |
|
|
end if;
|
| 2590 |
|
|
when others =>
|
| 2591 |
|
|
end case;
|
| 2592 |
|
|
end if;
|
| 2593 |
|
|
end if;
|
| 2594 |
|
|
end if;
|
| 2595 |
|
|
else -- break-in in during error mode
|
| 2596 |
|
|
if (iui.debug.dbreak and error) = '1' then vdsu.dmode := '1'; end if;
|
| 2597 |
|
|
end if;
|
| 2598 |
|
|
vdsu.dmode2 := vdsu.dmode or vdsu.dmode2;
|
| 2599 |
|
|
iuo.debug.error <= wr.error;
|
| 2600 |
|
|
end if;
|
| 2601 |
|
|
|
| 2602 |
|
|
write_reg := write_reg and holdn;
|
| 2603 |
|
|
if save_pc = '1' then wrdata(31 downto 0) := npc(31 downto 2) & "00";
|
| 2604 |
|
|
else wrdata(31 downto 0) := wr.result; end if;
|
| 2605 |
|
|
|
| 2606 |
|
|
if DEBUGPORT then
|
| 2607 |
|
|
iuo.debug.tt <= tt;
|
| 2608 |
|
|
iuo.debug.trap <= trapping;
|
| 2609 |
|
|
iuo.debug.result <= wrdata(31 downto 0);
|
| 2610 |
|
|
iuo.debug.wr <= wr.ctrl;
|
| 2611 |
|
|
iuo.debug.dmode <= vdsu.dstate;
|
| 2612 |
|
|
iuo.debug.dmode2 <= dsur.dmode2;
|
| 2613 |
|
|
iuo.debug.vdmode <= vdsu.dmode;
|
| 2614 |
|
|
iuo.debug.psrtt <= sregs.tt;
|
| 2615 |
|
|
iuo.debug.psrpil <= sregs.pil;
|
| 2616 |
|
|
|
| 2617 |
|
|
iuo.debug.write_reg <= write_reg;
|
| 2618 |
|
|
|
| 2619 |
|
|
end if;
|
| 2620 |
|
|
|
| 2621 |
|
|
-- reset handling
|
| 2622 |
|
|
|
| 2623 |
|
|
if rst = '0' then
|
| 2624 |
|
|
et := '0'; s := '1'; annul_all := '1';
|
| 2625 |
|
|
trapping := '0'; save_pc := '0'; exception := '0'; error := '0';
|
| 2626 |
|
|
vdsu.dmode := '0'; vdsu.dstate := '0'; vdsu.error := '0';
|
| 2627 |
|
|
|
| 2628 |
|
|
end if;
|
| 2629 |
|
|
|
| 2630 |
|
|
if not FPEN then ef := '0'; end if;
|
| 2631 |
|
|
if not CPEN then ec := '0'; end if;
|
| 2632 |
|
|
|
| 2633 |
|
|
if CPEN then
|
| 2634 |
|
|
cpi.exack <= cpexack;
|
| 2635 |
|
|
cpi.dcnt <= de.cnt;
|
| 2636 |
|
|
cpi.dinst <= de.inst;
|
| 2637 |
|
|
cpi.ex <= ex.ctrl;
|
| 2638 |
|
|
cpi.me <= me.ctrl;
|
| 2639 |
|
|
cpi.wr <= wr.ctrl;
|
| 2640 |
|
|
cpi.flush <= annul_all;
|
| 2641 |
|
|
cpi.lddata <= wr.result;
|
| 2642 |
|
|
end if;
|
| 2643 |
|
|
|
| 2644 |
|
|
if (FPIFTYPE = parallel) then
|
| 2645 |
|
|
fpi.exack <= fpexack;
|
| 2646 |
|
|
fpi.dcnt <= de.cnt;
|
| 2647 |
|
|
fpi.dinst <= de.inst;
|
| 2648 |
|
|
fpi.ex <= ex.ctrl;
|
| 2649 |
|
|
fpi.me <= me.ctrl;
|
| 2650 |
|
|
fpi.wr <= wr.ctrl;
|
| 2651 |
|
|
fpi.flush <= annul_all;
|
| 2652 |
|
|
fpi.lddata <= wr.result;
|
| 2653 |
|
|
fpi.debug.daddr <= iui.debug.daddr(6 downto 2);
|
| 2654 |
|
|
fpi.debug.dwrite_fsr <= fp_dwrite_fsr;
|
| 2655 |
|
|
fpi.debug.denable <= iui.debug.denable and dsur.dmode;
|
| 2656 |
|
|
fpi.debug.dwrite <= fp_dwrite;
|
| 2657 |
|
|
fpi.debug.ddata <= iui.debug.ddata;
|
| 2658 |
|
|
end if;
|
| 2659 |
|
|
|
| 2660 |
|
|
iuo.error <= wr.nerror;
|
| 2661 |
|
|
iuo.intack <= wr.intack and holdn;
|
| 2662 |
|
|
iuo.irqvec <= sregs.tt(3 downto 0);
|
| 2663 |
|
|
wr.annul_all <= annul_all;
|
| 2664 |
|
|
wrin.trapping <= trapping;
|
| 2665 |
|
|
wrin.tpcsel <= tpcsel;
|
| 2666 |
|
|
wrin.error <= error;
|
| 2667 |
|
|
wrin.nerror <= not error;
|
| 2668 |
|
|
wrin.intack <= intack;
|
| 2669 |
|
|
sregsin.cwp <= cwp;
|
| 2670 |
|
|
sregsin.icc <= icc;
|
| 2671 |
|
|
sregsin.ec <= ec;
|
| 2672 |
|
|
sregsin.ef <= ef;
|
| 2673 |
|
|
sregsin.pil <= pil;
|
| 2674 |
|
|
sregsin.s <= s;
|
| 2675 |
|
|
sregsin.ps <= ps;
|
| 2676 |
|
|
sregsin.et <= et;
|
| 2677 |
|
|
sregsin.wim <= wim;
|
| 2678 |
|
|
sregsin.tba <= tba;
|
| 2679 |
|
|
sregsin.tt <= tt;
|
| 2680 |
|
|
rfi.wraddr <= rd_address;
|
| 2681 |
|
|
rfi.wrdata <= wrdata;
|
| 2682 |
|
|
rfi.wren <= write_reg;
|
| 2683 |
|
|
fecomb.exception <= exception;
|
| 2684 |
|
|
fecomb.trap_address <= trap_address;
|
| 2685 |
|
|
fpu_regin.fsr <= vfsr;
|
| 2686 |
|
|
muli.flush <= wr.annul_all;
|
| 2687 |
|
|
divi.flush <= wr.annul_all;
|
| 2688 |
|
|
muli.y <= wr.y(7 downto 0);
|
| 2689 |
|
|
muli.asr18 <= wr.asr18;
|
| 2690 |
|
|
dsurin <= vdsu;
|
| 2691 |
|
|
|
| 2692 |
|
|
end process;
|
| 2693 |
|
|
|
| 2694 |
|
|
-- optional multiplier
|
| 2695 |
|
|
|
| 2696 |
|
|
mgen : if MULTIPLIER > iterative generate
|
| 2697 |
|
|
mul0 : mul port map (rst, clk, holdn, muli, mulo);
|
| 2698 |
|
|
end generate;
|
| 2699 |
|
|
|
| 2700 |
|
|
-- optional divider
|
| 2701 |
|
|
|
| 2702 |
|
|
dgen : if DIVIDER /= none generate
|
| 2703 |
|
|
div0 : div port map (rst, clk, holdn, divi, divo);
|
| 2704 |
|
|
end generate;
|
| 2705 |
|
|
|
| 2706 |
|
|
-- missed instruction and data registers
|
| 2707 |
|
|
|
| 2708 |
|
|
instmux : process(dein, ico, de, fecomb)
|
| 2709 |
|
|
begin
|
| 2710 |
|
|
if (ico.mds and fecomb.hold_pc) = '1' then
|
| 2711 |
|
|
dein.inst <= de.inst;
|
| 2712 |
|
|
dein.mexc <= de.mexc;
|
| 2713 |
|
|
else
|
| 2714 |
|
|
dein.inst <= ico.data;
|
| 2715 |
|
|
dein.mexc <= ico.exception;
|
| 2716 |
|
|
end if;
|
| 2717 |
|
|
end process;
|
| 2718 |
|
|
|
| 2719 |
|
|
-- debug unit diagnostic read
|
| 2720 |
|
|
|
| 2721 |
|
|
dsuread : if DEBUG_UNIT generate
|
| 2722 |
|
|
dsrd : process(iui, wr, sregs, tr, fe, dsur, fpu_reg, rfo, dco)
|
| 2723 |
|
|
variable rdata : std_logic_vector(31 downto 0);
|
| 2724 |
|
|
variable cwp : std_logic_vector(4 downto 0);
|
| 2725 |
|
|
variable wpi : integer;
|
| 2726 |
|
|
variable fp_dread_fsr : std_logic;
|
| 2727 |
|
|
begin
|
| 2728 |
|
|
rdata := (others => '0'); wpi := 0; cwp := (others => '0');
|
| 2729 |
|
|
fp_dread_fsr := '0';
|
| 2730 |
|
|
case iui.debug.daddr(20 downto 19) is
|
| 2731 |
|
|
when "00" =>
|
| 2732 |
|
|
rdata := rfo.data1(31 downto 0);
|
| 2733 |
|
|
if (FPIFTYPE = parallel) and FPEN then
|
| 2734 |
|
|
if iui.debug.daddr(17 downto 16) = "11" then
|
| 2735 |
|
|
rdata := fpo.data;
|
| 2736 |
|
|
end if;
|
| 2737 |
|
|
end if;
|
| 2738 |
|
|
when "01" =>
|
| 2739 |
|
|
case iui.debug.daddr(7 downto 2) is
|
| 2740 |
|
|
when "000000" => rdata := wr.y; -- Y
|
| 2741 |
|
|
when "000001" => cwp(NWINLOG2-1 downto 0) := sregs.cwp;
|
| 2742 |
|
|
rdata := std_logic_vector(IMPL) & std_logic_vector(VER) &
|
| 2743 |
|
|
sregs.icc & "000000" & sregs.ec & sregs.ef & sregs.pil & sregs.s
|
| 2744 |
|
|
& sregs.ps & sregs.et & cwp;
|
| 2745 |
|
|
when "000010" => rdata(NWINDOWS-1 downto 0) := sregs.wim; -- WIM
|
| 2746 |
|
|
when "000011" => rdata := sregs.tba & sregs.tt & "0000"; -- TBR
|
| 2747 |
|
|
when "000100" => rdata(31 downto PCLOW) := fe.pc; -- PC
|
| 2748 |
|
|
when "000101" => rdata(31 downto PCLOW) := dsur.pc; -- NPC
|
| 2749 |
|
|
when "000110" =>
|
| 2750 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
| 2751 |
|
|
rdata := fpu_reg.fsr.rd & "00" &
|
| 2752 |
|
|
fpu_reg.fsr.tem & "000" & std_logic_vector(FPUVER) &
|
| 2753 |
|
|
fpu_reg.fsr.ftt & "00" & fpu_reg.fsr.fcc & fpu_reg.fsr.aexc &
|
| 2754 |
|
|
fpu_reg.fsr.cexc;
|
| 2755 |
|
|
elsif ((FPIFTYPE = parallel) and FPEN) then
|
| 2756 |
|
|
fp_dread_fsr := '1';
|
| 2757 |
|
|
rdata := fpo.data;
|
| 2758 |
|
|
end if;
|
| 2759 |
|
|
when "000111" => rdata(12 downto 4) := dsur.error & dsur.tt; -- DSU TT
|
| 2760 |
|
|
|
| 2761 |
|
|
when others =>
|
| 2762 |
|
|
if (WATCHPOINTS > 0) and (iui.debug.daddr(7 downto 5) = "011") then
|
| 2763 |
|
|
wpi := conv_integer(unsigned(iui.debug.daddr(4 downto 3)));
|
| 2764 |
|
|
if iui.debug.daddr(2) = '0' then
|
| 2765 |
|
|
rdata := tr(wpi).addr & '0' & tr(wpi).exec;
|
| 2766 |
|
|
else rdata := tr(wpi).mask & tr(wpi).load & tr(wpi).store; end if;
|
| 2767 |
|
|
end if;
|
| 2768 |
|
|
end case;
|
| 2769 |
|
|
when others =>
|
| 2770 |
|
|
rdata := dco.dsudata;
|
| 2771 |
|
|
end case;
|
| 2772 |
|
|
iuo.debug.ddata <= rdata;
|
| 2773 |
|
|
fpi.debug.dread_fsr <= fp_dread_fsr;
|
| 2774 |
|
|
end process;
|
| 2775 |
|
|
end generate;
|
| 2776 |
|
|
|
| 2777 |
|
|
|
| 2778 |
|
|
|
| 2779 |
|
|
iregs : process (clk)
|
| 2780 |
|
|
begin
|
| 2781 |
|
|
if rising_edge(clk) then
|
| 2782 |
|
|
if (holdn or (not ico.mds)) = '1' then
|
| 2783 |
|
|
de.inst <= dein.inst;
|
| 2784 |
|
|
de.mexc <= dein.mexc;
|
| 2785 |
|
|
end if;
|
| 2786 |
|
|
end if;
|
| 2787 |
|
|
end process;
|
| 2788 |
|
|
dregs : process(clk)
|
| 2789 |
|
|
begin
|
| 2790 |
|
|
if rising_edge(clk) then
|
| 2791 |
|
|
if (holdn or (not dco.mds)) = '1' then
|
| 2792 |
|
|
wr.mexc <= dco.mexc;
|
| 2793 |
|
|
wr.result <= wrin.result;
|
| 2794 |
|
|
end if;
|
| 2795 |
|
|
end if;
|
| 2796 |
|
|
end process;
|
| 2797 |
|
|
|
| 2798 |
|
|
-- normal registers
|
| 2799 |
|
|
|
| 2800 |
|
|
|
| 2801 |
|
|
pregs : process (clk)
|
| 2802 |
|
|
begin
|
| 2803 |
|
|
if rising_edge(clk) then
|
| 2804 |
|
|
me.werr <= mein.werr;
|
| 2805 |
|
|
me.ipend <= mein.ipend;
|
| 2806 |
|
|
if (holdn = '1') then
|
| 2807 |
|
|
|
| 2808 |
|
|
-- fetch stage
|
| 2809 |
|
|
fe <= fein;
|
| 2810 |
|
|
-- decode stage
|
| 2811 |
|
|
de.annul <= dein.annul;
|
| 2812 |
|
|
de.cnt <= dein.cnt;
|
| 2813 |
|
|
de.mulcnt <= dein.mulcnt;
|
| 2814 |
|
|
de.cwp <= dein.cwp;
|
| 2815 |
|
|
de.pv <= dein.pv;
|
| 2816 |
|
|
de.pc <= dein.pc;
|
| 2817 |
|
|
|
| 2818 |
|
|
-- execute stage
|
| 2819 |
|
|
ex.ctrl <= exin.ctrl;
|
| 2820 |
|
|
ex.write_reg <= exin.write_reg;
|
| 2821 |
|
|
ex.write_cwp <= exin.write_cwp;
|
| 2822 |
|
|
ex.cwp <= exin.cwp;
|
| 2823 |
|
|
ex.write_y <= exin.write_y;
|
| 2824 |
|
|
ex.rst_mey <= exin.rst_mey;
|
| 2825 |
|
|
ex.write_icc <= exin.write_icc;
|
| 2826 |
|
|
ex.rs1data <= exin.rs1data;
|
| 2827 |
|
|
ex.rs2data <= exin.rs2data;
|
| 2828 |
|
|
ex.alu_cin <= exin.alu_cin;
|
| 2829 |
|
|
ex.aluop <= exin.aluop;
|
| 2830 |
|
|
ex.alusel <= exin.alusel;
|
| 2831 |
|
|
ex.aluadd <= exin.aluadd;
|
| 2832 |
|
|
ex.mulstep <= exin.mulstep;
|
| 2833 |
|
|
ex.mulinsn <= exin.mulinsn;
|
| 2834 |
|
|
ex.ymsb <= exin.ymsb;
|
| 2835 |
|
|
dci.write <= dciin.write;
|
| 2836 |
|
|
dci.asi <= dciin.asi;
|
| 2837 |
|
|
dci.enaddr <= dciin.enaddr;
|
| 2838 |
|
|
dci.read <= dciin.read;
|
| 2839 |
|
|
dci.lock <= dciin.lock;
|
| 2840 |
|
|
|
| 2841 |
|
|
-- memory stage
|
| 2842 |
|
|
me.result <= mein.result;
|
| 2843 |
|
|
me.y <= mein.y;
|
| 2844 |
|
|
me.ctrl <= mein.ctrl;
|
| 2845 |
|
|
dci.size <= mein.ld_size;
|
| 2846 |
|
|
me.memory_load <= mein.memory_load;
|
| 2847 |
|
|
dci.signed <= mein.signed;
|
| 2848 |
|
|
me.write_reg <= mein.write_reg;
|
| 2849 |
|
|
me.write_cwp <= ex.write_cwp;
|
| 2850 |
|
|
me.cwp <= ex.cwp;
|
| 2851 |
|
|
me.write_y <= mein.write_y;
|
| 2852 |
|
|
me.write_icc <= mein.write_icc;
|
| 2853 |
|
|
me.icc <= mein.icc;
|
| 2854 |
|
|
me.addr_misal <= mein.addr_misal;
|
| 2855 |
|
|
me.irqen <= mein.irqen;
|
| 2856 |
|
|
me.su <= mein.su;
|
| 2857 |
|
|
|
| 2858 |
|
|
-- write stage
|
| 2859 |
|
|
wr.y <= wrin.y;
|
| 2860 |
|
|
wr.ctrl <= wrin.ctrl;
|
| 2861 |
|
|
wr.write_reg <= wrin.write_reg;
|
| 2862 |
|
|
wr.write_cwp <= wrin.write_cwp;
|
| 2863 |
|
|
wr.cwp <= wrin.cwp;
|
| 2864 |
|
|
wr.write_icc <= me.write_icc;
|
| 2865 |
|
|
wr.icc <= wrin.icc;
|
| 2866 |
|
|
wr.tpcsel <= wrin.tpcsel;
|
| 2867 |
|
|
wr.trapping <= wrin.trapping;
|
| 2868 |
|
|
wr.error <= wrin.error;
|
| 2869 |
|
|
wr.nerror <= wrin.nerror;
|
| 2870 |
|
|
wr.intack <= wrin.intack;
|
| 2871 |
|
|
|
| 2872 |
|
|
-- special registers
|
| 2873 |
|
|
sregs.cwp <= sregsin.cwp;
|
| 2874 |
|
|
sregs.icc <= sregsin.icc;
|
| 2875 |
|
|
sregs.tt <= sregsin.tt;
|
| 2876 |
|
|
sregs.tba <= sregsin.tba;
|
| 2877 |
|
|
sregs.wim <= sregsin.wim;
|
| 2878 |
|
|
sregs.ec <= sregsin.ec;
|
| 2879 |
|
|
sregs.ef <= sregsin.ef;
|
| 2880 |
|
|
sregs.et <= sregsin.et;
|
| 2881 |
|
|
sregs.ps <= sregsin.ps;
|
| 2882 |
|
|
sregs.s <= sregsin.s;
|
| 2883 |
|
|
sregs.pil <= sregsin.pil;
|
| 2884 |
|
|
end if;
|
| 2885 |
|
|
|
| 2886 |
|
|
-- wathpoint registers
|
| 2887 |
|
|
for i in 0 to WATCHPOINTS-1 loop tr(i) <= trin(i); end loop;
|
| 2888 |
|
|
end if;
|
| 2889 |
|
|
|
| 2890 |
|
|
-- drive unused watchpoint signals to avoid tri-state buffers
|
| 2891 |
|
|
for i in WATCHPOINTS to 3 loop
|
| 2892 |
|
|
tr(i).addr <= (others => '0'); tr(i).mask <= (others => '0');
|
| 2893 |
|
|
tr(i).exec <= '0'; tr(i).load <= '0'; tr(i).store <= '0';
|
| 2894 |
|
|
end loop;
|
| 2895 |
|
|
end process;
|
| 2896 |
|
|
|
| 2897 |
|
|
-- DSU register
|
| 2898 |
|
|
|
| 2899 |
|
|
dsr0 : if DEBUG_UNIT generate
|
| 2900 |
|
|
dsuregs : process (clk)
|
| 2901 |
|
|
begin
|
| 2902 |
|
|
if rising_edge(clk) then
|
| 2903 |
|
|
if (holdn = '1') then
|
| 2904 |
|
|
dsur <= dsurin;
|
| 2905 |
|
|
wr.dsutrap <= wrin.dsutrap;
|
| 2906 |
|
|
de.step <= dein.step;
|
| 2907 |
|
|
end if;
|
| 2908 |
|
|
end if;
|
| 2909 |
|
|
end process;
|
| 2910 |
|
|
end generate;
|
| 2911 |
|
|
|
| 2912 |
|
|
-- MAC register
|
| 2913 |
|
|
|
| 2914 |
|
|
m0 : if MACEN generate
|
| 2915 |
|
|
mregs : process (clk)
|
| 2916 |
|
|
begin
|
| 2917 |
|
|
if rising_edge(clk) then
|
| 2918 |
|
|
if (holdn = '1') then
|
| 2919 |
|
|
wr.asr18 <= wrin.asr18;
|
| 2920 |
|
|
me.mulinsn <= ex.mulinsn;
|
| 2921 |
|
|
end if;
|
| 2922 |
|
|
end if;
|
| 2923 |
|
|
end process;
|
| 2924 |
|
|
end generate;
|
| 2925 |
|
|
|
| 2926 |
|
|
-- register for load bypass control if LDDELAY = 1
|
| 2927 |
|
|
|
| 2928 |
|
|
ldbpr0 : if LDDELAY = 1 generate
|
| 2929 |
|
|
lb : process(clk)
|
| 2930 |
|
|
begin
|
| 2931 |
|
|
if rising_edge(clk) then
|
| 2932 |
|
|
if (holdn = '1') then
|
| 2933 |
|
|
ex.ldbp1 <= exin.ldbp1; ex.ldbp2 <= exin.ldbp2;
|
| 2934 |
|
|
end if;
|
| 2935 |
|
|
end if;
|
| 2936 |
|
|
end process;
|
| 2937 |
|
|
end generate;
|
| 2938 |
|
|
|
| 2939 |
|
|
-- fpu support registers
|
| 2940 |
|
|
|
| 2941 |
|
|
fg3 : if ((FPIFTYPE = serial) and FPEN) generate
|
| 2942 |
|
|
fpureg : process (clk)
|
| 2943 |
|
|
begin
|
| 2944 |
|
|
if rising_edge(clk) then
|
| 2945 |
|
|
fpu_reg.fpld <= fpu_regin.fpld;
|
| 2946 |
|
|
fpu_reg.fpbusy <= fpu_regin.fpbusy;
|
| 2947 |
|
|
fpu_reg.rstdel <= fpu_regin.rstdel;
|
| 2948 |
|
|
if (holdn = '1') then
|
| 2949 |
|
|
fpu_reg.reset <= fpu_regin.reset;
|
| 2950 |
|
|
fpu_reg.fsr <= fpu_regin.fsr;
|
| 2951 |
|
|
fpu_reg.fpexc <= fpu_regin.fpexc;
|
| 2952 |
|
|
fpu_reg.op1h <= fpu_regin.op1h;
|
| 2953 |
|
|
fpu_reg.ex <= fpu_regin.ex;
|
| 2954 |
|
|
fpu_reg.me <= fpu_regin.me;
|
| 2955 |
|
|
fpu_reg.wr <= fpu_regin.wr;
|
| 2956 |
|
|
end if;
|
| 2957 |
|
|
end if;
|
| 2958 |
|
|
end process;
|
| 2959 |
|
|
end generate;
|
| 2960 |
|
|
|
| 2961 |
|
|
|
| 2962 |
|
|
fg4 : if ((FPIFTYPE = serial) and FPEN) generate
|
| 2963 |
|
|
fpu_regin.reset <= ((fpu_regin.fpop or fpu_reg.fpld or fpu_reg.fpbusy)
|
| 2964 |
|
|
and wr.annul_all) or not rst;
|
| 2965 |
|
|
fpu_regin.rstdel <= "11" when (fpu_reg.reset or fpu_regin.reset) = '1'
|
| 2966 |
|
|
else fpu_reg.rstdel - 1 when (fpu_reg.rstdel /= "00")
|
| 2967 |
|
|
-- pragma translate_off
|
| 2968 |
|
|
and not (is_x(fpu_reg.rstdel))
|
| 2969 |
|
|
-- pragma translate_on
|
| 2970 |
|
|
else fpu_reg.rstdel;
|
| 2971 |
|
|
fpui.fpop <= fpu_regin.fpop;
|
| 2972 |
|
|
fpu_regin.fpld <= fpu_regin.fpop or not rst;
|
| 2973 |
|
|
fpui.reset <= fpu_reg.reset or fpu_regin.reset or fpu_reg.rstdel(1)
|
| 2974 |
|
|
or fpu_reg.rstdel(0);
|
| 2975 |
|
|
fpu_regin.fpbusy <= fpuo.fpbusy;
|
| 2976 |
|
|
fpui.fpld <= fpu_reg.fpld;
|
| 2977 |
|
|
fpui.fpuholdn <= fpu_reg.reset or fpu_reg.rstdel(1) or fpu_reg.rstdel(0)
|
| 2978 |
|
|
or (not rst) or not (fpu_reg.fpbusy or fpu_reg.fpld);
|
| 2979 |
|
|
end generate;
|
| 2980 |
|
|
fg5 : if not ((FPIFTYPE = serial) and FPEN) generate
|
| 2981 |
|
|
fpui.fpuholdn <= '1';
|
| 2982 |
|
|
end generate;
|
| 2983 |
|
|
|
| 2984 |
|
|
|
| 2985 |
|
|
|
| 2986 |
|
|
|
| 2987 |
|
|
-- debugging support
|
| 2988 |
|
|
|
| 2989 |
|
|
debug0 : if DEBUGPORT generate
|
| 2990 |
|
|
|
| 2991 |
|
|
|
| 2992 |
|
|
iuo.debug.clk <= clk;
|
| 2993 |
|
|
|
| 2994 |
|
|
iuo.debug.rst <= rst;
|
| 2995 |
|
|
iuo.debug.holdn <= holdn;
|
| 2996 |
|
|
iuo.debug.ex <= ex.ctrl;
|
| 2997 |
|
|
iuo.debug.me <= me.ctrl;
|
| 2998 |
|
|
iuo.debug.mresult<= me.result;
|
| 2999 |
|
|
iuo.debug.diagrdy<= ico.diagrdy;
|
| 3000 |
|
|
iuo.debug.fpdbg <= fpo.debug;
|
| 3001 |
|
|
|
| 3002 |
|
|
end generate;
|
| 3003 |
|
|
|
| 3004 |
|
|
fadder : if FASTADD generate
|
| 3005 |
|
|
add0 : add32 port map (add32in1, add32in2, add32cin, sum32, open);
|
| 3006 |
|
|
end generate;
|
| 3007 |
|
|
|
| 3008 |
|
|
end;
|