1
0
mirror of https://github.com/j-core/j-core-ice40.git synced 2026-01-11 23:52:49 +00:00

Separate out predecoder. (Mostly Jeff's work.)

This commit is contained in:
Rob Landley 2019-11-15 02:21:29 -06:00
parent c4ac0a6e0e
commit 11c1ba7c5a
4 changed files with 77 additions and 67 deletions

View File

@ -3,6 +3,7 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.decode_pack.all;
use work.cpu2j0_pack.all;
use work.predecode_pack.all;
entity decode_core is
generic (

View File

@ -277,7 +277,6 @@ package decode_pack is
wb_stall : out pipeline_wb_stall_t
);
end component;
function predecode_rom_addr (code : std_logic_vector(15 downto 0)) return std_logic_vector;
function check_illegal_delay_slot (code : std_logic_vector(15 downto 0)) return std_logic;
function check_illegal_instruction (code : std_logic_vector(15 downto 0)) return std_logic;
type decode_core_reg_t is
@ -302,3 +301,73 @@ package decode_pack is
type system_event_instr_array is array (cpu_event_cmd_t range <>) of system_instr_t;
constant system_event_instrs : system_event_instr_array := (INT => INTERRUPT_I, ERR => ERROR_I, BREAK => BREAK_I, RST => RESET_CPU_I);
end;
package body decode_pack is
function isa_fmt (code : std_logic_vector(15 downto 0)) return isa_type_t is
variable ret : isa_type_t := ( (others => '0'), (others => '0'), (others => '0'),
NX, LONG,
(others => '0'), (others => '0'), (others => '0'));
begin
ret.ln := code(15 downto 12);
if (ret.ln = "0000" and code(2) = '1') or (ret.ln(3) = '0' and ret.ln(1) = '1') then
ret.fmt := NMX;
elsif ret.ln = "0100" and code(3 downto 2) = "11" and code (1 downto 0) /= "10" then
ret.fmt := NM;
elsif ret.ln = "0001" or ret.ln = "0101" then
ret.fmt := NM4;
elsif ret.ln = "0111" or ret.ln = "1001" or ret.ln = "1101" or ret.ln = "1110" then
ret.fmt := N8;
elsif ret.ln(3 downto 1) = "101" then
ret.fmt := I12;
elsif ret.ln = "1000" and code(11) = '0' then
ret.fmt := NX4;
elsif (ret.ln = "1000" and code(11) = '1') or ret.ln = "1100" then
ret.fmt := X8;
elsif (ret.ln = "0000" and code (3 downto 0) = "0011") or (ret.ln = "0100" and code(1) = '1') then
ret.fmt := MX;
end if;
ret.rn := code(11 downto 8);
ret.rm := code(7 downto 4);
if code(15 downto 10) = "100000" then ret.rm := code(11 downto 8); end if;
if ret.fmt = MX then ret.rn := code( 7 downto 4); end if;
if ret.fmt = I12 then ret.imm := code(11 downto 0);
elsif ret.fmt = N8 or ret.fmt = X8 then ret.imm := x"0" & code( 7 downto 0);
elsif ret.fmt = NM4 or ret.fmt = NX4 then ret.imm := x"00" & code( 3 downto 0); end if;
if ret.fmt = NX or ret.fmt = MX then ret.col := code( 5 downto 4);
elsif ret.fmt = NMX then ret.col := code( 1 downto 0);
elsif ret.fmt = NX4 or ret.fmt = X8 then ret.col := code( 9 downto 8); end if;
if ret.fmt = NX or ret.fmt = MX then ret.op := code( 3 downto 0);
elsif ret.fmt = NMX then ret.op := "00" & code( 3 downto 2);
elsif ret.fmt = NX4 or ret.fmt = X8 then ret.op := "00" & code(11 downto 10); end if;
if ret.col = "00" then ret.sz := BYTE;
elsif ret.col = "01" then ret.sz := WORD; end if;
return ret;
end function;
function check_illegal_delay_slot (code : std_logic_vector(15 downto 0)) return std_logic is
begin
-- Check for instructions that assign to PC:
-- RTE, RTS, JMP @Rm, JSR @Rm, BRAF Rm, BSRF Rm, BF label, BF /S label, BT label, BT /S label, BRA label, BSR label, TRAPA #imm
if ((code(15 downto 12) = "0000" and code(3 downto 2) = "00" and code(0) = '1') or (code(15 downto 14) = "10" and code(12 downto 11) = "01" and code(8) = '1') or code(15 downto 13) = "101" or (code(15) = '1' and code(13 downto 8) = "000011") or (code(15) = '0' and code(13 downto 12) = "00" and code(4 downto 0) = "01011")) then
return '1';
else
return '0';
end if;
end;
function check_illegal_instruction (code : std_logic_vector(15 downto 0)) return std_logic is
begin
-- TODO: Improve detection of illegal instructions
if code(15 downto 8) = x"ff" then
return '1';
else
return '0';
end if;
end;
end decode_pack;

View File

@ -9,8 +9,8 @@ rm -f *.o *.cf *.ghw
echo Analyze...
# General CPU plumbing, not architecture specific
ghdl -a cpu2j0_pkg.vhd components_pkg.vhd mult_pkg.vhd decode_pkg.vhd datapath_pkg.vhd
ghdl -a decode_body.vhd cpu.vhd decode.vhd decode_core.vhd decode_table.vhd datapath.vhd register_file_sync.vhd mult.vhd
ghdl -a cpu2j0_pkg.vhd components_pkg.vhd mult_pkg.vhd decode_pkg.vhd predecode_pkg.vhd datapath_pkg.vhd
ghdl -a cpu.vhd decode.vhd decode_core.vhd decode_table.vhd datapath.vhd register_file_sync.vhd mult.vhd
# Using the "staircase" version of the instruction decoder. The 2 other
# versions started life as generated code from the same microcode spreadsheet,

View File

@ -13,55 +13,14 @@ use ieee.numeric_std.all;
use work.decode_pack.all;
use work.cpu2j0_components_pack.all;
use work.mult_pkg.all;
package body decode_pack is
function isa_fmt (code : std_logic_vector(15 downto 0)) return isa_type_t is
variable ret : isa_type_t := ( (others => '0'), (others => '0'), (others => '0'),
NX, LONG,
(others => '0'), (others => '0'), (others => '0'));
begin
ret.ln := code(15 downto 12);
if (ret.ln = "0000" and code(2) = '1') or (ret.ln(3) = '0' and ret.ln(1) = '1') then
ret.fmt := NMX;
elsif ret.ln = "0100" and code(3 downto 2) = "11" and code (1 downto 0) /= "10" then
ret.fmt := NM;
elsif ret.ln = "0001" or ret.ln = "0101" then
ret.fmt := NM4;
elsif ret.ln = "0111" or ret.ln = "1001" or ret.ln = "1101" or ret.ln = "1110" then
ret.fmt := N8;
elsif ret.ln(3 downto 1) = "101" then
ret.fmt := I12;
elsif ret.ln = "1000" and code(11) = '0' then
ret.fmt := NX4;
elsif (ret.ln = "1000" and code(11) = '1') or ret.ln = "1100" then
ret.fmt := X8;
elsif (ret.ln = "0000" and code (3 downto 0) = "0011") or (ret.ln = "0100" and code(1) = '1') then
ret.fmt := MX;
end if;
package predecode_pack is
ret.rn := code(11 downto 8);
ret.rm := code(7 downto 4);
if code(15 downto 10) = "100000" then ret.rm := code(11 downto 8); end if;
if ret.fmt = MX then ret.rn := code( 7 downto 4); end if;
function predecode_rom_addr (code : std_logic_vector(15 downto 0)) return std_logic_vector;
if ret.fmt = I12 then ret.imm := code(11 downto 0);
elsif ret.fmt = N8 or ret.fmt = X8 then ret.imm := x"0" & code( 7 downto 0);
elsif ret.fmt = NM4 or ret.fmt = NX4 then ret.imm := x"00" & code( 3 downto 0); end if;
end package;
if ret.fmt = NX or ret.fmt = MX then ret.col := code( 5 downto 4);
elsif ret.fmt = NMX then ret.col := code( 1 downto 0);
elsif ret.fmt = NX4 or ret.fmt = X8 then ret.col := code( 9 downto 8); end if;
if ret.fmt = NX or ret.fmt = MX then ret.op := code( 3 downto 0);
elsif ret.fmt = NMX then ret.op := "00" & code( 3 downto 2);
elsif ret.fmt = NX4 or ret.fmt = X8 then ret.op := "00" & code(11 downto 10); end if;
if ret.col = "00" then ret.sz := BYTE;
elsif ret.col = "01" then ret.sz := WORD; end if;
return ret;
end function;
package body predecode_pack is
function predecode_rom_addr (code : std_logic_vector(15 downto 0)) return std_logic_vector is
variable addr : std_logic_vector(7 downto 0);
@ -313,23 +272,4 @@ package body decode_pack is
end case;
return addr;
end;
function check_illegal_delay_slot (code : std_logic_vector(15 downto 0)) return std_logic is
begin
-- Check for instructions that assign to PC:
-- RTE, RTS, JMP @Rm, JSR @Rm, BRAF Rm, BSRF Rm, BF label, BF /S label, BT label, BT /S label, BRA label, BSR label, TRAPA #imm
if ((code(15 downto 12) = "0000" and code(3 downto 2) = "00" and code(0) = '1') or (code(15 downto 14) = "10" and code(12 downto 11) = "01" and code(8) = '1') or code(15 downto 13) = "101" or (code(15) = '1' and code(13 downto 8) = "000011") or (code(15) = '0' and code(13 downto 12) = "00" and code(4 downto 0) = "01011")) then
return '1';
else
return '0';
end if;
end;
function check_illegal_instruction (code : std_logic_vector(15 downto 0)) return std_logic is
begin
-- TODO: Improve detection of illegal instructions
if code(15 downto 8) = x"ff" then
return '1';
else
return '0';
end if;
end;
end;