mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-23 10:48:09 +00:00
commit
900c131083
368
common.vhdl
368
common.vhdl
@ -5,212 +5,212 @@ library work;
|
||||
use work.decode_types.all;
|
||||
|
||||
package common is
|
||||
type ctrl_t is record
|
||||
lr: std_ulogic_vector(63 downto 0);
|
||||
ctr: std_ulogic_vector(63 downto 0);
|
||||
tb: std_ulogic_vector(63 downto 0);
|
||||
carry: std_ulogic;
|
||||
end record;
|
||||
type ctrl_t is record
|
||||
lr: std_ulogic_vector(63 downto 0);
|
||||
ctr: std_ulogic_vector(63 downto 0);
|
||||
tb: std_ulogic_vector(63 downto 0);
|
||||
carry: std_ulogic;
|
||||
end record;
|
||||
|
||||
type Fetch1ToIcacheType is record
|
||||
req: std_ulogic;
|
||||
stop_mark: std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
type Fetch1ToIcacheType is record
|
||||
req: std_ulogic;
|
||||
stop_mark: std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
|
||||
type IcacheToFetch2Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark: std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
type IcacheToFetch2Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark: std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
|
||||
type Fetch2ToDecode1Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark : std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
constant Fetch2ToDecode1Init : Fetch2ToDecode1Type := (valid => '0', stop_mark => '0', others => (others => '0'));
|
||||
type Fetch2ToDecode1Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark : std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
constant Fetch2ToDecode1Init : Fetch2ToDecode1Type := (valid => '0', stop_mark => '0', others => (others => '0'));
|
||||
|
||||
type Decode1ToDecode2Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark : std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
decode: decode_rom_t;
|
||||
end record;
|
||||
constant Decode1ToDecode2Init : Decode1ToDecode2Type := (valid => '0', stop_mark => '0', decode => decode_rom_init, others => (others => '0'));
|
||||
type Decode1ToDecode2Type is record
|
||||
valid: std_ulogic;
|
||||
stop_mark : std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
decode: decode_rom_t;
|
||||
end record;
|
||||
constant Decode1ToDecode2Init : Decode1ToDecode2Type := (valid => '0', stop_mark => '0', decode => decode_rom_init, others => (others => '0'));
|
||||
|
||||
type Decode2ToExecute1Type is record
|
||||
valid: std_ulogic;
|
||||
insn_type: insn_type_t;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
read_reg1: std_ulogic_vector(4 downto 0);
|
||||
read_reg2: std_ulogic_vector(4 downto 0);
|
||||
read_data1: std_ulogic_vector(63 downto 0);
|
||||
read_data2: std_ulogic_vector(63 downto 0);
|
||||
read_data3: std_ulogic_vector(63 downto 0);
|
||||
cr: std_ulogic_vector(31 downto 0);
|
||||
lr: std_ulogic;
|
||||
rc: std_ulogic;
|
||||
invert_a: std_ulogic;
|
||||
invert_out: std_ulogic;
|
||||
input_carry: carry_in_t;
|
||||
output_carry: std_ulogic;
|
||||
input_cr: std_ulogic;
|
||||
output_cr: std_ulogic;
|
||||
is_32bit: std_ulogic;
|
||||
is_signed: std_ulogic;
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
data_len: std_ulogic_vector(3 downto 0);
|
||||
end record;
|
||||
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
||||
(valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0',
|
||||
invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
|
||||
is_32bit => '0', is_signed => '0', others => (others => '0'));
|
||||
type Decode2ToExecute1Type is record
|
||||
valid: std_ulogic;
|
||||
insn_type: insn_type_t;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
read_reg1: std_ulogic_vector(4 downto 0);
|
||||
read_reg2: std_ulogic_vector(4 downto 0);
|
||||
read_data1: std_ulogic_vector(63 downto 0);
|
||||
read_data2: std_ulogic_vector(63 downto 0);
|
||||
read_data3: std_ulogic_vector(63 downto 0);
|
||||
cr: std_ulogic_vector(31 downto 0);
|
||||
lr: std_ulogic;
|
||||
rc: std_ulogic;
|
||||
invert_a: std_ulogic;
|
||||
invert_out: std_ulogic;
|
||||
input_carry: carry_in_t;
|
||||
output_carry: std_ulogic;
|
||||
input_cr: std_ulogic;
|
||||
output_cr: std_ulogic;
|
||||
is_32bit: std_ulogic;
|
||||
is_signed: std_ulogic;
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
data_len: std_ulogic_vector(3 downto 0);
|
||||
end record;
|
||||
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
||||
(valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0',
|
||||
invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
|
||||
is_32bit => '0', is_signed => '0', others => (others => '0'));
|
||||
|
||||
type Decode2ToMultiplyType is record
|
||||
valid: std_ulogic;
|
||||
insn_type: insn_type_t;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
data1: std_ulogic_vector(64 downto 0);
|
||||
data2: std_ulogic_vector(64 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant Decode2ToMultiplyInit : Decode2ToMultiplyType := (valid => '0', insn_type => OP_ILLEGAL, rc => '0', others => (others => '0'));
|
||||
type Decode2ToMultiplyType is record
|
||||
valid: std_ulogic;
|
||||
insn_type: insn_type_t;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
data1: std_ulogic_vector(64 downto 0);
|
||||
data2: std_ulogic_vector(64 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant Decode2ToMultiplyInit : Decode2ToMultiplyType := (valid => '0', insn_type => OP_ILLEGAL, rc => '0', others => (others => '0'));
|
||||
|
||||
type Decode2ToDividerType is record
|
||||
valid: std_ulogic;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
dividend: std_ulogic_vector(63 downto 0);
|
||||
divisor: std_ulogic_vector(63 downto 0);
|
||||
is_signed: std_ulogic;
|
||||
is_32bit: std_ulogic;
|
||||
is_extended: std_ulogic;
|
||||
is_modulus: std_ulogic;
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant Decode2ToDividerInit: Decode2ToDividerType := (valid => '0', is_signed => '0', is_32bit => '0', is_extended => '0', is_modulus => '0', rc => '0', others => (others => '0'));
|
||||
type Decode2ToDividerType is record
|
||||
valid: std_ulogic;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
dividend: std_ulogic_vector(63 downto 0);
|
||||
divisor: std_ulogic_vector(63 downto 0);
|
||||
is_signed: std_ulogic;
|
||||
is_32bit: std_ulogic;
|
||||
is_extended: std_ulogic;
|
||||
is_modulus: std_ulogic;
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant Decode2ToDividerInit: Decode2ToDividerType := (valid => '0', is_signed => '0', is_32bit => '0', is_extended => '0', is_modulus => '0', rc => '0', others => (others => '0'));
|
||||
|
||||
type Decode2ToRegisterFileType is record
|
||||
read1_enable : std_ulogic;
|
||||
read1_reg : std_ulogic_vector(4 downto 0);
|
||||
read2_enable : std_ulogic;
|
||||
read2_reg : std_ulogic_vector(4 downto 0);
|
||||
read3_enable : std_ulogic;
|
||||
read3_reg : std_ulogic_vector(4 downto 0);
|
||||
end record;
|
||||
type Decode2ToRegisterFileType is record
|
||||
read1_enable : std_ulogic;
|
||||
read1_reg : std_ulogic_vector(4 downto 0);
|
||||
read2_enable : std_ulogic;
|
||||
read2_reg : std_ulogic_vector(4 downto 0);
|
||||
read3_enable : std_ulogic;
|
||||
read3_reg : std_ulogic_vector(4 downto 0);
|
||||
end record;
|
||||
|
||||
type RegisterFileToDecode2Type is record
|
||||
read1_data : std_ulogic_vector(63 downto 0);
|
||||
read2_data : std_ulogic_vector(63 downto 0);
|
||||
read3_data : std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
type RegisterFileToDecode2Type is record
|
||||
read1_data : std_ulogic_vector(63 downto 0);
|
||||
read2_data : std_ulogic_vector(63 downto 0);
|
||||
read3_data : std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
|
||||
type Decode2ToCrFileType is record
|
||||
read : std_ulogic;
|
||||
end record;
|
||||
type Decode2ToCrFileType is record
|
||||
read : std_ulogic;
|
||||
end record;
|
||||
|
||||
type CrFileToDecode2Type is record
|
||||
read_cr_data : std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
type CrFileToDecode2Type is record
|
||||
read_cr_data : std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
|
||||
type Execute1ToFetch1Type is record
|
||||
redirect: std_ulogic;
|
||||
redirect_nia: std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
constant Execute1ToFetch1TypeInit : Execute1ToFetch1Type := (redirect => '0', others => (others => '0'));
|
||||
type Execute1ToFetch1Type is record
|
||||
redirect: std_ulogic;
|
||||
redirect_nia: std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
constant Execute1ToFetch1TypeInit : Execute1ToFetch1Type := (redirect => '0', others => (others => '0'));
|
||||
|
||||
type Decode2ToLoadstore1Type is record
|
||||
valid : std_ulogic;
|
||||
load : std_ulogic; -- is this a load or store
|
||||
addr1 : std_ulogic_vector(63 downto 0);
|
||||
addr2 : std_ulogic_vector(63 downto 0);
|
||||
data : std_ulogic_vector(63 downto 0); -- data to write, unused for read
|
||||
write_reg : std_ulogic_vector(4 downto 0); -- read data goes to this register
|
||||
length : std_ulogic_vector(3 downto 0);
|
||||
byte_reverse : std_ulogic;
|
||||
sign_extend : std_ulogic; -- do we need to sign extend?
|
||||
update : std_ulogic; -- is this an update instruction?
|
||||
update_reg : std_ulogic_vector(4 downto 0); -- if so, the register to update
|
||||
end record;
|
||||
constant Decode2ToLoadstore1Init : Decode2ToLoadstore1Type := (valid => '0', load => '0', byte_reverse => '0', sign_extend => '0', update => '0', others => (others => '0'));
|
||||
type Decode2ToLoadstore1Type is record
|
||||
valid : std_ulogic;
|
||||
load : std_ulogic; -- is this a load or store
|
||||
addr1 : std_ulogic_vector(63 downto 0);
|
||||
addr2 : std_ulogic_vector(63 downto 0);
|
||||
data : std_ulogic_vector(63 downto 0); -- data to write, unused for read
|
||||
write_reg : std_ulogic_vector(4 downto 0); -- read data goes to this register
|
||||
length : std_ulogic_vector(3 downto 0);
|
||||
byte_reverse : std_ulogic;
|
||||
sign_extend : std_ulogic; -- do we need to sign extend?
|
||||
update : std_ulogic; -- is this an update instruction?
|
||||
update_reg : std_ulogic_vector(4 downto 0); -- if so, the register to update
|
||||
end record;
|
||||
constant Decode2ToLoadstore1Init : Decode2ToLoadstore1Type := (valid => '0', load => '0', byte_reverse => '0', sign_extend => '0', update => '0', others => (others => '0'));
|
||||
|
||||
type Loadstore1ToLoadstore2Type is record
|
||||
valid : std_ulogic;
|
||||
load : std_ulogic;
|
||||
addr : std_ulogic_vector(63 downto 0);
|
||||
data : std_ulogic_vector(63 downto 0);
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
length : std_ulogic_vector(3 downto 0);
|
||||
byte_reverse : std_ulogic;
|
||||
sign_extend : std_ulogic;
|
||||
update : std_ulogic;
|
||||
update_reg : std_ulogic_vector(4 downto 0);
|
||||
end record;
|
||||
type Loadstore1ToLoadstore2Type is record
|
||||
valid : std_ulogic;
|
||||
load : std_ulogic;
|
||||
addr : std_ulogic_vector(63 downto 0);
|
||||
data : std_ulogic_vector(63 downto 0);
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
length : std_ulogic_vector(3 downto 0);
|
||||
byte_reverse : std_ulogic;
|
||||
sign_extend : std_ulogic;
|
||||
update : std_ulogic;
|
||||
update_reg : std_ulogic_vector(4 downto 0);
|
||||
end record;
|
||||
|
||||
type Loadstore2ToWritebackType is record
|
||||
valid : std_ulogic;
|
||||
write_enable: std_ulogic;
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
write_data : std_ulogic_vector(63 downto 0);
|
||||
write_len : std_ulogic_vector(3 downto 0);
|
||||
write_shift : std_ulogic_vector(2 downto 0);
|
||||
sign_extend : std_ulogic;
|
||||
byte_reverse : std_ulogic;
|
||||
second_word : std_ulogic;
|
||||
end record;
|
||||
constant Loadstore2ToWritebackInit : Loadstore2ToWritebackType := (valid => '0', write_enable => '0', sign_extend => '0', byte_reverse => '0', second_word => '0', others => (others => '0'));
|
||||
type Loadstore2ToWritebackType is record
|
||||
valid : std_ulogic;
|
||||
write_enable: std_ulogic;
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
write_data : std_ulogic_vector(63 downto 0);
|
||||
write_len : std_ulogic_vector(3 downto 0);
|
||||
write_shift : std_ulogic_vector(2 downto 0);
|
||||
sign_extend : std_ulogic;
|
||||
byte_reverse : std_ulogic;
|
||||
second_word : std_ulogic;
|
||||
end record;
|
||||
constant Loadstore2ToWritebackInit : Loadstore2ToWritebackType := (valid => '0', write_enable => '0', sign_extend => '0', byte_reverse => '0', second_word => '0', others => (others => '0'));
|
||||
|
||||
type Execute1ToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
rc : std_ulogic;
|
||||
write_enable : std_ulogic;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
write_data: std_ulogic_vector(63 downto 0);
|
||||
write_len : std_ulogic_vector(3 downto 0);
|
||||
write_cr_enable : std_ulogic;
|
||||
write_cr_mask : std_ulogic_vector(7 downto 0);
|
||||
write_cr_data : std_ulogic_vector(31 downto 0);
|
||||
sign_extend: std_ulogic;
|
||||
end record;
|
||||
constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', write_enable => '0', write_cr_enable => '0', sign_extend => '0', others => (others => '0'));
|
||||
type Execute1ToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
rc : std_ulogic;
|
||||
write_enable : std_ulogic;
|
||||
write_reg: std_ulogic_vector(4 downto 0);
|
||||
write_data: std_ulogic_vector(63 downto 0);
|
||||
write_len : std_ulogic_vector(3 downto 0);
|
||||
write_cr_enable : std_ulogic;
|
||||
write_cr_mask : std_ulogic_vector(7 downto 0);
|
||||
write_cr_data : std_ulogic_vector(31 downto 0);
|
||||
sign_extend: std_ulogic;
|
||||
end record;
|
||||
constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', write_enable => '0', write_cr_enable => '0', sign_extend => '0', others => (others => '0'));
|
||||
|
||||
type MultiplyToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
type MultiplyToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
|
||||
write_reg_enable : std_ulogic;
|
||||
write_reg_nr: std_ulogic_vector(4 downto 0);
|
||||
write_reg_data: std_ulogic_vector(63 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant MultiplyToWritebackInit : MultiplyToWritebackType := (valid => '0', write_reg_enable => '0', rc => '0', others => (others => '0'));
|
||||
write_reg_enable : std_ulogic;
|
||||
write_reg_nr: std_ulogic_vector(4 downto 0);
|
||||
write_reg_data: std_ulogic_vector(63 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant MultiplyToWritebackInit : MultiplyToWritebackType := (valid => '0', write_reg_enable => '0', rc => '0', others => (others => '0'));
|
||||
|
||||
type DividerToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
type DividerToWritebackType is record
|
||||
valid: std_ulogic;
|
||||
|
||||
write_reg_enable : std_ulogic;
|
||||
write_reg_nr: std_ulogic_vector(4 downto 0);
|
||||
write_reg_data: std_ulogic_vector(63 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant DividerToWritebackInit : DividerToWritebackType := (valid => '0', write_reg_enable => '0', rc => '0', others => (others => '0'));
|
||||
write_reg_enable : std_ulogic;
|
||||
write_reg_nr: std_ulogic_vector(4 downto 0);
|
||||
write_reg_data: std_ulogic_vector(63 downto 0);
|
||||
rc: std_ulogic;
|
||||
end record;
|
||||
constant DividerToWritebackInit : DividerToWritebackType := (valid => '0', write_reg_enable => '0', rc => '0', others => (others => '0'));
|
||||
|
||||
type WritebackToRegisterFileType is record
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
write_data : std_ulogic_vector(63 downto 0);
|
||||
write_enable : std_ulogic;
|
||||
end record;
|
||||
constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', others => (others => '0'));
|
||||
type WritebackToRegisterFileType is record
|
||||
write_reg : std_ulogic_vector(4 downto 0);
|
||||
write_data : std_ulogic_vector(63 downto 0);
|
||||
write_enable : std_ulogic;
|
||||
end record;
|
||||
constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', others => (others => '0'));
|
||||
|
||||
type WritebackToCrFileType is record
|
||||
write_cr_enable : std_ulogic;
|
||||
write_cr_mask : std_ulogic_vector(7 downto 0);
|
||||
write_cr_data : std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
constant WritebackToCrFileInit : WritebackToCrFileType := (write_cr_enable => '0', others => (others => '0'));
|
||||
type WritebackToCrFileType is record
|
||||
write_cr_enable : std_ulogic;
|
||||
write_cr_mask : std_ulogic_vector(7 downto 0);
|
||||
write_cr_data : std_ulogic_vector(31 downto 0);
|
||||
end record;
|
||||
constant WritebackToCrFileInit : WritebackToCrFileType := (write_cr_enable => '0', others => (others => '0'));
|
||||
end common;
|
||||
|
||||
package body common is
|
||||
|
||||
@ -5,13 +5,16 @@ library work;
|
||||
use work.common.all;
|
||||
|
||||
package crhelpers is
|
||||
function fxm_to_num(fxm: std_ulogic_vector(7 downto 0)) return integer;
|
||||
function num_to_fxm(num: integer) return std_ulogic_vector;
|
||||
subtype crnum_t is integer range 0 to 7;
|
||||
subtype crmask_t is std_ulogic_vector(7 downto 0);
|
||||
|
||||
function fxm_to_num(fxm: crmask_t) return crnum_t;
|
||||
function num_to_fxm(num: crnum_t) return crmask_t;
|
||||
end package crhelpers;
|
||||
|
||||
package body crhelpers is
|
||||
|
||||
function fxm_to_num(fxm: std_ulogic_vector(7 downto 0)) return integer is
|
||||
function fxm_to_num(fxm: crmask_t) return crnum_t is
|
||||
begin
|
||||
-- If multiple fields are set (undefined), match existing
|
||||
-- hardware by returning the first one.
|
||||
@ -27,7 +30,7 @@ package body crhelpers is
|
||||
return 7;
|
||||
end;
|
||||
|
||||
function num_to_fxm(num: integer) return std_ulogic_vector is
|
||||
function num_to_fxm(num: crnum_t) return crmask_t is
|
||||
begin
|
||||
case num is
|
||||
when 0 =>
|
||||
|
||||
668
execute1.vhdl
668
execute1.vhdl
@ -11,361 +11,361 @@ use work.insn_helpers.all;
|
||||
use work.ppc_fx_insns.all;
|
||||
|
||||
entity execute1 is
|
||||
generic (
|
||||
SIM : boolean := false
|
||||
generic (
|
||||
SIM : boolean := false
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
port (
|
||||
clk : in std_logic;
|
||||
|
||||
-- asynchronous
|
||||
flush_out : out std_ulogic;
|
||||
-- asynchronous
|
||||
flush_out : out std_ulogic;
|
||||
|
||||
e_in : in Decode2ToExecute1Type;
|
||||
e_in : in Decode2ToExecute1Type;
|
||||
|
||||
-- asynchronous
|
||||
f_out : out Execute1ToFetch1Type;
|
||||
-- asynchronous
|
||||
f_out : out Execute1ToFetch1Type;
|
||||
|
||||
e_out : out Execute1ToWritebackType;
|
||||
e_out : out Execute1ToWritebackType;
|
||||
|
||||
terminate_out : out std_ulogic
|
||||
terminate_out : out std_ulogic
|
||||
);
|
||||
end entity execute1;
|
||||
|
||||
architecture behaviour of execute1 is
|
||||
type reg_type is record
|
||||
--f : Execute1ToFetch1Type;
|
||||
e : Execute1ToWritebackType;
|
||||
end record;
|
||||
type reg_type is record
|
||||
--f : Execute1ToFetch1Type;
|
||||
e : Execute1ToWritebackType;
|
||||
end record;
|
||||
|
||||
signal r, rin : reg_type;
|
||||
signal r, rin : reg_type;
|
||||
|
||||
signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
|
||||
signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
|
||||
signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
|
||||
signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
|
||||
|
||||
signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
|
||||
signal rotator_result: std_ulogic_vector(63 downto 0);
|
||||
signal rotator_carry: std_ulogic;
|
||||
signal logical_result: std_ulogic_vector(63 downto 0);
|
||||
signal countzero_result: std_ulogic_vector(63 downto 0);
|
||||
signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
|
||||
signal rotator_result: std_ulogic_vector(63 downto 0);
|
||||
signal rotator_carry: std_ulogic;
|
||||
signal logical_result: std_ulogic_vector(63 downto 0);
|
||||
signal countzero_result: std_ulogic_vector(63 downto 0);
|
||||
|
||||
function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is
|
||||
begin
|
||||
case carry_sel is
|
||||
when ZERO =>
|
||||
return '0';
|
||||
when CA =>
|
||||
return ca_in;
|
||||
when ONE =>
|
||||
return '1';
|
||||
end case;
|
||||
end;
|
||||
function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is
|
||||
begin
|
||||
case carry_sel is
|
||||
when ZERO =>
|
||||
return '0';
|
||||
when CA =>
|
||||
return ca_in;
|
||||
when ONE =>
|
||||
return '1';
|
||||
end case;
|
||||
end;
|
||||
begin
|
||||
|
||||
rotator_0: entity work.rotator
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
ra => e_in.read_data1,
|
||||
shift => e_in.read_data2(6 downto 0),
|
||||
insn => e_in.insn,
|
||||
is_32bit => e_in.is_32bit,
|
||||
right_shift => right_shift,
|
||||
arith => e_in.is_signed,
|
||||
clear_left => rot_clear_left,
|
||||
clear_right => rot_clear_right,
|
||||
result => rotator_result,
|
||||
carry_out => rotator_carry
|
||||
);
|
||||
rotator_0: entity work.rotator
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
ra => e_in.read_data1,
|
||||
shift => e_in.read_data2(6 downto 0),
|
||||
insn => e_in.insn,
|
||||
is_32bit => e_in.is_32bit,
|
||||
right_shift => right_shift,
|
||||
arith => e_in.is_signed,
|
||||
clear_left => rot_clear_left,
|
||||
clear_right => rot_clear_right,
|
||||
result => rotator_result,
|
||||
carry_out => rotator_carry
|
||||
);
|
||||
|
||||
logical_0: entity work.logical
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
rb => e_in.read_data2,
|
||||
op => e_in.insn_type,
|
||||
invert_in => e_in.invert_a,
|
||||
invert_out => e_in.invert_out,
|
||||
result => logical_result
|
||||
);
|
||||
logical_0: entity work.logical
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
rb => e_in.read_data2,
|
||||
op => e_in.insn_type,
|
||||
invert_in => e_in.invert_a,
|
||||
invert_out => e_in.invert_out,
|
||||
result => logical_result
|
||||
);
|
||||
|
||||
countzero_0: entity work.zero_counter
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
count_right => e_in.insn(10),
|
||||
is_32bit => e_in.is_32bit,
|
||||
result => countzero_result
|
||||
);
|
||||
countzero_0: entity work.zero_counter
|
||||
port map (
|
||||
rs => e_in.read_data3,
|
||||
count_right => e_in.insn(10),
|
||||
is_32bit => e_in.is_32bit,
|
||||
result => countzero_result
|
||||
);
|
||||
|
||||
execute1_0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
r <= rin;
|
||||
ctrl <= ctrl_tmp;
|
||||
execute1_0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
r <= rin;
|
||||
ctrl <= ctrl_tmp;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
execute1_1: process(all)
|
||||
variable v : reg_type;
|
||||
variable a_inv : std_ulogic_vector(63 downto 0);
|
||||
variable result : std_ulogic_vector(63 downto 0);
|
||||
variable newcrf : std_ulogic_vector(3 downto 0);
|
||||
variable result_with_carry : std_ulogic_vector(64 downto 0);
|
||||
variable result_en : std_ulogic;
|
||||
variable crnum : crnum_t;
|
||||
variable crbit : integer range 0 to 31;
|
||||
variable scrnum : crnum_t;
|
||||
variable lo, hi : integer;
|
||||
variable sh, mb, me : std_ulogic_vector(5 downto 0);
|
||||
variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0);
|
||||
variable bo, bi : std_ulogic_vector(4 downto 0);
|
||||
variable bf, bfa : std_ulogic_vector(2 downto 0);
|
||||
variable l : std_ulogic;
|
||||
begin
|
||||
result := (others => '0');
|
||||
result_with_carry := (others => '0');
|
||||
result_en := '0';
|
||||
newcrf := (others => '0');
|
||||
|
||||
v := r;
|
||||
v.e := Execute1ToWritebackInit;
|
||||
--v.f := Execute1ToFetch1TypeInit;
|
||||
|
||||
ctrl_tmp <= ctrl;
|
||||
-- FIXME: run at 512MHz not core freq
|
||||
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
|
||||
|
||||
terminate_out <= '0';
|
||||
f_out <= Execute1ToFetch1TypeInit;
|
||||
|
||||
-- rotator control signals
|
||||
right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
|
||||
rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
|
||||
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
|
||||
|
||||
if e_in.valid = '1' then
|
||||
|
||||
v.e.valid := '1';
|
||||
v.e.write_reg := e_in.write_reg;
|
||||
v.e.write_len := x"8";
|
||||
v.e.sign_extend := '0';
|
||||
|
||||
case_0: case e_in.insn_type is
|
||||
|
||||
when OP_ILLEGAL =>
|
||||
terminate_out <= '1';
|
||||
report "illegal";
|
||||
when OP_NOP =>
|
||||
-- Do nothing
|
||||
when OP_ADD =>
|
||||
if e_in.invert_a = '0' then
|
||||
a_inv := e_in.read_data1;
|
||||
else
|
||||
a_inv := not e_in.read_data1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
execute1_1: process(all)
|
||||
variable v : reg_type;
|
||||
variable a_inv : std_ulogic_vector(63 downto 0);
|
||||
variable result : std_ulogic_vector(63 downto 0);
|
||||
variable newcrf : std_ulogic_vector(3 downto 0);
|
||||
variable result_with_carry : std_ulogic_vector(64 downto 0);
|
||||
variable result_en : integer;
|
||||
variable crnum : integer;
|
||||
variable scrnum : integer;
|
||||
variable lo, hi : integer;
|
||||
variable sh, mb, me : std_ulogic_vector(5 downto 0);
|
||||
variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0);
|
||||
variable bo, bi : std_ulogic_vector(4 downto 0);
|
||||
variable bf, bfa : std_ulogic_vector(2 downto 0);
|
||||
variable l : std_ulogic;
|
||||
begin
|
||||
result := (others => '0');
|
||||
result_with_carry := (others => '0');
|
||||
result_en := 0;
|
||||
newcrf := (others => '0');
|
||||
|
||||
v := r;
|
||||
v.e := Execute1ToWritebackInit;
|
||||
--v.f := Execute1ToFetch1TypeInit;
|
||||
|
||||
ctrl_tmp <= ctrl;
|
||||
-- FIXME: run at 512MHz not core freq
|
||||
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
|
||||
|
||||
terminate_out <= '0';
|
||||
f_out <= Execute1ToFetch1TypeInit;
|
||||
|
||||
-- rotator control signals
|
||||
right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
|
||||
rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
|
||||
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
|
||||
|
||||
if e_in.valid = '1' then
|
||||
|
||||
v.e.valid := '1';
|
||||
v.e.write_reg := e_in.write_reg;
|
||||
v.e.write_len := x"8";
|
||||
v.e.sign_extend := '0';
|
||||
|
||||
case_0: case e_in.insn_type is
|
||||
|
||||
when OP_ILLEGAL =>
|
||||
terminate_out <= '1';
|
||||
report "illegal";
|
||||
when OP_NOP =>
|
||||
-- Do nothing
|
||||
when OP_ADD =>
|
||||
if e_in.invert_a = '0' then
|
||||
a_inv := e_in.read_data1;
|
||||
else
|
||||
a_inv := not e_in.read_data1;
|
||||
end if;
|
||||
result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry));
|
||||
result := result_with_carry(63 downto 0);
|
||||
if e_in.output_carry then
|
||||
ctrl_tmp.carry <= result_with_carry(64);
|
||||
end if;
|
||||
result_en := 1;
|
||||
when OP_AND | OP_OR | OP_XOR =>
|
||||
result := logical_result;
|
||||
result_en := 1;
|
||||
when OP_B =>
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
|
||||
end if;
|
||||
when OP_BC =>
|
||||
bo := insn_bo(e_in.insn);
|
||||
bi := insn_bi(e_in.insn);
|
||||
if bo(4-2) = '0' then
|
||||
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
|
||||
end if;
|
||||
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
|
||||
end if;
|
||||
end if;
|
||||
when OP_BCREG =>
|
||||
-- bits 10 and 6 distinguish between bclr, bcctr and bctar
|
||||
bo := insn_bo(e_in.insn);
|
||||
bi := insn_bi(e_in.insn);
|
||||
if bo(4-2) = '0' and e_in.insn(10) = '0' then
|
||||
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
|
||||
end if;
|
||||
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
|
||||
f_out.redirect <= '1';
|
||||
if e_in.insn(10) = '0' then
|
||||
f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
|
||||
else
|
||||
f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
when OP_CMPB =>
|
||||
result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
|
||||
result_en := 1;
|
||||
when OP_CMP =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
l := insn_l(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2);
|
||||
end loop;
|
||||
when OP_CMPL =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
l := insn_l(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2);
|
||||
end loop;
|
||||
when OP_CNTZ =>
|
||||
result := countzero_result;
|
||||
result_en := 1;
|
||||
when OP_EXTS =>
|
||||
v.e.write_len := e_in.data_len;
|
||||
v.e.sign_extend := '1';
|
||||
result := e_in.read_data3;
|
||||
result_en := 1;
|
||||
when OP_ISEL =>
|
||||
crnum := to_integer(unsigned(insn_bc(e_in.insn)));
|
||||
if e_in.cr(31-crnum) = '1' then
|
||||
result := e_in.read_data1;
|
||||
else
|
||||
result := e_in.read_data2;
|
||||
end if;
|
||||
result_en := 1;
|
||||
when OP_MCRF =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
bfa := insn_bfa(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
scrnum := to_integer(unsigned(bfa));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := (7-i)*4;
|
||||
hi := lo + 3;
|
||||
if i = scrnum then
|
||||
newcrf := e_in.cr(hi downto lo);
|
||||
end if;
|
||||
end loop;
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := newcrf;
|
||||
end loop;
|
||||
when OP_MFSPR =>
|
||||
if std_match(e_in.insn(20 downto 11), "0100100000") then
|
||||
result := ctrl.ctr;
|
||||
result_en := 1;
|
||||
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
|
||||
result := ctrl.lr;
|
||||
result_en := 1;
|
||||
elsif std_match(e_in.insn(20 downto 11), "0110001000") then
|
||||
result := ctrl.tb;
|
||||
result_en := 1;
|
||||
end if;
|
||||
when OP_MFCR =>
|
||||
if e_in.insn(20) = '0' then
|
||||
-- mfcr
|
||||
result := x"00000000" & e_in.cr;
|
||||
else
|
||||
-- mfocrf
|
||||
crnum := fxm_to_num(insn_fxm(e_in.insn));
|
||||
result := (others => '0');
|
||||
for i in 0 to 7 loop
|
||||
lo := (7-i)*4;
|
||||
hi := lo + 3;
|
||||
if crnum = i then
|
||||
result(hi downto lo) := e_in.cr(hi downto lo);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
result_en := 1;
|
||||
when OP_MTCRF =>
|
||||
v.e.write_cr_enable := '1';
|
||||
if e_in.insn(20) = '0' then
|
||||
-- mtcrf
|
||||
v.e.write_cr_mask := insn_fxm(e_in.insn);
|
||||
else
|
||||
-- mtocrf: We require one hot priority encoding here
|
||||
crnum := fxm_to_num(insn_fxm(e_in.insn));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
end if;
|
||||
v.e.write_cr_data := e_in.read_data3(31 downto 0);
|
||||
when OP_MTSPR =>
|
||||
if std_match(e_in.insn(20 downto 11), "0100100000") then
|
||||
ctrl_tmp.ctr <= e_in.read_data3;
|
||||
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
|
||||
ctrl_tmp.lr <= e_in.read_data3;
|
||||
end if;
|
||||
when OP_POPCNTB =>
|
||||
result := ppc_popcntb(e_in.read_data3);
|
||||
result_en := 1;
|
||||
when OP_POPCNTW =>
|
||||
result := ppc_popcntw(e_in.read_data3);
|
||||
result_en := 1;
|
||||
when OP_POPCNTD =>
|
||||
result := ppc_popcntd(e_in.read_data3);
|
||||
result_en := 1;
|
||||
when OP_PRTYD =>
|
||||
result := ppc_prtyd(e_in.read_data3);
|
||||
result_en := 1;
|
||||
when OP_PRTYW =>
|
||||
result := ppc_prtyw(e_in.read_data3);
|
||||
result_en := 1;
|
||||
when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
|
||||
result := rotator_result;
|
||||
if e_in.output_carry = '1' then
|
||||
ctrl_tmp.carry <= rotator_carry;
|
||||
end if;
|
||||
result_en := 1;
|
||||
when OP_SIM_CONFIG =>
|
||||
-- bit 0 was used to select the microwatt console, which
|
||||
-- we no longer support.
|
||||
if SIM = true then
|
||||
result := x"0000000000000000";
|
||||
else
|
||||
result := x"0000000000000000";
|
||||
end if;
|
||||
result_en := 1;
|
||||
|
||||
when OP_TDI =>
|
||||
-- Keep our test cases happy for now, ignore trap instructions
|
||||
report "OP_TDI FIXME";
|
||||
|
||||
when others =>
|
||||
terminate_out <= '1';
|
||||
report "illegal";
|
||||
end case;
|
||||
|
||||
if e_in.lr = '1' then
|
||||
ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4);
|
||||
end if;
|
||||
|
||||
if result_en = 1 then
|
||||
v.e.write_data := result;
|
||||
v.e.write_enable := '1';
|
||||
v.e.rc := e_in.rc;
|
||||
end if;
|
||||
result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry));
|
||||
result := result_with_carry(63 downto 0);
|
||||
if e_in.output_carry then
|
||||
ctrl_tmp.carry <= result_with_carry(64);
|
||||
end if;
|
||||
result_en := '1';
|
||||
when OP_AND | OP_OR | OP_XOR =>
|
||||
result := logical_result;
|
||||
result_en := '1';
|
||||
when OP_B =>
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
|
||||
end if;
|
||||
when OP_BC =>
|
||||
bo := insn_bo(e_in.insn);
|
||||
bi := insn_bi(e_in.insn);
|
||||
if bo(4-2) = '0' then
|
||||
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
|
||||
end if;
|
||||
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
|
||||
end if;
|
||||
end if;
|
||||
when OP_BCREG =>
|
||||
-- bits 10 and 6 distinguish between bclr, bcctr and bctar
|
||||
bo := insn_bo(e_in.insn);
|
||||
bi := insn_bi(e_in.insn);
|
||||
if bo(4-2) = '0' and e_in.insn(10) = '0' then
|
||||
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
|
||||
end if;
|
||||
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
|
||||
f_out.redirect <= '1';
|
||||
if e_in.insn(10) = '0' then
|
||||
f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
|
||||
else
|
||||
f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
when OP_CMPB =>
|
||||
result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
|
||||
result_en := '1';
|
||||
when OP_CMP =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
l := insn_l(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2);
|
||||
end loop;
|
||||
when OP_CMPL =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
l := insn_l(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2);
|
||||
end loop;
|
||||
when OP_CNTZ =>
|
||||
result := countzero_result;
|
||||
result_en := '1';
|
||||
when OP_EXTS =>
|
||||
v.e.write_len := e_in.data_len;
|
||||
v.e.sign_extend := '1';
|
||||
result := e_in.read_data3;
|
||||
result_en := '1';
|
||||
when OP_ISEL =>
|
||||
crbit := to_integer(unsigned(insn_bc(e_in.insn)));
|
||||
if e_in.cr(31-crbit) = '1' then
|
||||
result := e_in.read_data1;
|
||||
else
|
||||
result := e_in.read_data2;
|
||||
end if;
|
||||
result_en := '1';
|
||||
when OP_MCRF =>
|
||||
bf := insn_bf(e_in.insn);
|
||||
bfa := insn_bfa(e_in.insn);
|
||||
v.e.write_cr_enable := '1';
|
||||
crnum := to_integer(unsigned(bf));
|
||||
scrnum := to_integer(unsigned(bfa));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
for i in 0 to 7 loop
|
||||
lo := (7-i)*4;
|
||||
hi := lo + 3;
|
||||
if i = scrnum then
|
||||
newcrf := e_in.cr(hi downto lo);
|
||||
end if;
|
||||
end loop;
|
||||
for i in 0 to 7 loop
|
||||
lo := i*4;
|
||||
hi := lo + 3;
|
||||
v.e.write_cr_data(hi downto lo) := newcrf;
|
||||
end loop;
|
||||
when OP_MFSPR =>
|
||||
if std_match(e_in.insn(20 downto 11), "0100100000") then
|
||||
result := ctrl.ctr;
|
||||
result_en := '1';
|
||||
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
|
||||
result := ctrl.lr;
|
||||
result_en := '1';
|
||||
elsif std_match(e_in.insn(20 downto 11), "0110001000") then
|
||||
result := ctrl.tb;
|
||||
result_en := '1';
|
||||
end if;
|
||||
when OP_MFCR =>
|
||||
if e_in.insn(20) = '0' then
|
||||
-- mfcr
|
||||
result := x"00000000" & e_in.cr;
|
||||
else
|
||||
-- mfocrf
|
||||
crnum := fxm_to_num(insn_fxm(e_in.insn));
|
||||
result := (others => '0');
|
||||
for i in 0 to 7 loop
|
||||
lo := (7-i)*4;
|
||||
hi := lo + 3;
|
||||
if crnum = i then
|
||||
result(hi downto lo) := e_in.cr(hi downto lo);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
result_en := '1';
|
||||
when OP_MTCRF =>
|
||||
v.e.write_cr_enable := '1';
|
||||
if e_in.insn(20) = '0' then
|
||||
-- mtcrf
|
||||
v.e.write_cr_mask := insn_fxm(e_in.insn);
|
||||
else
|
||||
-- mtocrf: We require one hot priority encoding here
|
||||
crnum := fxm_to_num(insn_fxm(e_in.insn));
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
end if;
|
||||
v.e.write_cr_data := e_in.read_data3(31 downto 0);
|
||||
when OP_MTSPR =>
|
||||
if std_match(e_in.insn(20 downto 11), "0100100000") then
|
||||
ctrl_tmp.ctr <= e_in.read_data3;
|
||||
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
|
||||
ctrl_tmp.lr <= e_in.read_data3;
|
||||
end if;
|
||||
when OP_POPCNTB =>
|
||||
result := ppc_popcntb(e_in.read_data3);
|
||||
result_en := '1';
|
||||
when OP_POPCNTW =>
|
||||
result := ppc_popcntw(e_in.read_data3);
|
||||
result_en := '1';
|
||||
when OP_POPCNTD =>
|
||||
result := ppc_popcntd(e_in.read_data3);
|
||||
result_en := '1';
|
||||
when OP_PRTYD =>
|
||||
result := ppc_prtyd(e_in.read_data3);
|
||||
result_en := '1';
|
||||
when OP_PRTYW =>
|
||||
result := ppc_prtyw(e_in.read_data3);
|
||||
result_en := '1';
|
||||
when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
|
||||
result := rotator_result;
|
||||
if e_in.output_carry = '1' then
|
||||
ctrl_tmp.carry <= rotator_carry;
|
||||
end if;
|
||||
result_en := '1';
|
||||
when OP_SIM_CONFIG =>
|
||||
-- bit 0 was used to select the microwatt console, which
|
||||
-- we no longer support.
|
||||
if SIM = true then
|
||||
result := x"0000000000000000";
|
||||
else
|
||||
result := x"0000000000000000";
|
||||
end if;
|
||||
result_en := '1';
|
||||
|
||||
-- Update registers
|
||||
rin <= v;
|
||||
when OP_TDI =>
|
||||
-- Keep our test cases happy for now, ignore trap instructions
|
||||
report "OP_TDI FIXME";
|
||||
|
||||
-- update outputs
|
||||
--f_out <= r.f;
|
||||
e_out <= r.e;
|
||||
flush_out <= f_out.redirect;
|
||||
end process;
|
||||
when others =>
|
||||
terminate_out <= '1';
|
||||
report "illegal";
|
||||
end case;
|
||||
|
||||
if e_in.lr = '1' then
|
||||
ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4);
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
v.e.write_data := result;
|
||||
v.e.write_enable := result_en;
|
||||
v.e.rc := e_in.rc;
|
||||
|
||||
-- Update registers
|
||||
rin <= v;
|
||||
|
||||
-- update outputs
|
||||
--f_out <= r.f;
|
||||
e_out <= r.e;
|
||||
flush_out <= f_out.redirect;
|
||||
end process;
|
||||
end architecture behaviour;
|
||||
|
||||
@ -95,7 +95,7 @@ begin
|
||||
partial_write <= '0';
|
||||
sign_extend <= '0';
|
||||
second_word <= '0';
|
||||
data_in <= (others => '0');
|
||||
data_in <= e_in.write_data;
|
||||
|
||||
if e_in.write_enable = '1' then
|
||||
w_out.write_reg <= e_in.write_reg;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user