Merge pull request #382 from paulusmack/master
Decode in block RAM and other improvementspull/397/head
commit
ff63ffdbfd
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,56 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
|
||||
-- Signed 33b x 33b multiplier giving 64-bit product, with no addend,
|
||||
-- with fixed 1-cycle latency.
|
||||
|
||||
entity multiply_32s is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
stall : in std_ulogic;
|
||||
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply_32s;
|
||||
|
||||
architecture behaviour of multiply_32s is
|
||||
type reg_type is record
|
||||
valid : std_ulogic;
|
||||
data : signed(65 downto 0);
|
||||
end record;
|
||||
constant reg_type_init : reg_type := (valid => '0', data => (others => '0'));
|
||||
|
||||
signal r, rin : reg_type := reg_type_init;
|
||||
begin
|
||||
multiply_0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) and stall = '0' then
|
||||
r <= rin;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
multiply_1: process(all)
|
||||
variable v : reg_type;
|
||||
variable d : std_ulogic_vector(63 downto 0);
|
||||
variable ov : std_ulogic;
|
||||
begin
|
||||
v.valid := m_in.valid;
|
||||
v.data := signed((m_in.is_signed and m_in.data1(31)) & m_in.data1(31 downto 0)) *
|
||||
signed((m_in.is_signed and m_in.data2(31)) & m_in.data2(31 downto 0));
|
||||
|
||||
d := std_ulogic_vector(r.data(63 downto 0));
|
||||
|
||||
ov := (or d(63 downto 31)) and not (and d(63 downto 31));
|
||||
|
||||
m_out.result <= 64x"0" & d;
|
||||
m_out.overflow <= ov;
|
||||
m_out.valid <= r.valid;
|
||||
|
||||
rin <= v;
|
||||
end process;
|
||||
end architecture behaviour;
|
@ -0,0 +1,592 @@
|
||||
-- Instruction pre-decoder for microwatt
|
||||
-- One cycle latency. Does 'WIDTH' instructions in parallel.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
use work.decode_types.all;
|
||||
use work.insn_helpers.all;
|
||||
|
||||
entity predecoder is
|
||||
generic (
|
||||
HAS_FPU : boolean := true;
|
||||
WIDTH : natural := 2;
|
||||
ICODE_LEN : natural := 10;
|
||||
IMAGE_LEN : natural := 26
|
||||
);
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
valid_in : in std_ulogic;
|
||||
insns_in : in std_ulogic_vector(WIDTH * 32 - 1 downto 0);
|
||||
icodes_out : out std_ulogic_vector(WIDTH * (ICODE_LEN + IMAGE_LEN) - 1 downto 0)
|
||||
);
|
||||
end entity predecoder;
|
||||
|
||||
architecture behaviour of predecoder is
|
||||
|
||||
type predecoder_rom_t is array(0 to 2047) of insn_code;
|
||||
|
||||
constant major_predecode_rom : predecoder_rom_t := (
|
||||
2#001100_00000# to 2#001100_11111# => INSN_addic,
|
||||
2#001101_00000# to 2#001101_11111# => INSN_addic_dot,
|
||||
2#001110_00000# to 2#001110_11111# => INSN_addi,
|
||||
2#001111_00000# to 2#001111_11111# => INSN_addis,
|
||||
2#010011_00100# to 2#010011_00101# => INSN_addpcis,
|
||||
2#011100_00000# to 2#011100_11111# => INSN_andi_dot,
|
||||
2#011101_00000# to 2#011101_11111# => INSN_andis_dot,
|
||||
2#000000_00000# => INSN_attn,
|
||||
2#010010_00000# to 2#010010_11111# => INSN_b,
|
||||
2#010000_00000# to 2#010000_11111# => INSN_bc,
|
||||
2#001011_00000# to 2#001011_11111# => INSN_cmpi,
|
||||
2#001010_00000# to 2#001010_11111# => INSN_cmpli,
|
||||
2#100010_00000# to 2#100010_11111# => INSN_lbz,
|
||||
2#100011_00000# to 2#100011_11111# => INSN_lbzu,
|
||||
2#110010_00000# to 2#110010_11111# => INSN_lfd,
|
||||
2#110011_00000# to 2#110011_11111# => INSN_lfdu,
|
||||
2#110000_00000# to 2#110000_11111# => INSN_lfs,
|
||||
2#110001_00000# to 2#110001_11111# => INSN_lfsu,
|
||||
2#101010_00000# to 2#101010_11111# => INSN_lha,
|
||||
2#101011_00000# to 2#101011_11111# => INSN_lhau,
|
||||
2#101000_00000# to 2#101000_11111# => INSN_lhz,
|
||||
2#101001_00000# to 2#101001_11111# => INSN_lhzu,
|
||||
2#100000_00000# to 2#100000_11111# => INSN_lwz,
|
||||
2#100001_00000# to 2#100001_11111# => INSN_lwzu,
|
||||
2#000111_00000# to 2#000111_11111# => INSN_mulli,
|
||||
2#011000_00000# to 2#011000_11111# => INSN_ori,
|
||||
2#011001_00000# to 2#011001_11111# => INSN_oris,
|
||||
2#010100_00000# to 2#010100_11111# => INSN_rlwimi,
|
||||
2#010101_00000# to 2#010101_11111# => INSN_rlwinm,
|
||||
2#010111_00000# to 2#010111_11111# => INSN_rlwnm,
|
||||
2#010001_00000# to 2#010001_11111# => INSN_sc,
|
||||
2#100110_00000# to 2#100110_11111# => INSN_stb,
|
||||
2#100111_00000# to 2#100111_11111# => INSN_stbu,
|
||||
2#110110_00000# to 2#110110_11111# => INSN_stfd,
|
||||
2#110111_00000# to 2#110111_11111# => INSN_stfdu,
|
||||
2#110100_00000# to 2#110100_11111# => INSN_stfs,
|
||||
2#110101_00000# to 2#110101_11111# => INSN_stfsu,
|
||||
2#101100_00000# to 2#101100_11111# => INSN_sth,
|
||||
2#101101_00000# to 2#101101_11111# => INSN_sthu,
|
||||
2#100100_00000# to 2#100100_11111# => INSN_stw,
|
||||
2#100101_00000# to 2#100101_11111# => INSN_stwu,
|
||||
2#001000_00000# to 2#001000_11111# => INSN_subfic,
|
||||
2#000010_00000# to 2#000010_11111# => INSN_tdi,
|
||||
2#000011_00000# to 2#000011_11111# => INSN_twi,
|
||||
2#011010_00000# to 2#011010_11111# => INSN_xori,
|
||||
2#011011_00000# to 2#011011_11111# => INSN_xoris,
|
||||
-- major opcode 4
|
||||
2#000100_10000# => INSN_maddhd,
|
||||
2#000100_10001# => INSN_maddhdu,
|
||||
2#000100_10011# => INSN_maddld,
|
||||
-- major opcode 30
|
||||
2#011110_01000# to 2#011110_01001# => INSN_rldic,
|
||||
2#011110_01010# to 2#011110_01011# => INSN_rldic,
|
||||
2#011110_00000# to 2#011110_00001# => INSN_rldicl,
|
||||
2#011110_00010# to 2#011110_00011# => INSN_rldicl,
|
||||
2#011110_00100# to 2#011110_00101# => INSN_rldicr,
|
||||
2#011110_00110# to 2#011110_00111# => INSN_rldicr,
|
||||
2#011110_01100# to 2#011110_01101# => INSN_rldimi,
|
||||
2#011110_01110# to 2#011110_01111# => INSN_rldimi,
|
||||
2#011110_10000# to 2#011110_10001# => INSN_rldcl,
|
||||
2#011110_10010# to 2#011110_10011# => INSN_rldcr,
|
||||
-- major opcode 58
|
||||
2#111010_00000# => INSN_ld,
|
||||
2#111010_00001# => INSN_ldu,
|
||||
2#111010_00010# => INSN_lwa,
|
||||
2#111010_00100# => INSN_ld,
|
||||
2#111010_00101# => INSN_ldu,
|
||||
2#111010_00110# => INSN_lwa,
|
||||
2#111010_01000# => INSN_ld,
|
||||
2#111010_01001# => INSN_ldu,
|
||||
2#111010_01010# => INSN_lwa,
|
||||
2#111010_01100# => INSN_ld,
|
||||
2#111010_01101# => INSN_ldu,
|
||||
2#111010_01110# => INSN_lwa,
|
||||
2#111010_10000# => INSN_ld,
|
||||
2#111010_10001# => INSN_ldu,
|
||||
2#111010_10010# => INSN_lwa,
|
||||
2#111010_10100# => INSN_ld,
|
||||
2#111010_10101# => INSN_ldu,
|
||||
2#111010_10110# => INSN_lwa,
|
||||
2#111010_11000# => INSN_ld,
|
||||
2#111010_11001# => INSN_ldu,
|
||||
2#111010_11010# => INSN_lwa,
|
||||
2#111010_11100# => INSN_ld,
|
||||
2#111010_11101# => INSN_ldu,
|
||||
2#111010_11110# => INSN_lwa,
|
||||
-- major opcode 59
|
||||
2#111011_00100# to 2#111011_00101# => INSN_fdivs,
|
||||
2#111011_01000# to 2#111011_01001# => INSN_fsubs,
|
||||
2#111011_01010# to 2#111011_01011# => INSN_fadds,
|
||||
2#111011_01100# to 2#111011_01101# => INSN_fsqrts,
|
||||
2#111011_10000# to 2#111011_10001# => INSN_fres,
|
||||
2#111011_10010# to 2#111011_10011# => INSN_fmuls,
|
||||
2#111011_10100# to 2#111011_10101# => INSN_frsqrtes,
|
||||
2#111011_11000# to 2#111011_11001# => INSN_fmsubs,
|
||||
2#111011_11010# to 2#111011_11011# => INSN_fmadds,
|
||||
2#111011_11100# to 2#111011_11101# => INSN_fnmsubs,
|
||||
2#111011_11110# to 2#111011_11111# => INSN_fnmadds,
|
||||
-- major opcode 62
|
||||
2#111110_00000# => INSN_std,
|
||||
2#111110_00001# => INSN_stdu,
|
||||
2#111110_00100# => INSN_std,
|
||||
2#111110_00101# => INSN_stdu,
|
||||
2#111110_01000# => INSN_std,
|
||||
2#111110_01001# => INSN_stdu,
|
||||
2#111110_01100# => INSN_std,
|
||||
2#111110_01101# => INSN_stdu,
|
||||
2#111110_10000# => INSN_std,
|
||||
2#111110_10001# => INSN_stdu,
|
||||
2#111110_10100# => INSN_std,
|
||||
2#111110_10101# => INSN_stdu,
|
||||
2#111110_11000# => INSN_std,
|
||||
2#111110_11001# => INSN_stdu,
|
||||
2#111110_11100# => INSN_std,
|
||||
2#111110_11101# => INSN_stdu,
|
||||
-- major opcode 63
|
||||
2#111111_00100# to 2#111111_00101# => INSN_fdiv,
|
||||
2#111111_01000# to 2#111111_01001# => INSN_fsub,
|
||||
2#111111_01010# to 2#111111_01011# => INSN_fadd,
|
||||
2#111111_01100# to 2#111111_01101# => INSN_fsqrt,
|
||||
2#111111_01110# to 2#111111_01111# => INSN_fsel,
|
||||
2#111111_10000# to 2#111111_10001# => INSN_fre,
|
||||
2#111111_10010# to 2#111111_10011# => INSN_fmul,
|
||||
2#111111_10100# to 2#111111_10101# => INSN_frsqrte,
|
||||
2#111111_11000# to 2#111111_11001# => INSN_fmsub,
|
||||
2#111111_11010# to 2#111111_11011# => INSN_fmadd,
|
||||
2#111111_11100# to 2#111111_11101# => INSN_fnmsub,
|
||||
2#111111_11110# to 2#111111_11111# => INSN_fnmadd,
|
||||
others => INSN_illegal
|
||||
);
|
||||
|
||||
constant row_predecode_rom : predecoder_rom_t := (
|
||||
-- Major opcode 31
|
||||
-- Address bits are 0, insn(10:1)
|
||||
2#0_01000_01010# => INSN_add,
|
||||
2#0_11000_01010# => INSN_add, -- addo
|
||||
2#0_00000_01010# => INSN_addc,
|
||||
2#0_10000_01010# => INSN_addc, -- addco
|
||||
2#0_00100_01010# => INSN_adde,
|
||||
2#0_10100_01010# => INSN_adde, -- addeo
|
||||
2#0_00101_01010# => INSN_addex,
|
||||
2#0_00010_01010# => INSN_addg6s,
|
||||
2#0_00111_01010# => INSN_addme,
|
||||
2#0_10111_01010# => INSN_addme, -- addmeo
|
||||
2#0_00110_01010# => INSN_addze,
|
||||
2#0_10110_01010# => INSN_addze, -- addzeo
|
||||
2#0_00000_11100# => INSN_and,
|
||||
2#0_00001_11100# => INSN_andc,
|
||||
2#0_00111_11100# => INSN_bperm,
|
||||
2#0_01001_11010# => INSN_cbcdtd,
|
||||
2#0_01000_11010# => INSN_cdtbcd,
|
||||
2#0_00000_00000# => INSN_cmp,
|
||||
2#0_01111_11100# => INSN_cmpb,
|
||||
2#0_00111_00000# => INSN_cmpeqb,
|
||||
2#0_00001_00000# => INSN_cmpl,
|
||||
2#0_00110_00000# => INSN_cmprb,
|
||||
2#0_00001_11010# => INSN_cntlzd,
|
||||
2#0_00000_11010# => INSN_cntlzw,
|
||||
2#0_10001_11010# => INSN_cnttzd,
|
||||
2#0_10000_11010# => INSN_cnttzw,
|
||||
2#0_10111_10011# => INSN_darn,
|
||||
2#0_00010_10110# => INSN_dcbf,
|
||||
2#0_00001_10110# => INSN_dcbst,
|
||||
2#0_01000_10110# => INSN_dcbt,
|
||||
2#0_00111_10110# => INSN_dcbtst,
|
||||
2#0_11111_10110# => INSN_dcbz,
|
||||
2#0_01100_01001# => INSN_divdeu,
|
||||
2#0_11100_01001# => INSN_divdeu, -- divdeuo
|
||||
2#0_01100_01011# => INSN_divweu,
|
||||
2#0_11100_01011# => INSN_divweu, -- divweuo
|
||||
2#0_01101_01001# => INSN_divde,
|
||||
2#0_11101_01001# => INSN_divde, -- divdeo
|
||||
2#0_01101_01011# => INSN_divwe,
|
||||
2#0_11101_01011# => INSN_divwe, -- divweo
|
||||
2#0_01110_01001# => INSN_divdu,
|
||||
2#0_11110_01001# => INSN_divdu, -- divduo
|
||||
2#0_01110_01011# => INSN_divwu,
|
||||
2#0_11110_01011# => INSN_divwu, -- divwuo
|
||||
2#0_01111_01001# => INSN_divd,
|
||||
2#0_11111_01001# => INSN_divd, -- divdo
|
||||
2#0_01111_01011# => INSN_divw,
|
||||
2#0_11111_01011# => INSN_divw, -- divwo
|
||||
2#0_11001_10110# => INSN_nop, -- dss
|
||||
2#0_01010_10110# => INSN_nop, -- dst
|
||||
2#0_01011_10110# => INSN_nop, -- dstst
|
||||
2#0_11010_10110# => INSN_eieio,
|
||||
2#0_01000_11100# => INSN_eqv,
|
||||
2#0_11101_11010# => INSN_extsb,
|
||||
2#0_11100_11010# => INSN_extsh,
|
||||
2#0_11110_11010# => INSN_extsw,
|
||||
2#0_11011_11010# => INSN_extswsli,
|
||||
2#0_11011_11011# => INSN_extswsli,
|
||||
2#0_11110_10110# => INSN_icbi,
|
||||
2#0_00000_10110# => INSN_icbt,
|
||||
2#0_00000_01111# => INSN_isel,
|
||||
2#0_00001_01111# => INSN_isel,
|
||||
2#0_00010_01111# => INSN_isel,
|
||||
2#0_00011_01111# => INSN_isel,
|
||||
2#0_00100_01111# => INSN_isel,
|
||||
2#0_00101_01111# => INSN_isel,
|
||||
2#0_00110_01111# => INSN_isel,
|
||||
2#0_00111_01111# => INSN_isel,
|
||||
2#0_01000_01111# => INSN_isel,
|
||||
2#0_01001_01111# => INSN_isel,
|
||||
2#0_01010_01111# => INSN_isel,
|
||||
2#0_01011_01111# => INSN_isel,
|
||||
2#0_01100_01111# => INSN_isel,
|
||||
2#0_01101_01111# => INSN_isel,
|
||||
2#0_01110_01111# => INSN_isel,
|
||||
2#0_01111_01111# => INSN_isel,
|
||||
2#0_10000_01111# => INSN_isel,
|
||||
2#0_10001_01111# => INSN_isel,
|
||||
2#0_10010_01111# => INSN_isel,
|
||||
2#0_10011_01111# => INSN_isel,
|
||||
2#0_10100_01111# => INSN_isel,
|
||||
2#0_10101_01111# => INSN_isel,
|
||||
2#0_10110_01111# => INSN_isel,
|
||||
2#0_10111_01111# => INSN_isel,
|
||||
2#0_11000_01111# => INSN_isel,
|
||||
2#0_11001_01111# => INSN_isel,
|
||||
2#0_11010_01111# => INSN_isel,
|
||||
2#0_11011_01111# => INSN_isel,
|
||||
2#0_11100_01111# => INSN_isel,
|
||||
2#0_11101_01111# => INSN_isel,
|
||||
2#0_11110_01111# => INSN_isel,
|
||||
2#0_11111_01111# => INSN_isel,
|
||||
2#0_00001_10100# => INSN_lbarx,
|
||||
2#0_11010_10101# => INSN_lbzcix,
|
||||
2#0_00011_10111# => INSN_lbzux,
|
||||
2#0_00010_10111# => INSN_lbzx,
|
||||
2#0_00010_10100# => INSN_ldarx,
|
||||
2#0_10000_10100# => INSN_ldbrx,
|
||||
2#0_11011_10101# => INSN_ldcix,
|
||||
2#0_00001_10101# => INSN_ldux,
|
||||
2#0_00000_10101# => INSN_ldx,
|
||||
2#0_10010_10111# => INSN_lfdx,
|
||||
2#0_10011_10111# => INSN_lfdux,
|
||||
2#0_11010_10111# => INSN_lfiwax,
|
||||
2#0_11011_10111# => INSN_lfiwzx,
|
||||
2#0_10000_10111# => INSN_lfsx,
|
||||
2#0_10001_10111# => INSN_lfsux,
|
||||
2#0_00011_10100# => INSN_lharx,
|
||||
2#0_01011_10111# => INSN_lhaux,
|
||||
2#0_01010_10111# => INSN_lhax,
|
||||
2#0_11000_10110# => INSN_lhbrx,
|
||||
2#0_11001_10101# => INSN_lhzcix,
|
||||
2#0_01001_10111# => INSN_lhzux,
|
||||
2#0_01000_10111# => INSN_lhzx,
|
||||
2#0_00000_10100# => INSN_lwarx,
|
||||
2#0_01011_10101# => INSN_lwaux,
|
||||
2#0_01010_10101# => INSN_lwax,
|
||||
2#0_10000_10110# => INSN_lwbrx,
|
||||
2#0_11000_10101# => INSN_lwzcix,
|
||||
2#0_00001_10111# => INSN_lwzux,
|
||||
2#0_00000_10111# => INSN_lwzx,
|
||||
2#0_10010_00000# => INSN_mcrxrx,
|
||||
2#0_00000_10011# => INSN_mfcr,
|
||||
2#0_00010_10011# => INSN_mfmsr,
|
||||
2#0_01010_10011# => INSN_mfspr,
|
||||
2#0_01000_01001# => INSN_modud,
|
||||
2#0_01000_01011# => INSN_moduw,
|
||||
2#0_11000_01001# => INSN_modsd,
|
||||
2#0_11000_01011# => INSN_modsw,
|
||||
2#0_00100_10000# => INSN_mtcrf,
|
||||
2#0_00100_10010# => INSN_mtmsr,
|
||||
2#0_00101_10010# => INSN_mtmsrd,
|
||||
2#0_01110_10011# => INSN_mtspr,
|
||||
2#0_00010_01001# => INSN_mulhd,
|
||||
2#0_00000_01001# => INSN_mulhdu,
|
||||
2#0_00010_01011# => INSN_mulhw,
|
||||
2#0_00000_01011# => INSN_mulhwu,
|
||||
-- next 4 have reserved bit set
|
||||
2#0_10010_01001# => INSN_mulhd,
|
||||
2#0_10000_01001# => INSN_mulhdu,
|
||||
2#0_10010_01011# => INSN_mulhw,
|
||||
2#0_10000_01011# => INSN_mulhwu,
|
||||
2#0_00111_01001# => INSN_mulld,
|
||||
2#0_10111_01001# => INSN_mulld, -- mulldo
|
||||
2#0_00111_01011# => INSN_mullw,
|
||||
2#0_10111_01011# => INSN_mullw, -- mullwo
|
||||
2#0_01110_11100# => INSN_nand,
|
||||
2#0_00011_01000# => INSN_neg,
|
||||
2#0_10011_01000# => INSN_neg, -- nego
|
||||
-- next 8 are reserved no-op instructions
|
||||
2#0_10000_10010# => INSN_nop,
|
||||
2#0_10001_10010# => INSN_nop,
|
||||
2#0_10010_10010# => INSN_nop,
|
||||
2#0_10011_10010# => INSN_nop,
|
||||
2#0_10100_10010# => INSN_nop,
|
||||
2#0_10101_10010# => INSN_nop,
|
||||
2#0_10110_10010# => INSN_nop,
|
||||
2#0_10111_10010# => INSN_nop,
|
||||
2#0_00011_11100# => INSN_nor,
|
||||
2#0_01101_11100# => INSN_or,
|
||||
2#0_01100_11100# => INSN_orc,
|
||||
2#0_00011_11010# => INSN_popcntb,
|
||||
2#0_01111_11010# => INSN_popcntd,
|
||||
2#0_01011_11010# => INSN_popcntw,
|
||||
2#0_00101_11010# => INSN_prtyd,
|
||||
2#0_00100_11010# => INSN_prtyw,
|
||||
2#0_00100_00000# => INSN_setb,
|
||||
2#0_01111_10010# => INSN_slbia,
|
||||
2#0_00000_11011# => INSN_sld,
|
||||
2#0_00000_11000# => INSN_slw,
|
||||
2#0_11000_11010# => INSN_srad,
|
||||
2#0_11001_11010# => INSN_sradi,
|
||||
2#0_11001_11011# => INSN_sradi,
|
||||
2#0_11000_11000# => INSN_sraw,
|
||||
2#0_11001_11000# => INSN_srawi,
|
||||
2#0_10000_11011# => INSN_srd,
|
||||
2#0_10000_11000# => INSN_srw,
|
||||
2#0_11110_10101# => INSN_stbcix,
|
||||
2#0_10101_10110# => INSN_stbcx,
|
||||
2#0_00111_10111# => INSN_stbux,
|
||||
2#0_00110_10111# => INSN_stbx,
|
||||
2#0_10100_10100# => INSN_stdbrx,
|
||||
2#0_11111_10101# => INSN_stdcix,
|
||||
2#0_00110_10110# => INSN_stdcx,
|
||||
2#0_00101_10101# => INSN_stdux,
|
||||
2#0_00100_10101# => INSN_stdx,
|
||||
2#0_10110_10111# => INSN_stfdx,
|
||||
2#0_10111_10111# => INSN_stfdux,
|
||||
2#0_11110_10111# => INSN_stfiwx,
|
||||
2#0_10100_10111# => INSN_stfsx,
|
||||
2#0_10101_10111# => INSN_stfsux,
|
||||
2#0_11100_10110# => INSN_sthbrx,
|
||||
2#0_11101_10101# => INSN_sthcix,
|
||||
2#0_10110_10110# => INSN_sthcx,
|
||||
2#0_01101_10111# => INSN_sthux,
|
||||
2#0_01100_10111# => INSN_sthx,
|
||||
2#0_10100_10110# => INSN_stwbrx,
|
||||
2#0_11100_10101# => INSN_stwcix,
|
||||
2#0_00100_10110# => INSN_stwcx,
|
||||
2#0_00101_10111# => INSN_stwux,
|
||||
2#0_00100_10111# => INSN_stwx,
|
||||
2#0_00001_01000# => INSN_subf,
|
||||
2#0_10001_01000# => INSN_subf, -- subfo
|
||||
2#0_00000_01000# => INSN_subfc,
|
||||
2#0_10000_01000# => INSN_subfc, -- subfco
|
||||
2#0_00100_01000# => INSN_subfe,
|
||||
2#0_10100_01000# => INSN_subfe, -- subfeo
|
||||
2#0_00111_01000# => INSN_subfme,
|
||||
2#0_10111_01000# => INSN_subfme, -- subfmeo
|
||||
2#0_00110_01000# => INSN_subfze,
|
||||
2#0_10110_01000# => INSN_subfze, -- subfzeo
|
||||
2#0_10010_10110# => INSN_sync,
|
||||
2#0_00010_00100# => INSN_td,
|
||||
2#0_00000_00100# => INSN_tw,
|
||||
2#0_01001_10010# => INSN_tlbie,
|
||||
2#0_01000_10010# => INSN_tlbiel,
|
||||
2#0_10001_10110# => INSN_tlbsync,
|
||||
2#0_00000_11110# => INSN_wait,
|
||||
2#0_01001_11100# => INSN_xor,
|
||||
|
||||
-- Major opcode 19
|
||||
-- Columns with insn(4) = '1' are all illegal and not mapped here; to
|
||||
-- fit into 2048 entries, the columns are remapped so that 16-24 are
|
||||
-- stored here as 8-15; in other words the address bits are
|
||||
-- 1, insn(10..6), 1, insn(5), insn(3..1)
|
||||
-- Columns 16-17 here are opcode 19 columns 0-1
|
||||
-- Columns 24-31 here are opcode 19 columns 16-23
|
||||
2#1_10000_11000# => INSN_bcctr,
|
||||
2#1_00000_11000# => INSN_bclr,
|
||||
2#1_10001_11000# => INSN_bctar,
|
||||
2#1_01000_10001# => INSN_crand,
|
||||
2#1_00100_10001# => INSN_crandc,
|
||||
2#1_01001_10001# => INSN_creqv,
|
||||
2#1_00111_10001# => INSN_crnand,
|
||||
2#1_00001_10001# => INSN_crnor,
|
||||
2#1_01110_10001# => INSN_cror,
|
||||
2#1_01101_10001# => INSN_crorc,
|
||||
2#1_00110_10001# => INSN_crxor,
|
||||
2#1_00100_11110# => INSN_isync,
|
||||
2#1_00000_10000# => INSN_mcrf,
|
||||
2#1_00000_11010# => INSN_rfid,
|
||||
|
||||
-- Major opcode 59
|
||||
-- Address bits are 1, insn(10..6), 1, 0, insn(3..1)
|
||||
-- Only column 14 is valid here; columns 16-31 are handled in the major table
|
||||
-- Column 14 is mapped to column 22.
|
||||
-- Columns 20-23 here are opcode 59 columns 12-15
|
||||
2#1_11010_10110# => INSN_fcfids,
|
||||
2#1_11110_10110# => INSN_fcfidus,
|
||||
|
||||
-- Major opcode 63
|
||||
-- Columns 0-15 are mapped here; columns 16-31 are in the major table.
|
||||
-- Address bits are 1, insn(10:6), 0, insn(4:1)
|
||||
-- Columns 0-15 here are opcode 63 columns 0-15
|
||||
2#1_00000_00000# => INSN_fcmpu,
|
||||
2#1_00001_00000# => INSN_fcmpo,
|
||||
2#1_00010_00000# => INSN_mcrfs,
|
||||
2#1_00100_00000# => INSN_ftdiv,
|
||||
2#1_00101_00000# => INSN_ftsqrt,
|
||||
2#1_00001_00110# => INSN_mtfsb,
|
||||
2#1_00010_00110# => INSN_mtfsb,
|
||||
2#1_00100_00110# => INSN_mtfsfi,
|
||||
2#1_11010_00110# => INSN_fmrgow,
|
||||
2#1_11110_00110# => INSN_fmrgew,
|
||||
2#1_10010_00111# => INSN_mffs,
|
||||
2#1_10110_00111# => INSN_mtfsf,
|
||||
2#1_00000_01000# => INSN_fcpsgn,
|
||||
2#1_00001_01000# => INSN_fneg,
|
||||
2#1_00010_01000# => INSN_fmr,
|
||||
2#1_00100_01000# => INSN_fnabs,
|
||||
2#1_01000_01000# => INSN_fabs,
|
||||
2#1_01100_01000# => INSN_frin,
|
||||
2#1_01101_01000# => INSN_friz,
|
||||
2#1_01110_01000# => INSN_frip,
|
||||
2#1_01111_01000# => INSN_frim,
|
||||
2#1_00000_01100# => INSN_frsp,
|
||||
2#1_00000_01110# => INSN_fctiw,
|
||||
2#1_00100_01110# => INSN_fctiwu,
|
||||
2#1_11001_01110# => INSN_fctid,
|
||||
2#1_11010_01110# => INSN_fcfid,
|
||||
2#1_11101_01110# => INSN_fctidu,
|
||||
2#1_11110_01110# => INSN_fcfidu,
|
||||
2#1_00000_01111# => INSN_fctiwz,
|
||||
2#1_00100_01111# => INSN_fctiwuz,
|
||||
2#1_11001_01111# => INSN_fctidz,
|
||||
2#1_11101_01111# => INSN_fctiduz,
|
||||
|
||||
others => INSN_illegal
|
||||
);
|
||||
|
||||
constant IOUT_LEN : natural := ICODE_LEN + IMAGE_LEN;
|
||||
|
||||
type predec_t is record
|
||||
image : std_ulogic_vector(31 downto 0);
|
||||
maj_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
row_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
end record;
|
||||
|
||||
subtype index_t is integer range 0 to WIDTH-1;
|
||||
type predec_array is array(index_t) of predec_t;
|
||||
|
||||
signal pred : predec_array;
|
||||
signal valid : std_ulogic;
|
||||
|
||||
begin
|
||||
predecode_0: process(clk)
|
||||
variable majaddr : std_ulogic_vector(10 downto 0);
|
||||
variable rowaddr : std_ulogic_vector(10 downto 0);
|
||||
variable iword : std_ulogic_vector(31 downto 0);
|
||||
variable majcode : insn_code;
|
||||
variable rowcode : insn_code;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
valid <= valid_in;
|
||||
for i in index_t loop
|
||||
iword := insns_in(i * 32 + 31 downto i * 32);
|
||||
pred(i).image <= iword;
|
||||
|
||||
if is_X(iword) then
|
||||
pred(i).maj_predecode <= (others => 'X');
|
||||
pred(i).row_predecode <= (others => 'X');
|
||||
else
|
||||
majaddr := iword(31 downto 26) & iword(4 downto 0);
|
||||
|
||||
-- row_predecode_rom is used for op 19, 31, 59, 63
|
||||
-- addr bit 10 is 0 for op 31, 1 for 19, 59, 63
|
||||
rowaddr(10) := iword(31) or not iword(29);
|
||||
rowaddr(9 downto 5) := iword(10 downto 6);
|
||||
if iword(28) = '0' then
|
||||
-- op 19 and op 59
|
||||
rowaddr(4 downto 3) := '1' & iword(5);
|
||||
else
|
||||
-- op 31 and 63; for 63 we only use this when iword(5) = '0'
|
||||
rowaddr(4 downto 3) := iword(5 downto 4);
|
||||
end if;
|
||||
rowaddr(2 downto 0) := iword(3 downto 1);
|
||||
|
||||
majcode := major_predecode_rom(to_integer(unsigned(majaddr)));
|
||||
pred(i).maj_predecode <= to_unsigned(insn_code'pos(majcode), ICODE_LEN);
|
||||
rowcode := row_predecode_rom(to_integer(unsigned(rowaddr)));
|
||||
pred(i).row_predecode <= to_unsigned(insn_code'pos(rowcode), ICODE_LEN);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
predecode_1: process(all)
|
||||
variable iword : std_ulogic_vector(31 downto 0);
|
||||
variable use_row : std_ulogic;
|
||||
variable illegal : std_ulogic;
|
||||
variable ici : std_ulogic_vector(IOUT_LEN - 1 downto 0);
|
||||
variable icode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
begin
|
||||
for i in index_t loop
|
||||
iword := pred(i).image;
|
||||
icode := pred(i).maj_predecode;
|
||||
use_row := '0';
|
||||
illegal := '0';
|
||||
|
||||
case iword(31 downto 26) is
|
||||
when "000100" => -- 4
|
||||
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
|
||||
illegal := not iword(5);
|
||||
|
||||
when "010011" => -- 19
|
||||
-- Columns 8-15 and 24-31 don't have any valid instructions
|
||||
-- (where insn(5..1) is the column number).
|
||||
-- addpcis (column 2) is in the major table
|
||||
-- Other valid columns are mapped to columns in the second
|
||||
-- half of the row table: columns 0-1 are mapped to 16-17
|
||||
-- and 16-23 are mapped to 24-31.
|
||||
illegal := iword(4);
|
||||
use_row := iword(5) or (not iword(3) and not iword(2));
|
||||
|
||||
when "011000" => -- 24
|
||||
-- ori, special-case the standard NOP
|
||||
if std_match(iword, "01100000000000000000000000000000") then
|
||||
icode := to_unsigned(insn_code'pos(INSN_nop), ICODE_LEN);
|
||||
end if;
|
||||
|
||||
when "011111" => -- 31
|
||||
-- major opcode 31, lots of things
|
||||
-- Use the first half of the row table for all columns
|
||||
use_row := '1';
|
||||
|
||||
when "111011" => -- 59
|
||||
-- floating point operations, mostly single-precision
|
||||
-- Columns 0-11 are illegal; columns 12-15 are mapped
|
||||
-- to columns 20-23 in the second half of the row table,
|
||||
-- and columns 16-31 are in the major table.
|
||||
illegal := not iword(5) and (not iword(4) or not iword(3));
|
||||
use_row := not iword(5);
|
||||
|
||||
when "111111" => -- 63
|
||||
-- floating point operations, general and double-precision
|
||||
-- Use columns 0-15 of the second half of the row table
|
||||
-- for columns 0-15, and the major table for columns 16-31.
|
||||
use_row := not iword(5);
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
if use_row = '1' then
|
||||
icode := pred(i).row_predecode;
|
||||
end if;
|
||||
|
||||
-- Mark FP instructions as illegal if we don't have an FPU
|
||||
if not HAS_FPU and not is_X(icode) and
|
||||
to_integer(icode) >= insn_code'pos(INSN_first_frs) then
|
||||
illegal := '1';
|
||||
end if;
|
||||
|
||||
ici(31 downto 0) := iword;
|
||||
ici(IOUT_LEN - 1 downto 32) := (others => '0');
|
||||
if valid = '0' or illegal = '1' or is_X(icode) or
|
||||
icode = to_unsigned(insn_code'pos(INSN_illegal), ICODE_LEN) then
|
||||
-- Since an insn_code currently fits in 9 bits, use just
|
||||
-- the most significant bit of ici to indicate illegal insns.
|
||||
ici(IOUT_LEN - 1) := '1';
|
||||
else
|
||||
ici(IOUT_LEN - 1 downto IMAGE_LEN) := std_ulogic_vector(icode);
|
||||
end if;
|
||||
icodes_out(i * IOUT_LEN + IOUT_LEN - 1 downto i * IOUT_LEN) <= ici;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
@ -0,0 +1,295 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
|
||||
-- Signed 33b x 33b multiplier giving 64-bit product, with no addend.
|
||||
|
||||
entity multiply_32s is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
stall : in std_ulogic;
|
||||
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply_32s;
|
||||
|
||||
architecture behaviour of multiply_32s is
|
||||
signal clocken : std_ulogic;
|
||||
signal data1 : std_ulogic_vector(52 downto 0);
|
||||
signal data2 : std_ulogic_vector(34 downto 0);
|
||||
signal m00_p, m01_p : std_ulogic_vector(47 downto 0);
|
||||
signal m00_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m10_p, m11_p : std_ulogic_vector(47 downto 0);
|
||||
signal m10_pc : std_ulogic_vector(47 downto 0);
|
||||
signal p0_pat, p0_patb : std_ulogic;
|
||||
signal p1_pat, p1_patb : std_ulogic;
|
||||
signal product_lo : std_ulogic_vector(22 downto 0);
|
||||
|
||||
begin
|
||||
-- sign extend if signed
|
||||
data1(31 downto 0) <= m_in.data1(31 downto 0);
|
||||
data1(52 downto 32) <= (others => m_in.is_signed and m_in.data1(31));
|
||||
data2(31 downto 0) <= m_in.data2(31 downto 0);
|
||||
data2(34 downto 32) <= (others => m_in.is_signed and m_in.data2(31));
|
||||
|
||||
clocken <= m_in.valid and not stall;
|
||||
|
||||
m00: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & data1(22 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
P => m00_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m00_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m01: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & data1(22 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => data2(34 downto 17),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "1010101",
|
||||
P => m01_p,
|
||||
PCIN => m00_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m10: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 1,
|
||||
INMODEREG => 0,
|
||||
MASK => x"fffffffe00ff",
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => data1(52 downto 23),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => std_ulogic_vector(resize(signed(m01_p(38 downto 6)), 48)),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => clocken,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => clocken,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
P => m10_p,
|
||||
PATTERNDETECT => p0_pat,
|
||||
PATTERNBDETECT => p0_patb,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m11: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MASK => x"fffffc000000",
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => data1(52 downto 23),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => data2(34 downto 17),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => clocken,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "1010101",
|
||||
P => m11_p,
|
||||
PATTERNDETECT => p1_pat,
|
||||
PATTERNBDETECT => p1_patb,
|
||||
PCIN => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m_out.result(127 downto 64) <= (others => '0');
|
||||
m_out.result(63 downto 40) <= m11_p(23 downto 0);
|
||||
m_out.result(39 downto 23) <= m10_p(16 downto 0);
|
||||
m_out.result(22 downto 0) <= product_lo;
|
||||
|
||||
m_out.overflow <= not ((p0_pat and p1_pat) or (p0_patb and p1_patb));
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) and stall = '0' then
|
||||
m_out.valid <= m_in.valid;
|
||||
product_lo <= m01_p(5 downto 0) & m00_p(16 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
Loading…
Reference in New Issue