Initial import of microwatt

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
pull/4/head
Anton Blanchard 5 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
when RA =>
e_out.read_data1 <= r_in.read1_data;
mul_a := r_in.read1_data;
l_out.addr1 <= r_in.read1_data;
when RA_OR_ZERO =>
e_out.read_data1 <= ra_or_zero(r_in.read1_data, insn_ra);
l_out.addr1 <= ra_or_zero(r_in.read1_data, insn_ra);
when RS =>
e_out.read_data1 <= r_in.read1_data;
when NONE =>
e_out.read_data1 <= (others => '0');
mul_a := (others => '0');
end case;

case d.decode.input_reg_b is
when RB =>
e_out.read_data2 <= r_in.read2_data;
mul_b := r_in.read2_data;
l_out.addr2 <= r_in.read2_data;
when RS =>
e_out.read_data2 <= r_in.read2_data;
when CONST_UI =>
e_out.read_data2 <= std_ulogic_vector(resize(unsigned(insn_ui), 64));
when CONST_SI =>
e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_si), 64));
l_out.addr2 <= std_ulogic_vector(resize(signed(insn_si), 64));
mul_b := std_ulogic_vector(resize(signed(insn_si), 64));
when CONST_SI_HI =>
e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_si) & x"0000", 64));
when CONST_UI_HI =>
e_out.read_data2 <= std_ulogic_vector(resize(unsigned(insn_si) & x"0000", 64));
when CONST_LI =>
e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_li) & "00", 64));
when CONST_BD =>
e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_bd) & "00", 64));
when CONST_DS =>
l_out.addr2 <= std_ulogic_vector(resize(signed(insn_ds) & "00", 64));
when NONE =>
e_out.read_data2 <= (others => '0');
l_out.addr2 <= (others => '0');
mul_b := (others => '0');
end case;

case d.decode.input_reg_c is
when RS =>
l_out.data <= r_in.read3_data;
when NONE =>
l_out.data <= (others => '0');
end case;

if d.decode.mul_32bit = '1' then
if d.decode.mul_signed = '1' then
m_out.data1 <= (others => mul_a(31));
m_out.data1(31 downto 0) <= mul_a(31 downto 0);
m_out.data2 <= (others => mul_b(31));
m_out.data2(31 downto 0) <= mul_b(31 downto 0);
else
m_out.data1 <= '0' & x"00000000" & mul_a(31 downto 0);
m_out.data2 <= '0' & x"00000000" & mul_b(31 downto 0);
end if;
else
if d.decode.mul_signed = '1' then
m_out.data1 <= mul_a(63) & mul_a;
m_out.data2 <= mul_b(63) & mul_b;
else
m_out.data1 <= '0' & mul_a;
m_out.data2 <= '0' & mul_b;
end if;
end if;

case d.decode.const_a is
when SH =>
e_out.const1(insn_sh'range) <= insn_sh;
when SH32 =>
e_out.const1(insn_sh32'range) <= insn_sh32;
when FXM =>
e_out.const1(insn_fxm'range) <= insn_fxm;
when BO =>
e_out.const1(insn_bo'range)<= insn_bo;
when BF =>
e_out.const1(insn_bf'range)<= insn_bf;
when TOO =>
e_out.const1(insn_to'range)<= insn_to;
when BC =>
e_out.const1(insn_bc'range)<= insn_bc;
when NONE =>
e_out.const1 <= (others => '0');
end case;

case d.decode.const_b is
when MB =>
e_out.const2(insn_mb'range) <= insn_mb;
when ME =>
e_out.const2(insn_me'range) <= insn_me;
when MB32 =>
e_out.const2(insn_mb32'range) <= insn_mb32;
when BI =>
e_out.const2(insn_bi'range) <= insn_bi;
when L =>
e_out.const2(0) <= insn_l;
when NONE =>
e_out.const2 <= (others => '0');
end case;

case d.decode.const_c is
when ME32 =>
e_out.const3(insn_me32'range) <= insn_me32;
when BH =>
e_out.const3(insn_bh'range) <= insn_bh;
when NONE =>
e_out.const3 <= (others => '0');
end case;

case d.decode.output_reg_a is
when RT =>
e_out.write_reg <= insn_rt;
l_out.write_reg <= insn_rt;
m_out.write_reg <= insn_rt;
when RA =>
e_out.write_reg <= insn_ra;
l_out.write_reg <= insn_ra;
when NONE =>
e_out.write_reg <= (others => '0');
l_out.write_reg <= (others => '0');
m_out.write_reg <= (others => '0');
end case;

case d.decode.rc is
when RC =>
e_out.rc <= insn_rc;
m_out.rc <= insn_rc;
when ONE =>
e_out.rc <= '1';
m_out.rc <= '1';
when NONE =>
e_out.rc <= '0';
m_out.rc <= '0';
end case;

-- load/store specific signals
if d.decode.insn_type = OP_LOAD then
l_out.load <= '1';
else
l_out.load <= '0';
end if;

case d.decode.length is
when is1B =>
l_out.length <= "0001";
when is2B =>
l_out.length <= "0010";
when is4B =>
l_out.length <= "0100";
when is8B =>
l_out.length <= "1000";
when NONE =>
l_out.length <= "0000";
end case;

l_out.byte_reverse <= d.decode.byte_reverse;
l_out.sign_extend <= d.decode.sign_extend;
l_out.update <= d.decode.update;
end process;
end architecture behaviour;

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

package decode_types is
type ppc_insn_t is (PPC_ILLEGAL, PPC_ADD, PPC_ADDC, PPC_ADDE,
PPC_ADDEX, PPC_ADDI, PPC_ADDIC, PPC_ADDIC_RC, PPC_ADDIS,
PPC_ADDME, PPC_ADDPCIS, PPC_ADDZE, PPC_AND, PPC_ANDC,
PPC_ANDI_RC, PPC_ANDIS_RC, PPC_ATTN, PPC_B, PPC_BA, PPC_BC,
PPC_BCA, PPC_BCCTR, PPC_BCLA, PPC_BCLR, PPC_BCTAR, PPC_BPERM,
PPC_CMP, PPC_CMPB, PPC_CMPEQB, PPC_CMPI, PPC_CMPL, PPC_CMPLI,
PPC_CMPRB, PPC_CNTLZD, PPC_CNTLZW, PPC_CNTTZD, PPC_CNTTZW,
PPC_CRAND, PPC_CRANDC, PPC_CREQV, PPC_CRNAND, PPC_CRNOR,
PPC_CROR, PPC_CRORC, PPC_CRXOR, PPC_DARN, PPC_DCBF, PPC_DCBST,
PPC_DCBT, PPC_DCBTST, PPC_DCBZ, PPC_DIVD, PPC_DIVDE,
PPC_DIVDEU, PPC_DIVDU, PPC_DIVW, PPC_DIVWE, PPC_DIVWEU,
PPC_DIVWU, PPC_EQV, PPC_EXTSB, PPC_EXTSH, PPC_EXTSW,
PPC_EXTSWSLI, PPC_ICBI, PPC_ICBT, PPC_ISEL, PPC_ISYNC,
PPC_LBARX, PPC_LBZ, PPC_LBZU, PPC_LBZUX, PPC_LBZX, PPC_LD,
PPC_LDARX, PPC_LDBRX, PPC_LDU, PPC_LDUX, PPC_LDX, PPC_LHA,
PPC_LHARX, PPC_LHAU, PPC_LHAUX, PPC_LHAX, PPC_LHBRX, PPC_LHZ,
PPC_LHZU, PPC_LHZUX, PPC_LHZX, PPC_LWA, PPC_LWARX, PPC_LWAUX,
PPC_LWAX, PPC_LWBRX, PPC_LWZ, PPC_LWZU, PPC_LWZUX, PPC_LWZX,
PPC_MADDHD, PPC_MADDHDU, PPC_MADDLD, PPC_MCRF, PPC_MCRXR,
PPC_MCRXRX, PPC_MFCR, PPC_MFOCRF, PPC_MFSPR, PPC_MFTB,
PPC_MODSD, PPC_MODSW, PPC_MODUD, PPC_MODUW, PPC_MTCRF,
PPC_MFCTR, PPC_MTCTR, PPC_MFLR, PPC_MTLR, PPC_MTOCRF,
PPC_MTSPR, PPC_MULHD, PPC_MULHDU, PPC_MULHW, PPC_MULHWU,
PPC_MULLD, PPC_MULLI, PPC_MULLW, PPC_NAND, PPC_NEG, PPC_NOR,
PPC_OR, PPC_ORC, PPC_ORI, PPC_ORIS, PPC_POPCNTB, PPC_POPCNTD,
PPC_POPCNTW, PPC_PRTYD, PPC_PRTYW, PPC_RLDCL, PPC_RLDCR,
PPC_RLDIC, PPC_RLDICL, PPC_RLDICR, PPC_RLDIMI, PPC_RLWIMI,
PPC_RLWINM, PPC_RLWNM, PPC_SETB, PPC_SLD, PPC_SLW, PPC_SRAD,
PPC_SRADI, PPC_SRAW, PPC_SRAWI, PPC_SRD, PPC_SRW, PPC_STB,
PPC_STBCX, PPC_STBU, PPC_STBUX, PPC_STBX, PPC_STD, PPC_STDBRX,
PPC_STDCX, PPC_STDU, PPC_STDUX, PPC_STDX, PPC_STH, PPC_STHBRX,
PPC_STHCX, PPC_STHU, PPC_STHUX, PPC_STHX, PPC_STW, PPC_STWBRX,
PPC_STWCX, PPC_STWU, PPC_STWUX, PPC_STWX, PPC_SUBF, PPC_SUBFC,
PPC_SUBFE, PPC_SUBFIC, PPC_SUBFME, PPC_SUBFZE, PPC_SYNC, PPC_TD,
PPC_TDI, PPC_TW, PPC_TWI, PPC_XOR, PPC_XORI, PPC_XORIS,
PPC_SIM_READ, PPC_SIM_POLL, PPC_SIM_WRITE, PPC_SIM_CONFIG);

type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, OP_ADDC, OP_ADDEX, OP_ADDME,
OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BA, OP_BC,
OP_BCA, OP_BCCTR, OP_BCLA, OP_BCLR, OP_BCTAR, OP_BPERM, OP_CMP,
OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB,
OP_CNTLZD, OP_CNTLZW, OP_CNTTZD, OP_CNTTZW, OP_CRAND,
OP_CRANDC, OP_CREQV, OP_CRNAND, OP_CRNOR, OP_CROR, OP_CRORC,
OP_CRXOR, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
OP_DCBZ, OP_DIVD, OP_DIVDE, OP_DIVDEU, OP_DIVDU, OP_DIVW,
OP_DIVWE, OP_DIVWEU, OP_DIVWU, OP_EQV, OP_EXTSB, OP_EXTSH,
OP_EXTSW, OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF,
OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFOCRF, OP_MFCTR, OP_MFLR,
OP_MFTB, OP_MFSPR, OP_MODSD, OP_MODSW, OP_MODUD, OP_MODUW,
OP_MTCRF, OP_MTOCRF, OP_MTCTR, OP_MTLR, OP_MTSPR, OP_MUL_L64,
OP_MUL_H64, OP_MUL_H32, OP_NAND, OP_NEG, OP_NOR, OP_OR,
OP_ORC, OP_POPCNTB, OP_POPCNTD, OP_POPCNTW, OP_PRTYD,
OP_PRTYW, OP_RLDCL, OP_RLDCR, OP_RLDIC, OP_RLDICL, OP_RLDICR,
OP_RLDIMI, OP_RLWIMI, OP_RLWINM, OP_RLWNM, OP_SETB, OP_SLD,
OP_SLW, OP_SRAD, OP_SRADI, OP_SRAW, OP_SRAWI, OP_SRD, OP_SRW,
OP_SUBF, OP_SUBFC, OP_SUBFME, OP_SYNC, OP_TD, OP_TDI, OP_TW,
OP_TWI, OP_XOR, OP_SIM_READ, OP_SIM_POLL, OP_SIM_WRITE,
OP_SIM_CONFIG);

type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RS);
type input_reg_b_t is (NONE, RB, RS, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS);
type input_reg_c_t is (NONE, RS);
type output_reg_a_t is (NONE, RT, RA);
type constant_a_t is (NONE, SH, SH32, FXM, BO, BF, TOO, BC);
type constant_b_t is (NONE, MB, ME, MB32, BI, L);
type constant_c_t is (NONE, ME32, BH);
type rc_t is (NONE, ONE, RC);

constant SH_OFFSET : integer := 0;
constant MB_OFFSET : integer := 1;
constant ME_OFFSET : integer := 1;
constant SH32_OFFSET : integer := 0;
constant MB32_OFFSET : integer := 1;
constant ME32_OFFSET : integer := 2;

constant FXM_OFFSET : integer := 0;

constant BO_OFFSET : integer := 0;
constant BI_OFFSET : integer := 1;
constant BH_OFFSET : integer := 2;

constant BF_OFFSET : integer := 0;
constant L_OFFSET : integer := 1;

constant TOO_OFFSET : integer := 0;

type unit_t is (NONE, ALU, LDST, MUL);
type length_t is (NONE, is1B, is2B, is4B, is8B);

type decode_rom_t is record
unit : unit_t;
insn_type : insn_type_t;
input_reg_a : input_reg_a_t;
input_reg_b : input_reg_b_t;
input_reg_c : input_reg_c_t;
output_reg_a : output_reg_a_t;

const_a : constant_a_t;
const_b : constant_b_t;
const_c : constant_c_t;

input_cr : std_ulogic;
output_cr : std_ulogic;

input_carry : std_ulogic;
output_carry : std_ulogic;

-- load/store signals
length : length_t;
byte_reverse : std_ulogic;
sign_extend : std_ulogic;
update : std_ulogic;
reserve : std_ulogic;

-- multiplier signals
mul_32bit : std_ulogic;
mul_signed : std_ulogic;

rc : rc_t;
lr : std_ulogic;
end record;
constant decode_rom_init : decode_rom_t := (unit => NONE,
insn_type => OP_ILLEGAL, input_reg_a => NONE,
input_reg_b => NONE, input_reg_c => NONE,
output_reg_a => NONE, const_a => NONE, const_b => NONE,
const_c => NONE, input_cr => '0', output_cr => '0',
input_carry => '0', output_carry => '0',
length => NONE, byte_reverse => '0', sign_extend => '0',
update => '0', reserve => '0', mul_32bit => '0',
mul_signed => '0', rc => NONE, lr => '0');

end decode_types;

package body decode_types is
end decode_types;

@ -0,0 +1,360 @@
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;
use work.crhelpers.all;
use work.ppc_fx_insns.all;
use work.sim_console.all;

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

e_in : in Decode2ToExecute1Type;
f_out : out Execute1ToFetch1Type;
e_out : out Execute1ToExecute2Type;

terminate_out : out std_ulogic
);
end entity execute1;

architecture behaviour of execute1 is
signal e: Decode2ToExecute1Type := Decode2ToExecute1Init;
signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
begin
execute1_0: process(clk)
begin
if rising_edge(clk) then
e <= e_in;
ctrl <= ctrl_tmp;
end if;
end process;

execute1_1: process(all)
variable result : std_ulogic_vector(63 downto 0);
variable result_with_carry : std_ulogic_vector(64 downto 0);
variable result_en : integer;
variable crnum : integer;
begin
result := (others => '0');
result_with_carry := (others => '0');
result_en := 0;

e_out <= Execute1ToExecute2Init;
f_out <= Execute1ToFetch1TypeInit;
ctrl_tmp <= ctrl;
-- FIXME: run at 512MHz not core freq
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);

terminate_out <= '0';

if e.valid = '1' then
e_out.valid <= '1';
e_out.write_reg <= e.write_reg;

report "execute " & to_hstring(e.nia);

case_0: case e.insn_type is

when OP_ILLEGAL =>
terminate_out <= '1';
report "illegal";
when OP_NOP =>
-- Do nothing
when OP_ADD =>
result := ppc_add(e.read_data1, e.read_data2);
result_en := 1;
when OP_ADDC =>
result_with_carry := ppc_adde(e.read_data1, e.read_data2, ctrl.carry and e.input_carry);
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64) and e.output_carry;
result_en := 1;
when OP_AND =>
result := ppc_and(e.read_data1, e.read_data2);
result_en := 1;
when OP_ANDC =>
result := ppc_andc(e.read_data1, e.read_data2);
result_en := 1;
when OP_B =>
f_out.redirect <= '1';
f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2));
when OP_BC =>
if e.const1(4-2) = '0' then
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
end if;
if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2));
end if;
when OP_BCLR =>
if e.const1(4-2) = '0' then
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
end if;
if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
end if;
when OP_BCCTR =>
if ppc_bcctr_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
end if;
when OP_CMPB =>
result := ppc_cmpb(e.read_data1, e.read_data2);
result_en := 1;
when OP_CMP =>
e_out.write_cr_enable <= '1';
crnum := to_integer(unsigned(e.const1(2 downto 0)));
e_out.write_cr_mask <= num_to_fxm(crnum);
e_out.write_cr_data <= (others => '0');
e_out.write_cr_data((4*(7-crnum)+3) downto (4*(7-crnum))) <= ppc_cmp(e.const2(0), e.read_data1, e.read_data2);
when OP_CMPL =>
e_out.write_cr_enable <= '1';
crnum := to_integer(unsigned(e.const1(2 downto 0)));
e_out.write_cr_mask <= num_to_fxm(crnum);
e_out.write_cr_data <= (others => '0');
e_out.write_cr_data((4*(7-crnum)+3) downto (4*(7-crnum))) <= ppc_cmpl(e.const2(0), e.read_data1, e.read_data2);
when OP_CNTLZW =>
result := ppc_cntlzw(e.read_data1);
result_en := 1;
when OP_CNTTZW =>
result := ppc_cnttzw(e.read_data1);
result_en := 1;
when OP_CNTLZD =>
result := ppc_cntlzd(e.read_data1);
result_en := 1;
when OP_CNTTZD =>
result := ppc_cnttzd(e.read_data1);
result_en := 1;
when OP_EXTSB =>
result := ppc_extsb(e.read_data1);
result_en := 1;
when OP_EXTSH =>
result := ppc_extsh(e.read_data1);
result_en := 1;
when OP_EXTSW =>
result := ppc_extsw(e.read_data1);
result_en := 1;
when OP_EQV =>
result := ppc_eqv(e.read_data1, e.read_data2);
result_en := 1;
when OP_ISEL =>
crnum := to_integer(unsigned(e.const1));
if e.cr(31-crnum) = '1' then
result := e.read_data1;
else
result := e.read_data2;
end if;
result_en := 1;
when OP_MFCTR =>
result := ctrl.ctr;
result_en := 1;
when OP_MFLR =>
result := ctrl.lr;
result_en := 1;
when OP_MFTB =>
result := ctrl.tb;
result_en := 1;
when OP_MTCTR =>
ctrl_tmp.ctr <= e.read_data1;
when OP_MTLR =>
ctrl_tmp.lr <= e.read_data1;
when OP_MFCR =>
result := x"00000000" & e.cr;
result_en := 1;
when OP_MFOCRF =>
crnum := fxm_to_num(e.const1(7 downto 0));
result := (others => '0');
result((4*(7-crnum)+3) downto (4*(7-crnum))) := e.cr((4*(7-crnum)+3) downto (4*(7-crnum)));
result_en := 1;
when OP_MTCRF =>
e_out.write_cr_enable <= '1';
e_out.write_cr_mask <= e.const1(7 downto 0);
e_out.write_cr_data <= e.read_data1(31 downto 0);
when OP_MTOCRF =>
e_out.write_cr_enable <= '1';
-- We require one hot priority encoding here
crnum := fxm_to_num(e.const1(7 downto 0));
e_out.write_cr_mask <= num_to_fxm(crnum);
e_out.write_cr_data <= e.read_data1(31 downto 0);
when OP_NAND =>
result := ppc_nand(e.read_data1, e.read_data2);
result_en := 1;
when OP_NEG =>
result := ppc_neg(e.read_data1);
result_en := 1;
when OP_NOR =>
result := ppc_nor(e.read_data1, e.read_data2);
result_en := 1;
when OP_OR =>
result := ppc_or(e.read_data1, e.read_data2);
result_en := 1;
when OP_ORC =>
result := ppc_orc(e.read_data1, e.read_data2);
result_en := 1;
when OP_POPCNTB =>
result := ppc_popcntb(e.read_data1);
result_en := 1;
when OP_POPCNTW =>
result := ppc_popcntw(e.read_data1);
result_en := 1;
when OP_POPCNTD =>
result := ppc_popcntd(e.read_data1);
result_en := 1;
when OP_PRTYD =>
result := ppc_prtyd(e.read_data1);
result_en := 1;
when OP_PRTYW =>
result := ppc_prtyw(e.read_data1);
result_en := 1;
when OP_RLDCL =>
result := ppc_rldcl(e.read_data1, e.read_data2, e.const2(5 downto 0));
result_en := 1;
when OP_RLDCR =>
result := ppc_rldcr(e.read_data1, e.read_data2, e.const2(5 downto 0));
result_en := 1;
when OP_RLDICL =>
result := ppc_rldicl(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
result_en := 1;
when OP_RLDICR =>
result := ppc_rldicr(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
result_en := 1;
when OP_RLWNM =>
result := ppc_rlwnm(e.read_data1, e.read_data2, e.const2(4 downto 0), e.const3(4 downto 0));
result_en := 1;
when OP_RLWINM =>
result := ppc_rlwinm(e.read_data1, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0));
result_en := 1;
when OP_RLDIC =>
result := ppc_rldic(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
result_en := 1;
when OP_RLDIMI =>
result := ppc_rldimi(e.read_data1, e.read_data2, e.const1(5 downto 0), e.const2(5 downto 0));
result_en := 1;
when OP_RLWIMI =>
result := ppc_rlwimi(e.read_data1, e.read_data2, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0));
result_en := 1;
when OP_SLD =>
result := ppc_sld(e.read_data1, e.read_data2);
result_en := 1;
when OP_SLW =>
result := ppc_slw(e.read_data1, e.read_data2);
result_en := 1;
when OP_SRAW =>
result_with_carry := ppc_sraw(e.read_data1, e.read_data2);
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRAWI =>
result_with_carry := ppc_srawi(e.read_data1, e.const1(5 downto 0));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRAD =>
result_with_carry := ppc_srad(e.read_data1, e.read_data2);
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRADI =>
result_with_carry := ppc_sradi(e.read_data1, e.const1(5 downto 0));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SUBF =>
result := ppc_subf(e.read_data1, e.read_data2);
result_en := 1;
when OP_SUBFC =>
result_with_carry := ppc_subfe(e.read_data1, e.read_data2, ctrl.carry or not(e.input_carry));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64) and e.output_carry;
result_en := 1;
when OP_XOR =>
result := ppc_xor(e.read_data1, e.read_data2);
result_en := 1;

-- sim console
when OP_SIM_READ =>
if SIM = true then
sim_console_read(result);
result_en := 1;
else
terminate_out <= '1';
report "illegal";
end if;
when OP_SIM_POLL =>
if SIM = true then
sim_console_poll(result);
result_en := 1;
else
terminate_out <= '1';
report "illegal";
end if;
when OP_SIM_WRITE =>
if SIM = true then
sim_console_write(e.read_data1);
else
terminate_out <= '1';
report "illegal";
end if;
when OP_SIM_CONFIG =>
if SIM = true then
result := x"0000000000000001";
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 OP_DIVDU =>
if SIM = true then
result := ppc_divdu(e.read_data1, e.read_data2);
result_en := 1;
else
terminate_out <= '1';
report "illegal";
end if;
when OP_DIVD =>
if SIM = true then
result := ppc_divd(e.read_data1, e.read_data2);
result_en := 1;
else
terminate_out <= '1';
report "illegal";
end if;
when OP_DIVWU =>
if SIM = true then
result := ppc_divwu(e.read_data1, e.read_data2);
result_en := 1;

else
terminate_out <= '1';
report "illegal";
end if;
when others =>
terminate_out <= '1';
report "illegal";
end case;

if e.lr = '1' then
ctrl_tmp.lr <= std_ulogic_vector(unsigned(e.nia) + 4);
end if;

if result_en = 1 then
e_out.write_data <= result;
e_out.write_enable <= '1';
e_out.rc <= e.rc;
end if;
end if;
end process;
end architecture behaviour;

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

library work;
use work.common.all;
use work.crhelpers.all;
use work.ppc_fx_insns.all;

-- 2 cycle ALU
-- We handle rc form instructions here

entity execute2 is
port (
clk : in std_ulogic;

e_in : in Execute1ToExecute2Type;
e_out : out Execute2ToWritebackType
);
end execute2;

architecture behave of execute2 is
signal e: Execute1ToExecute2Type;
begin
execute2_0: process(clk)
begin
if (rising_edge(clk)) then
e <= e_in;
end if;
end process;

execute2_1: process(all)
begin
e_out.valid <= e.valid;
e_out.write_enable <= e.write_enable;
e_out.write_reg <= e.write_reg;
e_out.write_data <= e.write_data;
e_out.write_cr_enable <= e.write_cr_enable;
e_out.write_cr_mask <= e.write_cr_mask;
e_out.write_cr_data <= e.write_cr_data;

if e.valid = '1' and e.rc = '1' then
e_out.write_cr_enable <= '1';
e_out.write_cr_mask <= num_to_fxm(0);
e_out.write_cr_data <= ppc_cmpi('1', e.write_data, x"0000") & x"0000000";
end if;
end process;
end;

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

library work;
use work.common.all;

entity fetch1 is
generic(
RESET_ADDRESS : std_logic_vector(63 downto 0)
);
port(
clk : in std_ulogic;
rst : in std_ulogic;

-- Control inputs:
fetch_one_in : in std_ulogic;

-- redirect from execution unit
e_in : in Execute1ToFetch1Type;

-- fetch data out
f_out : out Fetch1ToFetch2Type
);
end entity fetch1;

architecture behaviour of fetch1 is
type reg_type is record
pc : std_ulogic_vector(63 downto 0);
fetch_one : std_ulogic;
end record;

signal r : reg_type;
signal rin : reg_type;
begin
regs : process(clk)
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;

comb : process(all)
variable v : reg_type;
variable fetch_valid : std_ulogic;
variable fetch_nia : std_ulogic_vector(63 downto 0);
begin
v := r;

fetch_valid := '0';
fetch_nia := (others => '0');

v.fetch_one := v.fetch_one or fetch_one_in;

if e_in.redirect = '1' then
v.pc := e_in.redirect_nia;
end if;

if v.fetch_one = '1' then
fetch_nia := v.pc;
fetch_valid := '1';
v.pc := std_logic_vector(unsigned(v.pc) + 4);

v.fetch_one := '0';
end if;

if rst = '1' then
v.pc := RESET_ADDRESS;
v.fetch_one := '0';
end if;

rin <= v;

f_out.valid <= fetch_valid;
f_out.nia <= fetch_nia;
end process;

end architecture behaviour;

@ -0,0 +1,70 @@
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 fetch2 is
port(
clk : in std_ulogic;

-- instruction memory interface
wishbone_in : in wishbone_slave_out;
wishbone_out : out wishbone_master_out;

f_in : in Fetch1ToFetch2Type;

f_out : out Fetch2ToDecode1Type
);
end entity fetch2;

architecture behaviour of fetch2 is
type reg_type is record
valid : std_ulogic;
nia : std_ulogic_vector(63 downto 0);
end record;

signal f : Fetch1ToFetch2Type;
signal wishbone: wishbone_slave_out;
signal r : reg_type := (valid => '0', nia => (others => '0'));
signal rin : reg_type := (valid => '0', nia => (others => '0'));
begin
regs : process(clk)
begin
if rising_edge(clk) then
wishbone <= wishbone_in;
f <= f_in;
r <= rin;
end if;
end process;

comb : process(all)
variable v : reg_type;
begin
v := r;

if f.valid = '1' then
v.valid := '1';
v.nia := f.nia;
end if;

if v.valid = '1' and wishbone.ack = '1' then
v.valid := '0';
end if;

rin <= v;

wishbone_out.adr <= v.nia(63 downto 3) & "000";
wishbone_out.dat <= (others => '0');
wishbone_out.cyc <= v.valid;
wishbone_out.stb <= v.valid;
wishbone_out.sel <= "00001111" when v.nia(2) = '0' else "11110000";
wishbone_out.we <= '0';

f_out.valid <= wishbone.ack;
f_out.nia <= v.nia;
f_out.insn <= wishbone.dat(31 downto 0) when v.nia(2) = '0' else wishbone.dat(63 downto 32);
end process;
end architecture behaviour;

@ -0,0 +1,12 @@
Copyright (c) Kristian Klomsten Skordal
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,10 @@
set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]

set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports reset_n]

set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart0_txd]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart0_rxd]

set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

@ -0,0 +1,91 @@
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;

--! @brief A generic FIFO module.
--! Adopted from the FIFO module in <https://github.com/skordal/smallthings>.
entity pp_fifo is
generic(
DEPTH : natural := 64;
WIDTH : natural := 32
);
port(
-- Control lines:
clk : in std_logic;
reset : in std_logic;

-- Status lines:
full : out std_logic;
empty : out std_logic;

-- Data in:
data_in : in std_logic_vector(WIDTH - 1 downto 0);
data_out : out std_logic_vector(WIDTH - 1 downto 0);
push, pop : in std_logic
);
end entity pp_fifo;

architecture behaviour of pp_fifo is

type memory_array is array(0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0);
shared variable memory : memory_array := (others => (others => '0'));

subtype index_type is integer range 0 to DEPTH - 1;
signal top, bottom : index_type;

type fifo_op is (FIFO_POP, FIFO_PUSH);
signal prev_op : fifo_op := FIFO_POP;

begin

empty <= '1' when top = bottom and prev_op = FIFO_POP else '0';
full <= '1' when top = bottom and prev_op = FIFO_PUSH else '0';

read: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
bottom <= 0;
else
if pop = '1' then
data_out <= memory(bottom);
bottom <= (bottom + 1) mod DEPTH;
end if;
end if;
end if;
end process read;

write: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
top <= 0;
else
if push = '1' then
memory(top) := data_in;
top <= (top + 1) mod DEPTH;
end if;
end if;
end if;
end process write;

set_prev_op: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
prev_op <= FIFO_POP;
else
if push = '1' and pop = '1' then
prev_op <= FIFO_POP;
elsif push = '1' then
prev_op <= FIFO_PUSH;
elsif pop = '1' then
prev_op <= FIFO_POP;
end if;
end if;
end if;
end process set_prev_op;

end architecture behaviour;

@ -0,0 +1,106 @@
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

use work.pp_utilities.all;

--! @brief Simple memory module for use in Wishbone-based systems.
entity pp_soc_memory is
generic(
MEMORY_SIZE : natural := 4096 --! Memory size in bytes.
);
port(
clk : in std_logic;
reset : in std_logic;

-- Wishbone interface:
wb_adr_in : in std_logic_vector(log2(MEMORY_SIZE) - 1 downto 0);
wb_dat_in : in std_logic_vector(63 downto 0);
wb_dat_out : out std_logic_vector(63 downto 0);
wb_cyc_in : in std_logic;
wb_stb_in : in std_logic;
wb_sel_in : in std_logic_vector( 7 downto 0);
wb_we_in : in std_logic;
wb_ack_out : out std_logic
);
end entity pp_soc_memory;

architecture behaviour of pp_soc_memory is
type ram_t is array(0 to (MEMORY_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

impure function init_ram(name : STRING) return ram_t is
file ram_file : text open read_mode is name;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
begin
for i in 0 to (MEMORY_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i) := temp_word;
end loop;

return temp_ram;
end function;

signal memory : ram_t := init_ram("firmware.hex");

attribute ram_style : string;
attribute ram_style of memory : signal is "block";

attribute ram_decomp : string;
attribute ram_decomp of memory : signal is "power";

type state_type is (IDLE, ACK);
signal state : state_type;

signal read_ack : std_logic;

begin

wb_ack_out <= read_ack and wb_stb_in;

process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
read_ack <= '0';
state <= IDLE;
else
if wb_cyc_in = '1' then
case state is
when IDLE =>
if wb_stb_in = '1' and wb_we_in = '1' then
for i in 0 to 7 loop
if wb_sel_in(i) = '1' then
memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 3))))(((i + 1) * 8) - 1 downto i * 8)
<= wb_dat_in(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
read_ack <= '1';
state <= ACK;
elsif wb_stb_in = '1' then
wb_dat_out <= memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 3))));
read_ack <= '1';
state <= ACK;
end if;
when ACK =>
if wb_stb_in = '0' then
read_ack <= '0';
state <= IDLE;
end if;
end case;
else
state <= IDLE;
read_ack <= '0';
end if;
end if;
end if;
end process clk;

end architecture behaviour;

@ -0,0 +1,69 @@
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2018 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;
use work.pp_utilities.all;

--! @brief System reset unit.
--! Because most resets in the processor core are synchronous, at least one
--! clock pulse has to be given to the processor while the reset signal is
--! asserted. However, if the clock generator is being reset at the same time,
--! the system clock might not run during reset, preventing the processor from
--! properly resetting.
entity pp_soc_reset is
generic(
RESET_CYCLE_COUNT : natural := 20000000
);
port(
clk : in std_logic;

reset_n : in std_logic;
reset_out : out std_logic;

system_clk : in std_logic;
system_clk_locked : in std_logic
);
end entity pp_soc_reset;

architecture behaviour of pp_soc_reset is

subtype counter_type is natural range 0 to RESET_CYCLE_COUNT;
signal counter : counter_type;

signal fast_reset : std_logic := '0';
signal slow_reset : std_logic := '1';
begin

reset_out <= slow_reset;

-- process(clk)
-- begin
-- if rising_edge(clk) then
-- if reset_n = '0' then
-- fast_reset <= '1';
-- elsif system_clk_locked = '1' then
-- if fast_reset = '1' and slow_reset = '1' then
-- fast_reset <= '0';
-- end if;
-- end if;
-- end if;
-- end process;

process(system_clk)
begin
if rising_edge(system_clk) then
if reset_n = '0' then
slow_reset <= '1';
counter <= RESET_CYCLE_COUNT;
else
if counter = 0 then
slow_reset <= '0';
else
counter <= counter - 1;
end if;
end if;
end if;
end process;

end architecture behaviour;

@ -0,0 +1,384 @@
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2016 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--! @brief Simple UART module.
--! The following registers are defined:
--! |--------------------|--------------------------------------------|
--! | Address | Description |
--! |--------------------|--------------------------------------------|
--! | 0x00 | Transmit register (write-only) |
--! | 0x08 | Receive register (read-only) |
--! | 0x10 | Status register (read-only) |
--! | 0x18 | Sample clock divisor register (read/write) |
--! | 0x20 | Interrupt enable register (read/write) |
--! |--------------------|--------------------------------------------|
--!
--! The status register contains the following bits:
--! - Bit 0: receive buffer empty
--! - Bit 1: transmit buffer empty
--! - Bit 2: receive buffer full
--! - Bit 3: transmit buffer full
--!
--! The sample clock divisor should be set according to the formula:
--! sample_clk = (f_clk / (baudrate * 16)) - 1
--!
--! If the sample clock divisor register is set to 0, the sample clock
--! is stopped.
--!
--! Interrupts are enabled by setting the corresponding bit in the interrupt
--! enable register. The following bits are available:
--! - Bit 0: data received (receive buffer not empty)
--! - Bit 1: ready to send data (transmit buffer empty)
entity pp_soc_uart is
generic(
FIFO_DEPTH : natural := 64 --! Depth of the input and output FIFOs.
);
port(
clk : in std_logic;
reset : in std_logic;

-- UART ports:
txd : out std_logic;
rxd : in std_logic;

-- Interrupt signal:
irq : out std_logic;

-- Wishbone ports:
wb_adr_in : in std_logic_vector(11 downto 0);
wb_dat_in : in std_logic_vector( 7 downto 0);
wb_dat_out : out std_logic_vector( 7 downto 0);
wb_we_in : in std_logic;
wb_cyc_in : in std_logic;
wb_stb_in : in std_logic;
wb_ack_out : out std_logic
);
end entity pp_soc_uart;

architecture behaviour of pp_soc_uart is

subtype bitnumber is natural range 0 to 7; --! Type representing the index of a bit.

-- UART sample clock signals:
signal sample_clk : std_logic;
signal sample_clk_divisor : std_logic_vector(7 downto 0);
signal sample_clk_counter : std_logic_vector(sample_clk_divisor'range);

-- UART receive process signals:
type rx_state_type is (IDLE, RECEIVE, STARTBIT, STOPBIT);
signal rx_state : rx_state_type;
signal rx_byte : std_logic_vector(7 downto 0);
signal rx_current_bit : bitnumber;

subtype rx_sample_counter_type is natural range 0 to 15;
signal rx_sample_counter : rx_sample_counter_type;
signal rx_sample_value : rx_sample_counter_type;

subtype rx_sample_delay_type is natural range 0 to 7;
signal rx_sample_delay : rx_sample_delay_type;

-- UART transmit process signals:
type tx_state_type is (IDLE, TRANSMIT, STOPBIT);
signal tx_state : tx_state_type;
signal tx_byte : std_logic_vector(7 downto 0);
signal tx_current_bit : bitnumber;

-- UART transmit clock:
subtype uart_tx_counter_type is natural range 0 to 15;
signal uart_tx_counter : uart_tx_counter_type := 0;
signal uart_tx_clk : std_logic;

-- Buffer signals:
signal send_buffer_full, send_buffer_empty : std_logic;
signal recv_buffer_full, recv_buffer_empty : std_logic;
signal send_buffer_input, send_buffer_output : std_logic_vector(7 downto 0);
signal recv_buffer_input, recv_buffer_output : std_logic_vector(7 downto 0);
signal send_buffer_push, send_buffer_pop : std_logic := '0';
signal recv_buffer_push, recv_buffer_pop : std_logic := '0';

-- IRQ enable signals:
signal irq_recv_enable, irq_tx_ready_enable : std_logic := '0';

-- Wishbone signals:
type wb_state_type is (IDLE, WRITE_ACK, READ_ACK);
signal wb_state : wb_state_type;

signal wb_ack : std_logic; --! Wishbone acknowledge signal

begin

irq <= (irq_recv_enable and (not recv_buffer_empty))
or (irq_tx_ready_enable and send_buffer_empty);

---------- UART receive ----------

recv_buffer_input <= rx_byte;

uart_receive: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
rx_state <= IDLE;
recv_buffer_push <= '0';
else
case rx_state is
when IDLE =>
if recv_buffer_push = '1' then
recv_buffer_push <= '0';
end if;

if sample_clk = '1' and rxd = '0' then
rx_sample_value <= rx_sample_counter;
rx_sample_delay <= 0;
rx_current_bit <= 0;
rx_state <= STARTBIT;
end if;
when STARTBIT =>
if sample_clk = '1' then
if rx_sample_delay = 7 then
rx_state <= RECEIVE;
rx_sample_value <= rx_sample_counter;
rx_sample_delay <= 0;
else
rx_sample_delay <= rx_sample_delay + 1;
end if;
end if;
when RECEIVE =>
if sample_clk = '1' and rx_sample_counter = rx_sample_value then
if rx_current_bit /= 7 then
rx_byte(rx_current_bit) <= rxd;
rx_current_bit <= rx_current_bit + 1;
else
rx_byte(rx_current_bit) <= rxd;
rx_state <= STOPBIT;
end if;
end if;
when STOPBIT =>
if sample_clk = '1' and rx_sample_counter = rx_sample_value then
rx_state <= IDLE;

if recv_buffer_full = '0' then
recv_buffer_push <= '1';
end if;
end if;
end case;
end if;
end if;
end process uart_receive;

sample_counter: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
rx_sample_counter <= 0;
elsif sample_clk = '1' then
if rx_sample_counter = 15 then
rx_sample_counter <= 0;
else
rx_sample_counter <= rx_sample_counter + 1;
end if;
end if;
end if;
end process sample_counter;

---------- UART transmit ----------

tx_byte <= send_buffer_output;

uart_transmit: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
txd <= '1';
tx_state <= IDLE;
send_buffer_pop <= '0';
tx_current_bit <= 0;
else
case tx_state is
when IDLE =>
if send_buffer_empty = '0' and uart_tx_clk = '1' then
txd <= '0';
send_buffer_pop <= '1';
tx_current_bit <= 0;
tx_state <= TRANSMIT;
elsif uart_tx_clk = '1' then
txd <= '1';
end if;
when TRANSMIT =>
if send_buffer_pop = '1' then
send_buffer_pop <= '0';
elsif uart_tx_clk = '1' and tx_current_bit = 7 then
txd <= tx_byte(tx_current_bit);
tx_state <= STOPBIT;
elsif uart_tx_clk = '1' then
txd <= tx_byte(tx_current_bit);
tx_current_bit <= tx_current_bit + 1;
end if;
when STOPBIT =>
if uart_tx_clk = '1' then
txd <= '1';
tx_state <= IDLE;
end if;
end case;
end if;
end if;
end process uart_transmit;

uart_tx_clock_generator: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
uart_tx_counter <= 0;
uart_tx_clk <= '0';
else
if sample_clk = '1' then
if uart_tx_counter = 15 then
uart_tx_counter <= 0;
uart_tx_clk <= '1';
else
uart_tx_counter <= uart_tx_counter + 1;
uart_tx_clk <= '0';
end if;
else
uart_tx_clk <= '0';
end if;
end if;
end if;
end process uart_tx_clock_generator;

---------- Sample clock generator ----------

sample_clock_generator: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
sample_clk_counter <= (others => '0');
sample_clk <= '0';
else
if sample_clk_divisor /= x"00" then
if sample_clk_counter = sample_clk_divisor then
sample_clk_counter <= (others => '0');
sample_clk <= '1';
else
sample_clk_counter <= std_logic_vector(unsigned(sample_clk_counter) + 1);
sample_clk <= '0';
end if;
end if;
end if;
end if;
end process sample_clock_generator;

---------- Data Buffers ----------

send_buffer: entity work.pp_fifo
generic map(
DEPTH => FIFO_DEPTH,
WIDTH => 8
) port map(
clk => clk,
reset => reset,
full => send_buffer_full,
empty => send_buffer_empty,
data_in => send_buffer_input,
data_out => send_buffer_output,
push => send_buffer_push,
pop => send_buffer_pop
);

recv_buffer: entity work.pp_fifo
generic map(
DEPTH => FIFO_DEPTH,
WIDTH => 8
) port map(
clk => clk,
reset => reset,
full => recv_buffer_full,
empty => recv_buffer_empty,
data_in => recv_buffer_input,
data_out => recv_buffer_output,
push => recv_buffer_push,
pop => recv_buffer_pop
);

---------- Wishbone Interface ----------

wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in;

wishbone: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
wb_ack <= '0';
wb_state <= IDLE;
send_buffer_push <= '0';
recv_buffer_pop <= '0';
sample_clk_divisor <= (others => '0');
irq_recv_enable <= '0';
irq_tx_ready_enable <= '0';
else
case wb_state is
when IDLE =>
if wb_cyc_in = '1' and wb_stb_in = '1' then
if wb_we_in = '1' then -- Write to register
if wb_adr_in = x"000" then
send_buffer_input <= wb_dat_in;
send_buffer_push <= '1';
elsif wb_adr_in = x"018" then
sample_clk_divisor <= wb_dat_in;
elsif wb_adr_in = x"020" then
irq_recv_enable <= wb_dat_in(0);
irq_tx_ready_enable <= wb_dat_in(1);
end if;

-- Invalid writes are acked and ignored.

wb_ack <= '1';
wb_state <= WRITE_ACK;
else -- Read from register
if wb_adr_in = x"008" then
recv_buffer_pop <= '1';
elsif wb_adr_in = x"010" then
wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full & send_buffer_empty & recv_buffer_empty;
wb_ack <= '1';
elsif wb_adr_in = x"018" then
wb_dat_out <= sample_clk_divisor;
wb_ack <= '1';
elsif wb_adr_in = x"020" then
wb_dat_out <= (0 => irq_recv_enable, 1 => irq_tx_ready_enable, others => '0');
wb_ack <= '1';
else
wb_dat_out <= (others => '0');
wb_ack <= '1';
end if;
wb_state <= READ_ACK;
end if;
end if;
when WRITE_ACK =>
send_buffer_push <= '0';

if wb_stb_in = '0' then
wb_ack <= '0';
wb_state <= IDLE;
end if;
when READ_ACK =>
if recv_buffer_pop = '1' then
recv_buffer_pop <= '0';
else
wb_dat_out <= recv_buffer_output;
wb_ack <= '1';
end if;

if wb_stb_in = '0' then
wb_ack <= '0';
wb_state <= IDLE;
end if;
end case;
end if;
end if;
end process wishbone;

end architecture behaviour;

@ -0,0 +1,90 @@
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;

package pp_utilities is

--! Converts a boolean to an std_logic.
function to_std_logic(input : in boolean) return std_logic;

-- Checks if a number is 2^n:
function is_pow2(input : in natural) return boolean;

--! Calculates log2 with integers.
function log2(input : in natural) return natural;

-- Gets the value of the sel signals to the wishbone interconnect for the specified
-- operand size and address.
function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
return std_logic_vector;

end package pp_utilities;

package body pp_utilities is

function to_std_logic(input : in boolean) return std_logic is
begin
if input then
return '1';
else
return '0';
end if;
end function to_std_logic;

function is_pow2(input : in natural) return boolean is
variable c : natural := 1;
begin
for i in 0 to 31 loop
if input = c then
return true;
end if;

c := c * 2;
end loop;

return false;
end function is_pow2;

function log2(input : in natural) return natural is
variable retval : natural := 0;
variable temp : natural := input;
begin
while temp > 1 loop
retval := retval + 1;
temp := temp / 2;
end loop;

return retval;
end function log2;

function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
return std_logic_vector is
begin
case size is
when b"01" =>
case address(1 downto 0) is
when b"00" =>
return b"0001";
when b"01" =>
return b"0010";
when b"10" =>
return b"0100";
when b"11" =>
return b"1000";
when others =>
return b"0001";
end case;
when b"10" =>
if address(1) = '0' then
return b"0011";
else
return b"1100";
end if;
when others =>
return b"1111";
end case;
end function wb_get_data_sel;

end package body pp_utilities;

@ -0,0 +1,213 @@
-- The Potato Processor - SoC design for the Arty FPGA board
-- (c) Kristian Klomsten Skordal 2016 <kristian.skordal@wafflemail.net>

library ieee;
use ieee.std_logic_1164.all;

library work;
use work.wishbone_types.all;

-- 0x00000000: Main memory (1 MB)
-- 0xc0002000: UART0 (for host communication)
entity toplevel is
port(
clk : in std_logic;
reset_n : in std_logic;
-- UART0 signals:
uart0_txd : out std_logic;
uart0_rxd : in std_logic
);
end entity toplevel;

architecture behaviour of toplevel is

-- Reset signals:
signal reset : std_logic;

-- Internal clock signals:
signal system_clk : std_logic;
signal timer_clk : std_logic;
signal system_clk_locked : std_logic;

-- wishbone signals:
signal wishbone_proc_out: wishbone_master_out;
signal wishbone_proc_in: wishbone_slave_out;

-- Processor signals:
signal processor_adr_out : std_logic_vector(63 downto 0);
signal processor_sel_out : std_logic_vector(7 downto 0);
signal processor_cyc_out : std_logic;
signal processor_stb_out : std_logic;
signal processor_we_out : std_logic;
signal processor_dat_out : std_logic_vector(63 downto 0);
signal processor_dat_in : std_logic_vector(63 downto 0);
signal processor_ack_in : std_logic;
-- UART0 signals:
signal uart0_adr_in : std_logic_vector(11 downto 0);
signal uart0_dat_in : std_logic_vector( 7 downto 0);
signal uart0_dat_out : std_logic_vector( 7 downto 0);
signal uart0_cyc_in : std_logic;
signal uart0_stb_in : std_logic;
signal uart0_we_in : std_logic;
signal uart0_ack_out : std_logic;

-- Main memory signals:
signal main_memory_adr_in : std_logic_vector(19 downto 0);
signal main_memory_dat_in : std_logic_vector(63 downto 0);
signal main_memory_dat_out : std_logic_vector(63 downto 0);
signal main_memory_cyc_in : std_logic;
signal main_memory_stb_in : std_logic;
signal main_memory_sel_in : std_logic_vector(7 downto 0);
signal main_memory_we_in : std_logic;
signal main_memory_ack_out : std_logic;

-- Selected peripheral on the interconnect:
type intercon_peripheral_type is (
PERIPHERAL_UART0, PERIPHERAL_MAIN_MEMORY, PERIPHERAL_ERROR,
PERIPHERAL_NONE);
signal intercon_peripheral : intercon_peripheral_type := PERIPHERAL_NONE;

-- Interconnect address decoder state:
signal intercon_busy : boolean := false;

-- disable for now
signal gpio_pins : std_logic_vector(11 downto 0);
signal uart1_txd : std_logic;
signal uart1_rxd : std_logic;
begin

address_decoder: process(system_clk)
begin
if rising_edge(system_clk) then
if reset = '1' then
intercon_peripheral <= PERIPHERAL_NONE;
intercon_busy <= false;
else
if not intercon_busy then
if processor_cyc_out = '1' then
intercon_busy <= true;

if processor_adr_out(31 downto 24) = x"00" then -- Main memory space
intercon_peripheral <= PERIPHERAL_MAIN_MEMORY;
elsif processor_adr_out(31 downto 24) = x"c0" then -- Peripheral memory space
case processor_adr_out(15 downto 12) is
when x"2" =>
intercon_peripheral <= PERIPHERAL_UART0;
when others => -- Invalid address - delegated to the error peripheral
intercon_peripheral <= PERIPHERAL_ERROR;
end case;
else
intercon_peripheral <= PERIPHERAL_ERROR;
end if;
else
intercon_peripheral <= PERIPHERAL_NONE;
end if;
else
if processor_cyc_out = '0' then
intercon_busy <= false;
intercon_peripheral <= PERIPHERAL_NONE;
end if;
end if;
end if;
end if;
end process address_decoder;

processor_intercon: process(all)
begin
case intercon_peripheral is
when PERIPHERAL_UART0 =>
processor_ack_in <= uart0_ack_out;
processor_dat_in <= x"00000000000000" & uart0_dat_out;
when PERIPHERAL_MAIN_MEMORY =>
processor_ack_in <= main_memory_ack_out;
processor_dat_in <= main_memory_dat_out;
when PERIPHERAL_NONE =>
processor_ack_in <= '0';
processor_dat_in <= (others => '0');
when others =>
processor_ack_in <= '0';
processor_dat_in <= (others => '0');
end case;
end process processor_intercon;

reset_controller: entity work.pp_soc_reset
port map(
clk => system_clk,
reset_n => reset_n,
reset_out => reset,
system_clk => system_clk,
system_clk_locked => system_clk_locked
);

clkgen: entity work.clock_generator
port map(
clk => clk,
resetn => reset_n,
system_clk => system_clk,
locked => system_clk_locked
);

processor: entity work.core
port map(
clk => system_clk,
rst => reset,

wishbone_out => wishbone_proc_out,
wishbone_in => wishbone_proc_in
);
processor_adr_out <= wishbone_proc_out.adr;
processor_dat_out <= wishbone_proc_out.dat;
processor_sel_out <= wishbone_proc_out.sel;
processor_cyc_out <= wishbone_proc_out.cyc;
processor_stb_out <= wishbone_proc_out.stb;
processor_we_out <= wishbone_proc_out.we;
wishbone_proc_in.dat <= processor_dat_in;
wishbone_proc_in.ack <= processor_ack_in;

uart0: entity work.pp_soc_uart
generic map(
FIFO_DEPTH => 32
) port map(
clk => system_clk,
reset => reset,
txd => uart0_txd,
rxd => uart0_rxd,
wb_adr_in => uart0_adr_in,
wb_dat_in => uart0_dat_in,
wb_dat_out => uart0_dat_out,
wb_cyc_in => uart0_cyc_in,
wb_stb_in => uart0_stb_in,
wb_we_in => uart0_we_in,
wb_ack_out => uart0_ack_out
);
uart0_adr_in <= processor_adr_out(uart0_adr_in'range);
uart0_dat_in <= processor_dat_out(7 downto 0);
uart0_we_in <= processor_we_out;
uart0_cyc_in <= processor_cyc_out when intercon_peripheral = PERIPHERAL_UART0 else '0';
uart0_stb_in <= processor_stb_out when intercon_peripheral = PERIPHERAL_UART0 else '0';

main_memory: entity work.pp_soc_memory
generic map(
MEMORY_SIZE => 1048576
) port map(
clk => system_clk,
reset => reset,
wb_adr_in => main_memory_adr_in,
wb_dat_in => main_memory_dat_in,
wb_dat_out => main_memory_dat_out,
wb_cyc_in => main_memory_cyc_in,
wb_stb_in => main_memory_stb_in,
wb_sel_in => main_memory_sel_in,
wb_we_in => main_memory_we_in,
wb_ack_out => main_memory_ack_out
);
main_memory_adr_in <= processor_adr_out(main_memory_adr_in'range);
main_memory_dat_in <= processor_dat_out;
main_memory_we_in <= processor_we_out;
main_memory_sel_in <= processor_sel_out;
main_memory_cyc_in <= processor_cyc_out when intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
main_memory_stb_in <= processor_stb_out when intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
end architecture behaviour;

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

library work;
use work.glibc_random_helpers.all;

package glibc_random is
function pseudorand(a: integer) return std_ulogic_vector;
function pseudorand1 return std_ulogic;
end package glibc_random;

package body glibc_random is
function pseudorand(a: integer) return std_ulogic_vector is
variable tmp1, tmp2, tmp3, tmp4: std_ulogic_vector(31 downto 0);
variable ret: std_ulogic_vector(63 downto 0);
begin
tmp1 := std_ulogic_vector(to_unsigned(random, 32));
tmp2 := std_ulogic_vector(to_unsigned(random, 32));
if a <= 32 then
ret := tmp1 & tmp2;
else
tmp3 := std_ulogic_vector(to_unsigned(random, 32));
tmp4 := std_ulogic_vector(to_unsigned(random, 32));

ret := tmp1(15 downto 0) & tmp2(15 downto 0) & tmp3(15 downto 0) & tmp4(15 downto 0);
end if;

return ret((a-1) downto 0);
end;

function pseudorand1 return std_ulogic is
variable tmp: std_ulogic_vector(31 downto 0);
begin
tmp := std_ulogic_vector(to_unsigned(random, 32));
return tmp(0);
end;
end package body glibc_random;

@ -0,0 +1,19 @@
package glibc_random_helpers is
procedure srand (v : integer);
attribute foreign of srand : procedure is "VHPIDIRECT srand";

function random return integer;
attribute foreign of random : function is "VHPIDIRECT random";
end glibc_random_helpers;

package body glibc_random_helpers is
procedure srand (v : integer) is
begin
assert false severity failure;
end srand;

function random return integer is
begin
assert false severity failure;
end random;
end glibc_random_helpers;

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

library work;

package helpers is
function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer;
function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer;

function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer;
function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer;

function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector;
function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;

function ppc_signed_compare(a, b: signed(63 downto 0)) return std_ulogic_vector;
function ppc_unsigned_compare(a, b: unsigned(63 downto 0)) return std_ulogic_vector;

function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;

function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector;

function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector;
end package helpers;

package body helpers is
function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer is
variable ret: integer;
begin
ret := 32;
for i in val'range loop
if val(i) = '1' then
ret := 31 - i;
exit;
end if;
end loop;

return ret;
end;

function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer is
variable ret: integer;
begin
ret := 32;
for i in val'reverse_range loop
if val(i) = '1' then
ret := i;
exit;
end if;
end loop;

return ret;
end;

function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer is
variable ret: integer;
begin
ret := 64;
for i in val'range loop
if val(i) = '1' then
ret := 63 - i;
exit;
end if;
end loop;

return ret;
end;

function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer is
variable ret: integer;
begin
ret := 64;
for i in val'reverse_range loop
if val(i) = '1' then
ret := i;
exit;
end if;
end loop;

return ret;
end;

function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
variable ret: unsigned(3 downto 0) := (others => '0');
begin
for i in val'range loop
ret := ret + ("000" & val(i));
end loop;

return std_ulogic_vector(resize(ret, val'length));
end;

function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
variable ret: unsigned(5 downto 0) := (others => '0');
begin
for i in val'range loop
ret := ret + ("00000" & val(i));
end loop;

return std_ulogic_vector(resize(ret, val'length));
end;

function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: unsigned(6 downto 0) := (others => '0');
begin
for i in val'range loop
ret := ret + ("000000" & val(i));
end loop;

return std_ulogic_vector(resize(ret, val'length));
end;

function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector(7 downto 0);
begin
if a = b then
ret := x"ff";
else
ret := x"00";
end if;

return ret;
end;

function ppc_signed_compare(a, b: signed(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector(3 downto 0);
begin
if a < b then
ret := "1000";
elsif a > b then
ret := "0100";
else
ret := "0010";
end if;

return ret;
end;

function ppc_unsigned_compare(a, b: unsigned(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector(3 downto 0);
begin
if a < b then
ret := "1000";
elsif a > b then
ret := "0100";
else
ret := "0010";
end if;

return ret;
end;

function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
begin
if to_integer(unsigned(reg)) = 0 then
return x"0000000000000000";
else
return ra;
end if;
end;

function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector is
variable ret : std_ulogic_vector(63 downto 0) := (others => '0');
begin
-- Vivado doesn't support non constant vector slices, so we have to code
-- each of these.
case_0: case size is
when 2 =>
for_2 : for k in 0 to 1 loop
ret(((8*k)+7) downto (8*k)) := val((8*(1-k)+7) downto (8*(1-k)));
end loop;
when 4 =>
for_4 : for k in 0 to 3 loop
ret(((8*k)+7) downto (8*k)) := val((8*(3-k)+7) downto (8*(3-k)));
end loop;
when 8 =>
for_8 : for k in 0 to 7 loop
ret(((8*k)+7) downto (8*k)) := val((8*(7-k)+7) downto (8*(7-k)));
end loop;
when others =>
report "bad byte reverse length " & integer'image(size) severity failure;
end case;

return ret;
end;

function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector is
variable ret : signed(63 downto 0) := (others => '0');
variable upper : integer := 0;
begin
case_0: case size is
when 2 =>
upper := 15;
when 4 =>
upper := 31;
when 8 =>
upper := 63;
when others =>
report "bad byte reverse length " & integer'image(size) severity failure;
end case;

ret := resize(signed(val(upper downto 0)), 64);
return std_ulogic_vector(ret);
end;
end package body helpers;

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

library work;
use work.common.all;

-- 2 cycle LSU
-- We calculate the address in the first cycle

entity loadstore1 is
port (
clk : in std_ulogic;

l_in : in Decode2ToLoadstore1Type;
l_out : out Loadstore1ToLoadstore2Type
);
end loadstore1;

architecture behave of loadstore1 is
signal l : Decode2ToLoadstore1Type;
signal lsu_sum : std_ulogic_vector(63 downto 0);
begin
-- Calculate the address in the first cycle
lsu_sum <= std_ulogic_vector(unsigned(l.addr1) + unsigned(l.addr2)) when l.valid = '1' else (others => '0');

loadstore1_0: process(clk)
begin
if rising_edge(clk) then
l <= l_in;

if l_in.valid = '1' then
report "execute " & to_hstring(l_in.nia);
report "loadstore1 " & to_hstring(l_in.addr1) & " " & to_hstring(l_in.addr2);

end if;

end if;
end process;

loadstore1_1: process(all)
begin
l_out.valid <= l.valid;
l_out.load <= l.load;
l_out.data <= l.data;
l_out.write_reg <= l.write_reg;
l_out.length <= l.length;
l_out.byte_reverse <= l.byte_reverse;
l_out.sign_extend <= l.sign_extend;
l_out.update <= l.update;
l_out.update_reg <= l.update_reg;

l_out.addr <= lsu_sum;
end process;
end;

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

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

-- 2 cycle LSU
-- In this cycle we read or write any data and do sign extension and update if required.

entity loadstore2 is
port (
clk : in std_ulogic;

l_in : in Loadstore1ToLoadstore2Type;
w_out : out Loadstore2ToWritebackType;

m_in : in wishbone_slave_out;
m_out : out wishbone_master_out
);
end loadstore2;

architecture behave of loadstore2 is
signal l_saved : Loadstore1ToLoadstore2Type;
signal w_tmp : Loadstore2ToWritebackType;
signal m_tmp : wishbone_master_out;

type state_t is (IDLE, WAITING_FOR_READ_ACK, WAITING_FOR_WRITE_ACK);
signal state : state_t := IDLE;

function length_to_sel(length : in std_logic_vector(3 downto 0)) return std_ulogic_vector is
begin
case length is
when "0001" =>
return "00000001";
when "0010" =>
return "00000011";
when "0100" =>
return "00001111";
when "1000" =>
return "11111111";
when others =>
return "00000000";
end case;
end function length_to_sel;

function wishbone_data_shift(address : in std_ulogic_vector(63 downto 0)) return natural is
begin
return to_integer(unsigned(address(2 downto 0))) * 8;
end function wishbone_data_shift;

function wishbone_data_sel(size : in std_logic_vector(3 downto 0); address : in std_logic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(shift_left(unsigned(length_to_sel(size)), to_integer(unsigned(address(2 downto 0)))));
end function wishbone_data_sel;
begin
w_out <= w_tmp;
m_out <= m_tmp;

loadstore2_0: process(clk)
variable tmp : std_ulogic_vector(63 downto 0);
variable data : std_ulogic_vector(63 downto 0);
begin
if rising_edge(clk) then
tmp := (others => '0');
data := (others => '0');

w_tmp <= Loadstore2ToWritebackInit;

l_saved <= l_saved;

case_0: case state is
when IDLE =>
if l_in.valid = '1' then
m_tmp <= wishbone_master_out_init;

m_tmp.sel <= wishbone_data_sel(l_in.length, l_in.addr);
m_tmp.adr <= l_in.addr(63 downto 3) & "000";
m_tmp.cyc <= '1';
m_tmp.stb <= '1';

if l_in.load = '1' then
m_tmp.we <= '0';

l_saved <= l_in;
state <= WAITING_FOR_READ_ACK;
else
m_tmp.we <= '1';

w_tmp.valid <= '1';

data := l_in.data;
if l_in.byte_reverse = '1' then
data := byte_reverse(data, to_integer(unsigned(l_in.length)));
end if;

m_tmp.dat <= std_logic_vector(shift_left(unsigned(data), wishbone_data_shift(l_in.addr)));

assert l_in.sign_extend = '0' report "sign extension doesn't make sense for stores" severity failure;

if l_in.update = '1' then
w_tmp.write_enable <= '1';
w_tmp.write_reg <= l_in.update_reg;
w_tmp.write_data <= l_in.addr;
end if;

state <= WAITING_FOR_WRITE_ACK;
end if;
end if;

when WAITING_FOR_READ_ACK =>
if m_in.ack = '1' then
tmp := std_logic_vector(shift_right(unsigned(m_in.dat), wishbone_data_shift(l_saved.addr)));
data((to_integer(unsigned(l_saved.length))*8-1) downto 0) := tmp((to_integer(unsigned(l_saved.length))*8-1) downto 0);

if l_saved.sign_extend = '1' then
data := sign_extend(data, to_integer(unsigned(l_saved.length)));
end if;

if l_saved.byte_reverse = '1' then
data := byte_reverse(data, to_integer(unsigned(l_saved.length)));
end if;

w_tmp.write_data <= data;

-- write data to register file
w_tmp.valid <= '1';
w_tmp.write_enable <= '1';
w_tmp.write_reg <= l_saved.write_reg;

if l_saved.update = '1' then
w_tmp.write_enable2 <= '1';
w_tmp.write_reg2 <= l_saved.update_reg;
w_tmp.write_data2 <= l_saved.addr;
end if;

m_tmp <= wishbone_master_out_init;
state <= IDLE;
end if;

when WAITING_FOR_WRITE_ACK =>
if m_in.ack = '1' then
m_tmp <= wishbone_master_out_init;
state <= IDLE;
end if;
end case;
end if;
end process;
end;

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

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

entity multiply is
generic (
PIPELINE_DEPTH : integer := 6
);
port (
clk : in std_logic;

m_in : in Decode2ToMultiplyType;
m_out : out MultiplyToWritebackType
);
end entity multiply;

architecture behaviour of multiply is
signal m: Decode2ToMultiplyType;

type multiply_pipeline_stage is record
valid : std_ulogic;
insn_type : insn_type_t;
data : signed(129 downto 0);
write_reg : std_ulogic_vector(4 downto 0);
rc : std_ulogic;
end record;
constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0', insn_type => OP_ILLEGAL, rc => '0', data => (others => '0'), others => (others => '0'));

type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage;
constant MultiplyPipelineInit : multiply_pipeline_type := (others => MultiplyPipelineStageInit);

type reg_type is record
multiply_pipeline : multiply_pipeline_type;
end record;

signal r, rin : reg_type := (multiply_pipeline => MultiplyPipelineInit);
begin
multiply_0: process(clk)
begin
if rising_edge(clk) then
m <= m_in;
r <= rin;
end if;
end process;

multiply_1: process(all)
variable v : reg_type;
variable d : std_ulogic_vector(129 downto 0);
variable d2 : std_ulogic_vector(63 downto 0);
begin
v := r;

m_out <= MultiplyToWritebackInit;

if m.valid then
v.multiply_pipeline(0).valid := '1';
v.multiply_pipeline(0).insn_type := m.insn_type;
v.multiply_pipeline(0).data := signed(m.data1) * signed(m.data2);
v.multiply_pipeline(0).write_reg := m.write_reg;
v.multiply_pipeline(0).rc := m.rc;
else
v.multiply_pipeline(0).valid := '0';
end if;

loop_0: for i in 0 to PIPELINE_DEPTH-2 loop
v.multiply_pipeline(i+1) := r.multiply_pipeline(i);
end loop;

if v.multiply_pipeline(PIPELINE_DEPTH-1).valid then
d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data);

case_0: case v.multiply_pipeline(PIPELINE_DEPTH-1).insn_type is
when OP_MUL_L64 =>
d2 := d(63 downto 0);
when OP_MUL_H32 =>
d2 := d(63 downto 32) & d(63 downto 32);
when OP_MUL_H64 =>
d2 := d(127 downto 64);
when others =>
report "Illegal insn type in multiplier";
d2 := (others => '0');
end case;

m_out.valid <= '1';
m_out.write_reg_enable <= '1';
m_out.write_reg_nr <= v.multiply_pipeline(PIPELINE_DEPTH-1).write_reg;
m_out.write_reg_data <= d2;

if v.multiply_pipeline(PIPELINE_DEPTH-1).rc = '1' then
m_out.write_cr_enable <= '1';
m_out.write_cr_mask <= num_to_fxm(0);
m_out.write_cr_data <= ppc_cmpi('1', d2, x"0000") & x"0000000";
end if;
end if;

rin <= v;
end process;
end architecture behaviour;

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

library work;
use work.common.all;
use work.glibc_random.all;
use work.ppc_fx_insns.all;

entity multiply_tb is
end multiply_tb;

architecture behave of multiply_tb is
signal clk : std_ulogic;
constant clk_period : time := 10 ns;

constant pipeline_depth: integer := 6;

signal m1 : DecodeToMultiplyType;
signal m2 : MultiplyToWritebackType;
begin
multiply_0: entity work.multiply
generic map (PIPELINE_DEPTH => pipeline_depth)
port map (clk => clk, m_in => m1, m_out => m2);

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

stim_process: process
variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
variable si: std_ulogic_vector(15 downto 0);
begin
wait for clk_period;

m1.valid <= '1';
m1.mul_type <= LOWER_64;
m1.nia <= (others => '0');
m1.write_reg <= "10001";
m1.data1 <= '0' & x"0000000000001000";
m1.data2 <= '0' & x"0000000000001111";
m1.rc <= '0';

wait for clk_period;
assert m2.valid = '0';

m1.valid <= '0';

wait for clk_period;
assert m2.valid = '0';

wait for clk_period;
assert m2.valid = '0';

wait for clk_period;
assert m2.valid = '1';
assert m2.write_enable = '1';
assert m2.write_reg = "10001";
assert m2.write_data = x"0000000001111000";
assert m2.write_cr_enable = '0';

wait for clk_period;
assert m2.valid = '0';

m1.valid <= '1';
m1.rc <= '1';

wait for clk_period;
assert m2.valid = '0';

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert m2.write_enable = '1';
assert m2.write_reg = "10001";
assert m2.write_data = x"0000000001111000";
assert m2.write_cr_enable = '1';
assert m2.cr = x"4";

-- test mulld
mulld_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mulld(ra, rb);

m1.data1 <= '0' & ra;
m1.data2 <= '0' & rb;
m1.valid <= '1';
m1.mul_type <= LOWER_64;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mulhdu
mulhdu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mulhdu(ra, rb);

m1.data1 <= '0' & ra;
m1.data2 <= '0' & rb;
m1.valid <= '1';
m1.mul_type <= UPPER_64;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mulhd
mulhd_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mulhd(ra, rb);

m1.data1 <= ra(63) & ra;
m1.data2 <= rb(63) & rb;
m1.valid <= '1';
m1.mul_type <= UPPER_64;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mullw
mullw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mullw(ra, rb);

m1.data1 <= (others => ra(31));
m1.data1(31 downto 0) <= ra(31 downto 0);
m1.data2 <= (others => rb(31));
m1.data2(31 downto 0) <= rb(31 downto 0);
m1.valid <= '1';
m1.mul_type <= LOWER_64;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mulhw
mulhw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mulhw(ra, rb);

m1.data1 <= (others => ra(31));
m1.data1(31 downto 0) <= ra(31 downto 0);
m1.data2 <= (others => rb(31));
m1.data2(31 downto 0) <= rb(31 downto 0);
m1.valid <= '1';
m1.mul_type <= UPPER_32;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulhw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mulhwu
mulhwu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);

behave_rt := ppc_mulhwu(ra, rb);

m1.data1 <= (others => '0');
m1.data1(31 downto 0) <= ra(31 downto 0);
m1.data2 <= (others => '0');
m1.data2(31 downto 0) <= rb(31 downto 0);
m1.valid <= '1';
m1.mul_type <= UPPER_32;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulhwu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

-- test mulli
mulli_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
si := pseudorand(si'length);

behave_rt := ppc_mulli(ra, si);

m1.data1 <= ra(63) & ra;
m1.data2 <= (others => si(15));
m1.data2(15 downto 0) <= si;
m1.valid <= '1';
m1.mul_type <= LOWER_64;

wait for clk_period;

m1.valid <= '0';

wait for clk_period * (pipeline_depth-1);

assert m2.valid = '1';

assert to_hstring(behave_rt) = to_hstring(m2.write_data)
report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_data);
end loop;

assert false report "end of test" severity failure;
wait;
end process;
end behave;

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

library work;
use work.helpers.all;

package ppc_fx_insns is
function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;

function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rlwimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;

function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector;
function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer;
function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer;
end package ppc_fx_insns;

package body ppc_fx_insns is
function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + signed(si));
end;

function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + unsigned(resize(signed(si), 64)));
end;

function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + resize(unsigned(rb), 65) + carry);
end;

function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(unsigned(resize(signed(si), 64)) + resize(unsigned(not(ra)), 65) + 1);
end;

function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + 1);
end;

function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + carry);
end;

function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + carry);
end;

function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + shift_left(resize(signed(si), 32), 16));
end;

function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + signed(rb));
end;

function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(rb) - signed(ra));
end;

function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(-signed(ra));
end;

function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs and std_ulogic_vector(resize(unsigned(ui), 64));
end;

function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs and std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;

function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs or std_ulogic_vector(resize(unsigned(ui), 64));
end;

function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs or std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;

function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs xor std_ulogic_vector(resize(unsigned(ui), 64));
end;

function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs xor std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;

function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs and rb;
end;

function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs xor rb;
end;

function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs nand rb;
end;

function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs or rb;
end;

function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs nor rb;
end;

function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs and not(rb);
end;

function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return not(rs xor rb);
end;

function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs or not(rb);
end;

function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(7 downto 0)), rs'length));
end;

function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(15 downto 0)), rs'length));
end;

function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(31 downto 0)), rs'length));
end;

function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(fls_32(rs(31 downto 0)), rs'length));
end;

function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(ffs_32(rs(31 downto 0)), rs'length));
end;

function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(fls_64(rs), rs'length));
end;

function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(ffs_64(rs), rs'length));
end;

function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
ret := (others => '0');

for i in 1 to 8 loop
hi := (8*i)-1;
lo := 8*(i-1);
ret(hi downto lo) := popcnt8(rs(hi downto lo));
end loop;

return ret;
end;

function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
ret := (others => '0');

for i in 1 to 2 loop
hi := (32*i)-1;
lo := 32*(i-1);
ret(hi downto lo) := popcnt32(rs(hi downto lo));
end loop;

return ret;
end;

function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return popcnt64(rs);
end;

function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp : std_ulogic;
variable ret : std_ulogic_vector(63 downto 0);
begin
ret := (others => '0');

tmp := '0';
for i in 0 to 7 loop
tmp := tmp xor rs(i*8);
end loop;

ret(0) := tmp;
return ret;
end;

function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp : std_ulogic;
variable ret : std_ulogic_vector(63 downto 0);
begin
ret := (others => '0');

tmp := '0';
for i in 0 to 3 loop
tmp := tmp xor rs(i*8);
end loop;
ret(0) := tmp;

tmp := '0';
for i in 4 to 7 loop
tmp := tmp xor rs(i*8);
end loop;
ret(32) := tmp;

return ret;
end;

function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
tmp2(63 downto lo) := tmp1(63 downto lo);
tmp2(hi downto 0) := tmp1(hi downto 0);
else
tmp2(hi downto lo) := tmp1(hi downto lo);
end if;
return tmp2;
end;

function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
variable n : integer;
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
n := to_integer(unsigned(rb(4 downto 0)));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), n));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
tmp2(63 downto lo) := tmp1(63 downto lo);
tmp2(hi downto 0) := tmp1(hi downto 0);
else
tmp2(hi downto lo) := tmp1(hi downto lo);
end if;
return tmp2;
end;

function ppc_rlwimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
tmp2 := ra;
if hi < lo then
-- Mask wraps around
tmp2(63 downto lo) := tmp1(63 downto lo);
tmp2(hi downto 0) := tmp1(hi downto 0);
else
tmp2(hi downto lo) := tmp1(hi downto lo);
end if;
return tmp2;
end;

function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
tmp2(hi downto 0) := tmp1(hi downto 0);
return tmp2;
end;

function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
lo := 63-to_integer(unsigned(me));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
tmp2(63 downto lo) := tmp1(63 downto lo);
return tmp2;
end;

function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
lo := to_integer(unsigned(sh));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
tmp2(63 downto lo) := tmp1(63 downto lo);
tmp2(hi downto 0) := tmp1(hi downto 0);
else
tmp2(hi downto lo) := tmp1(hi downto lo);
end if;
return tmp2;
end;

function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
tmp2 := (others => '0');
tmp2(hi downto 0) := tmp1(hi downto 0);
return tmp2;
end;

function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
lo := 63-to_integer(unsigned(me));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
tmp2 := (others => '0');
tmp2(63 downto lo) := tmp1(63 downto lo);
return tmp2;
end;

function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(rs'range);
begin
hi := 63-to_integer(unsigned(mb));
lo := to_integer(unsigned(sh));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), lo));
tmp2 := ra;
if hi < lo then
-- Mask wraps around
tmp2(63 downto lo) := tmp1(63 downto lo);
tmp2(hi downto 0) := tmp1(hi downto 0);
else
tmp2(hi downto lo) := tmp1(hi downto lo);
end if;
return tmp2;
end;

function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : unsigned(31 downto 0);
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_left(unsigned(rs(31 downto 0)), n);

return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;

function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : unsigned(31 downto 0);
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_right(unsigned(rs(31 downto 0)), n);

return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;

function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : signed(31 downto 0);
variable carry: std_ulogic;
begin
n := to_integer(unsigned(sh));
tmp := shift_right(signed(rs(31 downto 0)), n);
-- what about n = 0?
carry := or rs(n-1 downto 0) and rs(31);

return carry & std_ulogic_vector(resize(tmp, rs'length));
end;

function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : natural;
variable tmp : signed(31 downto 0);
variable carry: std_ulogic;
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_right(signed(rs(31 downto 0)), n);
-- what about n = 0?
carry := or rs(n-1 downto 0) and rs(31);

return carry & std_ulogic_vector(resize(tmp, rs'length));
end;

function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
begin
n := to_integer(unsigned(rb(6 downto 0)));
return std_ulogic_vector(shift_left(unsigned(rs), n));
end;

function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
begin
n := to_integer(unsigned(rb(6 downto 0)));
return std_ulogic_vector(shift_right(unsigned(rs), n));
end;

function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable n : integer;
variable carry: std_ulogic;
begin
n := to_integer(unsigned(sh));
-- what about n = 0?
carry := or rs(n-1 downto 0) and rs(63);

return carry & std_ulogic_vector(shift_right(signed(rs), n));
end;

function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable carry: std_ulogic;
begin
n := to_integer(unsigned(rb(6 downto 0)));
-- what about n = 0?
carry := or rs(n-1 downto 0) and rs(63);

return carry & std_ulogic_vector(shift_right(signed(rs), n));
end;

-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(127 downto 0);
begin
tmp := signed(ra) * signed(rb);
return std_ulogic_vector(tmp(63 downto 0));
end;

-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(127 downto 0);
begin
tmp := signed(ra) * signed(rb);
return std_ulogic_vector(tmp(127 downto 64));
end;

-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(127 downto 0);
begin
tmp := unsigned(ra) * unsigned(rb);
return std_ulogic_vector(tmp(127 downto 64));
end;

-- Not sure how to better communicate the top 16 bits of the result is unused
function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
variable tmp: signed(79 downto 0);
begin
tmp := signed(ra) * signed(si);
return std_ulogic_vector(tmp(63 downto 0));
end;

function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra(31 downto 0)) * signed(rb(31 downto 0)));
end;

function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(63 downto 0);
begin
tmp := signed(ra(31 downto 0)) * signed(rb(31 downto 0));
return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
end;

function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(63 downto 0);
begin
tmp := unsigned(ra(31 downto 0)) * unsigned(rb(31 downto 0));
return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
end;

function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
variable tmp: signed(ra'range);
begin
tmp := signed(ra);
if l = '0' then
tmp := resize(signed(ra(31 downto 0)), tmp'length);
end if;

return ppc_signed_compare(tmp, resize(signed(si), tmp'length));
end;

function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmpa, tmpb: signed(ra'range);
begin
tmpa := signed(ra);
tmpb := signed(rb);
if l = '0' then
tmpa := resize(signed(ra(31 downto 0)), ra'length);
tmpb := resize(signed(rb(31 downto 0)), ra'length);
end if;

return ppc_signed_compare(tmpa, tmpb);
end;

function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(ra'range);
begin
tmp := unsigned(ra);
if l = '0' then
tmp := resize(unsigned(ra(31 downto 0)), tmp'length);
end if;

return ppc_unsigned_compare(tmp, resize(unsigned(si), tmp'length));
end;

function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmpa, tmpb: unsigned(ra'range);
begin
tmpa := unsigned(ra);
tmpb := unsigned(rb);
if l = '0' then
tmpa := resize(unsigned(ra(31 downto 0)), ra'length);
tmpb := resize(unsigned(rb(31 downto 0)), ra'length);
end if;

return ppc_unsigned_compare(tmpa, tmpb);
end;

function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
for i in 1 to 8 loop
hi := (8*i)-1;
lo := 8*(i-1);
ret(hi downto lo) := cmp_one_byte(rs(hi downto lo), rb(hi downto lo));
end loop;

return ret;
end;

-- Not synthesizable
function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(31 downto 0);
begin
tmp := signed(ra(31 downto 0)) / signed(rb(31 downto 0));

return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;

function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(63 downto 0) := (others => '0');
begin
if unsigned(rb) /= 0 then
tmp := unsigned(ra) / unsigned(rb);
end if;

return std_ulogic_vector(tmp);
end;

function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(63 downto 0) := (others => '0');
begin
if signed(rb) /= 0 then
tmp := signed(ra) / signed(rb);
end if;

return std_ulogic_vector(tmp);
end;

function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(31 downto 0) := (others => '0');
begin
if unsigned(rb(31 downto 0)) /= 0 then
tmp := unsigned(ra(31 downto 0)) / unsigned(rb(31 downto 0));
end if;

return std_ulogic_vector(resize(tmp, ra'length));
end;

function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(nia) + signed(bd & "00"));
end;

function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer is
variable crfield: integer;
variable crbit_match: std_ulogic;
variable ctr_not_zero: std_ulogic;
variable ctr_ok: std_ulogic;
variable cond_ok: std_ulogic;
variable ret: integer;
begin
crfield := to_integer(unsigned(bi));
-- BE bit numbering
crbit_match := '1' when cr(31-crfield) = bo(4-1) else '0';
-- We check this before it is decremented
ctr_not_zero := '1' when ctr /= x"0000000000000001" else '0';
ctr_ok := bo(4-2) or (ctr_not_zero xor bo(4-3));
cond_ok := bo(4-0) or crbit_match;
if ctr_ok = '1' and cond_ok = '1' then
ret := 1;
else
ret := 0;
end if;
return ret;
end;

function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer is
variable crfield: integer;
variable crbit_match: std_ulogic;
variable cond_ok: std_ulogic;
variable ret: integer;
begin
crfield := to_integer(unsigned(bi));
-- BE bit numbering
crbit_match := '1' when cr(31-crfield) = bo(4-1) else '0';
cond_ok := bo(4-0) or crbit_match;
if cond_ok = '1' then
ret := 1;
else
ret := 0;
end if;
return ret;
end;
end package body ppc_fx_insns;

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

library work;
use work.common.all;

entity register_file is
port(
clk : in std_logic;

d_in : in Decode2ToRegisterFileType;
d_out : out RegisterFileToDecode2Type;

w_in : in WritebackToRegisterFileType;

-- debug
registers_out : out regfile
);
end entity register_file;

architecture behaviour of register_file is
signal registers : regfile := (others => (others => '0'));
begin
-- synchronous writes
register_write_0: process(clk)
begin
if rising_edge(clk) then
if w_in.write_enable = '1' then
assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure;
report "Writing " & to_hstring(w_in.write_data) & " to " & to_hstring(w_in.write_reg);
registers(to_integer(unsigned(w_in.write_reg))) <= w_in.write_data;
end if;
if w_in.write_enable2 = '1' then
assert not(is_x(w_in.write_data2)) and not(is_x(w_in.write_reg2)) severity failure;
report "Writing " & to_hstring(w_in.write_data2) & " to " & to_hstring(w_in.write_reg2);
registers(to_integer(unsigned(w_in.write_reg2))) <= w_in.write_data2;
end if;
end if;
end process register_write_0;

-- asynchronous reads
register_read_0: process(all)
begin
report "read " & to_hstring(d_in.read1_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read1_reg))));
report "read " & to_hstring(d_in.read2_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read2_reg))));
report "read " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg))));
d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg)));
d_out.read2_data <= registers(to_integer(unsigned(d_in.read2_reg)));
d_out.read3_data <= registers(to_integer(unsigned(d_in.read3_reg)));

-- Forward any written data
--if w_in.write_enable = '1' then
--if d_in.read1_reg = w_in.write_reg then
--d_out.read1_data <= w_in.write_data;
--end if;
--if d_in.read2_reg = w_in.write_reg then
--d_out.read2_data <= w_in.write_data;
--end if;
--if d_in.read3_reg = w_in.write_reg then
--d_out.read3_data <= w_in.write_data;
--end if;
--end if;
end process register_read_0;

-- debug
registers_out <= registers;
end architecture behaviour;

@ -0,0 +1,25 @@
#!/usr/bin/python3

# Create makefile dependencies for VHDL files, looking for "use work" and
# "entity work" declarations

import sys
import re

work = re.compile('use work\.([^.]+)\.')
entity = re.compile('entity work\.(.*)')

for filename in sys.argv[1:]:
with open(filename, 'r') as f:
(basename, suffix) = filename.split('.')
print('%s.o:' % basename, end='')

for line in f:
m = work.search(line)
if m:
print(' %s.o' % m.group(1), end='')

m = entity.search(line)
if m:
print(' %s.o' % m.group(1), end='')
print()

@ -0,0 +1,16 @@
#!/usr/bin/python3

import re
import fileinput

r = re.compile("REG ([0-9A-F]+)");

regs = list()

for line in fileinput.input():
m = r.search(line)
if m:
regs.append(int(m.group(1), 16))
#print("%016X"% int(m.group(1), 16))

print("%x" % hash(tuple(regs)))

@ -0,0 +1,33 @@
#!/bin/bash

if [ $# -ne 1 ]; then
echo "Usage: run_test.sh <test>"
exit 1
fi

TEST=$1

TMPDIR=$(mktemp -d)

function finish {
rm -rf "$TMPDIR"
}

trap finish EXIT

MICROWATT_DIR=$PWD

Y=$(${MICROWATT_DIR}/scripts/hash.py tests/${TEST}.out)

cd $TMPDIR

cp ${MICROWATT_DIR}/tests/${TEST}.bin simple_ram_behavioural.bin

X=$( ${MICROWATT_DIR}/core_tb | ${MICROWATT_DIR}/scripts/hash.py )

if [ $X == $Y ]; then
echo "$TEST PASS"
else
echo "$TEST FAIL ********"
exit 1
fi

@ -0,0 +1,40 @@
#!/usr/bin/python3

import tempfile
import os
from shutil import copyfile
import subprocess
from pexpect import fdpexpect
import sys
import signal

tempdir = tempfile.TemporaryDirectory()
cwd = os.getcwd()
os.chdir(tempdir.name)

copyfile(os.path.join(cwd, 'tests/micropython.bin'),
os.path.join(tempdir.name, 'simple_ram_behavioural.bin'))

cmd = [ os.path.join(cwd, './core_tb') ]

devNull = open(os.devnull, 'w')
p = subprocess.Popen(cmd, stdout=devNull,
stdin=subprocess.PIPE, stderr=subprocess.PIPE)

exp = fdpexpect.fdspawn(p.stderr)
exp.logfile = sys.stdout.buffer

exp.expect('Type "help\(\)" for more information.')
exp.expect('>>>')

p.stdin.write(b'print("foo")\r\n')
p.stdin.flush()

# Catch the command echoed back to the console
exp.expect('foo', timeout=600)

# Now catch the output
exp.expect('foo', timeout=600)
exp.expect('>>>')

os.kill(p.pid, signal.SIGKILL)

@ -0,0 +1,48 @@
#!/usr/bin/python3

import tempfile
import os
from shutil import copyfile
import subprocess
from pexpect import fdpexpect
import sys
import signal

tempdir = tempfile.TemporaryDirectory()
cwd = os.getcwd()
os.chdir(tempdir.name)

copyfile(os.path.join(cwd, 'tests/micropython.bin'),
os.path.join(tempdir.name, 'simple_ram_behavioural.bin'))

cmd = [ os.path.join(cwd, './core_tb') ]

devNull = open(os.devnull, 'w')
p = subprocess.Popen(cmd, stdout=devNull,
stdin=subprocess.PIPE, stderr=subprocess.PIPE)

exp = fdpexpect.fdspawn(p.stderr)
exp.logfile = sys.stdout.buffer

exp.expect('Type "help\(\)" for more information.')
exp.expect('>>>')

p.stdin.write(b'n2=0\r\n')
p.stdin.write(b'n1=1\r\n')
p.stdin.write(b'for i in range(5):\r\n')
p.stdin.write(b' n0 = n1 + n2\r\n')
p.stdin.write(b' print(n0)\r\n')
p.stdin.write(b' n2 = n1\r\n')
p.stdin.write(b' n1 = n0\r\n')
p.stdin.write(b'\r\n')
p.stdin.flush()

exp.expect('n1 = n0', timeout=600)
exp.expect('1', timeout=600)
exp.expect('2', timeout=600)
exp.expect('3', timeout=600)
exp.expect('5', timeout=600)
exp.expect('8', timeout=600)
exp.expect('>>>', timeout=600)

os.kill(p.pid, signal.SIGKILL)

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

package sim_console is
procedure sim_console_read (val: out std_ulogic_vector(63 downto 0));
attribute foreign of sim_console_read : procedure is "VHPIDIRECT sim_console_read";

procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0));
attribute foreign of sim_console_poll : procedure is "VHPIDIRECT sim_console_poll";

procedure sim_console_write (val: std_ulogic_vector(63 downto 0));
attribute foreign of sim_console_write : procedure is "VHPIDIRECT sim_console_write";
end sim_console;

package body sim_console is
procedure sim_console_read (val: out std_ulogic_vector(63 downto 0)) is
begin
assert false report "VHPI" severity failure;
end sim_console_read;

procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0)) is
begin
assert false report "VHPI" severity failure;
end sim_console_poll;

procedure sim_console_write (val: std_ulogic_vector(63 downto 0)) is
begin
assert false report "VHPI" severity failure;
end sim_console_write;
end sim_console;

@ -0,0 +1,136 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <poll.h>


#define vhpi0 2 /* forcing 0 */
#define vhpi1 3 /* forcing 1 */

static uint64_t from_std_logic_vector(unsigned char *p, unsigned long len)
{
unsigned long ret = 0;

if (len > 64) {
fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
exit(1);
}

for (unsigned long i = 0; i < len; i++) {
unsigned char bit;

if (*p == vhpi0) {
bit = 0;
} else if (*p == vhpi1) {
bit = 1;
} else {
fprintf(stderr, "%s: bad bit %d\n", __func__, *p);
bit = 0;
}

ret = (ret << 1) | bit;
p++;
}

return ret;
}

static void to_std_logic_vector(unsigned long val, unsigned char *p,
unsigned long len)
{
if (len > 64) {
fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
exit(1);
}

for (unsigned long i = 0; i < len; i++) {
if ((val >> (len-1-i) & 1))
*p = vhpi1;
else
*p = vhpi0;

p++;
}
}

static struct termios oldt;

static void restore_termios(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
}

static void nonblocking(void)
{
static bool initialized = false;

if (!initialized) {
static struct termios newt;

tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON|ECHO);

newt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
newt.c_oflag &= ~(OPOST);
newt.c_cflag |= (CS8);
newt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);

tcsetattr(STDIN_FILENO, TCSANOW, &newt);
initialized = true;
atexit(restore_termios);
}
}

void sim_console_read(unsigned char *__rt)
{
int ret;
unsigned long val = 0;

nonblocking();

ret = read(STDIN_FILENO, &val, 1);
if (ret != 1) {
fprintf(stderr, "%s: read of stdin returns %d\n", __func__, ret);
exit(1);
}

//fprintf(stderr, "read returns %c\n", val);

to_std_logic_vector(val, __rt, 64);
}

void sim_console_poll(unsigned char *__rt)
{
int ret;
struct pollfd fdset[1];
uint8_t val = 0;

nonblocking();

memset(fdset, 0, sizeof(fdset));

fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;

ret = poll(fdset, 1, -1);
//fprintf(stderr, "poll returns %d\n", ret);

if (ret == 1)
val = 1;

to_std_logic_vector(val, __rt, 64);
}

void sim_console_write(unsigned char *__rs)
{
uint8_t val;

val = from_std_logic_vector(__rs, 64);

fprintf(stderr, "%c", val);
}

@ -0,0 +1,81 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.simple_ram_behavioural_helpers.all;

entity simple_ram_behavioural is
generic (
FILENAME : string;
SIZE : integer
);

port (
clk : in std_ulogic;
rst : in std_ulogic;

wishbone_in : in wishbone_master_out;
wishbone_out : out wishbone_slave_out
);
end simple_ram_behavioural;

architecture behave of simple_ram_behavioural is
type wishbone_state_t is (IDLE, ACK);

signal state : wishbone_state_t := IDLE;
signal ret_ack : std_ulogic := '0';
signal identifier : integer := behavioural_initialize(filename => FILENAME, size => SIZE);
signal reload : integer := 0;
begin
wishbone_process: process(clk)
variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0');
begin
wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb;
wishbone_out.dat <= ret_dat;

if rising_edge(clk) then
if rst = '1' then
state <= IDLE;
ret_ack <= '0';
report "MEM RST";
else
ret_dat := x"XXXXXXXXXXXXXXXX";

-- Active
if wishbone_in.cyc = '1' then
report "MEM CYC";
case state is
when IDLE =>
report "MEM IDLE";
if wishbone_in.stb = '1' then
-- write
if wishbone_in.we = '1' then
assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure;
report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr);
behavioural_write(wishbone_in.dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier);
reload <= reload + 1;
ret_ack <= '1';
state <= ACK;
else
behavioural_read(ret_dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload);
report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat);
ret_ack <= '1';
state <= ACK;
end if;
end if;
when ACK =>
report "MEM ACK";
ret_ack <= '0';
state <= IDLE;
end case;
else
ret_ack <= '0';
state <= IDLE;
end if;
end if;
end if;
end process;
end behave;

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

package simple_ram_behavioural_helpers is
function behavioural_initialize (filename: String; size: integer) return integer;
attribute foreign of behavioural_initialize : function is "VHPIDIRECT behavioural_initialize";

procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer);
attribute foreign of behavioural_read : procedure is "VHPIDIRECT behavioural_read";

procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer);
attribute foreign of behavioural_write : procedure is "VHPIDIRECT behavioural_write";
end simple_ram_behavioural_helpers;

package body simple_ram_behavioural_helpers is
function behavioural_initialize (filename: String; size: integer) return integer is
begin
assert false report "VHPI" severity failure;
end behavioural_initialize;

procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer) is
begin
assert false report "VHPI" severity failure;
end behavioural_read;

procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is
begin
assert false report "VHPI" severity failure;
end behavioural_write;
end simple_ram_behavioural_helpers;

@ -0,0 +1,258 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#define DEBUG

#define ALIGN_UP(VAL, SIZE) (((VAL) + ((SIZE)-1)) & ~((SIZE)-1))

#define vhpi0 2 /* forcing 0 */
#define vhpi1 3 /* forcing 1 */

struct int_bounds
{
int left;
int right;
char dir;
unsigned int len;
};

struct fat_pointer
{
void *base;
struct int_bounds *bounds;
};

static char *from_string(void *__p)
{
struct fat_pointer *p = __p;
unsigned long len = p->bounds->len;
char *m;

m = malloc(len+1);
if (!m) {
perror("malloc");
exit(1);
}

memcpy(m, p->base, len);
m[len] = 0x0;

return m;
}

static uint64_t from_std_logic_vector(unsigned char *p, unsigned long len)
{
unsigned long ret = 0;

if (len > 64) {
fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
exit(1);
}

for (unsigned long i = 0; i < len; i++) {
unsigned char bit;

if (*p == vhpi0) {
bit = 0;
} else if (*p == vhpi1) {
bit = 1;
} else {
fprintf(stderr, "%s: bad bit %d\n", __func__, *p);
bit = 0;
}

ret = (ret << 1) | bit;
p++;
}

return ret;
}

static void to_std_logic_vector(unsigned long val, unsigned char *p,
unsigned long len)
{
if (len > 64) {
fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
exit(1);
}

for (unsigned long i = 0; i < len; i++) {
if ((val >> (len-1-i) & 1))
*p = vhpi1;
else
*p = vhpi0;

p++;
}
}

#define MAX_REGIONS 128

struct ram_behavioural {
char *filename;
unsigned long size;
void *m;
};

static struct ram_behavioural behavioural_regions[MAX_REGIONS];
static unsigned long region_nr;

unsigned long behavioural_initialize(void *__f, unsigned long size)
{
struct ram_behavioural *r;
int fd;
struct stat buf;
unsigned long tmp_size;
void *mem;

if (region_nr == MAX_REGIONS) {
fprintf(stderr, "%s: too many regions, bump MAX_REGIONS\n");
exit(1);
}

r = &behavioural_regions[region_nr];

r->filename = from_string(__f);
r->size = ALIGN_UP(size, getpagesize());

fd = open(r->filename, O_RDWR);
if (fd == -1) {
fprintf(stderr, "%s: could not open %s\n", __func__,
r->filename);
exit(1);
}

if (fstat(fd, &buf)) {
perror("fstat");
exit(1);
}

/* XXX Do we need to truncate the underlying file? */
tmp_size = ALIGN_UP(buf.st_size, getpagesize());

if (r->size > tmp_size) {
void *m;

/*
* We have to pad the file. Allocate the total size, then
* create a space for the file.
*/
mem = mmap(NULL, r->size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) {
perror("mmap");
exit(1);
}

if (tmp_size) {
munmap(mem, tmp_size);

m = mmap(mem, tmp_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, fd, 0);
if (m == MAP_FAILED) {
perror("mmap");
exit(1);
}
if (m != mem) {
fprintf(stderr, "%s: mmap(MAP_FIXED) failed\n",
__func__);
exit(1);
}
}
} else {
mem = mmap(NULL, tmp_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
fd, 0);
if (mem == MAP_FAILED) {
perror("mmap");
exit(1);
}
}

behavioural_regions[region_nr].m = mem;
return region_nr++;
}

void behavioural_read(unsigned char *__val, unsigned char *__addr,
unsigned long sel, int identifier)
{
struct ram_behavioural *r;
unsigned long val = 0;
unsigned long addr = from_std_logic_vector(__addr, 64);
unsigned char *p;

if (identifier > region_nr) {
fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
exit(1);
}

r = &behavioural_regions[identifier];

for (unsigned long i = 0; i < 8; i++) {
#if 0
/* sel only used on writes */
if (!(sel & (1UL << i)))
continue;
#endif

if ((addr + i) > r->size) {
fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
addr+i, r->size);
exit(1);
}

p = (unsigned char *)(((unsigned long)r->m) + addr + i);
val |= (((unsigned long)*p) << (i*8));
}

#ifdef DEBUG
printf("MEM behave %d read %016lx addr %016lx sel %02lx\n", identifier, val,
addr, sel);
#endif

to_std_logic_vector(val, __val, 64);
}

void behavioural_write(unsigned char *__val, unsigned char *__addr,
unsigned int sel, int identifier)
{
struct ram_behavioural *r;
unsigned long val = from_std_logic_vector(__val, 64);
unsigned long addr = from_std_logic_vector(__addr, 64);
unsigned char *p;

if (identifier > region_nr) {
fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
exit(1);
}

r = &behavioural_regions[identifier];

p = (unsigned char *)(((unsigned long)r->m) + addr);

#ifdef DEBUG
printf("MEM behave %d write %016lx addr %016lx sel %02x\n", identifier, val,
addr, sel);
#endif

for (unsigned long i = 0; i < 8; i++) {
if (!(sel & (1UL << i)))
continue;

if ((addr + i) > r->size) {
fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
addr+i, r->size);
exit(1);
}

p = (unsigned char *)(((unsigned long)r->m) + addr + i);
*p = (val >> (i*8)) & 0xff;
}
}

Binary file not shown.

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

library work;
use work.wishbone_types.all;

entity simple_ram_behavioural_tb is
end simple_ram_behavioural_tb;

architecture behave of simple_ram_behavioural_tb is
signal clk : std_ulogic;
signal rst : std_ulogic := '1';

constant clk_period : time := 10 ns;

signal w_in : wishbone_slave_out;
signal w_out : wishbone_master_out;
begin
simple_ram_0: entity work.simple_ram_behavioural
generic map ( filename => "simple_ram_behavioural_tb.bin", size => 16 )
port map (clk => clk, rst => rst, wishbone_out => w_in, wishbone_in => w_out);

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

stim: process
begin
w_out.adr <= (others => '0');
w_out.dat <= (others => '0');
w_out.cyc <= '0';
w_out.stb <= '0';
w_out.sel <= (others => '0');
w_out.we <= '0';

wait for clk_period;
rst <= '0';

wait for clk_period;

w_out.cyc <= '1';

-- test various read lengths and alignments
w_out.stb <= '1';
w_out.sel <= "00000001";
w_out.adr <= x"0000000000000000";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(7 downto 0) = x"00" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000001";
w_out.adr <= x"0000000000000001";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(7 downto 0) = x"01" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000001";
w_out.adr <= x"0000000000000007";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(7 downto 0) = x"07" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000011";
w_out.adr <= x"0000000000000000";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(15 downto 0) = x"0100" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000011";
w_out.adr <= x"0000000000000001";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(15 downto 0) = x"0201" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000011";
w_out.adr <= x"0000000000000007";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(15 downto 0) = x"0807" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00001111";
w_out.adr <= x"0000000000000000";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(31 downto 0) = x"03020100" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00001111";
w_out.adr <= x"0000000000000001";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(31 downto 0) = x"04030201" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00001111";
w_out.adr <= x"0000000000000007";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(31 downto 0) = x"0A090807" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "11111111";
w_out.adr <= x"0000000000000000";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(63 downto 0) = x"0706050403020100" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "11111111";
w_out.adr <= x"0000000000000001";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(63 downto 0) = x"0807060504030201" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "11111111";
w_out.adr <= x"0000000000000007";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(63 downto 0) = x"0E0D0C0B0A090807" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

-- test various write lengths and alignments
w_out.stb <= '1';
w_out.sel <= "00000001";
w_out.adr <= x"0000000000000000";
w_out.we <= '1';
w_out.dat(7 downto 0) <= x"0F";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "00000001";
w_out.adr <= x"0000000000000000";
w_out.we <= '0';
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat(7 downto 0) = x"0F" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "11111111";
w_out.adr <= x"0000000000000007";
w_out.we <= '1';
w_out.dat <= x"BADC0FFEBADC0FFE";
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

w_out.stb <= '1';
w_out.sel <= "11111111";
w_out.adr <= x"0000000000000007";
w_out.we <= '0';
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
assert w_in.dat = x"BADC0FFEBADC0FFE" report to_hstring(w_in.dat);
w_out.stb <= '0';
wait for clk_period;
assert w_in.ack = '0';

assert false report "end of test" severity failure;
wait;
end process;
end behave;

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFFFFFEA9FF0004
REG 0000000072E50000
REG 0000000000000000
REG 0000000000001CAA
REG 0000000000000040
REG 0000000000000000
REG 0000000000000000
REG 000B000100000000
REG 0000000000000000
REG 000000000000131F
REG 0000000000000000
REG FFFFFFFFA9F40004
REG 000B000100000000
REG 0000000000000000
REG 0000000000040000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFF8D1AFFFF
REG 0000000000000004
REG 0000000028808000
REG 000000000161E8C0
REG 000000000000BCD9
REG FFFFFFFFFFFFFFF1
REG 000000000000471E
REG 000000000000BCD9
REG 0000000028808000
REG 000010000000BC00
REG 0000000000000000
REG 0000000100000001
REG 0000000000000000
REG 0000000000001CAA
REG 0000000051010001

Binary file not shown.

@ -0,0 +1,32 @@
REG 00000000290C5C65
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFC802
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFF04EC
REG FFFFFFFFDFFFFFFE
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000040
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000005800000
REG 0000000000000000
REG 0000000000000020
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000080000000

Binary file not shown.

@ -0,0 +1,32 @@
REG FC00000030B80F7E
REG FFFFFFFFFFFFFFFF
REG 000000000000001F
REG 0000000000000009
REG FFFFFFFFFFFFF03F
REG 0000000628C6749B
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFF4
REG 0000000000000FC0
REG 0000000000000F80
REG 0000000000000000
REG 000000000000001B
REG 000000000000AFC6
REG 00000000CAEC001F
REG FFFFFFFFFFFFFFE1
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000007
REG 0000000628C67484
REG FFFFFFF9FFF6101F
REG 000000002300001F
REG 0000000000000040
REG FFFFFFFFFFFFFFFF
REG 000000000000007C
REG 000000000000001F
REG FFFFFFF9FBC21000
REG 0000000000000000
REG FFFFFFFFFFFFF07F
REG 000000001CF4001F
REG 000000000000007C
REG 000000005FF10911

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000000000042
REG 00000000E0000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 00000000001CE494
REG 0000000000000000
REG 0000000000000002
REG FFFFFFFFFFFFABBB
REG 0000000000000000
REG 8000000000000000
REG 0000000000000039
REG 0000000000000000
REG 8000000000000000
REG 0000000100000001
REG FFFFFFFFFFFFFFC0
REG 0000000000000000
REG 00FFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 00FFFFFFFFFFFFFF
REG 0000000000000040
REG 00000000001D5A80
REG 0000000000000000
REG 0000000100000003
REG 0000000000000068
REG 0000000000000000
REG 0100000000000033
REG 0000000000000007
REG 0000000085000040

Binary file not shown.

@ -0,0 +1,32 @@
REG 00000000000000ED
REG 0000000000000000
REG 000000000000074A
REG 0000000000000001
REG 0000000000000000
REG 0000000006FE7D07
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000001
REG 0808000806FE7D06
REG 0000000000000004
REG 00000000B83A0000
REG 0000000000001B05
REG FFFFFFFFFFFFFFF8
REG 0003100000000000
REG 0000000000000000
REG 00000100000050EA
REG 0000000000000007
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 000002000000A1D0
REG 0000000020000000
REG 0000000000000007
REG 0000000000001B05
REG 0000000044882888
REG 0000000000000000
REG 0000000000000000
REG 0000000000001B05
REG 00000000810001E1

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFFFFFFFD338C3F
REG 0000000000000000
REG 0000000000004870
REG 000000003FFFFFC0
REG FFFFFFFFFFFFFFFF
REG 480085E048000000
REG FFFFFF8000001FE5
REG 0000000000000000
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 000000000000001A
REG 0000000005040001
REG FFFFFFFFFFFFFFFF
REG 0000002820000000
REG F58349ADEDA77E00
REG FFFFFFFFFFFFFFF8
REG 000000000000001A
REG FFFFFFFFE00003FF
REG 0000000000000020
REG 00000000000009E4
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000008
REG FFFFFFFFFFFFFFFF
REG FC0000000505CC9F
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 000000000A080003

Binary file not shown.

@ -0,0 +1,32 @@
REG FF9FFFFF21240000
REG 000000000017EE80
REG 00000001BFC00000
REG 0060000000780000
REG 0000000000000020
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFF95
REG FFFFFFFFE0CA9244
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG FFFFFFFFFFFF408B
REG 0000000040000000
REG 0000000000000000
REG FFFFFFFFFFFF9ED4
REG 00000000000002FD
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFE0CA9244
REG 0000000000000020
REG 000000000000EA01
REG 0000000000000000
REG 000000000D000000
REG 0000000000000000
REG FFFFFFFFFFE80000
REG 0000000000000000
REG 000000005A108491

Binary file not shown.

@ -0,0 +1,32 @@
REG 00003FFFFFFF8001
REG 0000000000000000
REG 0000000000000000
REG 49C2000000000082
REG 801F100000000000
REG FFFFFFFFFDF6D8F0
REG 49C2000000000082
REG 0000000000000026
REG FFFFFFFFFFFEFFFF
REG 801F100000000000
REG FFFFFF00FFFFFFFF
REG FFFFFF00FFFFFFFE
REG FFFFFF00FFFFFFFE
REG FFFFFFFFD56124E1
REG FFFFFF00FFFFFFFF
REG 0000000000008000
REG 0000000000000026
REG EAB09270E8409270
REG 0000000000000000
REG FFFFFF00FFFFFFFF
REG 000801F1000001E8
REG 0000000000000000
REG FFF7FE0EFFFFFFFF
REG 7FE0F00000000000
REG FFFFFF00FFFFFFFE
REG 00000000004124E1
REG 0000000038820000
REG 00000000004124E1
REG 03FFFFFFFF000000
REG 0000000000000000
REG 0000002500000025
REG 000000001090001E

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000048200024
REG FFFFFFFFFFFFFFFF
REG 0000000000000001
REG 0000000000000002
REG FFFFFFFF82410000
REG 0000000000000000
REG 00000000BA76001F
REG 020000202A26001F
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000002
REG 0000001F0000000A
REG 0004C0000004C000
REG FFFFFFFFF7FFFFFD
REG 0000000000000001
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG BE041CE7FFFBDC6A
REG 00000000000059A0
REG 0000000000000006
REG 0000000048200024
REG 0000000000000000
REG FFFB3FFFFFFB4000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000090400048

Binary file not shown.

@ -0,0 +1,32 @@
REG 000000070000075A
REG 0000000000000000
REG BFFFFFFFBE000004
REG 0000000001FFFFFB
REG 0000000000000000
REG FFFFFEF2FFFFA904
REG 0200000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFB
REG F873800000000000
REG 0000000000000000
REG 0000000000000001
REG FFFFFFFFFFFE1CE0
REG 0000000001FFFFFB
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 078C2C003F540004
REG 00000000000007E8
REG 0000000002000871
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFE000004
REG FFFFFFF1FFFFAB02
REG 0000000000000000
REG 078C2C003F540004
REG F873D3FFC1540004
REG 00000007184E0100
REG 4000000040000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000001
REG 0000000108800088

Binary file not shown.

@ -0,0 +1,32 @@
REG 7851A07EFFA70241
REG 0000000000000000
REG 0000000000004000
REG D30FE001D310661A
REG D3102F7BD3102F7B
REG FFFBFFFFFFFD7FFF
REG 87F000010000423F
REG FFFBFFFFFFFD7E00
REG 87F40015741BFFD1
REG 7B81FFFF4000001F
REG 0000000000000000
REG 0000000000000000
REG 00000000000C110F
REG FFFFFFFFFFFFFFCB
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFF5BC0
REG 00000000000007FF
REG 000000147419F50E
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 87F40015741C5662
REG 0000000000000000
REG FFFFFFF94C438180
REG 780BFFFEFFFD11AF
REG 00000000FFFFBDC0
REG 0000000000000000
REG FFFFFFF94C438180
REG FFFFFFF94C43C3BF
REG 780BFFFEFFFD11AF
REG 0000000040088004

Binary file not shown.

@ -0,0 +1,32 @@
REG 000000000000001E
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 0000000000000000
REG 0000000000000010
REG FFFFFFFFFFFFFFFF
REG 0000000000000040
REG 0000000000000000
REG 00003FFFCE9561AE
REG 0000000000000001
REG 0000000000000000
REG 0000000000000007
REG 0000001F9AA70020
REG 0000000000000000
REG 0000000000000001
REG FFFFFFFFFFFFFFFF
REG FFFFFFFF7FFFFFFF
REG 0000000000000000
REG FFFFFFFF76D1FFF0
REG FFFFFFFFFFFFFFF0
REG FFFFFFFFFFFFFFFF
REG 00000000892E0000
REG 00007FFFFFFFFFFF
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000040088088

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 000000004C5B0000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFC00000000000
REG FFFFFFFFFFFF8D9E
REG 0000000000000000
REG FFFFFFFFFFFF5E44
REG FFFFFFFFFFFFE8C8
REG 00000000FFFFFFFF
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 3FFFFFF8FFFFFFF8
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFF5E44
REG 000000004C5B0000
REG 0000000000000000
REG 0000000000000000
REG 0000000020000000
REG FFFFFFFFFFFFBD1F
REG FFFFFFFFFFFFFFFF
REG FFFFFFFF00000001
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 000000000000A1BB
REG 000000010401FFFE

Binary file not shown.

@ -0,0 +1,32 @@
REG 003AD23688890019
REG 0000000000000040
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 0000000000000040
REG 0000000000000000
REG 00000000972B0000
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 004080C0D0C0C089
REG 0000000000000000
REG 0000000000000317
REG FFC52DC9E05DFFFF
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFD1
REG 000000000000002F
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFF89A0
REG 0000000000000000
REG 0000000000000006
REG 0000000000000000
REG 0808080503040000
REG 0808080503040000
REG 0000000000000030
REG 0000000000000000
REG 0000000104005000

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000000000032
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000001
REG 0000000000000000
REG 0000000000000046
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFF9DDB
REG FFFFFFFF55B2FFBF
REG FFFFFFFFFFFFFFFF
REG 000000000000C6C3
REG 0000000000000000
REG FFFFFFFFFFFFFFB9
REG FFFFFFFFFFFF3983
REG 0000000000000033
REG 0000000000000000
REG 0000023000000030
REG 0000000000000000
REG 0000000000000000
REG 0000000000000003
REG 0000000000000008
REG 7C20000000000000
REG 0000000000000000
REG 0000000000000000
REG 0001FFFFFFFFFF73
REG 0000000000000002
REG FFFFFFFFFFFFFFBF
REG 0000000000000040
REG 0000000000000000
REG 00000001011E89F2

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFFFFFFFFFF9A6A
REG 0000000000000000
REG FFFFFFFFFFFFFFF7
REG 0000000000000000
REG 0000000000000000
REG 0000000000003350
REG FFFFFFFFFFFFFFFF
REG 00000FFFFFFFF7FF
REG 0000000000000001
REG FFFFFFFFFFFF9A6A
REG 0000000000000000
REG 0000001A00000012
REG FFFFFFFFFFF34D40
REG 000000002F280888
REG 0000000000000001
REG 0000000000000000
REG 0007FF0000000000
REG FFFFFFFFD0D7FFFF
REG FFFFFFFFFFFFB350
REG 0000000000000000
REG 0000000000000000
REG 000000000000003C
REG 0000000000000020
REG FFFFFFFFFFFF0000
REG 0000000000000000
REG FFFFFFFFFFFF5F77
REG D0D72F27D0D72F27
REG 0000000000000001
REG 0000002000000000
REG 0000002000000017
REG 0000000000000000
REG 0000000041FA11F1

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFFFFFFB357FFC1
REG 0000000000000021
REG 0000000000000000
REG FFFFFFFFFFFFFFCF
REG 0000000000008DF8
REG 000000007FFFF7C0
REG 0000000000000000
REG FFFFFFFFFFFFFFE1
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG 0000000000000000
REG 00000000000090D6
REG 0000000000000001
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFE1
REG 000000000000C4A7
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFE0
REG 0000000048D50000
REG 00000000000034E1
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFEAD2
REG 0000000000000000
REG FFFFFFFF44A9FFDF
REG 000000000000D120
REG FFFFFFFFFFFFFFDF
REG 00000000000090D5
REG 000000000000FC00
REG 0000000000000040
REG 0000000040000700

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFFFFF8E09C556F
REG 000000002448848E
REG 0000000083C40000
REG 000000000000FF00
REG E3A0008CE810D740
REG 0000080000000000
REG 09200002A89AE240
REG 8D7F3BB3449942C5
REG 0002A5B9121A971C
REG FC48980000189976
REG 0002A5B9121A975C
REG FFFFFFF8E0906D06
REG 00000000EDDA0035
REG FFB6FFFFEABB77ED
REG 0000000000005F00
REG FFFFFFFFFFFFFFFD
REG FFFFFFFFFFFFA0DA
REG 0000000000000035
REG 0000010000000000
REG 0000000000005F26
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000005F26
REG 0000000000000000
REG 0048FFFFFFFF8808
REG 0000000000000020
REG 0000000000000040
REG E3A0008CE810C566
REG FFFFFFFFEABAFFF6
REG FFFFFFDFFFFFA0FA
REG FFFFFFFFFFFFFFAA
REG 000000004891091D

Binary file not shown.

@ -0,0 +1,32 @@
REG BFFFFC0A1FFFF7DB
REG 0000000000000000
REG 0000000000000000
REG 800009200003F000
REG 0000000000000040
REG 000000004F7FE848
REG FFFFFFFFE00098C3
REG FFFFFFFF80000000
REG 000000001FFF673D
REG 0000000000000000
REG FFFFFFFFE000FBAF
REG FFFFFFFFFFFFF172
REG 0000000000000000
REG 00000000000FFFFE
REG 0007FFFEFFF00002
REG 0000000000004E91
REG 0000000000000000
REG FFFFFFFFE0005799
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFC0000000
REG 000003FFE000082E
REG 00000000FFFF7EDC
REG FFFFFFFFFFFFFFFF
REG 000000001FFF5799
REG 0000000000000000
REG 0000000017FD0000
REG FFFFBF6EE007BF6E
REG 0000000000000000
REG FFFFFFFFFFFF0000
REG FFFFFFFF80000000
REG 000000005EFFD110

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000000000042
REG FFFFFFFFFE48FFFF
REG 00006F3900006F39
REG 0000000000000000
REG 0000000000000000
REG 0000000003FE0000
REG 100106B000000000
REG FFFFFFFFFFFFFE13
REG FFFFFFFFFFFF4985
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFC19D3E63
REG FFFFFFFFE8250000
REG 0000000000000040
REG FFFFFFFFFE48FFFF
REG 0000000000008A9E
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 00000000106B0000
REG E00000000100FFFF
REG 0000000040828478
REG 000000007B490000
REG 8000340000000000
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFA8250000
REG FFFFFFFFFFFFFFFF
REG E800000000000000
REG 0000000000008A9D
REG 0000000117120811

Binary file not shown.

@ -0,0 +1,32 @@
REG 000000000045061D
REG FFFFFFFFC0ACFFFF
REG 0000000000450600
REG FFFFFFFFFFBAF9DF
REG 0000000000000000
REG 0000000000000380
REG 0000000000450600
REG 0000000000000020
REG FFFFFEDB201FFB60
REG FFFFFFFFC0AD0000
REG 0000000000000000
REG FFFFFEDB201FFB60
REG 0000000020040001
REG FFFFFFFFFFFFFFFF
REG 0808080802040808
REG 0000000000000000
REG 0000000000000001
REG 0000000000000020
REG 0000000000450600
REG 0000000000000020
REG 000000000044A8A4
REG 0000000000000007
REG FFFFFFFFFE056800
REG 0000000000000000
REG 000000007F02AE4D
REG 0000000000000000
REG 0000000000F811B2
REG 0000000000000007
REG 0080000000000000
REG 0000000000000000
REG 00001EE90DC27CF6
REG 0000000040509010

Binary file not shown.

@ -0,0 +1,32 @@
REG 000000002F423F42
REG 0000000000000C00
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFF0001CA8
REG FFFFFFFFF0007B0A
REG 0000000000000091
REG 0000000000000003
REG 0FFFFFD071FABD00
REG 0000400000000001
REG 0000000007080603
REG 0000000037FFFFE7
REG 000000007A114210
REG 000000002F083F42
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFF0007B0A
REG 0000000000000000
REG FFFFBFFFFFFFFFFF
REG 00000F33111EAA2C
REG 0000000000000040
REG FFFFFFFFFC0000BD
REG 00000000D0BDD7BE
REG FFFFFFFF2F422441
REG 000000000FFF84F5
REG 0000000000000020
REG 0000000000000000
REG 0000400000000001
REG 000000002F422842
REG 00000000D0B22BBE
REG 000000000E0500F5
REG 000000009E107E84

Binary file not shown.

@ -0,0 +1,32 @@
REG 01FFFFFFFFFFFFFD
REG 0000000000005802
REG 0000000000000200
REG FFFFFFFFFFFF9C43
REG FFFFFFE000FFEB94
REG 0000001FFF00146B
REG 0000000000000020
REG 0000000500000005
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFDFF
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFFFF
REG FFFFFFFC00000000
REG FFFFFF001E000000
REG FFFFFFFFFFFF693C
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0200001F0000001F
REG 0000000000000200
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFFFF
REG FE00000000000000
REG FFFFFFFFFFFFFFFF
REG 000000FFE200734A
REG FFFFFFFC00000000
REG FFFFFF8000000000
REG 00000000000096E3
REG 0000000000000000
REG 0000000000000000
REG 0000000108910888

Binary file not shown.

@ -0,0 +1,32 @@
REG 480000000002D4EC
REG 0000000000000000
REG 0000000000000000
REG 000FFFFFFFFFCAD8
REG 0000000000005469
REG EFBF28D8EFFFC305
REG 0000008FFFFFD7D8
REG 0000000000000020
REG FFFFFFFFFFFFFFC6
REG 0000009000000090
REG 0000000000000000
REG FFFD99E9FFFFFFEC
REG 00013B65A93C1F74
REG FFFD99E9FFFFFFEA
REG 0002661600026616
REG FFFFFFFFFFFFFFFF
REG 0000000000000041
REG 0000000000000006
REG FFFD99E9FFFFFFEB
REG 0000000000000005
REG 00000001FFFFF2B6
REG FFFFFFFF99CB0000
REG 0000000000000040
REG 000000000000006A
REG FFFFFFFFFFFFF2B6
REG FFFFFFFFFFFFFFFF
REG 0000000000000001
REG 0000000000000185
REG 0000000000000000
REG 0000000000000041
REG B7FD99E9FFFFFF95
REG 0000000104088088

Binary file not shown.

@ -0,0 +1,32 @@
REG 0000000000009F88
REG 0000000000000000
REG FFFFFC6CFFFFFC6C
REG 000779480007CC9B
REG 0000000000000000
REG FFFFFFFFEF290001
REG FFFFFFFFFFFF6077
REG FFFFFFFFBBFABFFF
REG 0000000010D6FFFF
REG 0000000000077948
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 000000000004F40C
REG 0000000000000000
REG 0007794800077948
REG 0000000000000000
REG 0000000000000000
REG 0000000000080000
REG FFFFFC6CFFFFFC6C
REG 0000000004000000
REG 0000000000000000
REG 0000000000000000
REG 00001C6CFFFFFC6C
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG FFFFFC6CFFFFFC6C
REG 000000000004F58D
REG FF3FFFFFFFFFFFFF
REG 00000000480A8004

Binary file not shown.

@ -0,0 +1,32 @@
REG 5CEFF00200008022
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 043BA020AF31A4FF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 00000000118007FF
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFFFFFFFFF
REG 0000000000000001
REG 0000000000FFB800
REG 0000000000000000
REG 0000000000000000
REG FFFFFFFFEE7FF800
REG 0000000000000000
REG 23100FFDFFFFD610
REG 0000000000000000
REG 00000000015B5000
REG 000000002E20A000
REG 000000000000001E
REG 0118007FF0000000
REG 0000000000000000
REG 0000000000000000
REG 000000000000000B
REG 0000000000000000
REG 0000000000000000
REG 00000000901E1000

Binary file not shown.

@ -0,0 +1,32 @@
REG FFFBFFBFFDC00001
REG FFFFFFFFFFFFFFFE
REG 0000000000000000
REG FFFFF9FFC92EFFFF
REG FFFFFFFFFF7FFFFF
REG 4000000000000000
REG FF85A9BEFCB8F7F7
REG 0000000000000000
REG 0000000000000000
REG FFFFF9FFE757FFFF
REG 17C49F006F000000
REG E481584E91000000
REG FFFFFFFFFF7FFFFF
REG 0000000000000040
REG 0000000094290000
REG E481584E91000000
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFFFF
REG C000000000000000
REG 0000000000000000
REG 007B564002400019
REG 0000000000000000
REG 0000000000000001
REG FFFFFFFFFFFFFFFF
REG FFFFFFFFFFFFFFC0
REG 20FBF9C507C70809
REG 0000000000000000
REG 0000000000000000
REG 0000000000000000
REG 0000020020011FFF
REG 0000000000000000
REG 00000000931C889F

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save