Initial import of microwatt

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
pull/4/head
Anton Blanchard 6 years ago committed by Anton Blanchard
commit 5a29cb4699

8
.gitignore vendored

@ -0,0 +1,8 @@
*.o
*~
*.cf
*.s
core_tb
fetch_tb
loadstore_tb
simple_ram_behavioural_tb

@ -0,0 +1,8 @@
© IBM Corp. 2019
This softcore is licensed under and subject to the terms of the CC-BY 4.0
license (https://creativecommons.org/licenses/by/4.0/legalcode).
Additional rights, including the right to physically implement a softcore
that is compliant with the required sections of the Power ISA
Specification, will be available at no cost via the OpenPOWER Foundation.
This README will be updated with additional information when OpenPOWER's
license is available.

@ -0,0 +1,74 @@
GHDL=ghdl
GHDLFLAGS=--std=08
CFLAGS=-O2

all = core_tb simple_ram_behavioural_tb
# XXX
# loadstore_tb fetch_tb

all: $(all)

%.o : %.vhdl
$(GHDL) -a $(GHDLFLAGS) $<

common.o: decode_types.o
core_tb.o: common.o wishbone_types.o core.o simple_ram_behavioural.o
core.o: common.o wishbone_types.o fetch1.o fetch2.o decode1.o decode2.o register_file.o cr_file.o execute1.o execute2.o loadstore1.o loadstore2.o multiply.o writeback.o wishbone_arbiter.o
cr_file.o: common.o
crhelpers.o: common.o
decode1.o: common.o decode_types.o
decode2.o: decode_types.o common.o helpers.o
decode_types.o:
execute1.o: decode_types.o common.o helpers.o crhelpers.o ppc_fx_insns.o sim_console.o
execute2.o: common.o crhelpers.o ppc_fx_insns.o
fetch1.o: common.o
fetch2.o: common.o wishbone_types.o
fetch_tb.o: common.o wishbone_types.o fetch.o
glibc_random_helpers.o:
glibc_random.o: glibc_random_helpers.o
helpers.o:
loadstore1.o: common.o
loadstore2.o: common.o helpers.o wishbone_types.o
loadstore_tb.o: common.o simple_ram_types.o simple_ram.o loadstore1.o loadstore2.o
multiply_tb.o: common.o glibc_random.o ppc_fx_insns.o multiply.o
multiply.o: common.o decode_types.o ppc_fx_insns.o crhelpers.o
ppc_fx_insns.o: helpers.o
register_file.o: common.o
sim_console.o:
simple_ram_behavioural_helpers.o:
simple_ram_behavioural_tb.o: wishbone_types.o simple_ram_behavioural.o
simple_ram_behavioural.o: wishbone_types.o simple_ram_behavioural_helpers.o
wishbone_arbiter.o: wishbone_types.o
wishbone_types.o:
writeback.o: common.o

core_tb: core_tb.o simple_ram_behavioural_helpers_c.o sim_console_c.o
$(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o -Wl,sim_console_c.o $@

fetch_tb: fetch_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

loadstore_tb: loadstore_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

simple_ram_tb: simple_ram_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

simple_ram_behavioural_tb: simple_ram_behavioural_helpers_c.o simple_ram_behavioural_tb.o
$(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@

tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out)))

check: $(tests) test_micropython test_micropython_long

$(tests): core_tb
@./scripts/run_test.sh $@

test_micropython:
@./scripts/test_micropython.py

test_micropython_long:
@./scripts/test_micropython_long.py

clean:
rm -f *.o work-*cf $(all)

@ -0,0 +1,58 @@
# Microwatt

A tiny Open POWER ISA softcore written in VHDL 2008. It aims to be simple and easy
to understand.

## Simulation

- Build micropython. If you aren't building on a ppc64le box you
will need a cross compiler. If it isn't available on your distro
grab the powerpc64le-power8 toolchain from https://toolchains.bootlin.com

```
git clone https://github.com/mikey/micropython
cd micropython
git checkout powerpc
cd ports/powerpc
make -j$(nproc)
cd ../../../
```

- Microwatt uses ghdl for simulation. Either install this from your
distro or build it. Next build microwatt:

```
git clone https://github.com/antonblanchard/microwatt
cd microwatt
make
```

- Link in the micropython image:

```
ln -s ../micropython/ports/powerpc/build/firmware.bin simple_ram_behavioural.bin
```

- Now run microwatt, sending debug output to /dev/null:

```
./core_tb > /dev/null
```

## Testing

- A simple test suite containing random execution test cases and a couple of
micropython test cases can be run with:

```
make -j$(nproc) check
```

## Issues

This is functional, but very simple. We still have quite a lot to do:

- Need to implement a simple non pipelined divide
- There are a few instructions still to be implemented
- Need to add caches and bypassing (in progress)
- Need to add supervisor state (in progress)

@ -0,0 +1,196 @@
library ieee;
use ieee.std_logic_1164.all;

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 Fetch1ToFetch2Type is record
valid: std_ulogic;
nia: std_ulogic_vector(63 downto 0);
end record;

type Fetch2ToDecode1Type is record
valid: std_ulogic;
nia: std_ulogic_vector(63 downto 0);
insn: std_ulogic_vector(31 downto 0);
end record;
constant Fetch2ToDecode1Init : Fetch2ToDecode1Type := (valid => '0', others => (others => '0'));

type Decode1ToDecode2Type is record
valid: 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', 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);
const1: std_ulogic_vector(23 downto 0);
const2: std_ulogic_vector(6 downto 0);
const3: std_ulogic_vector(6 downto 0);
cr: std_ulogic_vector(31 downto 0);
lr: std_ulogic;
rc: std_ulogic;
input_carry: std_ulogic;
output_carry: std_ulogic;
input_cr: std_ulogic;
output_cr: std_ulogic;
input_cr_data: std_ulogic_vector(31 downto 0);
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type := (valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', input_carry => '0', output_carry => '0', input_cr => '0', output_cr => '0', others => (others => '0'));

type Decode2ToMultiplyType 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);
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 Decode2ToRegisterFileType is record
read1_reg : std_ulogic_vector(4 downto 0);
read2_reg : std_ulogic_vector(4 downto 0);
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 Decode2ToCrFileType is record
read_cr_nr_1 : integer;
read_cr_nr_2 : integer;
end record;

type CrFileToDecode2Type is record
read_cr_data : std_ulogic_vector(31 downto 0);
read_cr_data_1 : std_ulogic_vector(3 downto 0);
read_cr_data_2 : std_ulogic_vector(3 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 Decode2ToLoadstore1Type is record
valid : std_ulogic;
nia: std_ulogic_vector(63 downto 0);
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 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_enable2: std_ulogic;
write_reg2 : std_ulogic_vector(4 downto 0);
write_data2 : std_ulogic_vector(63 downto 0);
end record;
constant Loadstore2ToWritebackInit : Loadstore2ToWritebackType := (valid => '0', write_enable => '0', write_enable2 => '0', others => (others => '0'));

type Execute1ToExecute2Type 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_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
rc : std_ulogic;
end record;
constant Execute1ToExecute2Init : Execute1ToExecute2Type := (valid => '0', write_enable => '0', write_cr_enable => '0', rc => '0', others => (others => '0'));

type Execute2ToWritebackType 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_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 Execute2ToWritebackInit : Execute2ToWritebackType := (valid => '0', write_enable => '0', write_cr_enable => '0', others => (others => '0'));

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);
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 MultiplyToWritebackInit : MultiplyToWritebackType := (valid => '0', write_reg_enable => '0', write_cr_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;
write_reg2 : std_ulogic_vector(4 downto 0);
write_data2 : std_ulogic_vector(63 downto 0);
write_enable2 : std_ulogic;
end record;
constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', write_enable2 => '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'));

-- Would prefer not to expose this outside the register file, but ghdl
-- doesn't support external names
type regfile is array(0 to 32) of std_ulogic_vector(63 downto 0);
end common;

package body common is
end common;

@ -0,0 +1,149 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;
use work.wishbone_types.all;

entity core is
generic (
SIM : boolean := false
);
port (
clk : in std_logic;
rst : in std_logic;

wishbone_in : in wishbone_slave_out;
wishbone_out : out wishbone_master_out;

-- Added for debug, ghdl doesn't support external names unfortunately
registers : out regfile;
terminate_out : out std_ulogic
);
end core;

architecture behave of core is
-- fetch signals
signal fetch1_to_fetch2: Fetch1ToFetch2Type;
signal fetch2_to_decode1: Fetch2ToDecode1Type;

-- decode signals
signal decode1_to_decode2: Decode1ToDecode2Type;
signal decode2_to_execute1: Decode2ToExecute1Type;

-- register file signals
signal register_file_to_decode2: RegisterFileToDecode2Type;
signal decode2_to_register_file: Decode2ToRegisterFileType;
signal writeback_to_register_file: WritebackToRegisterFileType;

-- CR file signals
signal decode2_to_cr_file: Decode2ToCrFileType;
signal cr_file_to_decode2: CrFileToDecode2Type;
signal writeback_to_cr_file: WritebackToCrFileType;

-- execute signals
signal execute1_to_execute2: Execute1ToExecute2Type;
signal execute2_to_writeback: Execute2ToWritebackType;
signal execute1_to_fetch1: Execute1ToFetch1Type;

-- load store signals
signal decode2_to_loadstore1: Decode2ToLoadstore1Type;
signal loadstore1_to_loadstore2: Loadstore1ToLoadstore2Type;
signal loadstore2_to_writeback: Loadstore2ToWritebackType;

-- multiply signals
signal decode2_to_multiply: Decode2ToMultiplyType;
signal multiply_to_writeback: MultiplyToWritebackType;

-- wishbone signals
signal wishbone_data_in : wishbone_slave_out;
signal wishbone_data_out : wishbone_master_out;
signal wishbone_insn_in : wishbone_slave_out;
signal wishbone_insn_out : wishbone_master_out;

-- local signals
signal fetch_enable: std_ulogic := '0';
signal complete: std_ulogic;
signal first_fetch: std_ulogic := '0';

signal terminate: std_ulogic;
begin

terminate_out <= terminate;

fetch1_0: entity work.fetch1
generic map (RESET_ADDRESS => (others => '0'))
port map (clk => clk, rst => rst, fetch_one_in => fetch_enable,
e_in => execute1_to_fetch1, f_out => fetch1_to_fetch2);

fetch2_0: entity work.fetch2
port map (clk => clk, wishbone_in => wishbone_insn_in,
wishbone_out => wishbone_insn_out, f_in => fetch1_to_fetch2,
f_out => fetch2_to_decode1);

decode1_0: entity work.decode1
port map (clk => clk, f_in => fetch2_to_decode1, d_out => decode1_to_decode2);

decode2_0: entity work.decode2
port map (clk => clk, d_in => decode1_to_decode2, e_out => decode2_to_execute1,
l_out => decode2_to_loadstore1, m_out => decode2_to_multiply,
r_in => register_file_to_decode2, r_out => decode2_to_register_file,
c_in => cr_file_to_decode2, c_out => decode2_to_cr_file);

register_file_0: entity work.register_file
port map (clk => clk, d_in => decode2_to_register_file,
d_out => register_file_to_decode2, w_in => writeback_to_register_file,
registers_out => registers);

cr_file_0: entity work.cr_file
port map (clk => clk, d_in => decode2_to_cr_file, d_out => cr_file_to_decode2,
w_in => writeback_to_cr_file);

execute1_0: entity work.execute1
generic map (SIM => SIM)
port map (clk => clk, e_in => decode2_to_execute1, f_out => execute1_to_fetch1,
e_out => execute1_to_execute2, terminate_out => terminate);

execute2_0: entity work.execute2
port map (clk => clk, e_in => execute1_to_execute2, e_out => execute2_to_writeback);

loadstore1_0: entity work.loadstore1
port map (clk => clk, l_in => decode2_to_loadstore1, l_out => loadstore1_to_loadstore2);

loadstore2_0: entity work.loadstore2
port map (clk => clk, l_in => loadstore1_to_loadstore2,
w_out => loadstore2_to_writeback, m_in => wishbone_data_in,
m_out => wishbone_data_out);

multiply_0: entity work.multiply
port map (clk => clk, m_in => decode2_to_multiply, m_out => multiply_to_writeback);

writeback_0: entity work.writeback
port map (clk => clk, w_in => execute2_to_writeback, l_in => loadstore2_to_writeback,
m_in => multiply_to_writeback, w_out => writeback_to_register_file,
c_out => writeback_to_cr_file, complete_out => complete);

wishbone_arbiter_0: entity work.wishbone_arbiter
port map (clk => clk, rst => rst, wb1_in => wishbone_data_out, wb1_out => wishbone_data_in,
wb2_in => wishbone_insn_out, wb2_out => wishbone_insn_in, wb_out => wishbone_out,
wb_in => wishbone_in);

-- Only single issue until we add bypass support
single_issue_0: process(clk)
begin
if (rising_edge(clk)) then
if rst = '1' then
first_fetch <= '1';
else
if first_fetch = '1' then
fetch_enable <= '1';
first_fetch <= '0';
else
fetch_enable <= complete;
end if;
end if;
end if;
end process single_issue_0;

end behave;

@ -0,0 +1,57 @@
library ieee;
use ieee.std_logic_1164.all;

library work;
use work.common.all;
use work.wishbone_types.all;

entity core_tb is
end core_tb;

architecture behave of core_tb is
signal clk, rst: std_logic;

signal wishbone_in : wishbone_slave_out;
signal wishbone_out : wishbone_master_out;

signal registers : regfile;
signal terminate : std_ulogic;

-- testbench signals
constant clk_period : time := 10 ns;
begin
core_0: entity work.core
generic map (SIM => true)
port map (clk => clk, rst => rst, wishbone_in => wishbone_in,
wishbone_out => wishbone_out, registers => registers, terminate_out => terminate);

simple_ram_0: entity work.simple_ram_behavioural
generic map ( filename => "simple_ram_behavioural.bin", size => 1048576)
port map (clk => clk, rst => rst, wishbone_in => wishbone_out, wishbone_out => wishbone_in);

clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;

rst_process: process
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait;
end process;

dump_registers: process(all)
begin
if terminate = '1' then
loop_0: for i in 0 to 31 loop
report "REG " & to_hstring(registers(i));
end loop loop_0;
assert false report "end of test" severity failure;
end if;
end process;
end;

@ -0,0 +1,65 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;

entity cr_file is
port(
clk : in std_logic;

d_in : in Decode2ToCrFileType;
d_out : out CrFileToDecode2Type;

w_in : in WritebackToCrFileType
);
end entity cr_file;

architecture behaviour of cr_file is
signal crs : std_ulogic_vector(31 downto 0) := (others => '0');
begin
-- synchronous writes
cr_write_0: process(clk)
variable hi, lo : integer := 0;
begin
if rising_edge(clk) then
if w_in.write_cr_enable = '1' then
report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask);

for i in 0 to 7 loop
if w_in.write_cr_mask(i) = '1' then
lo := i*4;
hi := lo + 3;
crs(hi downto lo) <= w_in.write_cr_data(hi downto lo);
end if;
end loop;
end if;
end if;
end process cr_write_0;

-- asynchronous reads
cr_read_0: process(all)
variable hi, lo : integer := 0;
begin
--lo := (7-d_in.read_cr_nr_1)*4;
--hi := lo + 3;

--report "read " & integer'image(d_in.read_cr_nr_1) & " from CR " & to_hstring(crs(hi downto lo));
--d_out.read_cr_data_1 <= crs(hi downto lo);

-- Also return the entire CR to make mfcrf easier for now
report "read CR " & to_hstring(crs);
d_out.read_cr_data <= crs;

-- -- Forward any written data
-- if w_in.write_cr_enable = '1' then
-- if d_in.read_cr_nr_1 = w_in.write_cr_nr then
-- d_out.read_cr_data_1 <= w_in.write_cr_data;
-- end if;
-- if d_in.read_cr_nr_2 = w_in.write_cr_nr then
-- d_out.read_cr_data_2 <= w_in.write_cr_data;
-- end if;
-- end if;
end process cr_read_0;
end architecture behaviour;

@ -0,0 +1,134 @@
library ieee;
use ieee.std_logic_1164.all;

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;
--function from_crfile(cr: crfile) return std_ulogic_vector;
--function extract_one_crfield(cr: crfile; fxm: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
--function insert_multiple_crfields(cr_in: crfile; rs: std_ulogic_vector(63 downto 0); fxm: std_ulogic_vector(7 downto 0)) return crfile;
--function insert_one_crfield(cr_in: crfile; rs: std_ulogic_vector(63 downto 0); fxm: std_ulogic_vector(7 downto 0)) return crfile;
end package crhelpers;

package body crhelpers is

function fxm_to_num(fxm: std_ulogic_vector(7 downto 0)) return integer is
begin
-- If multiple fields are set (undefined), match existing
-- hardware by returning the first one.
for i in 0 to 7 loop
-- Big endian bit numbering
if fxm(7-i) = '1' then
return i;
end if;
end loop;

-- If no fields are set (undefined), also match existing
-- hardware by returning cr7.
return 7;
end;

function num_to_fxm(num: integer) return std_ulogic_vector is
begin
case num is
when 0 =>
return "10000000";
when 1 =>
return "01000000";
when 2 =>
return "00100000";
when 3 =>
return "00010000";
when 4 =>
return "00001000";
when 5 =>
return "00000100";
when 6 =>
return "00000010";
when 7 =>
return "00000001";
when others =>
return "00000000";
end case;
end;

-- function from_crfile(cr: crfile) return std_ulogic_vector is
-- variable combined_cr : std_ulogic_vector(31 downto 0) := (others => '0');
-- variable high, low: integer range 0 to 31 := 0;
-- begin
-- for i in 0 to cr'length-1 loop
-- low := 4*(7-i);
-- high := low+3;
-- combined_cr(high downto low) := cr(i);
-- end loop;
--
-- return combined_cr;
-- end function;
--
-- function extract_one_crfield(cr: crfile; fxm: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
-- variable combined_cr : std_ulogic_vector(63 downto 0) := (others => '0');
-- variable crnum: integer range 0 to 7 := 0;
-- begin
-- crnum := fxm_to_num(fxm);
--
-- -- Vivado doesn't support non constant vector slice
-- -- low := 4*(7-crnum);
-- -- high := low+3;
-- -- combined_cr(high downto low) := cr(crnum);
-- case_0: case crnum is
-- when 0 =>
-- combined_cr(31 downto 28) := cr(0);
-- when 1 =>
-- combined_cr(27 downto 24) := cr(1);
-- when 2 =>
-- combined_cr(23 downto 20) := cr(2);
-- when 3 =>
-- combined_cr(19 downto 16) := cr(3);
-- when 4 =>
-- combined_cr(15 downto 12) := cr(4);
-- when 5 =>
-- combined_cr(11 downto 8) := cr(5);
-- when 6 =>
-- combined_cr(7 downto 4) := cr(6);
-- when 7 =>
-- combined_cr(3 downto 0) := cr(7);
-- end case;
--
-- return combined_cr;
-- end;
--
-- function insert_multiple_crfields(cr_in: crfile; rs: std_ulogic_vector(63 downto 0); fxm: std_ulogic_vector(7 downto 0)) return crfile is
-- variable cr : crfile;
-- variable combined_cr : std_ulogic_vector(63 downto 0) := (others => '0');
-- variable high, low: integer range 0 to 31 := 0;
-- begin
-- cr := cr_in;
--
-- for i in 0 to 7 loop
-- -- BE bit numbering
-- if fxm(7-i) = '1' then
-- low := 4*(7-i);
-- high := low+3;
-- cr(i) := rs(high downto low);
-- end if;
-- end loop;
--
-- return cr;
-- end;
--
-- function insert_one_crfield(cr_in: crfile; rs: std_ulogic_vector(63 downto 0); fxm: std_ulogic_vector(7 downto 0)) return crfile is
-- variable cr : crfile;
-- variable crnum: integer range 0 to 7 := 0;
-- variable high, low: integer range 0 to 31 := 0;
-- begin
-- cr := cr_in;
-- crnum := fxm_to_num(fxm);
-- low := 4*(7-crnum);
-- high := low+3;
-- cr(crnum) := rs(high downto low);
-- return cr;
-- end;
end package body crhelpers;

@ -0,0 +1,847 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;
use work.decode_types.all;

entity decode1 is
port (
clk : in std_ulogic;

f_in : in Fetch2ToDecode1Type;
d_out : out Decode1ToDecode2Type
);
end entity decode1;

architecture behaviour of decode1 is
signal f : Fetch2ToDecode1Type := Fetch2ToDecode1Init;

type decode_rom_array_t is array(ppc_insn_t) of decode_rom_t;

-- Note: reformat with column -t -o ' '
constant decode_rom_array : decode_rom_array_t := (
-- unit internal in1 in2 in3 out const const const CR CR cry cry ldst ld BR sgn upd mul mul rc lk
-- op 1 2 3 in out in out len ext 32 sgn
PPC_ILLEGAL => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ADD => (ALU, OP_ADD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ADDC => (ALU, OP_ADDC, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ADDE => (ALU, OP_ADDC, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_ADDEX
PPC_ADDI => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_ADDIC => (ALU, OP_ADDC, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_ADDIC_RC => (ALU, OP_ADDC, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0'),
PPC_ADDIS => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_ADDME
--PPC_ADDPCIS
PPC_ADDZE => (ALU, OP_ADDC, RA, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_AND => (ALU, OP_AND, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ANDC => (ALU, OP_ANDC, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ANDI_RC => (ALU, OP_AND, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0'),
PPC_ANDIS_RC => (ALU, OP_AND, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0'),
PPC_ATTN => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_B => (ALU, OP_B, NONE, CONST_LI, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1'),
--PPC_BA
PPC_BC => (ALU, OP_BC, NONE, CONST_BD, NONE, NONE, BO, BI, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1'),
--PPC_BCA
PPC_BCCTR => (ALU, OP_BCCTR, NONE, NONE, NONE, NONE, BO, BI, BH, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1'),
--PPC_BCLA
PPC_BCLR => (ALU, OP_BCLR, NONE, NONE, NONE, NONE, BO, BI, BH, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1'),
--PPC_BCTAR
--PPC_BPERM
PPC_CMP => (ALU, OP_CMP, RA, RB, NONE, NONE, BF, L, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_CMPB => (ALU, OP_CMPB, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_CMPEQB
PPC_CMPI => (ALU, OP_CMP, RA, CONST_SI, NONE, NONE, BF, L, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_CMPL => (ALU, OP_CMPL, RA, RB, NONE, NONE, BF, L, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_CMPLI => (ALU, OP_CMPL, RA, CONST_UI, NONE, NONE, BF, L, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_CMPRB
PPC_CNTLZD => (ALU, OP_CNTLZD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_CNTLZW => (ALU, OP_CNTLZW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_CNTTZD => (ALU, OP_CNTTZD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_CNTTZW => (ALU, OP_CNTTZW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_CRAND
--PPC_CRANDC
--PPC_CREQV
--PPC_CRNAND
--PPC_CRNOR
--PPC_CROR
--PPC_CRORC
--PPC_CRXOR
--PPC_DARN
PPC_DCBF => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_DCBST => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_DCBT => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_DCBTST => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_DCBZ
PPC_DIVD => (ALU, OP_DIVD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_DIVDE
--PPC_DIVDEU
PPC_DIVDU => (ALU, OP_DIVDU, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_DIVW => (ALU, OP_DIVW, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_DIVWE
--PPC_DIVWEU
PPC_DIVWU => (ALU, OP_DIVWU, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_EQV => (ALU, OP_EQV, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_EXTSB => (ALU, OP_EXTSB, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_EXTSH => (ALU, OP_EXTSH, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_EXTSW => (ALU, OP_EXTSW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_EXTSWSLI
--PPC_ICBI
PPC_ICBT => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_ISEL => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, BC, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_ISYNC => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LBARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0'),
--CONST_LI matches CONST_SI, so reuse it
PPC_LBZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LBZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LBZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LBZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LD => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LDARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_LDBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LDU => (LDST, OP_LOAD, RA, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LDUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LDX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LHA => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0'),
PPC_LHARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_LHAU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0'),
PPC_LHAUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0'),
PPC_LHAX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0'),
PPC_LHBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LHZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LHZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LHZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LHZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LWA => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0'),
PPC_LWARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_LWAUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0'),
PPC_LWAX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0'),
PPC_LWBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LWZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_LWZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LWZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_LWZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_MADDHD
--PPC_MADDHDU
--PPC_MADDLD
--PPC_MCRF
--PPC_MCRXR
--PPC_MCRXRX
PPC_MFCR => (ALU, OP_MFCR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MFOCRF => (ALU, OP_MFOCRF, NONE, NONE, NONE, RT, FXM, NONE, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MFCTR => (ALU, OP_MFCTR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MFLR => (ALU, OP_MFLR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MFTB => (ALU, OP_MFTB, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MTCTR => (ALU, OP_MTCTR, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MTLR => (ALU, OP_MTLR, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_MFSPR
--PPC_MODSD
--PPC_MODSW
--PPC_MODUD
--PPC_MODUW
PPC_MTCRF => (ALU, OP_MTCRF, RS, NONE, NONE, NONE, FXM, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_MTOCRF => (ALU, OP_MTOCRF, RS, NONE, NONE, NONE, FXM, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_MTSPR
PPC_MULHD => (MUL, OP_MUL_H64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0'),
PPC_MULHDU => (MUL, OP_MUL_H64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_MULHW => (MUL, OP_MUL_H32, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0'),
PPC_MULHWU => (MUL, OP_MUL_H32, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0'),
PPC_MULLD => (MUL, OP_MUL_L64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0'),
PPC_MULLI => (MUL, OP_MUL_L64, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0'),
PPC_MULLW => (MUL, OP_MUL_L64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0'),
PPC_NAND => (ALU, OP_NAND, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_NEG => (ALU, OP_NEG, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_NOR => (ALU, OP_NOR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_OR => (ALU, OP_OR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ORC => (ALU, OP_ORC, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_ORI => (ALU, OP_OR, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_ORIS => (ALU, OP_OR, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_POPCNTB => (ALU, OP_POPCNTB, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_POPCNTD => (ALU, OP_POPCNTD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_POPCNTW => (ALU, OP_POPCNTW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_PRTYD => (ALU, OP_PRTYD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_PRTYW => (ALU, OP_PRTYW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_RLDCL => (ALU, OP_RLDCL, RS, RB, NONE, RA, NONE, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLDCR => (ALU, OP_RLDCR, RS, RB, NONE, RA, NONE, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLDIC => (ALU, OP_RLDIC, RS, NONE, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLDICL => (ALU, OP_RLDICL, RS, NONE, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLDICR => (ALU, OP_RLDICR, RS, NONE, NONE, RA, SH, ME, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLDIMI => (ALU, OP_RLDIMI, RA, RS, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLWIMI => (ALU, OP_RLWIMI, RA, RS, NONE, RA, SH32, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLWINM => (ALU, OP_RLWINM, RS, NONE, NONE, RA, SH32, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_RLWNM => (ALU, OP_RLWNM, RS, RB, NONE, RA, NONE, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
--PPC_SETB
PPC_SLD => (ALU, OP_SLD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SLW => (ALU, OP_SLW, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRAD => (ALU, OP_SRAD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRADI => (ALU, OP_SRADI, RS, NONE, NONE, RA, SH, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRAW => (ALU, OP_SRAW, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRAWI => (ALU, OP_SRAWI, RS, NONE, NONE, RA, SH, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRD => (ALU, OP_SRD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SRW => (ALU, OP_SRW, RS, RB, RS, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_STB => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_STBCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '1', '0', '0', RC, '0'),
PPC_STBU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0'),
PPC_STBUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0'),
PPC_STBX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_STD => (LDST, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STDBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STDCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_STDU => (LDST, OP_STORE, RA, CONST_DS, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STDUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STDX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STH => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STHBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STHCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_STHU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STHUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STHX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STW => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STWBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0'),
PPC_STWCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0'),
PPC_STWU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STWUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0'),
PPC_STWX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_SUBF => (ALU, OP_SUBF, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SUBFC => (ALU, OP_SUBFC, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SUBFE => (ALU, OP_SUBFC, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SUBFIC => (ALU, OP_SUBFC, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_SUBFME
PPC_SUBFZE => (ALU, OP_SUBFC, RA, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_SYNC => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_TD
PPC_TDI => (ALU, OP_TDI, RA, CONST_SI, NONE, NONE, TOO, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
--PPC_TW
--PPC_TWI
PPC_XOR => (ALU, OP_XOR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0'),
PPC_XORI => (ALU, OP_XOR, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_XORIS => (ALU, OP_XOR, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_SIM_READ => (ALU, OP_SIM_READ, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_SIM_POLL => (ALU, OP_SIM_POLL, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_SIM_WRITE => (ALU, OP_SIM_WRITE, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),
PPC_SIM_CONFIG => (ALU, OP_SIM_CONFIG,NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0'),

others => decode_rom_init
);

begin
decode1_0: process(clk)
begin
if rising_edge(clk) then
f <= f_in;
end if;
end process;

decode1_1: process(all)
variable ppc_insn: ppc_insn_t;
begin
d_out <= Decode1ToDecode2Init;
ppc_insn := PPC_ILLEGAL;

d_out.valid <= f.valid;

if f.valid then
d_out.nia <= f.nia;
d_out.insn <= f.insn;

report "Decode insn " & to_hstring(f.insn);
if std_match(f.insn, "011111---------------0100001010-") then
report "PPC_add";
ppc_insn := PPC_ADD;
elsif std_match(f.insn, "011111---------------0000001010-") then
report "PPC_addc";
ppc_insn := PPC_ADDC;
elsif std_match(f.insn, "011111---------------0010001010-") then
report "PPC_adde";
ppc_insn := PPC_ADDE;
elsif std_match(f.insn, "011111---------------0010101010-") then
report "PPC_addex";
ppc_insn := PPC_ADDEX;
elsif std_match(f.insn, "001110--------------------------") then
report "PPC_addi";
ppc_insn := PPC_ADDI;
elsif std_match(f.insn, "001100--------------------------") then
report "PPC_addic";
ppc_insn := PPC_ADDIC;
elsif std_match(f.insn, "001101--------------------------") then
report "PPC_addic.";
ppc_insn := PPC_ADDIC_RC;
elsif std_match(f.insn, "001111--------------------------") then
report "PPC_addis";
ppc_insn := PPC_ADDIS;
elsif std_match(f.insn, "011111---------------0011101010-") then
report "PPC_addme";
ppc_insn := PPC_ADDME;
elsif std_match(f.insn, "010011--------------------00010-") then
report "PPC_addpcis";
ppc_insn := PPC_ADDPCIS;
elsif std_match(f.insn, "011111---------------0011001010-") then
report "PPC_addze";
ppc_insn := PPC_ADDZE;
elsif std_match(f.insn, "011111---------------0000011100-") then
report "PPC_and";
ppc_insn := PPC_AND;
elsif std_match(f.insn, "011111---------------0000111100-") then
report "PPC_andc";
ppc_insn := PPC_ANDC;
elsif std_match(f.insn, "011100--------------------------") then
report "PPC_andi.";
ppc_insn := PPC_ANDI_RC;
elsif std_match(f.insn, "011101--------------------------") then
report "PPC_andis.";
ppc_insn := PPC_ANDIS_RC;
elsif std_match(f.insn, "000000---------------0100000000-") then
report "PPC_attn";
ppc_insn := PPC_ATTN;
elsif std_match(f.insn, "010010------------------------0-") then
report "PPC_b";
ppc_insn := PPC_B;
elsif std_match(f.insn, "010010------------------------1-") then
report "PPC_ba";
ppc_insn := PPC_BA;
elsif std_match(f.insn, "010000------------------------0-") then
report "PPC_bc";
ppc_insn := PPC_BC;
elsif std_match(f.insn, "010000------------------------10") then
report "PPC_bca";
ppc_insn := PPC_BCA;
elsif std_match(f.insn, "010011---------------1000010000-") then
report "PPC_bcctr";
ppc_insn := PPC_BCCTR;
elsif std_match(f.insn, "010000------------------------11") then
report "PPC_bcla";
ppc_insn := PPC_BCLA;
elsif std_match(f.insn, "010011---------------0000010000-") then
report "PPC_bclr";
ppc_insn := PPC_BCLR;
elsif std_match(f.insn, "010011---------------1000110000-") then
report "PPC_bctar";
ppc_insn := PPC_BCTAR;
elsif std_match(f.insn, "011111---------------0011111100-") then
report "PPC_bperm";
ppc_insn := PPC_BPERM;
elsif std_match(f.insn, "011111---------------0000000000-") then
report "PPC_cmp";
ppc_insn := PPC_CMP;
elsif std_match(f.insn, "011111---------------0111111100-") then
report "PPC_cmpb";
ppc_insn := PPC_CMPB;
elsif std_match(f.insn, "011111---------------0011100000-") then
report "PPC_cmpeqb";
ppc_insn := PPC_CMPEQB;
elsif std_match(f.insn, "001011--------------------------") then
report "PPC_cmpi";
ppc_insn := PPC_CMPI;
elsif std_match(f.insn, "011111---------------0000100000-") then
report "PPC_cmpl";
ppc_insn := PPC_CMPL;
elsif std_match(f.insn, "001010--------------------------") then
report "PPC_cmpli";
ppc_insn := PPC_CMPLI;
elsif std_match(f.insn, "011111---------------0011000000-") then
report "PPC_cmprb";
ppc_insn := PPC_CMPRB;
elsif std_match(f.insn, "011111---------------0000111010-") then
report "PPC_cntlzd";
ppc_insn := PPC_CNTLZD;
elsif std_match(f.insn, "011111---------------0000011010-") then
report "PPC_cntlzw";
ppc_insn := PPC_CNTLZW;
elsif std_match(f.insn, "011111---------------1000111010-") then
report "PPC_cnttzd";
ppc_insn := PPC_CNTTZD;
elsif std_match(f.insn, "011111---------------1000011010-") then
report "PPC_cnttzw";
ppc_insn := PPC_CNTTZW;
elsif std_match(f.insn, "010011---------------0100000001-") then
report "PPC_crand";
ppc_insn := PPC_CRAND;
elsif std_match(f.insn, "010011---------------0010000001-") then
report "PPC_crandc";
ppc_insn := PPC_CRANDC;
elsif std_match(f.insn, "010011---------------0100100001-") then
report "PPC_creqv";
ppc_insn := PPC_CREQV;
elsif std_match(f.insn, "010011---------------0011100001-") then
report "PPC_crnand";
ppc_insn := PPC_CRNAND;
elsif std_match(f.insn, "010011---------------0000100001-") then
report "PPC_crnor";
ppc_insn := PPC_CRNOR;
elsif std_match(f.insn, "010011---------------0111000001-") then
report "PPC_cror";
ppc_insn := PPC_CROR;
elsif std_match(f.insn, "010011---------------0110100001-") then
report "PPC_crorc";
ppc_insn := PPC_CRORC;
elsif std_match(f.insn, "010011---------------0011000001-") then
report "PPC_crxor";
ppc_insn := PPC_CRXOR;
elsif std_match(f.insn, "011111---------------1011110011-") then
report "PPC_darn";
ppc_insn := PPC_DARN;
elsif std_match(f.insn, "011111---------------0001010110-") then
report "PPC_dcbf";
ppc_insn := PPC_DCBF;
elsif std_match(f.insn, "011111---------------0000110110-") then
report "PPC_dcbst";
ppc_insn := PPC_DCBST;
elsif std_match(f.insn, "011111---------------0100010110-") then
report "PPC_dcbt";
ppc_insn := PPC_DCBT;
elsif std_match(f.insn, "011111---------------0011110110-") then
report "PPC_dcbtst";
ppc_insn := PPC_DCBTST;
elsif std_match(f.insn, "011111---------------1111110110-") then
report "PPC_dcbz";
ppc_insn := PPC_DCBZ;
elsif std_match(f.insn, "011111---------------0111101001-") then
report "PPC_divd";
ppc_insn := PPC_DIVD;
elsif std_match(f.insn, "011111---------------0110101001-") then
report "PPC_divde";
ppc_insn := PPC_DIVDE;
elsif std_match(f.insn, "011111---------------0110001001-") then
report "PPC_divdeu";
ppc_insn := PPC_DIVDEU;
elsif std_match(f.insn, "011111---------------0111001001-") then
report "PPC_divdu";
ppc_insn := PPC_DIVDU;
elsif std_match(f.insn, "011111---------------0111101011-") then
report "PPC_divw";
ppc_insn := PPC_DIVW;
elsif std_match(f.insn, "011111---------------0110101011-") then
report "PPC_divwe";
ppc_insn := PPC_DIVWE;
elsif std_match(f.insn, "011111---------------0110001011-") then
report "PPC_divweu";
ppc_insn := PPC_DIVWEU;
elsif std_match(f.insn, "011111---------------0111001011-") then
report "PPC_divwu";
ppc_insn := PPC_DIVWU;
elsif std_match(f.insn, "011111---------------0100011100-") then
report "PPC_eqv";
ppc_insn := PPC_EQV;
elsif std_match(f.insn, "011111---------------1110111010-") then
report "PPC_extsb";
ppc_insn := PPC_EXTSB;
elsif std_match(f.insn, "011111---------------1110011010-") then
report "PPC_extsh";
ppc_insn := PPC_EXTSH;
elsif std_match(f.insn, "011111---------------1111011010-") then
report "PPC_extsw";
ppc_insn := PPC_EXTSW;
elsif std_match(f.insn, "011111---------------110111101--") then
report "PPC_extswsli";
ppc_insn := PPC_EXTSWSLI;
elsif std_match(f.insn, "011111---------------1111010110-") then
report "PPC_icbi";
ppc_insn := PPC_ICBI;
elsif std_match(f.insn, "011111---------------0000010110-") then
report "PPC_icbt";
ppc_insn := PPC_ICBT;
elsif std_match(f.insn, "011111--------------------01111-") then
report "PPC_isel";
ppc_insn := PPC_ISEL;
elsif std_match(f.insn, "010011---------------0010010110-") then
report "PPC_isync";
ppc_insn := PPC_ISYNC;
elsif std_match(f.insn, "011111---------------0000110100-") then
report "PPC_lbarx";
ppc_insn := PPC_LBARX;
elsif std_match(f.insn, "100010--------------------------") then
report "PPC_lbz";
ppc_insn := PPC_LBZ;
elsif std_match(f.insn, "100011--------------------------") then
report "PPC_lbzu";
ppc_insn := PPC_LBZU;
elsif std_match(f.insn, "011111---------------0001110111-") then
report "PPC_lbzux";
ppc_insn := PPC_LBZUX;
elsif std_match(f.insn, "011111---------------0001010111-") then
report "PPC_lbzx";
ppc_insn := PPC_LBZX;
elsif std_match(f.insn, "111010------------------------00") then
report "PPC_ld";
ppc_insn := PPC_LD;
elsif std_match(f.insn, "011111---------------0001010100-") then
report "PPC_ldarx";
ppc_insn := PPC_LDARX;
elsif std_match(f.insn, "011111---------------1000010100-") then
report "PPC_ldbrx";
ppc_insn := PPC_LDBRX;
elsif std_match(f.insn, "111010------------------------01") then
report "PPC_ldu";
ppc_insn := PPC_LDU;
elsif std_match(f.insn, "011111---------------0000110101-") then
report "PPC_ldux";
ppc_insn := PPC_LDUX;
elsif std_match(f.insn, "011111---------------0000010101-") then
report "PPC_ldx";
ppc_insn := PPC_LDX;
elsif std_match(f.insn, "101010--------------------------") then
report "PPC_lha";
ppc_insn := PPC_LHA;
elsif std_match(f.insn, "011111---------------0001110100-") then
report "PPC_lharx";
ppc_insn := PPC_LHARX;
elsif std_match(f.insn, "101011--------------------------") then
report "PPC_lhau";
ppc_insn := PPC_LHAU;
elsif std_match(f.insn, "011111---------------0101110111-") then
report "PPC_lhaux";
ppc_insn := PPC_LHAUX;
elsif std_match(f.insn, "011111---------------0101010111-") then
report "PPC_lhax";
ppc_insn := PPC_LHAX;
elsif std_match(f.insn, "011111---------------1100010110-") then
report "PPC_lhbrx";
ppc_insn := PPC_LHBRX;
elsif std_match(f.insn, "101000--------------------------") then
report "PPC_lhz";
ppc_insn := PPC_LHZ;
elsif std_match(f.insn, "101001--------------------------") then
report "PPC_lhzu";
ppc_insn := PPC_LHZU;
elsif std_match(f.insn, "011111---------------0100110111-") then
report "PPC_lhzux";
ppc_insn := PPC_LHZUX;
elsif std_match(f.insn, "011111---------------0100010111-") then
report "PPC_lhzx";
ppc_insn := PPC_LHZX;
elsif std_match(f.insn, "111010------------------------10") then
report "PPC_lwa";
ppc_insn := PPC_LWA;
elsif std_match(f.insn, "011111---------------0000010100-") then
report "PPC_lwarx";
ppc_insn := PPC_LWARX;
elsif std_match(f.insn, "011111---------------0101110101-") then
report "PPC_lwaux";
ppc_insn := PPC_LWAUX;
elsif std_match(f.insn, "011111---------------0101010101-") then
report "PPC_lwax";
ppc_insn := PPC_LWAX;
elsif std_match(f.insn, "011111---------------1000010110-") then
report "PPC_lwbrx";
ppc_insn := PPC_LWBRX;
elsif std_match(f.insn, "100000--------------------------") then
report "PPC_lwz";
ppc_insn := PPC_LWZ;
elsif std_match(f.insn, "100001--------------------------") then
report "PPC_lwzu";
ppc_insn := PPC_LWZU;
elsif std_match(f.insn, "011111---------------0000110111-") then
report "PPC_lwzux";
ppc_insn := PPC_LWZUX;
elsif std_match(f.insn, "011111---------------0000010111-") then
report "PPC_lwzx";
ppc_insn := PPC_LWZX;
elsif std_match(f.insn, "000100--------------------110000") then
report "PPC_maddhd";
ppc_insn := PPC_MADDHD;
elsif std_match(f.insn, "000100--------------------110001") then
report "PPC_maddhdu";
ppc_insn := PPC_MADDHDU;
elsif std_match(f.insn, "000100--------------------110011") then
report "PPC_maddld";
ppc_insn := PPC_MADDLD;
elsif std_match(f.insn, "010011---------------0000000000-") then
report "PPC_mcrf";
ppc_insn := PPC_MCRF;
elsif std_match(f.insn, "011111---------------1000000000-") then
report "PPC_mcrxr";
ppc_insn := PPC_MCRXR;
elsif std_match(f.insn, "011111---------------1001000000-") then
report "PPC_mcrxrx";
ppc_insn := PPC_MCRXRX;
elsif std_match(f.insn, "011111-----0---------0000010011-") then
report "PPC_mfcr";
ppc_insn := PPC_MFCR;
elsif std_match(f.insn, "011111-----1---------0000010011-") then
report "PPC_mfocrf";
ppc_insn := PPC_MFOCRF;
-- Specific MF/MT SPR encodings first
elsif std_match(f.insn, "011111-----01001000000101010011-") then
report "PPC_mfctr";
ppc_insn := PPC_MFCTR;
elsif std_match(f.insn, "011111-----01000000000101010011-") then
report "PPC_mflr";
ppc_insn := PPC_MFLR;
elsif std_match(f.insn, "011111-----01100010000101010011-") then
report "PPC_mftb";
ppc_insn := PPC_MFTB;
elsif std_match(f.insn, "011111-----01001000000111010011-") then
report "PPC_mtctr";
ppc_insn := PPC_MTCTR;
elsif std_match(f.insn, "011111-----01000000000111010011-") then
report "PPC_mtlr";
ppc_insn := PPC_MTLR;
elsif std_match(f.insn, "011111---------------0101010011-") then
report "PPC_mfspr";
ppc_insn := PPC_MFSPR;
elsif std_match(f.insn, "011111---------------1100001001-") then
report "PPC_modsd";
ppc_insn := PPC_MODSD;
elsif std_match(f.insn, "011111---------------1100001011-") then
report "PPC_modsw";
ppc_insn := PPC_MODSW;
elsif std_match(f.insn, "011111---------------0100001001-") then
report "PPC_modud";
ppc_insn := PPC_MODUD;
elsif std_match(f.insn, "011111---------------0100001011-") then
report "PPC_moduw";
ppc_insn := PPC_MODUW;
elsif std_match(f.insn, "011111-----0---------0010010000-") then
report "PPC_mtcrf";
ppc_insn := PPC_MTCRF;
elsif std_match(f.insn, "011111-----1---------0010010000-") then
report "PPC_mtocrf";
ppc_insn := PPC_MTOCRF;
elsif std_match(f.insn, "011111---------------0111010011-") then
report "PPC_mtspr";
ppc_insn := PPC_MTSPR;
elsif std_match(f.insn, "011111----------------001001001-") then
report "PPC_mulhd";
ppc_insn := PPC_MULHD;
elsif std_match(f.insn, "011111----------------000001001-") then
report "PPC_mulhdu";
ppc_insn := PPC_MULHDU;
elsif std_match(f.insn, "011111----------------001001011-") then
report "PPC_mulhw";
ppc_insn := PPC_MULHW;
elsif std_match(f.insn, "011111----------------000001011-") then
report "PPC_mulhwu";
ppc_insn := PPC_MULHWU;
elsif std_match(f.insn, "011111---------------0011101001-") then
report "PPC_mulld";
ppc_insn := PPC_MULLD;
elsif std_match(f.insn, "000111--------------------------") then
report "PPC_mulli";
ppc_insn := PPC_MULLI;
elsif std_match(f.insn, "011111---------------0011101011-") then
report "PPC_mullw";
ppc_insn := PPC_MULLW;
elsif std_match(f.insn, "011111---------------0111011100-") then
report "PPC_nand";
ppc_insn := PPC_NAND;
elsif std_match(f.insn, "011111---------------0001101000-") then
report "PPC_neg";
ppc_insn := PPC_NEG;
elsif std_match(f.insn, "011111---------------0001111100-") then
report "PPC_nor";
ppc_insn := PPC_NOR;
elsif std_match(f.insn, "011111---------------0110111100-") then
report "PPC_or";
ppc_insn := PPC_OR;
elsif std_match(f.insn, "011111---------------0110011100-") then
report "PPC_orc";
ppc_insn := PPC_ORC;
elsif std_match(f.insn, "011000--------------------------") then
report "PPC_ori";
ppc_insn := PPC_ORI;
elsif std_match(f.insn, "011001--------------------------") then
report "PPC_oris";
ppc_insn := PPC_ORIS;
elsif std_match(f.insn, "011111---------------0001111010-") then
report "PPC_popcntb";
ppc_insn := PPC_POPCNTB;
elsif std_match(f.insn, "011111---------------0111111010-") then
report "PPC_popcntd";
ppc_insn := PPC_POPCNTD;
elsif std_match(f.insn, "011111---------------0101111010-") then
report "PPC_popcntw";
ppc_insn := PPC_POPCNTW;
elsif std_match(f.insn, "011111---------------0010111010-") then
report "PPC_prtyd";
ppc_insn := PPC_PRTYD;
elsif std_match(f.insn, "011111---------------0010011010-") then
report "PPC_prtyw";
ppc_insn := PPC_PRTYW;
elsif std_match(f.insn, "011110---------------------1000-") then
report "PPC_rldcl";
ppc_insn := PPC_RLDCL;
elsif std_match(f.insn, "011110---------------------1001-") then
report "PPC_rldcr";
ppc_insn := PPC_RLDCR;
elsif std_match(f.insn, "011110---------------------010--") then
report "PPC_rldic";
ppc_insn := PPC_RLDIC;
elsif std_match(f.insn, "011110---------------------000--") then
report "PPC_rldicl";
ppc_insn := PPC_RLDICL;
elsif std_match(f.insn, "011110---------------------001--") then
report "PPC_rldicr";
ppc_insn := PPC_RLDICR;
elsif std_match(f.insn, "011110---------------------011--") then
report "PPC_rldimi";
ppc_insn := PPC_RLDIMI;
elsif std_match(f.insn, "010100--------------------------") then
report "PPC_rlwimi";
ppc_insn := PPC_RLWIMI;
elsif std_match(f.insn, "010101--------------------------") then
report "PPC_rlwinm";
ppc_insn := PPC_RLWINM;
elsif std_match(f.insn, "010111--------------------------") then
report "PPC_rlwnm";
ppc_insn := PPC_RLWNM;
elsif std_match(f.insn, "011111---------------0010000000-") then
report "PPC_setb";
ppc_insn := PPC_SETB;
elsif std_match(f.insn, "011111---------------0000011011-") then
report "PPC_sld";
ppc_insn := PPC_SLD;
elsif std_match(f.insn, "011111---------------0000011000-") then
report "PPC_slw";
ppc_insn := PPC_SLW;
elsif std_match(f.insn, "011111---------------1100011010-") then
report "PPC_srad";
ppc_insn := PPC_SRAD;
elsif std_match(f.insn, "011111---------------110011101--") then
report "PPC_sradi";
ppc_insn := PPC_SRADI;
elsif std_match(f.insn, "011111---------------1100011000-") then
report "PPC_sraw";
ppc_insn := PPC_SRAW;
elsif std_match(f.insn, "011111---------------1100111000-") then
report "PPC_srawi";
ppc_insn := PPC_SRAWI;
elsif std_match(f.insn, "011111---------------1000011011-") then
report "PPC_srd";
ppc_insn := PPC_SRD;
elsif std_match(f.insn, "011111---------------1000011000-") then
report "PPC_srw";
ppc_insn := PPC_SRW;
elsif std_match(f.insn, "100110--------------------------") then
report "PPC_stb";
ppc_insn := PPC_STB;
elsif std_match(f.insn, "011111---------------1010110110-") then
report "PPC_stbcx";
ppc_insn := PPC_STBCX;
elsif std_match(f.insn, "100111--------------------------") then
report "PPC_stbu";
ppc_insn := PPC_STBU;
elsif std_match(f.insn, "011111---------------0011110111-") then
report "PPC_stbux";
ppc_insn := PPC_STBUX;
elsif std_match(f.insn, "011111---------------0011010111-") then
report "PPC_stbx";
ppc_insn := PPC_STBX;
elsif std_match(f.insn, "111110------------------------00") then
report "PPC_std";
ppc_insn := PPC_STD;
elsif std_match(f.insn, "011111---------------1010010100-") then
report "PPC_stdbrx";
ppc_insn := PPC_STDBRX;
elsif std_match(f.insn, "011111---------------0011010110-") then
report "PPC_stdcx";
ppc_insn := PPC_STDCX;
elsif std_match(f.insn, "111110------------------------01") then
report "PPC_stdu";
ppc_insn := PPC_STDU;
elsif std_match(f.insn, "011111---------------0010110101-") then
report "PPC_stdux";
ppc_insn := PPC_STDUX;
elsif std_match(f.insn, "011111---------------0010010101-") then
report "PPC_stdx";
ppc_insn := PPC_STDX;
elsif std_match(f.insn, "101100--------------------------") then
report "PPC_sth";
ppc_insn := PPC_STH;
elsif std_match(f.insn, "011111---------------1110010110-") then
report "PPC_sthbrx";
ppc_insn := PPC_STHBRX;
elsif std_match(f.insn, "011111---------------1011010110-") then
report "PPC_sthcx";
ppc_insn := PPC_STHCX;
elsif std_match(f.insn, "101101--------------------------") then
report "PPC_sthu";
ppc_insn := PPC_STHU;
elsif std_match(f.insn, "011111---------------0110110111-") then
report "PPC_sthux";
ppc_insn := PPC_STHUX;
elsif std_match(f.insn, "011111---------------0110010111-") then
report "PPC_sthx";
ppc_insn := PPC_STHX;
elsif std_match(f.insn, "100100--------------------------") then
report "PPC_stw";
ppc_insn := PPC_STW;
elsif std_match(f.insn, "011111---------------1010010110-") then
report "PPC_stwbrx";
ppc_insn := PPC_STWBRX;
elsif std_match(f.insn, "011111---------------0010010110-") then
report "PPC_stwcx";
ppc_insn := PPC_STWCX;
elsif std_match(f.insn, "100101--------------------------") then
report "PPC_stwu";
ppc_insn := PPC_STWU;
elsif std_match(f.insn, "011111---------------0010110111-") then
report "PPC_stwux";
ppc_insn := PPC_STWUX;
elsif std_match(f.insn, "011111---------------0010010111-") then
report "PPC_stwx";
ppc_insn := PPC_STWX;
elsif std_match(f.insn, "011111---------------0000101000-") then
report "PPC_subf";
ppc_insn := PPC_SUBF;
elsif std_match(f.insn, "011111---------------0000001000-") then
report "PPC_subfc";
ppc_insn := PPC_SUBFC;
elsif std_match(f.insn, "011111---------------0010001000-") then
report "PPC_subfe";
ppc_insn := PPC_SUBFE;
elsif std_match(f.insn, "001000--------------------------") then
report "PPC_subfic";
ppc_insn := PPC_SUBFIC;
elsif std_match(f.insn, "011111---------------0011101000-") then
report "PPC_subfme";
ppc_insn := PPC_SUBFME;
elsif std_match(f.insn, "011111---------------0011001000-") then
report "PPC_subfze";
ppc_insn := PPC_SUBFZE;
elsif std_match(f.insn, "011111---------------1001010110-") then
report "PPC_sync";
ppc_insn := PPC_SYNC;
elsif std_match(f.insn, "011111---------------0001000100-") then
report "PPC_td";
ppc_insn := PPC_TD;
elsif std_match(f.insn, "000010--------------------------") then
report "PPC_tdi";
ppc_insn := PPC_TDI;
elsif std_match(f.insn, "011111---------------0000000100-") then
report "PPC_tw";
ppc_insn := PPC_TW;
elsif std_match(f.insn, "000011--------------------------") then
report "PPC_twi";
ppc_insn := PPC_TWI;
elsif std_match(f.insn, "011111---------------0100111100-") then
report "PPC_xor";
ppc_insn := PPC_XOR;
elsif std_match(f.insn, "011010--------------------------") then
report "PPC_xori";
ppc_insn := PPC_XORI;
elsif std_match(f.insn, "011011--------------------------") then
report "PPC_xoris";
ppc_insn := PPC_XORIS;
elsif std_match(f.insn, "000001---------------0000000000-") then
report "PPC_SIM_READ";
ppc_insn := PPC_SIM_READ;
elsif std_match(f.insn, "000001---------------0000000001-") then
report "PPC_SIM_POLL";
ppc_insn := PPC_SIM_POLL;
elsif std_match(f.insn, "000001---------------0000000010-") then
report "PPC_SIM_WRITE";
ppc_insn := PPC_SIM_WRITE;
elsif std_match(f.insn, "000001---------------0000000011-") then
report "PPC_SIM_CONFIG";
ppc_insn := PPC_SIM_CONFIG;
else
report "PPC_illegal";
ppc_insn := PPC_ILLEGAL;
end if;

d_out.decode <= decode_rom_array(ppc_insn);
end if;
end process;
end architecture behaviour;

@ -0,0 +1,324 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.decode_types.all;
use work.common.all;
use work.helpers.all;

entity decode2 is
port (
clk : in std_ulogic;

d_in : in Decode1ToDecode2Type;

e_out : out Decode2ToExecute1Type;
m_out : out Decode2ToMultiplyType;
l_out : out Decode2ToLoadstore1Type;

r_in : in RegisterFileToDecode2Type;
r_out : out Decode2ToRegisterFileType;

c_in : in CrFileToDecode2Type;
c_out : out Decode2ToCrFileType
);
end entity decode2;

architecture behaviour of decode2 is
signal d : Decode1ToDecode2Type;

alias insn_rs : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
alias insn_rt : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
alias insn_ra : std_ulogic_vector(4 downto 0) is d.insn(20 downto 16);
alias insn_rb : std_ulogic_vector(4 downto 0) is d.insn(15 downto 11);
alias insn_si : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
alias insn_ui : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
alias insn_l : std_ulogic is d.insn(21);
alias insn_sh32 : std_ulogic_vector(4 downto 0) is d.insn(15 downto 11);
alias insn_mb32 : std_ulogic_vector(4 downto 0) is d.insn(10 downto 6);
alias insn_me32 : std_ulogic_vector(4 downto 0) is d.insn(5 downto 1);
alias insn_li : std_ulogic_vector(23 downto 0) is d.insn(25 downto 2);
alias insn_lk : std_ulogic is d.insn(0);
alias insn_rc : std_ulogic is d.insn(0);
alias insn_bd : std_ulogic_vector(13 downto 0) is d.insn(15 downto 2);
alias insn_bf : std_ulogic_vector(2 downto 0) is d.insn(25 downto 23);
alias insn_fxm : std_ulogic_vector(7 downto 0) is d.insn(19 downto 12);
alias insn_bo : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
alias insn_bi : std_ulogic_vector(4 downto 0) is d.insn(20 downto 16);
alias insn_bh : std_ulogic_vector(1 downto 0) is d.insn(12 downto 11);
alias insn_d : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
alias insn_ds : std_ulogic_vector(13 downto 0) is d.insn(15 downto 2);
alias insn_to : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
alias insn_bc : std_ulogic_vector(4 downto 0) is d.insn(10 downto 6);

-- can't use an alias for these
signal insn_sh : std_ulogic_vector(5 downto 0);
signal insn_me : std_ulogic_vector(5 downto 0);
signal insn_mb : std_ulogic_vector(5 downto 0);
begin
insn_sh <= d.insn(1) & d.insn(15 downto 11);
insn_me <= d.insn(5) & d.insn(10 downto 6);
insn_mb <= d.insn(5) & d.insn(10 downto 6);

decode2_0: process(clk)
begin
if rising_edge(clk) then
d <= d_in;
end if;
end process;

r_out.read1_reg <= insn_ra when (d.decode.input_reg_a = RA) else
insn_ra when d.decode.input_reg_a = RA_OR_ZERO else
insn_rs when d.decode.input_reg_a = RS else
(others => '0');

r_out.read2_reg <= insn_rb when d.decode.input_reg_b = RB else
insn_rs when d.decode.input_reg_b = RS else
(others => '0');

r_out.read3_reg <= insn_rs when d.decode.input_reg_c = RS else
(others => '0');

decode2_1: process(all)
variable mul_a : std_ulogic_vector(63 downto 0);
variable mul_b : std_ulogic_vector(63 downto 0);
begin
e_out <= Decode2ToExecute1Init;
l_out <= Decode2ToLoadStore1Init;
m_out <= Decode2ToMultiplyInit;

mul_a := (others => '0');
mul_b := (others => '0');

e_out.nia <= d.nia;
l_out.nia <= d.nia;
m_out.nia <= d.nia;

--e_out.input_cr <= d.decode.input_cr;
--m_out.input_cr <= d.decode.input_cr;
--e_out.output_cr <= d.decode.output_cr;

e_out.cr <= c_in.read_cr_data;

e_out.input_carry <= d.decode.input_carry;
e_out.output_carry <= d.decode.output_carry;

if d.decode.lr then
e_out.lr <= insn_lk;
end if;

-- XXX This is getting too complicated. Use variables and assign to each unit later

case d.decode.unit is
when ALU =>
e_out.insn_type <= d.decode.insn_type;
e_out.valid <= d.valid;
when LDST =>
l_out.valid <= d.valid;
when MUL =>
m_out.insn_type <= d.decode.insn_type;
m_out.valid <= d.valid;
when NONE =>
e_out.insn_type <= OP_ILLEGAL;
e_out.valid <= d.valid;
end case;

-- required for bypassing
case d.decode.input_reg_a is
when RA =>
e_out.read_reg1 <= insn_ra;
l_out.update_reg <= insn_ra;
when RA_OR_ZERO =>
e_out.read_reg1 <= insn_ra;
l_out.update_reg <= insn_ra;
when RS =>
e_out.read_reg1 <= insn_rs;
when NONE =>
e_out.read_reg1 <= (others => '0');
l_out.update_reg <= (others => '0');
end case;

-- required for bypassing
case d.decode.input_reg_b is
when RB =>
e_out.read_reg2 <= insn_rb;
when RS =>
e_out.read_reg2 <= insn_rs;
when others =>
e_out.read_reg2 <= (others => '0');
end case;

-- required for bypassing
--case d.decode.input_reg_c is
--when RS =>
--e_out.read_reg3 <= insn_rs;
--when NONE =>
--e_out.read_reg3 <= (others => '0');
--end case;

case d.decode.input_reg_a is