📄 iu.vhd
字号:
-----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- See the file COPYING for the full details of the license.
-----------------------------------------------------------------------------
-- Entity: iu
-- File: iu.vhd
-- Author: Jiri Gaisler - ESA/ESTEC
-- Description: LEON integer unit. Consists of 5 pipline stages: fetch,
-- decode, execute, memory and write-back. Each stage is
-- implemented in a separate process.
------------------------------------------------------------------------------
-- Version control:
-- 07-11-1997: First implemetation
-- 26-09-1999: Release 1.0
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned."+";
use IEEE.std_logic_unsigned."-";
use IEEE.std_logic_unsigned.conv_integer;
use work.config.all;
use work.sparcv8.all;
use work.iface.all;
use work.macro.all;
entity iu is
port (
Rst : in std_logic; -- reset
Clk : in std_logic; -- main clock
iclk : in std_logic; -- missed instruction clock
dclk : in std_logic; -- missed data clock
holdn : in std_logic; -- pipeline hold
ici : out icache_in_type; -- icache input
ico : in icache_out_type; -- icache output
dci : out dcache_in_type; -- dcache input
dco : in dcache_out_type; -- dcache output
rfi : out rf_in_type; -- register-file input
rfo : in rf_out_type; -- register-file output
sysi : in sys_in_type; -- system input
syso : out sys_out_type -- system output
-- pragma translate_off
;debug : out iu_debug_type
-- pragma translate_on
);
end;
architecture rtl of iu is
-- pipeline_control type is defined in package iface
type fetch_stage_inputs is record
branch : std_logic; -- select branch address
jump : std_logic; -- select jump address
exception : std_logic; -- select exception address
hold_pc : std_logic; -- hold PC (multi-cycle inst.)
branch_address : std_logic_vector(31 downto PCLOW); -- branch address
jump_address : std_logic_vector(31 downto PCLOW); -- jump address
trap_address : std_logic_vector(31 downto PCLOW); -- trap address
end record;
type fetch_stage_registers is record
pc : std_logic_vector(31 downto PCLOW); -- program counter
branch : std_logic; -- branch indicator
end record;
type decode_stage_type is record
inst : std_logic_vector(31 downto 0); -- instruction
pc : std_logic_vector(31 downto PCLOW); -- program counter
mexc : std_logic; -- memory exception (fetch)
annul : std_logic; -- instruction annul bit
cnt : std_logic_vector(1 downto 0); -- cycle number (multi-cycle inst)
mulcnt : std_logic_vector(4 downto 0); -- cycle number (multi-cycle inst)
pv : std_logic; -- PC valid flag
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
end record;
type execute_stage_type is record
write_cwp, write_icc, write_reg, write_y, rst_mey : std_logic;
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
icc : std_logic_vector(3 downto 0); -- integer condition codes
alu_cin : std_logic; -- ALU carry-in
ycarry : std_logic; -- MULSCC carry-in
ymsb : std_logic; -- MULSCC Y(msb)
rs1data : std_logic_vector(31 downto 0); -- source operand 1
rs2data : std_logic_vector(31 downto 0); -- source operand 2
aluop : std_logic_vector(2 downto 0); -- Alu operation
alusel : std_logic_vector(1 downto 0); -- Alu result select
aluadd : std_logic; -- add/sub select
mulstep : std_logic; -- MULSCC
mulinsn : std_logic; -- SMUL/UMUL
ldbp1, ldbp2 : std_logic; -- load bypass enable
ctrl : pipeline_control_type;
result : std_logic_vector(31 downto 0); -- data forward from execute stage
micc : std_logic_vector(3 downto 0); -- icc for multiply insn
licc : std_logic_vector(3 downto 0); -- icc to me stage
end record;
type memory_stage_type is record
inull : std_logic;
signed : std_logic;
addr_misal : std_logic;
write_cwp, write_icc, write_reg, write_y : std_logic;
cwp : std_logic_vector(NWINLOG2-1 downto 0);
icc : std_logic_vector(3 downto 0);
result : std_logic_vector(31 downto 0);
y : std_logic_vector(31 downto 0);
memory_load : std_logic;
ld_size : std_logic_vector(1 downto 0); -- Load size
ctrl : pipeline_control_type;
end record;
type write_stage_type is record
write_cwp, write_icc, write_reg : std_logic;
cwp : std_logic_vector(NWINLOG2-1 downto 0);
icc : std_logic_vector(3 downto 0);
result : std_logic_vector(31 downto 0);
y : std_logic_vector(31 downto 0);
annul_all : std_logic;
trapping : std_logic;
error : std_logic;
mexc : std_logic;
wexc : std_logic;
intack : std_logic;
tpcsel : std_logic_vector(1 downto 0); -- Trap pc select
ctrl : pipeline_control_type;
end record;
type special_register_type is record
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
icc : std_logic_vector(3 downto 0); -- integer condition codes
tt : std_logic_vector(7 downto 0); -- trap type
tba : std_logic_vector(19 downto 0); -- trap base address
wim : std_logic_vector(NWINDOWS-1 downto 0); -- window invalid mask
pil : std_logic_vector(3 downto 0); -- processor interrupt level
ec : std_logic; -- enable CP
ef : std_logic; -- enable FP
ps : std_logic; -- previous supervisor flag
s : std_logic; -- supervisor flag
et : std_logic; -- enable traps
end record;
-- registers
signal fecomb : fetch_stage_inputs;
signal fe, fein : fetch_stage_registers;
signal de, dein : decode_stage_type;
signal ex, exin : execute_stage_type;
signal me, mein : memory_stage_type;
signal wr, wrin : write_stage_type;
signal sregsin, sregs : special_register_type;
signal dciin : dcache_in_type;
begin
-------------------------------------------------------------------------------
-- Instruction fetch stage
-------------------------------------------------------------------------------
fetch_stage : process(fecomb, fe, rst, de, mein)
variable v : fetch_stage_registers;
begin
v := fe;
-- pc generation
if (rst = '0') then
v.pc := (others => '0'); v.branch := '0';
elsif fecomb.exception = '1' then -- exception: use tbr
v.branch := '1'; v.pc := fecomb.trap_address;
elsif (not mein.inull and fecomb.hold_pc) = '1' then
v.pc := fe.pc; v.branch := fe.branch;
elsif fecomb.jump = '1' then
v.pc := fecomb.jump_address; v.branch := '1';
elsif fecomb.branch = '1' then
v.pc := fecomb.branch_address; v.branch := '1';
else
v.branch := '0';
-- pragma translate_off
if not is_x(fe.pc) then
-- pragma translate_on
v.pc(31 downto 2) := fe.pc(31 downto 2) + 1; -- Address incrementer
-- pragma translate_off
else
v.pc := (others => 'X');
end if;
-- pragma translate_on
end if;
-- drive register inputs
fein <= v;
-- drive some icache inputs
ici.rpc(31 downto PCLOW) <= v.pc(31 downto PCLOW);
ici.rpc(1 downto 0) <= "00";
ici.fpc(31 downto PCLOW) <= fe.pc(31 downto PCLOW);
ici.fpc(1 downto 0) <= "00";
ici.branch <= fe.branch;
end process;
-------------------------------------------------------------------------------
-- Instruction decode stage
-------------------------------------------------------------------------------
decode_stage : process(fe, de, Rst, ex, me, mein, wr, sregs, ico, rfo)
variable op : std_logic_vector(1 downto 0);
variable op2 : std_logic_vector(2 downto 0);
variable op3 : std_logic_vector(5 downto 0);
variable cond : std_logic_vector(3 downto 0);
variable rs1, rs2, rd : std_logic_vector(4 downto 0);
variable write_cwp, write_icc, write_reg, write_y : std_logic;
variable cnt : std_logic_vector(1 downto 0); -- cycle number
variable cwp_new : std_logic_vector(NWINLOG2-1 downto 0);
variable icc : std_logic_vector(3 downto 0);
variable alu_cin : std_logic;
variable immediate_data : std_logic_vector(31 downto 0);
variable n, z, v, c : std_logic; -- temporary condition codes
variable i : std_logic; -- immidiate data bit
variable su : std_logic; -- local supervisor bit;
variable et : std_logic; -- local enable trap bit
variable inull, annul, annul_current : std_logic;
variable branch, annul_next, bres, branch_true: std_logic;
variable aluop : std_logic_vector(2 downto 0);
variable alusel : std_logic_vector(1 downto 0);
variable aluadd : std_logic;
variable mulstep : std_logic;
variable mulinsn : std_logic;
variable y0 : std_logic;
variable branch_address : std_logic_vector(31 downto PCLOW);
variable rs1data, rs2data : std_logic_vector(31 downto 0);
variable operand2_select : std_logic_vector(1 downto 0);
variable read_addr1 : std_logic_vector(RABITS-1 downto 0);
variable read_addr2 : std_logic_vector(RABITS-1 downto 0);
variable hold_pc : std_logic; -- Hold PC during multi-cycle ops
variable pv : std_logic; -- PC valid
variable ldlock, ldcheck1, ldcheck2 : std_logic; -- load interlock signals
variable ldchkex, ldchkme : std_logic; -- load interlock for ex and me
variable illegal_inst : std_logic; -- illegal instruction
variable privileged_inst : std_logic; -- privileged instruction trap
variable cp_disabled : std_logic; -- CP disable trap
variable fp_disabled : std_logic; -- FP disable trap
variable winovf_exception : std_logic; -- window overflow trap
variable winunf_exception : std_logic; -- window underflow trap
variable fp_exception : std_logic; -- window underflow trap
variable ticc_exception : std_logic; -- TICC trap
variable ctrl : pipeline_control_type;
variable ldbp1, ldbp2 : std_logic; -- load bypass enable
variable mulcnt : std_logic_vector(4 downto 0); -- multiply cycle number
variable ymsb : std_logic; -- next msb of Y during MUL
variable rst_mey : std_logic; -- reset me stage Y register
begin
-- instruction bit-field decoding
op := de.inst(31 downto 30);
op2 := de.inst(24 downto 22);
op3 := de.inst(24 downto 19);
cond := de.inst(28 downto 25);
annul := de.inst(29);
rs1 := de.inst(18 downto 14);
rs2 := de.inst(4 downto 0);
rd := de.inst(29 downto 25);
i := de.inst(13);
-- reset handling
if Rst = '0' then
ctrl.annul := '0'; ctrl.cnt := "00";
ctrl.pv := '0'; pv := '0';
else
ctrl.annul := de.annul; ctrl.cnt := de.cnt;
ctrl.pv := de.pv; pv := '1';
end if;
-- common initialisation
cnt := "00"; ctrl.tt := "000000"; ctrl.ld := '0'; ctrl.rett := '0';
ctrl.pc := de.pc; ctrl.inst := de.inst; mulcnt := de.mulcnt;
write_y := '0';
winovf_exception := '0'; winunf_exception := '0';
write_cwp := '0'; cwp_new := de.cwp;
-- detect RETT instruction in the pipeline and set the local psr.su and psr.et
if ((ex.ctrl.rett and not ex.ctrl.annul) or (me.ctrl.rett and not me.ctrl.annul) or
(wr.ctrl.rett and not wr.ctrl.annul)) = '1'
then
su := sregs.ps; et := '1';
else
su := sregs.s; et := sregs.et;
end if;
-- Check for illegal and privileged instructions
illegal_inst := '0'; privileged_inst := '0'; cp_disabled := '0';
fp_disabled := '0'; fp_exception := '0';
case op is
when CALL => null;
when FMT2 =>
case op2 is
when SETHI | BICC => null;
when FBFCC => fp_disabled := FPDIS or not sregs.ef;
when CBCCC => cp_disabled := '1';
when others => illegal_inst := '1';
end case;
when FMT3 =>
case op3 is
when IAND | ANDCC | ANDN | ANDNCC | IOR | ORCC | ORN | ORNCC | IXOR |
XORCC | IXNOR | XNORCC | ISLL | ISRL | ISRA | MULSCC | IADD | ADDX |
ADDCC | ADDXCC | TADDCC | TADDCCTV | ISUB | SUBX | SUBCC | SUBXCC |
TSUBCC | TSUBCCTV | FLUSH | JMPL | TICC | SAVE | RESTORE | RDY => null;
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = none then illegal_inst := '1'; end if;
when RETT => illegal_inst := et; privileged_inst := not su;
when RDPSR | RDTBR | RDWIM => privileged_inst := not su;
when WRY =>
if rd /= "00000" then illegal_inst := '1'; end if;
privileged_inst := not su;
when WRPSR =>
privileged_inst := not su;
when WRWIM | WRTBR => privileged_inst := not su;
when FPOP1 | FPOP2 => fp_disabled := FPDIS or not sregs.ef;
when CPOP1 | CPOP2 => cp_disabled := '1';
when others => illegal_inst := '1';
end case;
when others => -- LDST
case op3 is
when LDD | ISTD => illegal_inst := rd(0); -- trap if odd destination register
when LD | LDUB | LDSTUB | LDUH | LDSB | LDSH | ST | STB | STH | SWAP =>
null;
when LDDA | STDA =>
illegal_inst := i or rd(0); privileged_inst := not su;
when LDA | LDUBA| LDSTUBA | LDUHA | LDSBA | LDSHA | STA | STBA | STHA |
SWAPA =>
illegal_inst := i; privileged_inst := not su;
when LDDF | STDF =>
fp_disabled := FPDIS or not sregs.ef; fp_exception := rd(0);
when STDFQ =>
privileged_inst := not su; fp_disabled := FPDIS or not sregs.ef;
when LDF | LDFSR | STF | STFSR =>
fp_disabled := FPDIS or not sregs.ef;
when STDCQ =>
privileged_inst := not su; cp_disabled := '1';
when LDC | LDCSR | LDDC | STC | STCSR | STDC =>
cp_disabled := '1';
when others => illegal_inst := '1';
end case;
end case;
-- branch address adder
branch_address := (others => '0');
if op = CALL then branch_address(31 downto 2) := de.inst(29 downto 0);
else branch_address(31 downto 2) := de.inst(21) & de.inst(21) & de.inst(21) &
de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) &
de.inst(21) & de.inst(21 downto 0);
end if;
-- pragma translate_off
if not (is_x(branch_address) or is_x(de.pc)) then
-- pragma translate_on
branch_address := branch_address + de.pc; -- address adder (branch)
-- pragma translate_off
else
branch_address := (others => 'X');
end if;
-- pragma translate_on
fecomb.branch_address <= branch_address;
-- Load decoding
if de.annul = '0' then
case op is
when LDST => ctrl.ld := not op3(2);
when others => null;
end case;
end if;
-- ICC pipeline and forwarding
if (ex.write_icc and not ex.ctrl.annul) = '1' then
icc := ex.icc;
elsif (me.write_icc and not me.ctrl.annul) = '1' then
icc := me.icc;
elsif (wr.write_icc and not wr.ctrl.annul) = '1' then
icc := wr.icc;
else
icc := sregs.icc;
end if;
write_icc := '0'; alu_cin := '0';
case op is
when FMT3 =>
case op3 is
when SUBCC | TSUBCC | TSUBCCTV =>
write_icc := '1';
when ADDCC | ANDCC | ORCC | XORCC | ANDNCC | ORNCC | XNORCC | MULSCC |
TADDCC | TADDCCTV =>
write_icc := '1';
when UMULCC | SMULCC =>
if MULTIPLIER = iterative then
if de.cnt /= "11" then write_icc := '1'; end if;
end if;
when ADDX | SUBX =>
alu_cin := icc(0);
when ADDXCC | SUBXCC =>
write_icc := '1'; alu_cin := icc(0);
when others => null;
end case;
when others => null;
end case;
exin.write_icc <= write_icc;
exin.alu_cin <= alu_cin;
-- BICC/TICC evaluation
n := icc(3); z := icc(2); v := icc(1); c := icc(0);
case cond(2 downto 0) is
when "000" => bres := '0'; -- bn, ba
when "001" => bres := z; -- be, bne
when "010" => bres := z or (n xor v); -- ble, bg
when "011" => bres := n xor v; -- bl, bge
when "100" => bres := c or z; -- blue, bgu
when "101" => bres := c; -- bcs, bcc
when "110" => bres := n; -- bneg, bpos
when others => bres := v; -- bvs. bvc
end case;
branch_true := cond(3) xor bres;
-- Alu operation generation
aluop := ALU_NOP; alusel := ALU_RES_MISC; aluadd := '1';
mulstep := '0'; mulinsn := '0';
case op is
when FMT2 =>
case op2 is
when SETHI => aluop := ALU_PASS2;
when others => aluop := ALU_NOP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -