mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
Merge pull request #382 from paulusmack/master
Decode in block RAM and other improvements
This commit is contained in:
commit
ff63ffdbfd
8
Makefile
8
Makefile
@ -56,13 +56,13 @@ all = core_tb icache_tb dcache_tb dmi_dtm_tb \
|
||||
all: $(all)
|
||||
|
||||
core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \
|
||||
utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \
|
||||
utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl predecode.vhdl \
|
||||
decode1.vhdl helpers.vhdl insn_helpers.vhdl \
|
||||
control.vhdl decode2.vhdl register_file.vhdl \
|
||||
cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \
|
||||
logical.vhdl countbits.vhdl multiply.vhdl divider.vhdl execute1.vhdl \
|
||||
loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \
|
||||
core.vhdl fpu.vhdl pmu.vhdl
|
||||
logical.vhdl countbits.vhdl multiply.vhdl multiply-32s.vhdl divider.vhdl \
|
||||
execute1.vhdl loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl \
|
||||
core_debug.vhdl core.vhdl fpu.vhdl pmu.vhdl
|
||||
|
||||
soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \
|
||||
wishbone_debug_master.vhdl xics.vhdl syscon.vhdl gpio.vhdl soc.vhdl \
|
||||
|
||||
@ -7,6 +7,7 @@ entity cache_ram is
|
||||
generic(
|
||||
ROW_BITS : integer := 16;
|
||||
WIDTH : integer := 64;
|
||||
BYTEWID : integer := 8;
|
||||
TRACE : boolean := false;
|
||||
ADD_BUF : boolean := false
|
||||
);
|
||||
@ -16,7 +17,7 @@ entity cache_ram is
|
||||
rd_en : in std_logic;
|
||||
rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
|
||||
rd_data : out std_logic_vector(WIDTH - 1 downto 0);
|
||||
wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0);
|
||||
wr_sel : in std_logic_vector(WIDTH/BYTEWID - 1 downto 0);
|
||||
wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
|
||||
wr_data : in std_logic_vector(WIDTH - 1 downto 0)
|
||||
);
|
||||
@ -38,7 +39,7 @@ begin
|
||||
variable lbit : integer range 0 to WIDTH - 1;
|
||||
variable mbit : integer range 0 to WIDTH - 1;
|
||||
variable widx : integer range 0 to SIZE - 1;
|
||||
constant sel0 : std_logic_vector(WIDTH/8 - 1 downto 0)
|
||||
constant sel0 : std_logic_vector(WIDTH/BYTEWID - 1 downto 0)
|
||||
:= (others => '0');
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
@ -49,9 +50,9 @@ begin
|
||||
" dat:" & to_hstring(wr_data);
|
||||
end if;
|
||||
end if;
|
||||
for i in 0 to WIDTH/8-1 loop
|
||||
lbit := i * 8;
|
||||
mbit := lbit + 7;
|
||||
for i in 0 to WIDTH/BYTEWID-1 loop
|
||||
lbit := i * BYTEWID;
|
||||
mbit := lbit + BYTEWID - 1;
|
||||
widx := to_integer(unsigned(wr_addr));
|
||||
if wr_sel(i) = '1' then
|
||||
ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit);
|
||||
|
||||
25
common.vhdl
25
common.vhdl
@ -246,10 +246,13 @@ package common is
|
||||
fetch_failed: std_ulogic;
|
||||
nia: std_ulogic_vector(63 downto 0);
|
||||
insn: std_ulogic_vector(31 downto 0);
|
||||
icode: insn_code;
|
||||
big_endian: std_ulogic;
|
||||
next_predicted: std_ulogic;
|
||||
next_pred_ntaken: std_ulogic;
|
||||
end record;
|
||||
constant IcacheToDecode1Init : IcacheToDecode1Type :=
|
||||
(nia => (others => '0'), insn => (others => '0'), icode => INSN_illegal, others => '0');
|
||||
|
||||
type IcacheEventType is record
|
||||
icache_miss : std_ulogic;
|
||||
@ -317,6 +320,9 @@ package common is
|
||||
read_data1: std_ulogic_vector(63 downto 0);
|
||||
read_data2: std_ulogic_vector(63 downto 0);
|
||||
read_data3: std_ulogic_vector(63 downto 0);
|
||||
reg_valid1: std_ulogic;
|
||||
reg_valid2: std_ulogic;
|
||||
reg_valid3: std_ulogic;
|
||||
cr: std_ulogic_vector(31 downto 0);
|
||||
xerc: xer_common_t;
|
||||
lr: std_ulogic;
|
||||
@ -363,6 +369,7 @@ package common is
|
||||
is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0',
|
||||
byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'),
|
||||
read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'),
|
||||
reg_valid1 => '0', reg_valid2 => '0', reg_valid3 => '0',
|
||||
cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'),
|
||||
result_sel => "000", sub_select => "000",
|
||||
repeat => '0', second => '0', spr_select => spr_id_init,
|
||||
@ -378,12 +385,11 @@ package common is
|
||||
data1: std_ulogic_vector(63 downto 0);
|
||||
data2: std_ulogic_vector(63 downto 0);
|
||||
addend: std_ulogic_vector(127 downto 0);
|
||||
is_32bit: std_ulogic;
|
||||
not_result: std_ulogic;
|
||||
is_signed: std_ulogic;
|
||||
subtract: std_ulogic; -- 0 => addend + data1 * data2, 1 => addend - data1 * data2
|
||||
end record;
|
||||
constant MultiplyInputInit : MultiplyInputType := (valid => '0',
|
||||
is_32bit => '0', not_result => '0',
|
||||
others => (others => '0'));
|
||||
constant MultiplyInputInit : MultiplyInputType := (data1 => 64x"0", data2 => 64x"0",
|
||||
addend => 128x"0", others => '0');
|
||||
|
||||
type MultiplyOutputType is record
|
||||
valid: std_ulogic;
|
||||
@ -476,7 +482,6 @@ package common is
|
||||
type Execute1ToLoadstore1Type is record
|
||||
valid : std_ulogic;
|
||||
op : insn_type_t; -- what ld/st or m[tf]spr or TLB op to do
|
||||
nia : std_ulogic_vector(63 downto 0);
|
||||
insn : std_ulogic_vector(31 downto 0);
|
||||
instr_tag : instr_tag_t;
|
||||
addr1 : std_ulogic_vector(63 downto 0);
|
||||
@ -504,7 +509,7 @@ package common is
|
||||
(valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
|
||||
sign_extend => '0', update => '0', xerc => xerc_init,
|
||||
reserve => '0', rc => '0', virt_mode => '0', priv_mode => '0',
|
||||
nia => (others => '0'), insn => (others => '0'),
|
||||
insn => (others => '0'),
|
||||
instr_tag => instr_tag_init,
|
||||
addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
|
||||
write_reg => (others => '0'),
|
||||
@ -525,8 +530,6 @@ package common is
|
||||
dcbz : std_ulogic;
|
||||
nc : std_ulogic;
|
||||
reserve : std_ulogic;
|
||||
atomic : std_ulogic; -- part of a multi-transfer atomic op
|
||||
atomic_last : std_ulogic;
|
||||
virt_mode : std_ulogic;
|
||||
priv_mode : std_ulogic;
|
||||
addr : std_ulogic_vector(63 downto 0);
|
||||
@ -674,6 +677,9 @@ package common is
|
||||
fra : std_ulogic_vector(63 downto 0);
|
||||
frb : std_ulogic_vector(63 downto 0);
|
||||
frc : std_ulogic_vector(63 downto 0);
|
||||
valid_a : std_ulogic;
|
||||
valid_b : std_ulogic;
|
||||
valid_c : std_ulogic;
|
||||
frt : gspr_index_t;
|
||||
rc : std_ulogic;
|
||||
m32b : std_ulogic;
|
||||
@ -687,6 +693,7 @@ package common is
|
||||
insn => (others => '0'), fe_mode => "00", rc => '0',
|
||||
fra => (others => '0'), frb => (others => '0'),
|
||||
frc => (others => '0'), frt => (others => '0'),
|
||||
valid_a => '0', valid_b => '0', valid_c => '0',
|
||||
single => '0', is_signed => '0', out_cr => '0',
|
||||
m32b => '0', oe => '0', xerc => xerc_init,
|
||||
stall => '0');
|
||||
|
||||
13
core.vhdl
13
core.vhdl
@ -13,7 +13,6 @@ entity core is
|
||||
EX1_BYPASS : boolean := true;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
ALT_RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0');
|
||||
LOG_LENGTH : natural := 512;
|
||||
ICACHE_NUM_LINES : natural := 64;
|
||||
@ -246,6 +245,7 @@ begin
|
||||
icache_0: entity work.icache
|
||||
generic map(
|
||||
SIM => SIM,
|
||||
HAS_FPU => HAS_FPU,
|
||||
LINE_SIZE => 64,
|
||||
NUM_LINES => ICACHE_NUM_LINES,
|
||||
NUM_WAYS => ICACHE_NUM_WAYS,
|
||||
@ -266,7 +266,7 @@ begin
|
||||
wishbone_in => wishbone_insn_in,
|
||||
wb_snoop_in => wb_snoop_in,
|
||||
events => icache_events,
|
||||
log_out => log_data(96 downto 43)
|
||||
log_out => log_data(100 downto 43)
|
||||
);
|
||||
|
||||
icache_stall_in <= decode1_busy;
|
||||
@ -287,7 +287,7 @@ begin
|
||||
d_out => decode1_to_decode2,
|
||||
f_out => decode1_to_fetch1,
|
||||
r_out => decode1_to_register_file,
|
||||
log_out => log_data(109 downto 97)
|
||||
log_out => log_data(113 downto 101)
|
||||
);
|
||||
|
||||
decode1_stall_in <= decode2_stall_out;
|
||||
@ -319,7 +319,7 @@ begin
|
||||
writeback_bypass => writeback_bypass,
|
||||
dbg_spr_req => dbg_spr_req,
|
||||
dbg_spr_addr => dbg_spr_addr,
|
||||
log_out => log_data(119 downto 110)
|
||||
log_out => log_data(123 downto 114)
|
||||
);
|
||||
decode2_busy_in <= ex1_busy_out;
|
||||
|
||||
@ -365,7 +365,6 @@ begin
|
||||
SIM => SIM,
|
||||
EX1_BYPASS => EX1_BYPASS,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
LOG_LENGTH => LOG_LENGTH
|
||||
)
|
||||
port map (
|
||||
@ -398,7 +397,7 @@ begin
|
||||
dbg_spr_data => dbg_spr_data,
|
||||
sim_dump => sim_ex_dump,
|
||||
sim_dump_done => sim_cr_dump,
|
||||
log_out => log_data(134 downto 120),
|
||||
log_out => log_data(135 downto 124),
|
||||
log_rd_addr => log_rd_addr,
|
||||
log_rd_data => log_rd_data,
|
||||
log_wr_addr => log_wr_addr
|
||||
@ -500,7 +499,7 @@ begin
|
||||
);
|
||||
|
||||
log_data(150) <= '0';
|
||||
log_data(139 downto 135) <= "00000";
|
||||
log_data(139 downto 136) <= "0000";
|
||||
|
||||
debug_0: entity work.core_debug
|
||||
generic map (
|
||||
|
||||
@ -175,7 +175,8 @@ begin
|
||||
gspr_index <= (others => '0');
|
||||
else
|
||||
if do_log_trigger = '1' or log_trigger_delay /= 0 then
|
||||
if log_trigger_delay = 255 then
|
||||
if log_trigger_delay = 255 or
|
||||
(LOG_LENGTH < 1024 and log_trigger_delay = LOG_LENGTH / 4) then
|
||||
log_dmi_trigger(1) <= '1';
|
||||
log_trigger_delay <= 0;
|
||||
else
|
||||
|
||||
@ -1004,10 +1004,10 @@ begin
|
||||
-- XXX or if r0.req.nc = '1'
|
||||
if r0.req.load = '1' then
|
||||
-- load with reservation
|
||||
set_rsrv <= r0.req.atomic_last;
|
||||
set_rsrv <= '1';
|
||||
else
|
||||
-- store conditional
|
||||
clear_rsrv <= r0.req.atomic_last;
|
||||
clear_rsrv <= '1';
|
||||
if reservation.valid = '0' or
|
||||
r0.req.addr(63 downto LINE_OFF_BITS) /= reservation.addr then
|
||||
cancel_store <= '1';
|
||||
|
||||
1067
decode1.vhdl
1067
decode1.vhdl
File diff suppressed because it is too large
Load Diff
55
decode2.vhdl
55
decode2.vhdl
@ -58,10 +58,6 @@ architecture behaviour of decode2 is
|
||||
busy : std_ulogic;
|
||||
sgl_pipe : std_ulogic;
|
||||
prev_sgl : std_ulogic;
|
||||
reg_a_valid : std_ulogic;
|
||||
reg_b_valid : std_ulogic;
|
||||
reg_c_valid : std_ulogic;
|
||||
reg_o_valid : std_ulogic;
|
||||
input_ov : std_ulogic;
|
||||
output_ov : std_ulogic;
|
||||
read_rspr : std_ulogic;
|
||||
@ -192,7 +188,7 @@ architecture behaviour of decode2 is
|
||||
function decode_rc (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is
|
||||
begin
|
||||
case t is
|
||||
when RC =>
|
||||
when RC | RCOE =>
|
||||
return insn_rc(insn_in);
|
||||
when ONE =>
|
||||
return '1';
|
||||
@ -393,6 +389,7 @@ begin
|
||||
variable v : reg_type;
|
||||
variable length : std_ulogic_vector(3 downto 0);
|
||||
variable op : insn_type_t;
|
||||
variable unit : unit_t;
|
||||
variable valid_in : std_ulogic;
|
||||
variable decctr : std_ulogic;
|
||||
variable sprs_busy : std_ulogic;
|
||||
@ -405,6 +402,7 @@ begin
|
||||
v.e := Decode2ToExecute1Init;
|
||||
|
||||
sprs_busy := '0';
|
||||
unit := d_in.decode.unit;
|
||||
|
||||
if d_in.valid = '1' then
|
||||
v.prev_sgl := dc2.sgl_pipe;
|
||||
@ -429,32 +427,40 @@ begin
|
||||
end if;
|
||||
case d_in.decode.insn_type is
|
||||
when OP_ADD | OP_MUL_L64 | OP_DIV | OP_DIVE =>
|
||||
-- OE field is valid in OP_ADD/OP_MUL_L64 with major opcode 31 only
|
||||
if d_in.insn(31 downto 26) = "011111" and insn_oe(d_in.insn) = '1' then
|
||||
if d_in.decode.rc = RCOE and insn_oe(d_in.insn) = '1' then
|
||||
v.e.oe := '1';
|
||||
v.e.output_xer := '1';
|
||||
v.output_ov := '1';
|
||||
v.input_ov := '1'; -- need SO state if setting OV to 0
|
||||
end if;
|
||||
when OP_MFSPR =>
|
||||
if decode_spr_num(d_in.insn) = SPR_XER then
|
||||
v.input_ov := '1';
|
||||
end if;
|
||||
case decode_spr_num(d_in.insn) is
|
||||
when SPR_XER =>
|
||||
v.input_ov := '1';
|
||||
when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR =>
|
||||
unit := LDST;
|
||||
when others =>
|
||||
end case;
|
||||
when OP_MTSPR =>
|
||||
if decode_spr_num(d_in.insn) = SPR_XER then
|
||||
v.e.output_xer := '1';
|
||||
v.output_ov := '1';
|
||||
case decode_spr_num(d_in.insn) is
|
||||
when SPR_XER =>
|
||||
v.e.output_xer := '1';
|
||||
v.output_ov := '1';
|
||||
when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR =>
|
||||
unit := LDST;
|
||||
if d_in.valid = '1' then
|
||||
v.sgl_pipe := '1';
|
||||
end if;
|
||||
when others =>
|
||||
end case;
|
||||
if d_in.spr_info.valid = '1' and d_in.valid = '1' then
|
||||
v.sgl_pipe := '1';
|
||||
end if;
|
||||
when OP_CMP | OP_MCRXRX =>
|
||||
v.input_ov := '1';
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
v.reg_a_valid := decoded_reg_a.reg_valid;
|
||||
v.reg_b_valid := decoded_reg_b.reg_valid;
|
||||
v.reg_c_valid := decoded_reg_c.reg_valid;
|
||||
v.reg_o_valid := decoded_reg_o.reg_valid;
|
||||
|
||||
if d_in.decode.lr = '1' then
|
||||
v.e.lr := insn_lk(d_in.insn);
|
||||
-- b and bc have even major opcodes; bcreg is considered absolute
|
||||
@ -537,11 +543,14 @@ begin
|
||||
|
||||
-- execute unit
|
||||
v.e.nia := d_in.nia;
|
||||
v.e.unit := d_in.decode.unit;
|
||||
v.e.unit := unit;
|
||||
v.e.fac := d_in.decode.facility;
|
||||
v.e.read_reg1 := d_in.reg_a;
|
||||
v.e.read_reg2 := d_in.reg_b;
|
||||
v.e.read_reg3 := d_in.reg_c;
|
||||
v.e.reg_valid1 := decoded_reg_a.reg_valid;
|
||||
v.e.reg_valid2 := decoded_reg_b.reg_valid;
|
||||
v.e.reg_valid3 := decoded_reg_c.reg_valid;
|
||||
v.e.write_reg := decoded_reg_o.reg;
|
||||
v.e.write_reg_enable := decoded_reg_o.reg_valid;
|
||||
v.e.invert_a := d_in.decode.invert_a;
|
||||
@ -583,16 +592,16 @@ begin
|
||||
control_valid_in <= valid_in;
|
||||
control_serialize <= v.sgl_pipe or v.prev_sgl;
|
||||
|
||||
gpr_write_valid <= v.reg_o_valid;
|
||||
gpr_write_valid <= v.e.write_reg_enable;
|
||||
gpr_write <= v.e.write_reg;
|
||||
|
||||
gpr_a_read_valid <= v.reg_a_valid;
|
||||
gpr_a_read_valid <= v.e.reg_valid1;
|
||||
gpr_a_read <= v.e.read_reg1;
|
||||
|
||||
gpr_b_read_valid <= v.reg_b_valid;
|
||||
gpr_b_read_valid <= v.e.reg_valid2;
|
||||
gpr_b_read <= v.e.read_reg2;
|
||||
|
||||
gpr_c_read_valid <= v.reg_c_valid;
|
||||
gpr_c_read_valid <= v.e.reg_valid3;
|
||||
gpr_c_read <= v.e.read_reg3;
|
||||
|
||||
cr_write_valid <= v.e.output_cr or v.e.rc;
|
||||
|
||||
@ -4,14 +4,16 @@ use ieee.std_logic_1164.all;
|
||||
package decode_types is
|
||||
type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD,
|
||||
OP_AND, OP_ATTN, OP_B, OP_BC, OP_BCREG,
|
||||
OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPRB,
|
||||
OP_BCD, OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPRB,
|
||||
OP_CNTZ, OP_CROP,
|
||||
OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
|
||||
OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS, OP_EXTSWSLI,
|
||||
OP_FPOP, OP_FPOP_I,
|
||||
OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
|
||||
OP_DCBZ, OP_ICBI, OP_ICBT,
|
||||
OP_FP_CMP, OP_FP_ARITH, OP_FP_MOVE, OP_FP_MISC,
|
||||
OP_DIV, OP_DIVE, OP_MOD,
|
||||
OP_EXTS, OP_EXTSWSLI,
|
||||
OP_ISEL, OP_ISYNC,
|
||||
OP_LOAD, OP_STORE,
|
||||
OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD,
|
||||
OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR,
|
||||
OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64,
|
||||
OP_MUL_H64, OP_MUL_H32, OP_OR,
|
||||
OP_POPCNT, OP_PRTY, OP_RFID,
|
||||
@ -19,15 +21,349 @@ package decode_types is
|
||||
OP_SHL, OP_SHR,
|
||||
OP_SYNC, OP_TLBIE, OP_TRAP,
|
||||
OP_XOR,
|
||||
OP_BCD, OP_ADDG6S,
|
||||
OP_ADDG6S,
|
||||
OP_FETCH_FAILED
|
||||
);
|
||||
|
||||
-- The following list is ordered in such a way that we can know some
|
||||
-- things about which registers are accessed by an instruction by its place
|
||||
-- in the list. In other words we can decide whether an instruction
|
||||
-- accesses FPRs and whether it has an RB operand by doing simple
|
||||
-- comparisons of the insn_code for the instruction with a few constants.
|
||||
type insn_code is (
|
||||
-- The following instructions don't have an RB operand or access FPRs
|
||||
INSN_illegal, -- 0
|
||||
INSN_fetch_fail,
|
||||
INSN_addi,
|
||||
INSN_addic,
|
||||
INSN_addic_dot,
|
||||
INSN_addis,
|
||||
INSN_addme,
|
||||
INSN_addpcis,
|
||||
INSN_addze,
|
||||
INSN_andi_dot,
|
||||
INSN_andis_dot, -- 10
|
||||
INSN_attn,
|
||||
INSN_b,
|
||||
INSN_bc,
|
||||
INSN_bcctr,
|
||||
INSN_bclr,
|
||||
INSN_bctar,
|
||||
INSN_cbcdtd,
|
||||
INSN_cdtbcd,
|
||||
INSN_cmpi,
|
||||
INSN_cmpli, -- 20
|
||||
INSN_cntlzw,
|
||||
INSN_cntlzd,
|
||||
INSN_cnttzw,
|
||||
INSN_cnttzd,
|
||||
INSN_crand,
|
||||
INSN_crandc,
|
||||
INSN_creqv,
|
||||
INSN_crnand,
|
||||
INSN_crnor,
|
||||
INSN_cror, -- 30
|
||||
INSN_crorc,
|
||||
INSN_crxor,
|
||||
INSN_darn,
|
||||
INSN_eieio,
|
||||
INSN_extsb,
|
||||
INSN_extsh,
|
||||
INSN_extsw,
|
||||
INSN_extswsli,
|
||||
INSN_isync,
|
||||
INSN_lbz, -- 40
|
||||
INSN_lbzu,
|
||||
INSN_ld,
|
||||
INSN_ldu,
|
||||
INSN_lha,
|
||||
INSN_lhau,
|
||||
INSN_lhz,
|
||||
INSN_lhzu,
|
||||
INSN_lwa,
|
||||
INSN_lwz,
|
||||
INSN_lwzu, -- 50
|
||||
INSN_mcrf,
|
||||
INSN_mcrfs,
|
||||
INSN_mcrxrx,
|
||||
INSN_mfcr,
|
||||
INSN_mfmsr,
|
||||
INSN_mfspr,
|
||||
INSN_mtcrf,
|
||||
INSN_mtfsb,
|
||||
INSN_mtfsfi,
|
||||
INSN_mtmsr, -- 60
|
||||
INSN_mtmsrd,
|
||||
INSN_mtspr,
|
||||
INSN_mulli,
|
||||
INSN_neg,
|
||||
INSN_nop,
|
||||
INSN_ori,
|
||||
INSN_oris,
|
||||
INSN_popcntb,
|
||||
INSN_popcntw,
|
||||
INSN_popcntd, -- 70
|
||||
INSN_prtyw,
|
||||
INSN_prtyd,
|
||||
INSN_rfid,
|
||||
INSN_rldic,
|
||||
INSN_rldicl,
|
||||
INSN_rldicr,
|
||||
INSN_rldimi,
|
||||
INSN_rlwimi,
|
||||
INSN_rlwinm,
|
||||
INSN_sc, -- 80
|
||||
INSN_setb,
|
||||
INSN_slbia,
|
||||
INSN_sradi,
|
||||
INSN_srawi,
|
||||
INSN_stb,
|
||||
INSN_stbu,
|
||||
INSN_std,
|
||||
INSN_stdu,
|
||||
INSN_sth,
|
||||
INSN_sthu, -- 90
|
||||
INSN_stw,
|
||||
INSN_stwu,
|
||||
INSN_subfic,
|
||||
INSN_subfme,
|
||||
INSN_subfze,
|
||||
INSN_sync,
|
||||
INSN_tdi,
|
||||
INSN_tlbsync,
|
||||
INSN_twi,
|
||||
INSN_wait, -- 100
|
||||
INSN_xori,
|
||||
INSN_xoris,
|
||||
|
||||
-- pad to 112 to simplify comparison logic
|
||||
INSN_103,
|
||||
INSN_104, INSN_105, INSN_106, INSN_107,
|
||||
INSN_108, INSN_109, INSN_110, INSN_111,
|
||||
|
||||
-- The following instructions have an RB operand but don't access FPRs
|
||||
INSN_add,
|
||||
INSN_addc,
|
||||
INSN_adde,
|
||||
INSN_addex,
|
||||
INSN_addg6s,
|
||||
INSN_and,
|
||||
INSN_andc,
|
||||
INSN_bperm,
|
||||
INSN_cmp, -- 120
|
||||
INSN_cmpb,
|
||||
INSN_cmpeqb,
|
||||
INSN_cmpl,
|
||||
INSN_cmprb,
|
||||
INSN_dcbf,
|
||||
INSN_dcbst,
|
||||
INSN_dcbt,
|
||||
INSN_dcbtst,
|
||||
INSN_dcbz,
|
||||
INSN_divd, -- 130
|
||||
INSN_divdu,
|
||||
INSN_divde,
|
||||
INSN_divdeu,
|
||||
INSN_divw,
|
||||
INSN_divwu,
|
||||
INSN_divwe,
|
||||
INSN_divweu,
|
||||
INSN_eqv,
|
||||
INSN_icbi,
|
||||
INSN_icbt, -- 140
|
||||
INSN_isel,
|
||||
INSN_lbarx,
|
||||
INSN_lbzcix,
|
||||
INSN_lbzux,
|
||||
INSN_lbzx,
|
||||
INSN_ldarx,
|
||||
INSN_ldbrx,
|
||||
INSN_ldcix,
|
||||
INSN_ldx,
|
||||
INSN_ldux, -- 150
|
||||
INSN_lharx,
|
||||
INSN_lhax,
|
||||
INSN_lhaux,
|
||||
INSN_lhbrx,
|
||||
INSN_lhzcix,
|
||||
INSN_lhzx,
|
||||
INSN_lhzux,
|
||||
INSN_lwarx,
|
||||
INSN_lwax,
|
||||
INSN_lwaux, -- 160
|
||||
INSN_lwbrx,
|
||||
INSN_lwzcix,
|
||||
INSN_lwzx,
|
||||
INSN_lwzux,
|
||||
INSN_modsd,
|
||||
INSN_modsw,
|
||||
INSN_moduw,
|
||||
INSN_modud,
|
||||
INSN_mulhw,
|
||||
INSN_mulhwu, -- 170
|
||||
INSN_mulhd,
|
||||
INSN_mulhdu,
|
||||
INSN_mullw,
|
||||
INSN_mulld,
|
||||
INSN_nand,
|
||||
INSN_nor,
|
||||
INSN_or,
|
||||
INSN_orc,
|
||||
INSN_rldcl,
|
||||
INSN_rldcr, -- 180
|
||||
INSN_rlwnm,
|
||||
INSN_slw,
|
||||
INSN_sld,
|
||||
INSN_sraw,
|
||||
INSN_srad,
|
||||
INSN_srw,
|
||||
INSN_srd,
|
||||
INSN_stbcix,
|
||||
INSN_stbcx,
|
||||
INSN_stbx, -- 190
|
||||
INSN_stbux,
|
||||
INSN_stdbrx,
|
||||
INSN_stdcix,
|
||||
INSN_stdcx,
|
||||
INSN_stdx,
|
||||
INSN_stdux,
|
||||
INSN_sthbrx,
|
||||
INSN_sthcix,
|
||||
INSN_sthcx,
|
||||
INSN_sthx, -- 200
|
||||
INSN_sthux,
|
||||
INSN_stwbrx,
|
||||
INSN_stwcix,
|
||||
INSN_stwcx,
|
||||
INSN_stwx,
|
||||
INSN_stwux,
|
||||
INSN_subf,
|
||||
INSN_subfc,
|
||||
INSN_subfe,
|
||||
INSN_td, -- 210
|
||||
INSN_tlbie,
|
||||
INSN_tlbiel,
|
||||
INSN_tw,
|
||||
INSN_xor,
|
||||
|
||||
-- pad to 224 to simplify comparison logic
|
||||
INSN_215,
|
||||
INSN_216, INSN_217, INSN_218, INSN_219,
|
||||
INSN_220, INSN_221, INSN_222, INSN_223,
|
||||
|
||||
-- The following instructions have a third input addressed by RC
|
||||
INSN_maddld,
|
||||
INSN_maddhd,
|
||||
INSN_maddhdu,
|
||||
|
||||
-- pad to 256 to simplify comparison logic
|
||||
INSN_227,
|
||||
INSN_228, INSN_229, INSN_230, INSN_231,
|
||||
INSN_232, INSN_233, INSN_234, INSN_235,
|
||||
INSN_236, INSN_237, INSN_238, INSN_239,
|
||||
INSN_240, INSN_241, INSN_242, INSN_243,
|
||||
INSN_244, INSN_245, INSN_246, INSN_247,
|
||||
INSN_248, INSN_249, INSN_250, INSN_251,
|
||||
INSN_252, INSN_253, INSN_254, INSN_255,
|
||||
|
||||
-- The following instructions access floating-point registers
|
||||
-- These ones have an FRS operand, but RA/RB are GPRs
|
||||
INSN_stfd,
|
||||
INSN_stfdu,
|
||||
INSN_stfs,
|
||||
INSN_stfsu,
|
||||
INSN_stfdux, -- 260
|
||||
INSN_stfdx,
|
||||
INSN_stfiwx,
|
||||
INSN_stfsux,
|
||||
INSN_stfsx,
|
||||
-- These ones don't actually have an FRS operand (rather an FRT destination)
|
||||
-- but are here so that all FP instructions are >= INST_first_frs.
|
||||
INSN_lfd,
|
||||
INSN_lfdu,
|
||||
INSN_lfs,
|
||||
INSN_lfsu,
|
||||
INSN_lfdx,
|
||||
INSN_lfdux, -- 270
|
||||
INSN_lfiwax,
|
||||
INSN_lfiwzx,
|
||||
INSN_lfsx,
|
||||
INSN_lfsux,
|
||||
INSN_275, -- padding
|
||||
|
||||
-- The following instructions access FRA and/or FRB operands
|
||||
INSN_fabs,
|
||||
INSN_fadd,
|
||||
INSN_fadds,
|
||||
INSN_fcfid,
|
||||
INSN_fcfids, -- 280
|
||||
INSN_fcfidu,
|
||||
INSN_fcfidus,
|
||||
INSN_fcmpo,
|
||||
INSN_fcmpu,
|
||||
INSN_fcpsgn,
|
||||
INSN_fctid,
|
||||
INSN_fctidz,
|
||||
INSN_fctidu,
|
||||
INSN_fctiduz,
|
||||
INSN_fctiw, -- 290
|
||||
INSN_fctiwz,
|
||||
INSN_fctiwu,
|
||||
INSN_fctiwuz,
|
||||
INSN_fdiv,
|
||||
INSN_fdivs,
|
||||
INSN_fmr,
|
||||
INSN_fmrgew,
|
||||
INSN_fmrgow,
|
||||
INSN_fnabs,
|
||||
INSN_fneg, -- 300
|
||||
INSN_fre,
|
||||
INSN_fres,
|
||||
INSN_frim,
|
||||
INSN_frin,
|
||||
INSN_frip,
|
||||
INSN_friz,
|
||||
INSN_frsp,
|
||||
INSN_frsqrte,
|
||||
INSN_frsqrtes,
|
||||
INSN_fsqrt, -- 310
|
||||
INSN_fsqrts,
|
||||
INSN_fsub,
|
||||
INSN_fsubs,
|
||||
INSN_ftdiv,
|
||||
INSN_ftsqrt,
|
||||
INSN_mffs,
|
||||
INSN_mtfsf,
|
||||
|
||||
-- pad to 320
|
||||
INSN_318, INSN_319,
|
||||
|
||||
-- The following instructions access FRA, FRB (possibly) and FRC operands
|
||||
INSN_fmul, -- 320
|
||||
INSN_fmuls,
|
||||
INSN_fmadd,
|
||||
INSN_fmadds,
|
||||
INSN_fmsub,
|
||||
INSN_fmsubs,
|
||||
INSN_fnmadd,
|
||||
INSN_fnmadds,
|
||||
INSN_fnmsub,
|
||||
INSN_fnmsubs,
|
||||
INSN_fsel -- 330
|
||||
);
|
||||
|
||||
constant INSN_first_rb : insn_code := INSN_add;
|
||||
constant INSN_first_rc : insn_code := INSN_maddld;
|
||||
constant INSN_first_frs : insn_code := INSN_stfd;
|
||||
constant INSN_first_frab : insn_code := INSN_fabs;
|
||||
constant INSN_first_frabc : insn_code := INSN_fmul;
|
||||
|
||||
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, CIA, FRA);
|
||||
type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD,
|
||||
CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, FRB);
|
||||
type input_reg_c_t is (NONE, RS, RCR, FRC, FRS);
|
||||
type output_reg_a_t is (NONE, RT, RA, FRT);
|
||||
type rc_t is (NONE, ONE, RC);
|
||||
type rc_t is (NONE, ONE, RC, RCOE);
|
||||
type carry_in_t is (ZERO, CA, OV, ONE);
|
||||
|
||||
constant SH_OFFSET : integer := 0;
|
||||
|
||||
221
execute1.vhdl
221
execute1.vhdl
@ -15,7 +15,6 @@ entity execute1 is
|
||||
SIM : boolean := false;
|
||||
EX1_BYPASS : boolean := true;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
-- Non-zero to enable log data collection
|
||||
LOG_LENGTH : natural := 0
|
||||
);
|
||||
@ -65,7 +64,7 @@ entity execute1 is
|
||||
sim_dump : in std_ulogic;
|
||||
sim_dump_done : out std_ulogic;
|
||||
|
||||
log_out : out std_ulogic_vector(14 downto 0);
|
||||
log_out : out std_ulogic_vector(11 downto 0);
|
||||
log_rd_addr : out std_ulogic_vector(31 downto 0);
|
||||
log_rd_data : in std_ulogic_vector(63 downto 0);
|
||||
log_wr_addr : in std_ulogic_vector(31 downto 0)
|
||||
@ -85,6 +84,7 @@ architecture behaviour of execute1 is
|
||||
write_pmuspr : std_ulogic;
|
||||
ramspr_write_even : std_ulogic;
|
||||
ramspr_write_odd : std_ulogic;
|
||||
mult_32s : std_ulogic;
|
||||
end record;
|
||||
constant side_effect_init : side_effect_type := (others => '0');
|
||||
|
||||
@ -203,6 +203,8 @@ architecture behaviour of execute1 is
|
||||
-- multiply signals
|
||||
signal x_to_multiply: MultiplyInputType;
|
||||
signal multiply_to_x: MultiplyOutputType;
|
||||
signal x_to_mult_32s: MultiplyInputType;
|
||||
signal mult_32s_to_x: MultiplyOutputType;
|
||||
|
||||
-- divider signals
|
||||
signal x_to_divider: Execute1ToDividerType;
|
||||
@ -411,6 +413,14 @@ begin
|
||||
m_out => multiply_to_x
|
||||
);
|
||||
|
||||
mult_32s_0: entity work.multiply_32s
|
||||
port map (
|
||||
clk => clk,
|
||||
stall => stage2_stall,
|
||||
m_in => x_to_mult_32s,
|
||||
m_out => mult_32s_to_x
|
||||
);
|
||||
|
||||
divider_0: if not HAS_FPU generate
|
||||
div_0: entity work.divider
|
||||
port map (
|
||||
@ -437,17 +447,6 @@ begin
|
||||
p_out => pmu_to_x
|
||||
);
|
||||
|
||||
short_mult_0: if HAS_SHORT_MULT generate
|
||||
begin
|
||||
short_mult: entity work.short_multiply
|
||||
port map (
|
||||
clk => clk,
|
||||
a_in => a_in(15 downto 0),
|
||||
b_in => b_in(15 downto 0),
|
||||
m_out => mshort_p
|
||||
);
|
||||
end generate;
|
||||
|
||||
dbg_ctrl_out <= ctrl;
|
||||
log_rd_addr <= ex2.log_addr_spr;
|
||||
|
||||
@ -684,77 +683,81 @@ begin
|
||||
overflow_32 <= calc_ov(a_inv(31), b_in(31), carry_32, sum_with_carry(31));
|
||||
overflow_64 <= calc_ov(a_inv(63), b_in(63), carry_64, sum_with_carry(63));
|
||||
|
||||
-- signals to multiply and divide units
|
||||
sign1 := '0';
|
||||
sign2 := '0';
|
||||
if e_in.is_signed = '1' then
|
||||
if e_in.is_32bit = '1' then
|
||||
sign1 := a_in(31);
|
||||
sign2 := b_in(31);
|
||||
else
|
||||
sign1 := a_in(63);
|
||||
sign2 := b_in(63);
|
||||
end if;
|
||||
end if;
|
||||
-- take absolute values
|
||||
if sign1 = '0' then
|
||||
abs1 := signed(a_in);
|
||||
else
|
||||
abs1 := - signed(a_in);
|
||||
end if;
|
||||
if sign2 = '0' then
|
||||
abs2 := signed(b_in);
|
||||
else
|
||||
abs2 := - signed(b_in);
|
||||
end if;
|
||||
|
||||
-- Interface to multiply and divide units
|
||||
x_to_divider.is_signed <= e_in.is_signed;
|
||||
x_to_divider.is_32bit <= e_in.is_32bit;
|
||||
x_to_divider.is_extended <= '0';
|
||||
x_to_divider.is_modulus <= '0';
|
||||
if e_in.insn_type = OP_MOD then
|
||||
x_to_divider.is_modulus <= '1';
|
||||
end if;
|
||||
x_to_divider.flush <= flush_in;
|
||||
|
||||
-- signals to multiplier
|
||||
addend := (others => '0');
|
||||
if e_in.insn(26) = '0' then
|
||||
if e_in.reg_valid3 = '1' then
|
||||
-- integer multiply-add, major op 4 (if it is a multiply)
|
||||
addend(63 downto 0) := c_in;
|
||||
if e_in.is_signed = '1' then
|
||||
addend(127 downto 64) := (others => c_in(63));
|
||||
end if;
|
||||
end if;
|
||||
if (sign1 xor sign2) = '1' then
|
||||
addend := not addend;
|
||||
x_to_multiply.data1 <= std_ulogic_vector(a_in);
|
||||
x_to_multiply.data2 <= std_ulogic_vector(b_in);
|
||||
x_to_multiply.is_signed <= e_in.is_signed;
|
||||
x_to_multiply.subtract <= '0';
|
||||
x_to_multiply.addend <= addend;
|
||||
|
||||
-- Interface to divide unit
|
||||
if not HAS_FPU then
|
||||
sign1 := '0';
|
||||
sign2 := '0';
|
||||
if e_in.is_signed = '1' then
|
||||
if e_in.is_32bit = '1' then
|
||||
sign1 := a_in(31);
|
||||
sign2 := b_in(31);
|
||||
else
|
||||
sign1 := a_in(63);
|
||||
sign2 := b_in(63);
|
||||
end if;
|
||||
end if;
|
||||
-- take absolute values
|
||||
if sign1 = '0' then
|
||||
abs1 := signed(a_in);
|
||||
else
|
||||
abs1 := - signed(a_in);
|
||||
end if;
|
||||
if sign2 = '0' then
|
||||
abs2 := signed(b_in);
|
||||
else
|
||||
abs2 := - signed(b_in);
|
||||
end if;
|
||||
|
||||
x_to_divider.is_signed <= e_in.is_signed;
|
||||
x_to_divider.is_32bit <= e_in.is_32bit;
|
||||
x_to_divider.is_extended <= '0';
|
||||
x_to_divider.is_modulus <= '0';
|
||||
if e_in.insn_type = OP_MOD then
|
||||
x_to_divider.is_modulus <= '1';
|
||||
end if;
|
||||
x_to_divider.flush <= flush_in;
|
||||
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
|
||||
if e_in.is_32bit = '0' then
|
||||
-- 64-bit forms
|
||||
if e_in.insn_type = OP_DIVE then
|
||||
x_to_divider.is_extended <= '1';
|
||||
end if;
|
||||
x_to_divider.dividend <= std_ulogic_vector(abs1);
|
||||
x_to_divider.divisor <= std_ulogic_vector(abs2);
|
||||
else
|
||||
-- 32-bit forms
|
||||
x_to_divider.is_extended <= '0';
|
||||
if e_in.insn_type = OP_DIVE then -- extended forms
|
||||
x_to_divider.dividend <= std_ulogic_vector(abs1(31 downto 0)) & x"00000000";
|
||||
else
|
||||
x_to_divider.dividend <= x"00000000" & std_ulogic_vector(abs1(31 downto 0));
|
||||
end if;
|
||||
x_to_divider.divisor <= x"00000000" & std_ulogic_vector(abs2(31 downto 0));
|
||||
end if;
|
||||
end if;
|
||||
|
||||
x_to_multiply.is_32bit <= e_in.is_32bit;
|
||||
x_to_multiply.not_result <= sign1 xor sign2;
|
||||
x_to_multiply.addend <= addend;
|
||||
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
|
||||
if e_in.is_32bit = '0' then
|
||||
-- 64-bit forms
|
||||
x_to_multiply.data1 <= std_ulogic_vector(abs1);
|
||||
x_to_multiply.data2 <= std_ulogic_vector(abs2);
|
||||
if e_in.insn_type = OP_DIVE then
|
||||
x_to_divider.is_extended <= '1';
|
||||
end if;
|
||||
x_to_divider.dividend <= std_ulogic_vector(abs1);
|
||||
x_to_divider.divisor <= std_ulogic_vector(abs2);
|
||||
else
|
||||
-- 32-bit forms
|
||||
x_to_multiply.data1 <= x"00000000" & std_ulogic_vector(abs1(31 downto 0));
|
||||
x_to_multiply.data2 <= x"00000000" & std_ulogic_vector(abs2(31 downto 0));
|
||||
x_to_divider.is_extended <= '0';
|
||||
if e_in.insn_type = OP_DIVE then -- extended forms
|
||||
x_to_divider.dividend <= std_ulogic_vector(abs1(31 downto 0)) & x"00000000";
|
||||
else
|
||||
x_to_divider.dividend <= x"00000000" & std_ulogic_vector(abs1(31 downto 0));
|
||||
end if;
|
||||
x_to_divider.divisor <= x"00000000" & std_ulogic_vector(abs2(31 downto 0));
|
||||
end if;
|
||||
-- signals to 32-bit multiplier
|
||||
x_to_mult_32s.data1 <= 32x"0" & a_in(31 downto 0);
|
||||
x_to_mult_32s.data2 <= 32x"0" & b_in(31 downto 0);
|
||||
x_to_mult_32s.is_signed <= e_in.is_signed;
|
||||
-- The following are unused, but set here to avoid X states
|
||||
x_to_mult_32s.subtract <= '0';
|
||||
x_to_mult_32s.addend <= (others => '0');
|
||||
|
||||
shortmul_result <= std_ulogic_vector(resize(signed(mshort_p), 64));
|
||||
case ex1.mul_select is
|
||||
@ -1271,13 +1274,10 @@ begin
|
||||
v.se.icache_inval := '1';
|
||||
|
||||
when OP_MUL_L64 =>
|
||||
if HAS_SHORT_MULT and e_in.insn(26) = '1' and
|
||||
fits_in_n_bits(a_in, 16) and fits_in_n_bits(b_in, 16) then
|
||||
-- Operands fit into 16 bits, so use short multiplier
|
||||
if e_in.oe = '1' then
|
||||
-- Note 16x16 multiply can't overflow, even for mullwo
|
||||
set_ov(v.e, '0', '0');
|
||||
end if;
|
||||
if e_in.is_32bit = '1' then
|
||||
v.se.mult_32s := '1';
|
||||
v.res2_sel := "00";
|
||||
slow_op := '1';
|
||||
else
|
||||
-- Use standard multiplier
|
||||
v.start_mul := '1';
|
||||
@ -1285,11 +1285,16 @@ begin
|
||||
owait := '1';
|
||||
end if;
|
||||
|
||||
when OP_MUL_H64 | OP_MUL_H32 =>
|
||||
when OP_MUL_H64 =>
|
||||
v.start_mul := '1';
|
||||
slow_op := '1';
|
||||
owait := '1';
|
||||
|
||||
when OP_MUL_H32 =>
|
||||
v.se.mult_32s := '1';
|
||||
v.res2_sel := "01";
|
||||
slow_op := '1';
|
||||
|
||||
when OP_DIV | OP_DIVE | OP_MOD =>
|
||||
if not HAS_FPU then
|
||||
v.start_div := '1';
|
||||
@ -1370,6 +1375,7 @@ begin
|
||||
fv := Execute1ToFPUInit;
|
||||
|
||||
x_to_multiply.valid <= '0';
|
||||
x_to_mult_32s.valid <= '0';
|
||||
x_to_divider.valid <= '0';
|
||||
v.ext_interrupt := '0';
|
||||
v.taken_branch_event := '0';
|
||||
@ -1456,6 +1462,7 @@ begin
|
||||
v.res2_sel := actions.res2_sel;
|
||||
v.msr := actions.new_msr;
|
||||
x_to_multiply.valid <= actions.start_mul;
|
||||
x_to_mult_32s.valid <= actions.se.mult_32s;
|
||||
v.mul_in_progress := actions.start_mul;
|
||||
x_to_divider.valid <= actions.start_div;
|
||||
v.div_in_progress := actions.start_div;
|
||||
@ -1481,7 +1488,7 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if ex1.div_in_progress = '1' then
|
||||
if not HAS_FPU and ex1.div_in_progress = '1' then
|
||||
v.div_in_progress := not divider_to_x.valid;
|
||||
v.busy := not divider_to_x.valid;
|
||||
if divider_to_x.valid = '1' and ex1.oe = '1' then
|
||||
@ -1554,7 +1561,6 @@ begin
|
||||
|
||||
-- Outputs to loadstore1 (async)
|
||||
lv.op := e_in.insn_type;
|
||||
lv.nia := e_in.nia;
|
||||
lv.instr_tag := e_in.instr_tag;
|
||||
lv.addr1 := a_in;
|
||||
lv.addr2 := b_in;
|
||||
@ -1568,11 +1574,9 @@ begin
|
||||
lv.reserve := e_in.reserve;
|
||||
lv.rc := e_in.rc;
|
||||
lv.insn := e_in.insn;
|
||||
-- decode l*cix and st*cix instructions here
|
||||
if e_in.insn(31 downto 26) = "011111" and e_in.insn(10 downto 9) = "11" and
|
||||
e_in.insn(5 downto 1) = "10101" then
|
||||
lv.ci := '1';
|
||||
end if;
|
||||
-- invert_a field is overloaded for load/store instructions
|
||||
-- to mark l*cix and st*cix
|
||||
lv.ci := e_in.invert_a;
|
||||
lv.virt_mode := ex1.msr(MSR_DR);
|
||||
lv.priv_mode := not ex1.msr(MSR_PR);
|
||||
lv.mode_32bit := not ex1.msr(MSR_SF);
|
||||
@ -1591,6 +1595,9 @@ begin
|
||||
fv.fra := a_in;
|
||||
fv.frb := b_in;
|
||||
fv.frc := c_in;
|
||||
fv.valid_a := e_in.reg_valid1;
|
||||
fv.valid_b := e_in.reg_valid2;
|
||||
fv.valid_c := e_in.reg_valid3;
|
||||
fv.frt := e_in.write_reg;
|
||||
fv.rc := e_in.rc;
|
||||
fv.out_cr := e_in.output_cr;
|
||||
@ -1624,11 +1631,6 @@ begin
|
||||
-- Second execute stage control
|
||||
execute2_1: process(all)
|
||||
variable v : reg_stage2_type;
|
||||
variable overflow : std_ulogic;
|
||||
variable lv : Execute1ToLoadstore1Type;
|
||||
variable fv : Execute1ToFPUType;
|
||||
variable k : integer;
|
||||
variable go : std_ulogic;
|
||||
variable bypass_valid : std_ulogic;
|
||||
variable rcresult : std_ulogic_vector(63 downto 0);
|
||||
variable sprres : std_ulogic_vector(63 downto 0);
|
||||
@ -1647,6 +1649,14 @@ begin
|
||||
v.br_mispredict := ex1.br_mispredict;
|
||||
end if;
|
||||
|
||||
if ex1.se.mult_32s = '1' and ex1.oe = '1' then
|
||||
v.e.xerc.ov := mult_32s_to_x.overflow;
|
||||
v.e.xerc.ov32 := mult_32s_to_x.overflow;
|
||||
if mult_32s_to_x.overflow = '1' then
|
||||
v.e.xerc.so := '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
ctrl_tmp <= ctrl;
|
||||
-- FIXME: run at 512MHz not core freq
|
||||
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
|
||||
@ -1667,24 +1677,34 @@ begin
|
||||
v.e.write_xerc_enable := '0';
|
||||
v.e.redirect := '0';
|
||||
v.e.br_last := '0';
|
||||
v.se := side_effect_init;
|
||||
v.taken_branch_event := '0';
|
||||
v.br_mispredict := '0';
|
||||
end if;
|
||||
if flush_in = '1' then
|
||||
v.e.valid := '0';
|
||||
v.e.interrupt := '0';
|
||||
v.se := side_effect_init;
|
||||
v.ext_interrupt := '0';
|
||||
end if;
|
||||
|
||||
-- This is split like this because mfspr doesn't have an Rc bit,
|
||||
-- and we don't want the zero-detect logic to be after the
|
||||
-- SPR mux for timing reasons.
|
||||
if ex1.res2_sel(0) = '0' then
|
||||
if ex1.se.mult_32s = '1' then
|
||||
if ex1.res2_sel(0) = '0' then
|
||||
rcresult := mult_32s_to_x.result(63 downto 0);
|
||||
else
|
||||
rcresult := mult_32s_to_x.result(63 downto 32) &
|
||||
mult_32s_to_x.result(63 downto 32);
|
||||
end if;
|
||||
elsif ex1.res2_sel(0) = '0' then
|
||||
rcresult := ex1.e.write_data;
|
||||
sprres := spr_result;
|
||||
else
|
||||
rcresult := countbits_result;
|
||||
end if;
|
||||
if ex1.res2_sel(0) = '0' then
|
||||
sprres := spr_result;
|
||||
else
|
||||
sprres := pmu_to_x.spr_val;
|
||||
end if;
|
||||
if ex1.res2_sel(1) = '0' then
|
||||
@ -1708,7 +1728,7 @@ begin
|
||||
cr_res(31) := sign;
|
||||
cr_res(30) := not (sign or zero);
|
||||
cr_res(29) := zero;
|
||||
cr_res(28) := ex1.e.xerc.so;
|
||||
cr_res(28) := v.e.xerc.so;
|
||||
cr_mask(7) := '1';
|
||||
end if;
|
||||
|
||||
@ -1802,7 +1822,7 @@ begin
|
||||
end generate;
|
||||
|
||||
e1_log: if LOG_LENGTH > 0 generate
|
||||
signal log_data : std_ulogic_vector(14 downto 0);
|
||||
signal log_data : std_ulogic_vector(11 downto 0);
|
||||
begin
|
||||
ex1_log : process(clk)
|
||||
begin
|
||||
@ -1812,7 +1832,6 @@ begin
|
||||
exception_log &
|
||||
irq_valid_log &
|
||||
interrupt_in.intr &
|
||||
"000" &
|
||||
ex2.e.write_enable &
|
||||
ex2.e.valid &
|
||||
(ex2.e.redirect or ex2.e.interrupt) &
|
||||
|
||||
@ -16,7 +16,6 @@ entity toplevel is
|
||||
CLK_FREQUENCY : positive := 100000000;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
USE_LITEDRAM : boolean := false;
|
||||
NO_BRAM : boolean := false;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
@ -199,7 +198,6 @@ begin
|
||||
CLK_FREQ => CLK_FREQUENCY,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_BTC => HAS_BTC,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
HAS_DRAM => USE_LITEDRAM,
|
||||
DRAM_SIZE => 256 * 1024 * 1024,
|
||||
DRAM_INIT_SIZE => PAYLOAD_SIZE,
|
||||
|
||||
@ -13,7 +13,6 @@ entity toplevel is
|
||||
CLK_FREQUENCY : positive := 100000000;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := false;
|
||||
HAS_SHORT_MULT: boolean := false;
|
||||
ICACHE_NUM_LINES : natural := 64;
|
||||
LOG_LENGTH : natural := 512;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
@ -75,7 +74,6 @@ begin
|
||||
CLK_FREQ => CLK_FREQUENCY,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_BTC => HAS_BTC,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
ICACHE_NUM_LINES => ICACHE_NUM_LINES,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
|
||||
|
||||
@ -16,7 +16,6 @@ entity toplevel is
|
||||
CLK_FREQUENCY : positive := 100000000;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := true;
|
||||
HAS_SHORT_MULT: boolean := false;
|
||||
USE_LITEDRAM : boolean := false;
|
||||
NO_BRAM : boolean := false;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
@ -175,7 +174,6 @@ begin
|
||||
CLK_FREQ => CLK_FREQUENCY,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_BTC => HAS_BTC,
|
||||
HAS_SHORT_MULT=> HAS_SHORT_MULT,
|
||||
HAS_DRAM => USE_LITEDRAM,
|
||||
DRAM_SIZE => 512 * 1024 * 1024,
|
||||
DRAM_INIT_SIZE => PAYLOAD_SIZE,
|
||||
|
||||
@ -188,7 +188,6 @@ begin
|
||||
HAS_UART1 => HAS_UART1,
|
||||
HAS_SD_CARD => USE_LITESDCARD,
|
||||
ICACHE_NUM_LINES => ICACHE_NUM_LINES,
|
||||
HAS_SHORT_MULT => true,
|
||||
NGPIO => NGPIO
|
||||
)
|
||||
port map (
|
||||
|
||||
@ -16,7 +16,6 @@ entity toplevel is
|
||||
CLK_FREQUENCY : positive := 100000000;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
USE_LITEDRAM : boolean := false;
|
||||
NO_BRAM : boolean := false;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
@ -175,7 +174,6 @@ begin
|
||||
CLK_FREQ => CLK_FREQUENCY,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_BTC => HAS_BTC,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
HAS_DRAM => USE_LITEDRAM,
|
||||
DRAM_SIZE => 256 * 1024 * 1024,
|
||||
DRAM_INIT_SIZE => PAYLOAD_SIZE,
|
||||
|
||||
136
icache.vhdl
136
icache.vhdl
@ -23,6 +23,7 @@ use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.utils.all;
|
||||
use work.common.all;
|
||||
use work.decode_types.all;
|
||||
use work.wishbone_types.all;
|
||||
|
||||
-- 64 bit direct mapped icache. All instructions are 4B aligned.
|
||||
@ -30,6 +31,7 @@ use work.wishbone_types.all;
|
||||
entity icache is
|
||||
generic (
|
||||
SIM : boolean := false;
|
||||
HAS_FPU : boolean := true;
|
||||
-- Line size in bytes
|
||||
LINE_SIZE : positive := 64;
|
||||
-- BRAM organisation: We never access more than wishbone_data_bits at
|
||||
@ -69,7 +71,7 @@ entity icache is
|
||||
wb_snoop_in : in wishbone_master_out := wishbone_master_out_init;
|
||||
|
||||
events : out IcacheEventType;
|
||||
log_out : out std_ulogic_vector(53 downto 0)
|
||||
log_out : out std_ulogic_vector(57 downto 0)
|
||||
);
|
||||
end entity icache;
|
||||
|
||||
@ -122,8 +124,20 @@ architecture rtl of icache is
|
||||
subtype way_t is integer range 0 to NUM_WAYS-1;
|
||||
subtype row_in_line_t is unsigned(ROW_LINEBITS-1 downto 0);
|
||||
|
||||
-- We store a pre-decoded 10-bit insn_code along with the bottom 26 bits of
|
||||
-- each instruction, giving a total of 36 bits per instruction, which
|
||||
-- fits neatly into the block RAMs available on FPGAs.
|
||||
-- For illegal instructions, the top 4 bits are ones and the bottom 6 bits
|
||||
-- are the instruction's primary opcode, so we have the whole instruction
|
||||
-- word available (e.g. to put in HEIR). For other instructions, the
|
||||
-- primary opcode is not stored but could be determined from the insn_code.
|
||||
constant PREDECODE_BITS : natural := 10;
|
||||
constant INSN_IMAGE_BITS : natural := 26;
|
||||
constant ICWORDLEN : natural := PREDECODE_BITS + INSN_IMAGE_BITS;
|
||||
constant ROW_WIDTH : natural := INSN_PER_ROW * ICWORDLEN;
|
||||
|
||||
-- The cache data BRAM organized as described above for each way
|
||||
subtype cache_row_t is std_ulogic_vector(ROW_SIZE_BITS-1 downto 0);
|
||||
subtype cache_row_t is std_ulogic_vector(ROW_WIDTH-1 downto 0);
|
||||
|
||||
-- The cache tags LUTRAM has a row per set. Vivado is a pain and will
|
||||
-- not handle a clean (commented) definition of the cache tags as a 3d
|
||||
@ -184,6 +198,8 @@ architecture rtl of icache is
|
||||
wb : wishbone_master_out;
|
||||
store_way : way_t;
|
||||
store_index : index_t;
|
||||
recv_row : row_t;
|
||||
recv_valid : std_ulogic;
|
||||
store_row : row_t;
|
||||
store_tag : cache_tag_t;
|
||||
store_valid : std_ulogic;
|
||||
@ -214,7 +230,9 @@ architecture rtl of icache is
|
||||
|
||||
-- Cache RAM interface
|
||||
type cache_ram_out_t is array(way_t) of cache_row_t;
|
||||
signal cache_out : cache_ram_out_t;
|
||||
signal cache_out : cache_ram_out_t;
|
||||
signal cache_wr_data : std_ulogic_vector(ROW_WIDTH - 1 downto 0);
|
||||
signal wb_rd_data : std_ulogic_vector(ROW_SIZE_BITS - 1 downto 0);
|
||||
|
||||
-- PLRU output interface
|
||||
type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0);
|
||||
@ -226,6 +244,8 @@ architecture rtl of icache is
|
||||
signal snoop_index : index_t;
|
||||
signal snoop_hits : cache_way_valids_t;
|
||||
|
||||
signal log_insn : std_ulogic_vector(35 downto 0);
|
||||
|
||||
-- Return the cache line index (tag index) for an address
|
||||
function get_index(addr: std_ulogic_vector) return index_t is
|
||||
begin
|
||||
@ -293,7 +313,7 @@ architecture rtl of icache is
|
||||
variable word: integer range 0 to INSN_PER_ROW-1;
|
||||
begin
|
||||
word := to_integer(unsigned(addr(INSN_BITS+2-1 downto 2)));
|
||||
return data(31+word*32 downto word*32);
|
||||
return data(word * ICWORDLEN + ICWORDLEN - 1 downto word * ICWORDLEN);
|
||||
end;
|
||||
|
||||
-- Get the tag value from the address
|
||||
@ -327,6 +347,34 @@ architecture rtl of icache is
|
||||
|
||||
begin
|
||||
|
||||
-- byte-swap read data if big endian
|
||||
process(all)
|
||||
variable j: integer;
|
||||
begin
|
||||
if r.store_tag(TAG_BITS - 1) = '0' then
|
||||
wb_rd_data <= wishbone_in.dat;
|
||||
else
|
||||
for ii in 0 to (wishbone_in.dat'length / 8) - 1 loop
|
||||
j := ((ii / 4) * 4) + (3 - (ii mod 4));
|
||||
wb_rd_data(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8);
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
predecoder_0: entity work.predecoder
|
||||
generic map (
|
||||
HAS_FPU => HAS_FPU,
|
||||
WIDTH => INSN_PER_ROW,
|
||||
ICODE_LEN => PREDECODE_BITS,
|
||||
IMAGE_LEN => INSN_IMAGE_BITS
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
valid_in => wishbone_in.ack,
|
||||
insns_in => wb_rd_data,
|
||||
icodes_out => cache_wr_data
|
||||
);
|
||||
|
||||
assert LINE_SIZE mod ROW_SIZE = 0;
|
||||
assert ispow2(LINE_SIZE) report "LINE_SIZE not power of 2" severity FAILURE;
|
||||
assert ispow2(NUM_LINES) report "NUM_LINES not power of 2" severity FAILURE;
|
||||
@ -367,13 +415,13 @@ begin
|
||||
signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
|
||||
signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
|
||||
signal dout : cache_row_t;
|
||||
signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0);
|
||||
signal wr_dat : std_ulogic_vector(wishbone_in.dat'left downto 0);
|
||||
signal wr_sel : std_ulogic_vector(0 downto 0);
|
||||
begin
|
||||
way: entity work.cache_ram
|
||||
generic map (
|
||||
ROW_BITS => ROW_BITS,
|
||||
WIDTH => ROW_SIZE_BITS
|
||||
WIDTH => ROW_WIDTH,
|
||||
BYTEWID => ROW_WIDTH
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
@ -382,31 +430,19 @@ begin
|
||||
rd_data => dout,
|
||||
wr_sel => wr_sel,
|
||||
wr_addr => wr_addr,
|
||||
wr_data => wr_dat
|
||||
wr_data => cache_wr_data
|
||||
);
|
||||
process(all)
|
||||
variable j: integer;
|
||||
begin
|
||||
-- byte-swap read data if big endian
|
||||
if r.store_tag(TAG_BITS - 1) = '0' then
|
||||
wr_dat <= wishbone_in.dat;
|
||||
else
|
||||
for ii in 0 to (wishbone_in.dat'length / 8) - 1 loop
|
||||
j := ((ii / 4) * 4) + (3 - (ii mod 4));
|
||||
wr_dat(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8);
|
||||
end loop;
|
||||
end if;
|
||||
do_read <= not stall_in;
|
||||
do_write <= '0';
|
||||
if wishbone_in.ack = '1' and replace_way = i then
|
||||
if r.recv_valid = '1' and r.store_way = i then
|
||||
do_write <= '1';
|
||||
end if;
|
||||
cache_out(i) <= dout;
|
||||
rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
|
||||
wr_addr <= std_ulogic_vector(to_unsigned(r.store_row, ROW_BITS));
|
||||
for ii in 0 to ROW_SIZE-1 loop
|
||||
wr_sel(ii) <= do_write;
|
||||
end loop;
|
||||
wr_sel(0) <= do_write;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
@ -515,6 +551,8 @@ begin
|
||||
icache_comb : process(all)
|
||||
variable is_hit : std_ulogic;
|
||||
variable hit_way : way_t;
|
||||
variable insn : std_ulogic_vector(ICWORDLEN - 1 downto 0);
|
||||
variable icode : insn_code;
|
||||
begin
|
||||
-- Extract line, row and tag from request
|
||||
if not is_X(i_in.nia) then
|
||||
@ -575,11 +613,19 @@ begin
|
||||
-- I prefer not to do just yet as it would force fetch2 to know about
|
||||
-- some of the cache geometry information.
|
||||
--
|
||||
insn := (others => '0');
|
||||
icode := INSN_illegal;
|
||||
if r.hit_valid = '1' then
|
||||
i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way));
|
||||
else
|
||||
i_out.insn <= (others => '0');
|
||||
insn := read_insn_word(r.hit_nia, cache_out(r.hit_way));
|
||||
-- Currently we use only the top bit for indicating illegal
|
||||
-- instructions because we know that insn_codes fit into 9 bits.
|
||||
if insn(ICWORDLEN - 1) = '0' then
|
||||
icode := insn_code'val(to_integer(unsigned(insn(ICWORDLEN-1 downto INSN_IMAGE_BITS))));
|
||||
end if;
|
||||
end if;
|
||||
i_out.insn <= insn(31 downto 0);
|
||||
i_out.icode <= icode;
|
||||
log_insn <= cache_wr_data(35 downto 0);
|
||||
i_out.valid <= r.hit_valid;
|
||||
i_out.nia <= r.hit_nia;
|
||||
i_out.stop_mark <= r.hit_smark;
|
||||
@ -640,9 +686,11 @@ begin
|
||||
variable snoop_addr : real_addr_t;
|
||||
variable snoop_tag : cache_tag_t;
|
||||
variable snoop_cache_tags : cache_tags_set_t;
|
||||
variable replace_way : way_t;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
ev.icache_miss <= '0';
|
||||
r.recv_valid <= '0';
|
||||
-- On reset, clear all valid bits to force misses
|
||||
if rst = '1' then
|
||||
for i in index_t loop
|
||||
@ -714,13 +762,13 @@ begin
|
||||
" IR:" & std_ulogic'image(i_in.virt_mode) &
|
||||
" SM:" & std_ulogic'image(i_in.stop_mark) &
|
||||
" idx:" & integer'image(req_index) &
|
||||
" way:" & integer'image(replace_way) &
|
||||
" tag:" & to_hstring(req_tag) &
|
||||
" RA:" & to_hstring(real_addr);
|
||||
ev.icache_miss <= '1';
|
||||
|
||||
-- Keep track of our index and way for subsequent stores
|
||||
r.store_index <= req_index;
|
||||
r.recv_row <= get_row(req_raddr);
|
||||
r.store_row <= get_row(req_raddr);
|
||||
r.store_tag <= req_tag;
|
||||
r.store_valid <= '1';
|
||||
@ -740,6 +788,7 @@ begin
|
||||
when CLR_TAG | WAIT_ACK =>
|
||||
if r.state = CLR_TAG then
|
||||
-- Get victim way from plru
|
||||
replace_way := to_integer(unsigned(plru_victim(r.store_index)));
|
||||
r.store_way <= replace_way;
|
||||
|
||||
-- Force misses on that way while reloading that line
|
||||
@ -757,6 +806,19 @@ begin
|
||||
r.state <= WAIT_ACK;
|
||||
end if;
|
||||
|
||||
-- If we are writing in this cycle, mark row valid and see if we are done
|
||||
if r.recv_valid = '1' then
|
||||
r.rows_valid(r.store_row mod ROW_PER_LINE) <= not inval_in;
|
||||
if is_last_row(r.store_row, r.end_row_ix) then
|
||||
-- Cache line is now valid
|
||||
cache_valids(r.store_index)(r.store_way) <= r.store_valid and not inval_in;
|
||||
-- We are done
|
||||
r.state <= IDLE;
|
||||
end if;
|
||||
-- Increment store row counter
|
||||
r.store_row <= r.recv_row;
|
||||
end if;
|
||||
|
||||
-- If we are still sending requests, was one accepted ?
|
||||
if wishbone_in.stall = '0' and r.wb.stb = '1' then
|
||||
-- That was the last word ? We are done sending. Clear stb.
|
||||
@ -777,33 +839,27 @@ begin
|
||||
|
||||
-- Incoming acks processing
|
||||
if wishbone_in.ack = '1' then
|
||||
r.rows_valid(r.store_row mod ROW_PER_LINE) <= not inval_in;
|
||||
-- Check for completion
|
||||
if is_last_row(r.store_row, r.end_row_ix) then
|
||||
if is_last_row(r.recv_row, r.end_row_ix) then
|
||||
-- Complete wishbone cycle
|
||||
r.wb.cyc <= '0';
|
||||
|
||||
-- Cache line is now valid
|
||||
cache_valids(r.store_index)(replace_way) <= r.store_valid and not inval_in;
|
||||
|
||||
-- We are done
|
||||
r.state <= IDLE;
|
||||
end if;
|
||||
r.recv_valid <= '1';
|
||||
|
||||
-- Increment store row counter
|
||||
r.store_row <= next_row(r.store_row);
|
||||
-- Increment receive row counter
|
||||
r.recv_row <= next_row(r.recv_row);
|
||||
end if;
|
||||
|
||||
when STOP_RELOAD =>
|
||||
-- Wait for all outstanding requests to be satisfied, then
|
||||
-- go to IDLE state.
|
||||
if get_row_of_line(r.store_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then
|
||||
if get_row_of_line(r.recv_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then
|
||||
r.wb.cyc <= '0';
|
||||
r.state <= IDLE;
|
||||
end if;
|
||||
if wishbone_in.ack = '1' then
|
||||
-- Increment store row counter
|
||||
r.store_row <= next_row(r.store_row);
|
||||
r.recv_row <= next_row(r.recv_row);
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
@ -819,7 +875,7 @@ begin
|
||||
|
||||
icache_log: if LOG_LENGTH > 0 generate
|
||||
-- Output data to logger
|
||||
signal log_data : std_ulogic_vector(53 downto 0);
|
||||
signal log_data : std_ulogic_vector(57 downto 0);
|
||||
begin
|
||||
data_log: process(clk)
|
||||
variable lway: way_t;
|
||||
@ -832,7 +888,7 @@ begin
|
||||
wstate := '1';
|
||||
end if;
|
||||
log_data <= i_out.valid &
|
||||
i_out.insn &
|
||||
log_insn &
|
||||
wishbone_in.ack &
|
||||
r.wb.adr(2 downto 0) &
|
||||
r.wb.stb & r.wb.cyc &
|
||||
|
||||
@ -83,8 +83,6 @@ architecture behave of loadstore1 is
|
||||
update : std_ulogic;
|
||||
xerc : xer_common_t;
|
||||
reserve : std_ulogic;
|
||||
atomic : std_ulogic;
|
||||
atomic_last : std_ulogic;
|
||||
rc : std_ulogic;
|
||||
nc : std_ulogic; -- non-cacheable access
|
||||
virt_mode : std_ulogic;
|
||||
@ -108,7 +106,7 @@ architecture behave of loadstore1 is
|
||||
elt_length => x"0", byte_reverse => '0', brev_mask => "000",
|
||||
sign_extend => '0', update => '0',
|
||||
xerc => xerc_init, reserve => '0',
|
||||
atomic => '0', atomic_last => '0', rc => '0', nc => '0',
|
||||
rc => '0', nc => '0',
|
||||
virt_mode => '0', priv_mode => '0', load_sp => '0',
|
||||
sprsel => "00", ric => "00", is_slbia => '0', align_intr => '0',
|
||||
dword_index => '0', two_dwords => '0', incomplete => '0');
|
||||
@ -439,15 +437,9 @@ begin
|
||||
|
||||
addr := lsu_sum;
|
||||
if l_in.second = '1' then
|
||||
if l_in.update = '0' then
|
||||
-- for the second half of a 16-byte transfer,
|
||||
-- use the previous address plus 8.
|
||||
addr := std_ulogic_vector(unsigned(r1.addr0(63 downto 3)) + 1) & r1.addr0(2 downto 0);
|
||||
else
|
||||
-- for an update-form load, use the previous address
|
||||
-- as the value to write back to RA.
|
||||
addr := r1.addr0;
|
||||
end if;
|
||||
-- for an update-form load, use the previous address
|
||||
-- as the value to write back to RA.
|
||||
addr := r1.addr0;
|
||||
end if;
|
||||
if l_in.mode_32bit = '1' then
|
||||
addr(63 downto 32) := (others => '0');
|
||||
@ -474,14 +466,12 @@ begin
|
||||
misaligned := or (addr_mask and addr(2 downto 0));
|
||||
v.align_intr := l_in.reserve and misaligned;
|
||||
|
||||
v.atomic := not misaligned;
|
||||
v.atomic_last := not misaligned and (l_in.second or not l_in.repeat);
|
||||
|
||||
case l_in.op is
|
||||
when OP_STORE =>
|
||||
v.store := '1';
|
||||
when OP_LOAD =>
|
||||
if l_in.update = '0' or l_in.second = '0' then
|
||||
-- Note: only RA updates have l_in.second = 1
|
||||
if l_in.second = '0' then
|
||||
v.load := '1';
|
||||
if HAS_FPU and l_in.is_32bit = '1' then
|
||||
-- Allow an extra cycle for SP->DP precision conversion
|
||||
@ -507,7 +497,6 @@ begin
|
||||
when OP_FETCH_FAILED =>
|
||||
-- send it to the MMU to do the radix walk
|
||||
v.instr_fault := '1';
|
||||
v.addr := l_in.nia;
|
||||
v.mmu_op := '1';
|
||||
when others =>
|
||||
end case;
|
||||
@ -953,8 +942,6 @@ begin
|
||||
d_out.dcbz <= stage1_req.dcbz;
|
||||
d_out.nc <= stage1_req.nc;
|
||||
d_out.reserve <= stage1_req.reserve;
|
||||
d_out.atomic <= stage1_req.atomic;
|
||||
d_out.atomic_last <= stage1_req.atomic_last;
|
||||
d_out.addr <= stage1_req.addr;
|
||||
d_out.byte_sel <= stage1_req.byte_sel;
|
||||
d_out.virt_mode <= stage1_req.virt_mode;
|
||||
@ -965,8 +952,6 @@ begin
|
||||
d_out.dcbz <= r2.req.dcbz;
|
||||
d_out.nc <= r2.req.nc;
|
||||
d_out.reserve <= r2.req.reserve;
|
||||
d_out.atomic <= r2.req.atomic;
|
||||
d_out.atomic_last <= r2.req.atomic_last;
|
||||
d_out.addr <= r2.req.addr;
|
||||
d_out.byte_sel <= r2.req.byte_sel;
|
||||
d_out.virt_mode <= r2.req.virt_mode;
|
||||
|
||||
@ -9,6 +9,7 @@ filesets:
|
||||
- wishbone_types.vhdl
|
||||
- common.vhdl
|
||||
- fetch1.vhdl
|
||||
- predecode.vhdl
|
||||
- decode1.vhdl
|
||||
- helpers.vhdl
|
||||
- decode2.vhdl
|
||||
@ -65,6 +66,7 @@ filesets:
|
||||
xilinx_specific:
|
||||
files:
|
||||
- xilinx-mult.vhdl : {file_type : vhdlSource-2008}
|
||||
- xilinx-mult-32s.vhdl : {file_type : vhdlSource-2008}
|
||||
- fpga/fpga-random.vhdl : {file_type : vhdlSource-2008}
|
||||
- fpga/fpga-random.xdc : {file_type : xdc}
|
||||
|
||||
@ -144,7 +146,6 @@ targets:
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
tools:
|
||||
vivado: {part : xc7a100tcsg324-1}
|
||||
toplevel : toplevel
|
||||
@ -250,7 +251,6 @@ targets:
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
generate: [litedram_nexys_video, liteeth_nexys_video, litesdcard_nexys_video]
|
||||
tools:
|
||||
vivado: {part : xc7a200tsbg484-1}
|
||||
@ -271,7 +271,6 @@ targets:
|
||||
- has_uart1
|
||||
- has_fpu=false
|
||||
- has_btc=false
|
||||
- has_short_mult
|
||||
- use_litesdcard
|
||||
tools:
|
||||
vivado: {part : xc7a35ticsg324-1L}
|
||||
@ -294,7 +293,6 @@ targets:
|
||||
- has_uart1
|
||||
- has_fpu=false
|
||||
- has_btc=false
|
||||
- has_short_mult
|
||||
generate: [litedram_arty, liteeth_arty, litesdcard_arty]
|
||||
tools:
|
||||
vivado: {part : xc7a35ticsg324-1L}
|
||||
@ -315,7 +313,6 @@ targets:
|
||||
- has_uart1
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
- use_litesdcard
|
||||
tools:
|
||||
vivado: {part : xc7a100ticsg324-1L}
|
||||
@ -338,7 +335,6 @@ targets:
|
||||
- has_uart1
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
generate: [litedram_arty, liteeth_arty, litesdcard_arty]
|
||||
tools:
|
||||
vivado: {part : xc7a100ticsg324-1L}
|
||||
@ -360,7 +356,6 @@ targets:
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
generate: [litesdcard_wukong-v2]
|
||||
tools:
|
||||
vivado: {part : xc7a100tfgg676-1}
|
||||
@ -382,7 +377,6 @@ targets:
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
- has_short_mult
|
||||
generate: [litedram_wukong-v2, liteeth_wukong-v2, litesdcard_wukong-v2]
|
||||
tools:
|
||||
vivado: {part : xc7a100tfgg676-1}
|
||||
@ -498,12 +492,6 @@ parameters:
|
||||
paramtype : generic
|
||||
default : true
|
||||
|
||||
has_short_mult:
|
||||
datatype : bool
|
||||
description : Include a 16 bit x 16 bit single-cycle multiplier in the core
|
||||
paramtype : generic
|
||||
default : false
|
||||
|
||||
disable_flatten_core:
|
||||
datatype : bool
|
||||
description : Prevent Vivado from flattening the main core components
|
||||
|
||||
56
multiply-32s.vhdl
Normal file
56
multiply-32s.vhdl
Normal file
@ -0,0 +1,56 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
|
||||
-- Signed 33b x 33b multiplier giving 64-bit product, with no addend,
|
||||
-- with fixed 1-cycle latency.
|
||||
|
||||
entity multiply_32s is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
stall : in std_ulogic;
|
||||
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply_32s;
|
||||
|
||||
architecture behaviour of multiply_32s is
|
||||
type reg_type is record
|
||||
valid : std_ulogic;
|
||||
data : signed(65 downto 0);
|
||||
end record;
|
||||
constant reg_type_init : reg_type := (valid => '0', data => (others => '0'));
|
||||
|
||||
signal r, rin : reg_type := reg_type_init;
|
||||
begin
|
||||
multiply_0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) and stall = '0' then
|
||||
r <= rin;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
multiply_1: process(all)
|
||||
variable v : reg_type;
|
||||
variable d : std_ulogic_vector(63 downto 0);
|
||||
variable ov : std_ulogic;
|
||||
begin
|
||||
v.valid := m_in.valid;
|
||||
v.data := signed((m_in.is_signed and m_in.data1(31)) & m_in.data1(31 downto 0)) *
|
||||
signed((m_in.is_signed and m_in.data2(31)) & m_in.data2(31 downto 0));
|
||||
|
||||
d := std_ulogic_vector(r.data(63 downto 0));
|
||||
|
||||
ov := (or d(63 downto 31)) and not (and d(63 downto 31));
|
||||
|
||||
m_out.result <= 64x"0" & d;
|
||||
m_out.overflow <= ov;
|
||||
m_out.valid <= r.valid;
|
||||
|
||||
rin <= v;
|
||||
end process;
|
||||
end architecture behaviour;
|
||||
@ -7,7 +7,7 @@ use work.common.all;
|
||||
|
||||
entity multiply is
|
||||
generic (
|
||||
PIPELINE_DEPTH : natural := 4
|
||||
PIPELINE_DEPTH : natural := 3
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
@ -23,11 +23,8 @@ architecture behaviour of multiply is
|
||||
type multiply_pipeline_stage is record
|
||||
valid : std_ulogic;
|
||||
data : unsigned(127 downto 0);
|
||||
is_32bit : std_ulogic;
|
||||
not_res : std_ulogic;
|
||||
end record;
|
||||
constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0',
|
||||
is_32bit => '0', not_res => '0',
|
||||
data => (others => '0'));
|
||||
|
||||
type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage;
|
||||
@ -52,31 +49,29 @@ begin
|
||||
|
||||
multiply_1: process(all)
|
||||
variable v : reg_type;
|
||||
variable a, b : std_ulogic_vector(64 downto 0);
|
||||
variable prod : std_ulogic_vector(129 downto 0);
|
||||
variable d : std_ulogic_vector(127 downto 0);
|
||||
variable d2 : std_ulogic_vector(63 downto 0);
|
||||
variable ov : std_ulogic;
|
||||
begin
|
||||
v := r;
|
||||
a := (m.is_signed and m.data1(63)) & m.data1;
|
||||
b := (m.is_signed and m.data2(63)) & m.data2;
|
||||
prod := std_ulogic_vector(signed(a) * signed(b));
|
||||
v.multiply_pipeline(0).valid := m.valid;
|
||||
v.multiply_pipeline(0).data := (unsigned(m.data1) * unsigned(m.data2)) + unsigned(m.addend);
|
||||
v.multiply_pipeline(0).is_32bit := m.is_32bit;
|
||||
v.multiply_pipeline(0).not_res := m.not_result;
|
||||
if m.subtract = '1' then
|
||||
v.multiply_pipeline(0).data := unsigned(m.addend) - unsigned(prod(127 downto 0));
|
||||
else
|
||||
v.multiply_pipeline(0).data := unsigned(m.addend) + unsigned(prod(127 downto 0));
|
||||
end if;
|
||||
|
||||
loop_0: for i in 1 to PIPELINE_DEPTH-1 loop
|
||||
v.multiply_pipeline(i) := r.multiply_pipeline(i-1);
|
||||
end loop;
|
||||
|
||||
d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data);
|
||||
if v.multiply_pipeline(PIPELINE_DEPTH-1).not_res = '1' then
|
||||
d := not d;
|
||||
end if;
|
||||
|
||||
ov := '0';
|
||||
if v.multiply_pipeline(PIPELINE_DEPTH-1).is_32bit = '1' then
|
||||
ov := (or d(63 downto 31)) and not (and d(63 downto 31));
|
||||
else
|
||||
ov := (or d(127 downto 63)) and not (and d(127 downto 63));
|
||||
end if;
|
||||
ov := (or d(127 downto 63)) and not (and d(127 downto 63));
|
||||
ovf_in <= ov;
|
||||
|
||||
m_out.result <= d;
|
||||
|
||||
@ -26,15 +26,6 @@ architecture behave of multiply_tb is
|
||||
signal m1 : MultiplyInputType := MultiplyInputInit;
|
||||
signal m2 : MultiplyOutputType;
|
||||
|
||||
function absval(x: std_ulogic_vector) return std_ulogic_vector is
|
||||
begin
|
||||
if x(x'left) = '1' then
|
||||
return std_ulogic_vector(- signed(x));
|
||||
else
|
||||
return x;
|
||||
end if;
|
||||
end;
|
||||
|
||||
begin
|
||||
multiply_0: entity work.multiply
|
||||
generic map (PIPELINE_DEPTH => pipeline_depth)
|
||||
@ -51,7 +42,6 @@ begin
|
||||
stim_process: process
|
||||
variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
|
||||
variable si: std_ulogic_vector(15 downto 0);
|
||||
variable sign: std_ulogic;
|
||||
variable rnd : RandomPType;
|
||||
begin
|
||||
rnd.InitSeed(stim_process'path_name);
|
||||
@ -102,11 +92,11 @@ begin
|
||||
|
||||
behave_rt := ppc_mulld(ra, rb);
|
||||
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= absval(rb);
|
||||
sign := ra(63) xor rb(63);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.data1 <= ra;
|
||||
m1.data2 <= rb;
|
||||
m1.is_signed <= '1';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@ -128,7 +118,8 @@ begin
|
||||
|
||||
m1.data1 <= ra;
|
||||
m1.data2 <= rb;
|
||||
m1.not_result <= '0';
|
||||
m1.is_signed <= '0';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
@ -149,11 +140,11 @@ begin
|
||||
|
||||
behave_rt := ppc_mulhd(ra, rb);
|
||||
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= absval(rb);
|
||||
sign := ra(63) xor rb(63);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.data1 <= ra;
|
||||
m1.data2 <= rb;
|
||||
m1.is_signed <= '1';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@ -173,13 +164,13 @@ begin
|
||||
|
||||
behave_rt := ppc_mullw(ra, rb);
|
||||
|
||||
m1.data1 <= (others => '0');
|
||||
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
|
||||
sign := ra(31) xor rb(31);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
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.is_signed <= '1';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@ -199,13 +190,13 @@ begin
|
||||
|
||||
behave_rt := ppc_mulhw(ra, rb);
|
||||
|
||||
m1.data1 <= (others => '0');
|
||||
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
|
||||
sign := ra(31) xor rb(31);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
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.is_signed <= '1';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@ -229,7 +220,8 @@ begin
|
||||
m1.data1(31 downto 0) <= ra(31 downto 0);
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= rb(31 downto 0);
|
||||
m1.not_result <= '0';
|
||||
m1.is_signed <= '0';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
@ -250,12 +242,12 @@ begin
|
||||
|
||||
behave_rt := ppc_mulli(ra, si);
|
||||
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(15 downto 0) <= absval(si);
|
||||
sign := ra(63) xor si(15);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.data1 <= ra;
|
||||
m1.data2 <= (others => si(15));
|
||||
m1.data2(15 downto 0) <= si;
|
||||
m1.is_signed <= '1';
|
||||
m1.subtract <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
|
||||
592
predecode.vhdl
Normal file
592
predecode.vhdl
Normal file
@ -0,0 +1,592 @@
|
||||
-- Instruction pre-decoder for microwatt
|
||||
-- One cycle latency. Does 'WIDTH' instructions in parallel.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
use work.decode_types.all;
|
||||
use work.insn_helpers.all;
|
||||
|
||||
entity predecoder is
|
||||
generic (
|
||||
HAS_FPU : boolean := true;
|
||||
WIDTH : natural := 2;
|
||||
ICODE_LEN : natural := 10;
|
||||
IMAGE_LEN : natural := 26
|
||||
);
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
valid_in : in std_ulogic;
|
||||
insns_in : in std_ulogic_vector(WIDTH * 32 - 1 downto 0);
|
||||
icodes_out : out std_ulogic_vector(WIDTH * (ICODE_LEN + IMAGE_LEN) - 1 downto 0)
|
||||
);
|
||||
end entity predecoder;
|
||||
|
||||
architecture behaviour of predecoder is
|
||||
|
||||
type predecoder_rom_t is array(0 to 2047) of insn_code;
|
||||
|
||||
constant major_predecode_rom : predecoder_rom_t := (
|
||||
2#001100_00000# to 2#001100_11111# => INSN_addic,
|
||||
2#001101_00000# to 2#001101_11111# => INSN_addic_dot,
|
||||
2#001110_00000# to 2#001110_11111# => INSN_addi,
|
||||
2#001111_00000# to 2#001111_11111# => INSN_addis,
|
||||
2#010011_00100# to 2#010011_00101# => INSN_addpcis,
|
||||
2#011100_00000# to 2#011100_11111# => INSN_andi_dot,
|
||||
2#011101_00000# to 2#011101_11111# => INSN_andis_dot,
|
||||
2#000000_00000# => INSN_attn,
|
||||
2#010010_00000# to 2#010010_11111# => INSN_b,
|
||||
2#010000_00000# to 2#010000_11111# => INSN_bc,
|
||||
2#001011_00000# to 2#001011_11111# => INSN_cmpi,
|
||||
2#001010_00000# to 2#001010_11111# => INSN_cmpli,
|
||||
2#100010_00000# to 2#100010_11111# => INSN_lbz,
|
||||
2#100011_00000# to 2#100011_11111# => INSN_lbzu,
|
||||
2#110010_00000# to 2#110010_11111# => INSN_lfd,
|
||||
2#110011_00000# to 2#110011_11111# => INSN_lfdu,
|
||||
2#110000_00000# to 2#110000_11111# => INSN_lfs,
|
||||
2#110001_00000# to 2#110001_11111# => INSN_lfsu,
|
||||
2#101010_00000# to 2#101010_11111# => INSN_lha,
|
||||
2#101011_00000# to 2#101011_11111# => INSN_lhau,
|
||||
2#101000_00000# to 2#101000_11111# => INSN_lhz,
|
||||
2#101001_00000# to 2#101001_11111# => INSN_lhzu,
|
||||
2#100000_00000# to 2#100000_11111# => INSN_lwz,
|
||||
2#100001_00000# to 2#100001_11111# => INSN_lwzu,
|
||||
2#000111_00000# to 2#000111_11111# => INSN_mulli,
|
||||
2#011000_00000# to 2#011000_11111# => INSN_ori,
|
||||
2#011001_00000# to 2#011001_11111# => INSN_oris,
|
||||
2#010100_00000# to 2#010100_11111# => INSN_rlwimi,
|
||||
2#010101_00000# to 2#010101_11111# => INSN_rlwinm,
|
||||
2#010111_00000# to 2#010111_11111# => INSN_rlwnm,
|
||||
2#010001_00000# to 2#010001_11111# => INSN_sc,
|
||||
2#100110_00000# to 2#100110_11111# => INSN_stb,
|
||||
2#100111_00000# to 2#100111_11111# => INSN_stbu,
|
||||
2#110110_00000# to 2#110110_11111# => INSN_stfd,
|
||||
2#110111_00000# to 2#110111_11111# => INSN_stfdu,
|
||||
2#110100_00000# to 2#110100_11111# => INSN_stfs,
|
||||
2#110101_00000# to 2#110101_11111# => INSN_stfsu,
|
||||
2#101100_00000# to 2#101100_11111# => INSN_sth,
|
||||
2#101101_00000# to 2#101101_11111# => INSN_sthu,
|
||||
2#100100_00000# to 2#100100_11111# => INSN_stw,
|
||||
2#100101_00000# to 2#100101_11111# => INSN_stwu,
|
||||
2#001000_00000# to 2#001000_11111# => INSN_subfic,
|
||||
2#000010_00000# to 2#000010_11111# => INSN_tdi,
|
||||
2#000011_00000# to 2#000011_11111# => INSN_twi,
|
||||
2#011010_00000# to 2#011010_11111# => INSN_xori,
|
||||
2#011011_00000# to 2#011011_11111# => INSN_xoris,
|
||||
-- major opcode 4
|
||||
2#000100_10000# => INSN_maddhd,
|
||||
2#000100_10001# => INSN_maddhdu,
|
||||
2#000100_10011# => INSN_maddld,
|
||||
-- major opcode 30
|
||||
2#011110_01000# to 2#011110_01001# => INSN_rldic,
|
||||
2#011110_01010# to 2#011110_01011# => INSN_rldic,
|
||||
2#011110_00000# to 2#011110_00001# => INSN_rldicl,
|
||||
2#011110_00010# to 2#011110_00011# => INSN_rldicl,
|
||||
2#011110_00100# to 2#011110_00101# => INSN_rldicr,
|
||||
2#011110_00110# to 2#011110_00111# => INSN_rldicr,
|
||||
2#011110_01100# to 2#011110_01101# => INSN_rldimi,
|
||||
2#011110_01110# to 2#011110_01111# => INSN_rldimi,
|
||||
2#011110_10000# to 2#011110_10001# => INSN_rldcl,
|
||||
2#011110_10010# to 2#011110_10011# => INSN_rldcr,
|
||||
-- major opcode 58
|
||||
2#111010_00000# => INSN_ld,
|
||||
2#111010_00001# => INSN_ldu,
|
||||
2#111010_00010# => INSN_lwa,
|
||||
2#111010_00100# => INSN_ld,
|
||||
2#111010_00101# => INSN_ldu,
|
||||
2#111010_00110# => INSN_lwa,
|
||||
2#111010_01000# => INSN_ld,
|
||||
2#111010_01001# => INSN_ldu,
|
||||
2#111010_01010# => INSN_lwa,
|
||||
2#111010_01100# => INSN_ld,
|
||||
2#111010_01101# => INSN_ldu,
|
||||
2#111010_01110# => INSN_lwa,
|
||||
2#111010_10000# => INSN_ld,
|
||||
2#111010_10001# => INSN_ldu,
|
||||
2#111010_10010# => INSN_lwa,
|
||||
2#111010_10100# => INSN_ld,
|
||||
2#111010_10101# => INSN_ldu,
|
||||
2#111010_10110# => INSN_lwa,
|
||||
2#111010_11000# => INSN_ld,
|
||||
2#111010_11001# => INSN_ldu,
|
||||
2#111010_11010# => INSN_lwa,
|
||||
2#111010_11100# => INSN_ld,
|
||||
2#111010_11101# => INSN_ldu,
|
||||
2#111010_11110# => INSN_lwa,
|
||||
-- major opcode 59
|
||||
2#111011_00100# to 2#111011_00101# => INSN_fdivs,
|
||||
2#111011_01000# to 2#111011_01001# => INSN_fsubs,
|
||||
2#111011_01010# to 2#111011_01011# => INSN_fadds,
|
||||
2#111011_01100# to 2#111011_01101# => INSN_fsqrts,
|
||||
2#111011_10000# to 2#111011_10001# => INSN_fres,
|
||||
2#111011_10010# to 2#111011_10011# => INSN_fmuls,
|
||||
2#111011_10100# to 2#111011_10101# => INSN_frsqrtes,
|
||||
2#111011_11000# to 2#111011_11001# => INSN_fmsubs,
|
||||
2#111011_11010# to 2#111011_11011# => INSN_fmadds,
|
||||
2#111011_11100# to 2#111011_11101# => INSN_fnmsubs,
|
||||
2#111011_11110# to 2#111011_11111# => INSN_fnmadds,
|
||||
-- major opcode 62
|
||||
2#111110_00000# => INSN_std,
|
||||
2#111110_00001# => INSN_stdu,
|
||||
2#111110_00100# => INSN_std,
|
||||
2#111110_00101# => INSN_stdu,
|
||||
2#111110_01000# => INSN_std,
|
||||
2#111110_01001# => INSN_stdu,
|
||||
2#111110_01100# => INSN_std,
|
||||
2#111110_01101# => INSN_stdu,
|
||||
2#111110_10000# => INSN_std,
|
||||
2#111110_10001# => INSN_stdu,
|
||||
2#111110_10100# => INSN_std,
|
||||
2#111110_10101# => INSN_stdu,
|
||||
2#111110_11000# => INSN_std,
|
||||
2#111110_11001# => INSN_stdu,
|
||||
2#111110_11100# => INSN_std,
|
||||
2#111110_11101# => INSN_stdu,
|
||||
-- major opcode 63
|
||||
2#111111_00100# to 2#111111_00101# => INSN_fdiv,
|
||||
2#111111_01000# to 2#111111_01001# => INSN_fsub,
|
||||
2#111111_01010# to 2#111111_01011# => INSN_fadd,
|
||||
2#111111_01100# to 2#111111_01101# => INSN_fsqrt,
|
||||
2#111111_01110# to 2#111111_01111# => INSN_fsel,
|
||||
2#111111_10000# to 2#111111_10001# => INSN_fre,
|
||||
2#111111_10010# to 2#111111_10011# => INSN_fmul,
|
||||
2#111111_10100# to 2#111111_10101# => INSN_frsqrte,
|
||||
2#111111_11000# to 2#111111_11001# => INSN_fmsub,
|
||||
2#111111_11010# to 2#111111_11011# => INSN_fmadd,
|
||||
2#111111_11100# to 2#111111_11101# => INSN_fnmsub,
|
||||
2#111111_11110# to 2#111111_11111# => INSN_fnmadd,
|
||||
others => INSN_illegal
|
||||
);
|
||||
|
||||
constant row_predecode_rom : predecoder_rom_t := (
|
||||
-- Major opcode 31
|
||||
-- Address bits are 0, insn(10:1)
|
||||
2#0_01000_01010# => INSN_add,
|
||||
2#0_11000_01010# => INSN_add, -- addo
|
||||
2#0_00000_01010# => INSN_addc,
|
||||
2#0_10000_01010# => INSN_addc, -- addco
|
||||
2#0_00100_01010# => INSN_adde,
|
||||
2#0_10100_01010# => INSN_adde, -- addeo
|
||||
2#0_00101_01010# => INSN_addex,
|
||||
2#0_00010_01010# => INSN_addg6s,
|
||||
2#0_00111_01010# => INSN_addme,
|
||||
2#0_10111_01010# => INSN_addme, -- addmeo
|
||||
2#0_00110_01010# => INSN_addze,
|
||||
2#0_10110_01010# => INSN_addze, -- addzeo
|
||||
2#0_00000_11100# => INSN_and,
|
||||
2#0_00001_11100# => INSN_andc,
|
||||
2#0_00111_11100# => INSN_bperm,
|
||||
2#0_01001_11010# => INSN_cbcdtd,
|
||||
2#0_01000_11010# => INSN_cdtbcd,
|
||||
2#0_00000_00000# => INSN_cmp,
|
||||
2#0_01111_11100# => INSN_cmpb,
|
||||
2#0_00111_00000# => INSN_cmpeqb,
|
||||
2#0_00001_00000# => INSN_cmpl,
|
||||
2#0_00110_00000# => INSN_cmprb,
|
||||
2#0_00001_11010# => INSN_cntlzd,
|
||||
2#0_00000_11010# => INSN_cntlzw,
|
||||
2#0_10001_11010# => INSN_cnttzd,
|
||||
2#0_10000_11010# => INSN_cnttzw,
|
||||
2#0_10111_10011# => INSN_darn,
|
||||
2#0_00010_10110# => INSN_dcbf,
|
||||
2#0_00001_10110# => INSN_dcbst,
|
||||
2#0_01000_10110# => INSN_dcbt,
|
||||
2#0_00111_10110# => INSN_dcbtst,
|
||||
2#0_11111_10110# => INSN_dcbz,
|
||||
2#0_01100_01001# => INSN_divdeu,
|
||||
2#0_11100_01001# => INSN_divdeu, -- divdeuo
|
||||
2#0_01100_01011# => INSN_divweu,
|
||||
2#0_11100_01011# => INSN_divweu, -- divweuo
|
||||
2#0_01101_01001# => INSN_divde,
|
||||
2#0_11101_01001# => INSN_divde, -- divdeo
|
||||
2#0_01101_01011# => INSN_divwe,
|
||||
2#0_11101_01011# => INSN_divwe, -- divweo
|
||||
2#0_01110_01001# => INSN_divdu,
|
||||
2#0_11110_01001# => INSN_divdu, -- divduo
|
||||
2#0_01110_01011# => INSN_divwu,
|
||||
2#0_11110_01011# => INSN_divwu, -- divwuo
|
||||
2#0_01111_01001# => INSN_divd,
|
||||
2#0_11111_01001# => INSN_divd, -- divdo
|
||||
2#0_01111_01011# => INSN_divw,
|
||||
2#0_11111_01011# => INSN_divw, -- divwo
|
||||
2#0_11001_10110# => INSN_nop, -- dss
|
||||
2#0_01010_10110# => INSN_nop, -- dst
|
||||
2#0_01011_10110# => INSN_nop, -- dstst
|
||||
2#0_11010_10110# => INSN_eieio,
|
||||
2#0_01000_11100# => INSN_eqv,
|
||||
2#0_11101_11010# => INSN_extsb,
|
||||
2#0_11100_11010# => INSN_extsh,
|
||||
2#0_11110_11010# => INSN_extsw,
|
||||
2#0_11011_11010# => INSN_extswsli,
|
||||
2#0_11011_11011# => INSN_extswsli,
|
||||
2#0_11110_10110# => INSN_icbi,
|
||||
2#0_00000_10110# => INSN_icbt,
|
||||
2#0_00000_01111# => INSN_isel,
|
||||
2#0_00001_01111# => INSN_isel,
|
||||
2#0_00010_01111# => INSN_isel,
|
||||
2#0_00011_01111# => INSN_isel,
|
||||
2#0_00100_01111# => INSN_isel,
|
||||
2#0_00101_01111# => INSN_isel,
|
||||
2#0_00110_01111# => INSN_isel,
|
||||
2#0_00111_01111# => INSN_isel,
|
||||
2#0_01000_01111# => INSN_isel,
|
||||
2#0_01001_01111# => INSN_isel,
|
||||
2#0_01010_01111# => INSN_isel,
|
||||
2#0_01011_01111# => INSN_isel,
|
||||
2#0_01100_01111# => INSN_isel,
|
||||
2#0_01101_01111# => INSN_isel,
|
||||
2#0_01110_01111# => INSN_isel,
|
||||
2#0_01111_01111# => INSN_isel,
|
||||
2#0_10000_01111# => INSN_isel,
|
||||
2#0_10001_01111# => INSN_isel,
|
||||
2#0_10010_01111# => INSN_isel,
|
||||
2#0_10011_01111# => INSN_isel,
|
||||
2#0_10100_01111# => INSN_isel,
|
||||
2#0_10101_01111# => INSN_isel,
|
||||
2#0_10110_01111# => INSN_isel,
|
||||
2#0_10111_01111# => INSN_isel,
|
||||
2#0_11000_01111# => INSN_isel,
|
||||
2#0_11001_01111# => INSN_isel,
|
||||
2#0_11010_01111# => INSN_isel,
|
||||
2#0_11011_01111# => INSN_isel,
|
||||
2#0_11100_01111# => INSN_isel,
|
||||
2#0_11101_01111# => INSN_isel,
|
||||
2#0_11110_01111# => INSN_isel,
|
||||
2#0_11111_01111# => INSN_isel,
|
||||
2#0_00001_10100# => INSN_lbarx,
|
||||
2#0_11010_10101# => INSN_lbzcix,
|
||||
2#0_00011_10111# => INSN_lbzux,
|
||||
2#0_00010_10111# => INSN_lbzx,
|
||||
2#0_00010_10100# => INSN_ldarx,
|
||||
2#0_10000_10100# => INSN_ldbrx,
|
||||
2#0_11011_10101# => INSN_ldcix,
|
||||
2#0_00001_10101# => INSN_ldux,
|
||||
2#0_00000_10101# => INSN_ldx,
|
||||
2#0_10010_10111# => INSN_lfdx,
|
||||
2#0_10011_10111# => INSN_lfdux,
|
||||
2#0_11010_10111# => INSN_lfiwax,
|
||||
2#0_11011_10111# => INSN_lfiwzx,
|
||||
2#0_10000_10111# => INSN_lfsx,
|
||||
2#0_10001_10111# => INSN_lfsux,
|
||||
2#0_00011_10100# => INSN_lharx,
|
||||
2#0_01011_10111# => INSN_lhaux,
|
||||
2#0_01010_10111# => INSN_lhax,
|
||||
2#0_11000_10110# => INSN_lhbrx,
|
||||
2#0_11001_10101# => INSN_lhzcix,
|
||||
2#0_01001_10111# => INSN_lhzux,
|
||||
2#0_01000_10111# => INSN_lhzx,
|
||||
2#0_00000_10100# => INSN_lwarx,
|
||||
2#0_01011_10101# => INSN_lwaux,
|
||||
2#0_01010_10101# => INSN_lwax,
|
||||
2#0_10000_10110# => INSN_lwbrx,
|
||||
2#0_11000_10101# => INSN_lwzcix,
|
||||
2#0_00001_10111# => INSN_lwzux,
|
||||
2#0_00000_10111# => INSN_lwzx,
|
||||
2#0_10010_00000# => INSN_mcrxrx,
|
||||
2#0_00000_10011# => INSN_mfcr,
|
||||
2#0_00010_10011# => INSN_mfmsr,
|
||||
2#0_01010_10011# => INSN_mfspr,
|
||||
2#0_01000_01001# => INSN_modud,
|
||||
2#0_01000_01011# => INSN_moduw,
|
||||
2#0_11000_01001# => INSN_modsd,
|
||||
2#0_11000_01011# => INSN_modsw,
|
||||
2#0_00100_10000# => INSN_mtcrf,
|
||||
2#0_00100_10010# => INSN_mtmsr,
|
||||
2#0_00101_10010# => INSN_mtmsrd,
|
||||
2#0_01110_10011# => INSN_mtspr,
|
||||
2#0_00010_01001# => INSN_mulhd,
|
||||
2#0_00000_01001# => INSN_mulhdu,
|
||||
2#0_00010_01011# => INSN_mulhw,
|
||||
2#0_00000_01011# => INSN_mulhwu,
|
||||
-- next 4 have reserved bit set
|
||||
2#0_10010_01001# => INSN_mulhd,
|
||||
2#0_10000_01001# => INSN_mulhdu,
|
||||
2#0_10010_01011# => INSN_mulhw,
|
||||
2#0_10000_01011# => INSN_mulhwu,
|
||||
2#0_00111_01001# => INSN_mulld,
|
||||
2#0_10111_01001# => INSN_mulld, -- mulldo
|
||||
2#0_00111_01011# => INSN_mullw,
|
||||
2#0_10111_01011# => INSN_mullw, -- mullwo
|
||||
2#0_01110_11100# => INSN_nand,
|
||||
2#0_00011_01000# => INSN_neg,
|
||||
2#0_10011_01000# => INSN_neg, -- nego
|
||||
-- next 8 are reserved no-op instructions
|
||||
2#0_10000_10010# => INSN_nop,
|
||||
2#0_10001_10010# => INSN_nop,
|
||||
2#0_10010_10010# => INSN_nop,
|
||||
2#0_10011_10010# => INSN_nop,
|
||||
2#0_10100_10010# => INSN_nop,
|
||||
2#0_10101_10010# => INSN_nop,
|
||||
2#0_10110_10010# => INSN_nop,
|
||||
2#0_10111_10010# => INSN_nop,
|
||||
2#0_00011_11100# => INSN_nor,
|
||||
2#0_01101_11100# => INSN_or,
|
||||
2#0_01100_11100# => INSN_orc,
|
||||
2#0_00011_11010# => INSN_popcntb,
|
||||
2#0_01111_11010# => INSN_popcntd,
|
||||
2#0_01011_11010# => INSN_popcntw,
|
||||
2#0_00101_11010# => INSN_prtyd,
|
||||
2#0_00100_11010# => INSN_prtyw,
|
||||
2#0_00100_00000# => INSN_setb,
|
||||
2#0_01111_10010# => INSN_slbia,
|
||||
2#0_00000_11011# => INSN_sld,
|
||||
2#0_00000_11000# => INSN_slw,
|
||||
2#0_11000_11010# => INSN_srad,
|
||||
2#0_11001_11010# => INSN_sradi,
|
||||
2#0_11001_11011# => INSN_sradi,
|
||||
2#0_11000_11000# => INSN_sraw,
|
||||
2#0_11001_11000# => INSN_srawi,
|
||||
2#0_10000_11011# => INSN_srd,
|
||||
2#0_10000_11000# => INSN_srw,
|
||||
2#0_11110_10101# => INSN_stbcix,
|
||||
2#0_10101_10110# => INSN_stbcx,
|
||||
2#0_00111_10111# => INSN_stbux,
|
||||
2#0_00110_10111# => INSN_stbx,
|
||||
2#0_10100_10100# => INSN_stdbrx,
|
||||
2#0_11111_10101# => INSN_stdcix,
|
||||
2#0_00110_10110# => INSN_stdcx,
|
||||
2#0_00101_10101# => INSN_stdux,
|
||||
2#0_00100_10101# => INSN_stdx,
|
||||
2#0_10110_10111# => INSN_stfdx,
|
||||
2#0_10111_10111# => INSN_stfdux,
|
||||
2#0_11110_10111# => INSN_stfiwx,
|
||||
2#0_10100_10111# => INSN_stfsx,
|
||||
2#0_10101_10111# => INSN_stfsux,
|
||||
2#0_11100_10110# => INSN_sthbrx,
|
||||
2#0_11101_10101# => INSN_sthcix,
|
||||
2#0_10110_10110# => INSN_sthcx,
|
||||
2#0_01101_10111# => INSN_sthux,
|
||||
2#0_01100_10111# => INSN_sthx,
|
||||
2#0_10100_10110# => INSN_stwbrx,
|
||||
2#0_11100_10101# => INSN_stwcix,
|
||||
2#0_00100_10110# => INSN_stwcx,
|
||||
2#0_00101_10111# => INSN_stwux,
|
||||
2#0_00100_10111# => INSN_stwx,
|
||||
2#0_00001_01000# => INSN_subf,
|
||||
2#0_10001_01000# => INSN_subf, -- subfo
|
||||
2#0_00000_01000# => INSN_subfc,
|
||||
2#0_10000_01000# => INSN_subfc, -- subfco
|
||||
2#0_00100_01000# => INSN_subfe,
|
||||
2#0_10100_01000# => INSN_subfe, -- subfeo
|
||||
2#0_00111_01000# => INSN_subfme,
|
||||
2#0_10111_01000# => INSN_subfme, -- subfmeo
|
||||
2#0_00110_01000# => INSN_subfze,
|
||||
2#0_10110_01000# => INSN_subfze, -- subfzeo
|
||||
2#0_10010_10110# => INSN_sync,
|
||||
2#0_00010_00100# => INSN_td,
|
||||
2#0_00000_00100# => INSN_tw,
|
||||
2#0_01001_10010# => INSN_tlbie,
|
||||
2#0_01000_10010# => INSN_tlbiel,
|
||||
2#0_10001_10110# => INSN_tlbsync,
|
||||
2#0_00000_11110# => INSN_wait,
|
||||
2#0_01001_11100# => INSN_xor,
|
||||
|
||||
-- Major opcode 19
|
||||
-- Columns with insn(4) = '1' are all illegal and not mapped here; to
|
||||
-- fit into 2048 entries, the columns are remapped so that 16-24 are
|
||||
-- stored here as 8-15; in other words the address bits are
|
||||
-- 1, insn(10..6), 1, insn(5), insn(3..1)
|
||||
-- Columns 16-17 here are opcode 19 columns 0-1
|
||||
-- Columns 24-31 here are opcode 19 columns 16-23
|
||||
2#1_10000_11000# => INSN_bcctr,
|
||||
2#1_00000_11000# => INSN_bclr,
|
||||
2#1_10001_11000# => INSN_bctar,
|
||||
2#1_01000_10001# => INSN_crand,
|
||||
2#1_00100_10001# => INSN_crandc,
|
||||
2#1_01001_10001# => INSN_creqv,
|
||||
2#1_00111_10001# => INSN_crnand,
|
||||
2#1_00001_10001# => INSN_crnor,
|
||||
2#1_01110_10001# => INSN_cror,
|
||||
2#1_01101_10001# => INSN_crorc,
|
||||
2#1_00110_10001# => INSN_crxor,
|
||||
2#1_00100_11110# => INSN_isync,
|
||||
2#1_00000_10000# => INSN_mcrf,
|
||||
2#1_00000_11010# => INSN_rfid,
|
||||
|
||||
-- Major opcode 59
|
||||
-- Address bits are 1, insn(10..6), 1, 0, insn(3..1)
|
||||
-- Only column 14 is valid here; columns 16-31 are handled in the major table
|
||||
-- Column 14 is mapped to column 22.
|
||||
-- Columns 20-23 here are opcode 59 columns 12-15
|
||||
2#1_11010_10110# => INSN_fcfids,
|
||||
2#1_11110_10110# => INSN_fcfidus,
|
||||
|
||||
-- Major opcode 63
|
||||
-- Columns 0-15 are mapped here; columns 16-31 are in the major table.
|
||||
-- Address bits are 1, insn(10:6), 0, insn(4:1)
|
||||
-- Columns 0-15 here are opcode 63 columns 0-15
|
||||
2#1_00000_00000# => INSN_fcmpu,
|
||||
2#1_00001_00000# => INSN_fcmpo,
|
||||
2#1_00010_00000# => INSN_mcrfs,
|
||||
2#1_00100_00000# => INSN_ftdiv,
|
||||
2#1_00101_00000# => INSN_ftsqrt,
|
||||
2#1_00001_00110# => INSN_mtfsb,
|
||||
2#1_00010_00110# => INSN_mtfsb,
|
||||
2#1_00100_00110# => INSN_mtfsfi,
|
||||
2#1_11010_00110# => INSN_fmrgow,
|
||||
2#1_11110_00110# => INSN_fmrgew,
|
||||
2#1_10010_00111# => INSN_mffs,
|
||||
2#1_10110_00111# => INSN_mtfsf,
|
||||
2#1_00000_01000# => INSN_fcpsgn,
|
||||
2#1_00001_01000# => INSN_fneg,
|
||||
2#1_00010_01000# => INSN_fmr,
|
||||
2#1_00100_01000# => INSN_fnabs,
|
||||
2#1_01000_01000# => INSN_fabs,
|
||||
2#1_01100_01000# => INSN_frin,
|
||||
2#1_01101_01000# => INSN_friz,
|
||||
2#1_01110_01000# => INSN_frip,
|
||||
2#1_01111_01000# => INSN_frim,
|
||||
2#1_00000_01100# => INSN_frsp,
|
||||
2#1_00000_01110# => INSN_fctiw,
|
||||
2#1_00100_01110# => INSN_fctiwu,
|
||||
2#1_11001_01110# => INSN_fctid,
|
||||
2#1_11010_01110# => INSN_fcfid,
|
||||
2#1_11101_01110# => INSN_fctidu,
|
||||
2#1_11110_01110# => INSN_fcfidu,
|
||||
2#1_00000_01111# => INSN_fctiwz,
|
||||
2#1_00100_01111# => INSN_fctiwuz,
|
||||
2#1_11001_01111# => INSN_fctidz,
|
||||
2#1_11101_01111# => INSN_fctiduz,
|
||||
|
||||
others => INSN_illegal
|
||||
);
|
||||
|
||||
constant IOUT_LEN : natural := ICODE_LEN + IMAGE_LEN;
|
||||
|
||||
type predec_t is record
|
||||
image : std_ulogic_vector(31 downto 0);
|
||||
maj_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
row_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
end record;
|
||||
|
||||
subtype index_t is integer range 0 to WIDTH-1;
|
||||
type predec_array is array(index_t) of predec_t;
|
||||
|
||||
signal pred : predec_array;
|
||||
signal valid : std_ulogic;
|
||||
|
||||
begin
|
||||
predecode_0: process(clk)
|
||||
variable majaddr : std_ulogic_vector(10 downto 0);
|
||||
variable rowaddr : std_ulogic_vector(10 downto 0);
|
||||
variable iword : std_ulogic_vector(31 downto 0);
|
||||
variable majcode : insn_code;
|
||||
variable rowcode : insn_code;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
valid <= valid_in;
|
||||
for i in index_t loop
|
||||
iword := insns_in(i * 32 + 31 downto i * 32);
|
||||
pred(i).image <= iword;
|
||||
|
||||
if is_X(iword) then
|
||||
pred(i).maj_predecode <= (others => 'X');
|
||||
pred(i).row_predecode <= (others => 'X');
|
||||
else
|
||||
majaddr := iword(31 downto 26) & iword(4 downto 0);
|
||||
|
||||
-- row_predecode_rom is used for op 19, 31, 59, 63
|
||||
-- addr bit 10 is 0 for op 31, 1 for 19, 59, 63
|
||||
rowaddr(10) := iword(31) or not iword(29);
|
||||
rowaddr(9 downto 5) := iword(10 downto 6);
|
||||
if iword(28) = '0' then
|
||||
-- op 19 and op 59
|
||||
rowaddr(4 downto 3) := '1' & iword(5);
|
||||
else
|
||||
-- op 31 and 63; for 63 we only use this when iword(5) = '0'
|
||||
rowaddr(4 downto 3) := iword(5 downto 4);
|
||||
end if;
|
||||
rowaddr(2 downto 0) := iword(3 downto 1);
|
||||
|
||||
majcode := major_predecode_rom(to_integer(unsigned(majaddr)));
|
||||
pred(i).maj_predecode <= to_unsigned(insn_code'pos(majcode), ICODE_LEN);
|
||||
rowcode := row_predecode_rom(to_integer(unsigned(rowaddr)));
|
||||
pred(i).row_predecode <= to_unsigned(insn_code'pos(rowcode), ICODE_LEN);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
predecode_1: process(all)
|
||||
variable iword : std_ulogic_vector(31 downto 0);
|
||||
variable use_row : std_ulogic;
|
||||
variable illegal : std_ulogic;
|
||||
variable ici : std_ulogic_vector(IOUT_LEN - 1 downto 0);
|
||||
variable icode : unsigned(ICODE_LEN - 1 downto 0);
|
||||
begin
|
||||
for i in index_t loop
|
||||
iword := pred(i).image;
|
||||
icode := pred(i).maj_predecode;
|
||||
use_row := '0';
|
||||
illegal := '0';
|
||||
|
||||
case iword(31 downto 26) is
|
||||
when "000100" => -- 4
|
||||
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
|
||||
illegal := not iword(5);
|
||||
|
||||
when "010011" => -- 19
|
||||
-- Columns 8-15 and 24-31 don't have any valid instructions
|
||||
-- (where insn(5..1) is the column number).
|
||||
-- addpcis (column 2) is in the major table
|
||||
-- Other valid columns are mapped to columns in the second
|
||||
-- half of the row table: columns 0-1 are mapped to 16-17
|
||||
-- and 16-23 are mapped to 24-31.
|
||||
illegal := iword(4);
|
||||
use_row := iword(5) or (not iword(3) and not iword(2));
|
||||
|
||||
when "011000" => -- 24
|
||||
-- ori, special-case the standard NOP
|
||||
if std_match(iword, "01100000000000000000000000000000") then
|
||||
icode := to_unsigned(insn_code'pos(INSN_nop), ICODE_LEN);
|
||||
end if;
|
||||
|
||||
when "011111" => -- 31
|
||||
-- major opcode 31, lots of things
|
||||
-- Use the first half of the row table for all columns
|
||||
use_row := '1';
|
||||
|
||||
when "111011" => -- 59
|
||||
-- floating point operations, mostly single-precision
|
||||
-- Columns 0-11 are illegal; columns 12-15 are mapped
|
||||
-- to columns 20-23 in the second half of the row table,
|
||||
-- and columns 16-31 are in the major table.
|
||||
illegal := not iword(5) and (not iword(4) or not iword(3));
|
||||
use_row := not iword(5);
|
||||
|
||||
when "111111" => -- 63
|
||||
-- floating point operations, general and double-precision
|
||||
-- Use columns 0-15 of the second half of the row table
|
||||
-- for columns 0-15, and the major table for columns 16-31.
|
||||
use_row := not iword(5);
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
if use_row = '1' then
|
||||
icode := pred(i).row_predecode;
|
||||
end if;
|
||||
|
||||
-- Mark FP instructions as illegal if we don't have an FPU
|
||||
if not HAS_FPU and not is_X(icode) and
|
||||
to_integer(icode) >= insn_code'pos(INSN_first_frs) then
|
||||
illegal := '1';
|
||||
end if;
|
||||
|
||||
ici(31 downto 0) := iword;
|
||||
ici(IOUT_LEN - 1 downto 32) := (others => '0');
|
||||
if valid = '0' or illegal = '1' or is_X(icode) or
|
||||
icode = to_unsigned(insn_code'pos(INSN_illegal), ICODE_LEN) then
|
||||
-- Since an insn_code currently fits in 9 bits, use just
|
||||
-- the most significant bit of ici to indicate illegal insns.
|
||||
ici(IOUT_LEN - 1) := '1';
|
||||
else
|
||||
ici(IOUT_LEN - 1 downto IMAGE_LEN) := std_ulogic_vector(icode);
|
||||
end if;
|
||||
icodes_out(i * IOUT_LEN + IOUT_LEN - 1 downto i * IOUT_LEN) <= ici;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
||||
@ -22,7 +22,7 @@ struct log_entry {
|
||||
u64 ic_wb_adr: 3;
|
||||
u64 ic_wb_ack: 1;
|
||||
|
||||
u64 ic_insn: 32;
|
||||
u64 ic_insn: 36;
|
||||
u64 ic_valid: 1;
|
||||
u64 d1_valid: 1;
|
||||
u64 d1_unit: 2;
|
||||
@ -39,9 +39,8 @@ struct log_entry {
|
||||
u64 e1_stall_out: 1;
|
||||
u64 e1_redirect: 1;
|
||||
u64 e1_valid: 1;
|
||||
u64 e1_write_enable: 1;
|
||||
u64 e1_unused: 3;
|
||||
|
||||
u64 e1_write_enable: 1;
|
||||
u64 e1_irq_state: 1;
|
||||
u64 e1_irq: 1;
|
||||
u64 e1_exception: 1;
|
||||
@ -49,7 +48,7 @@ struct log_entry {
|
||||
u64 e1_msr_ir: 1;
|
||||
u64 e1_msr_pr: 1;
|
||||
u64 e1_msr_ee: 1;
|
||||
u64 pad1: 5;
|
||||
u64 pad1: 4;
|
||||
u64 ls_state: 3;
|
||||
u64 ls_dw_done: 1;
|
||||
u64 ls_min_done: 1;
|
||||
@ -88,13 +87,13 @@ const char *units[4] = { "--", "al", "ls", "fp" };
|
||||
const char *ops[64] =
|
||||
{
|
||||
"illegal", "nop ", "add ", "and ", "attn ", "b ", "bc ", "bcreg ",
|
||||
"bperm ", "cmp ", "cmpb ", "cmpeqb ", "cmprb ", "cntz ", "crop ", "darn ",
|
||||
"dcbf ", "dcbst ", "dcbt ", "dcbtst ", "dcbz ", "div ", "dive ", "exts ",
|
||||
"extswsl", "fpop ", "fpopi ", "icbi ", "icbt ", "isel ", "isync ", "ld ",
|
||||
"st ", "mcrxrx ", "mfcr ", "mfmsr ", "mfspr ", "mod ", "mtcrf ", "mtmsr ",
|
||||
"mtspr ", "mull64 ", "mulh64 ", "mulh32 ", "or ", "popcnt ", "prty ", "rfid ",
|
||||
"rlc ", "rlcl ", "rlcr ", "sc ", "setb ", "shl ", "shr ", "sync ",
|
||||
"tlbie ", "trap ", "xor ", "bcd ", "addg6s ", "ffail ", "?62 ", "?63 "
|
||||
"bcd ", "bperm ", "cmp ", "cmpb ", "cmpeqb ", "cmprb ", "cntz ", "crop ",
|
||||
"darn ", "dcbf ", "dcbst ", "dcbt ", "dcbtst ", "dcbz ", "icbi ", "icbt ",
|
||||
"fpcmp ", "fparith", "fpmove ", "fpmisc ", "div ", "dive ", "mod ", "exts ",
|
||||
"extswsl", "isel ", "isync ", "ld ", "st ", "mcrxrx ", "mfcr ", "mfmsr ",
|
||||
"mfspr ", "mtcrf ", "mtmsr ", "mtspr ", "mull64 ", "mulh64 ", "mulh32 ", "or ",
|
||||
"popcnt ", "prty ", "rfid ", "rlc ", "rlcl ", "rlcr ", "sc ", "setb ",
|
||||
"shl ", "shr ", "sync ", "tlbie ", "trap ", "xor ", "addg6s ", "ffail ",
|
||||
};
|
||||
|
||||
const char *spr_names[13] =
|
||||
@ -134,9 +133,9 @@ int main(int ac, char **av)
|
||||
full_nia[log.nia_lo & 0xf] = (log.nia_hi? 0xc000000000000000: 0) |
|
||||
(log.nia_lo << 2);
|
||||
if (lineno % 20 == 1) {
|
||||
printf(" fetch1 NIA icache decode1 decode2 execute1 loadstore dcache CR GSPR\n");
|
||||
printf(" ---------------- TAHW S -WB-- pN --insn-- pN un op pN byp FR IIE MSR WC SD MM CE SRTO DE -WB-- c ms reg val\n");
|
||||
printf(" LdMy t csnSa IA IA it IA abc le srx EPID em tw rd mx tAwp vr csnSa 0 k\n");
|
||||
printf(" fetch1 NIA icache decode1 decode2 execute1 loadstore dcache CR GSPR\n");
|
||||
printf(" ---------------- TAHW S -WB-- pN ic --insn-- pN un op pN byp FR IIE MSR WC SD MM CE SRTO DE -WB-- c ms reg val\n");
|
||||
printf(" LdMy t csnSa IA IA it IA abc le srx EPID em tw rd mx tAwp vr csnSa 0 k\n");
|
||||
}
|
||||
printf("%4ld %c0000%.11llx %c ", lineno,
|
||||
(log.nia_hi? 'c': '0'),
|
||||
@ -154,12 +153,16 @@ int main(int ac, char **av)
|
||||
FLAG(ic_wb_stall, 'S'),
|
||||
FLAG(ic_wb_ack, 'a'),
|
||||
PNIA(ic_part_nia));
|
||||
if (log.ic_valid)
|
||||
printf("%.8x", log.ic_insn);
|
||||
else if (log.ic_fetch_failed)
|
||||
printf("!!!!!!!!");
|
||||
if (log.ic_valid) {
|
||||
if (log.ic_insn & (1ul << 35))
|
||||
printf("ill %.8lx", log.ic_insn & 0xfffffffful);
|
||||
else
|
||||
printf("%3lu x%.7lx", (long)(log.ic_insn >> 26),
|
||||
(unsigned long)(log.ic_insn & 0x3ffffff));
|
||||
} else if (log.ic_fetch_failed)
|
||||
printf(" !!!!!!!!");
|
||||
else
|
||||
printf("--------");
|
||||
printf("--- --------");
|
||||
printf(" %c%c %.2llx ",
|
||||
FLAG(ic_valid, '>'),
|
||||
FLAG(d2_stall_out, '|'),
|
||||
|
||||
2
soc.vhdl
2
soc.vhdl
@ -59,7 +59,6 @@ entity soc is
|
||||
SIM : boolean;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_BTC : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (23 downto 0 => '0', others => '1');
|
||||
HAS_DRAM : boolean := false;
|
||||
@ -335,7 +334,6 @@ begin
|
||||
SIM => SIM,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_BTC => HAS_BTC,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
DISABLE_FLATTEN => DISABLE_FLATTEN_CORE,
|
||||
ALT_RESET_ADDRESS => ALT_RESET_ADDRESS,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
|
||||
@ -92,21 +92,20 @@ begin
|
||||
intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt;
|
||||
interrupt_out.intr <= intr;
|
||||
|
||||
if intr = '1' then
|
||||
srr1 := (others => '0');
|
||||
if e_in.interrupt = '1' then
|
||||
vec := e_in.intr_vec;
|
||||
srr1 := e_in.srr1;
|
||||
elsif l_in.interrupt = '1' then
|
||||
vec := l_in.intr_vec;
|
||||
srr1 := l_in.srr1;
|
||||
elsif fp_in.interrupt = '1' then
|
||||
vec := fp_in.intr_vec;
|
||||
srr1 := fp_in.srr1;
|
||||
end if;
|
||||
interrupt_out.srr1 <= srr1;
|
||||
srr1 := (others => '0');
|
||||
if e_in.interrupt = '1' then
|
||||
vec := e_in.intr_vec;
|
||||
srr1 := e_in.srr1;
|
||||
elsif l_in.interrupt = '1' then
|
||||
vec := l_in.intr_vec;
|
||||
srr1 := l_in.srr1;
|
||||
elsif fp_in.interrupt = '1' then
|
||||
vec := fp_in.intr_vec;
|
||||
srr1 := fp_in.srr1;
|
||||
end if;
|
||||
interrupt_out.srr1 <= srr1;
|
||||
|
||||
else
|
||||
if intr = '0' then
|
||||
if e_in.write_enable = '1' then
|
||||
w_out.write_reg <= e_in.write_reg;
|
||||
w_out.write_data <= e_in.write_data;
|
||||
|
||||
295
xilinx-mult-32s.vhdl
Normal file
295
xilinx-mult-32s.vhdl
Normal file
@ -0,0 +1,295 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
|
||||
-- Signed 33b x 33b multiplier giving 64-bit product, with no addend.
|
||||
|
||||
entity multiply_32s is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
stall : in std_ulogic;
|
||||
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply_32s;
|
||||
|
||||
architecture behaviour of multiply_32s is
|
||||
signal clocken : std_ulogic;
|
||||
signal data1 : std_ulogic_vector(52 downto 0);
|
||||
signal data2 : std_ulogic_vector(34 downto 0);
|
||||
signal m00_p, m01_p : std_ulogic_vector(47 downto 0);
|
||||
signal m00_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m10_p, m11_p : std_ulogic_vector(47 downto 0);
|
||||
signal m10_pc : std_ulogic_vector(47 downto 0);
|
||||
signal p0_pat, p0_patb : std_ulogic;
|
||||
signal p1_pat, p1_patb : std_ulogic;
|
||||
signal product_lo : std_ulogic_vector(22 downto 0);
|
||||
|
||||
begin
|
||||
-- sign extend if signed
|
||||
data1(31 downto 0) <= m_in.data1(31 downto 0);
|
||||
data1(52 downto 32) <= (others => m_in.is_signed and m_in.data1(31));
|
||||
data2(31 downto 0) <= m_in.data2(31 downto 0);
|
||||
data2(34 downto 32) <= (others => m_in.is_signed and m_in.data2(31));
|
||||
|
||||
clocken <= m_in.valid and not stall;
|
||||
|
||||
m00: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & data1(22 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
P => m00_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m00_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m01: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & data1(22 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => data2(34 downto 17),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "1010101",
|
||||
P => m01_p,
|
||||
PCIN => m00_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m10: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 1,
|
||||
INMODEREG => 0,
|
||||
MASK => x"fffffffe00ff",
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => data1(52 downto 23),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => std_ulogic_vector(resize(signed(m01_p(38 downto 6)), 48)),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => clocken,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => clocken,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
P => m10_p,
|
||||
PATTERNDETECT => p0_pat,
|
||||
PATTERNBDETECT => p0_patb,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m11: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MASK => x"fffffc000000",
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => data1(52 downto 23),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => data2(34 downto 17),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => clocken,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "1010101",
|
||||
P => m11_p,
|
||||
PATTERNDETECT => p1_pat,
|
||||
PATTERNBDETECT => p1_patb,
|
||||
PCIN => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
RSTB => '0',
|
||||
RSTC => '0',
|
||||
RSTCTRL => '0',
|
||||
RSTD => '0',
|
||||
RSTINMODE => '0',
|
||||
RSTM => '0',
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
m_out.result(127 downto 64) <= (others => '0');
|
||||
m_out.result(63 downto 40) <= m11_p(23 downto 0);
|
||||
m_out.result(39 downto 23) <= m10_p(16 downto 0);
|
||||
m_out.result(22 downto 0) <= product_lo;
|
||||
|
||||
m_out.overflow <= not ((p0_pat and p1_pat) or (p0_patb and p1_patb));
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) and stall = '0' then
|
||||
m_out.valid <= m_in.valid;
|
||||
product_lo <= m01_p(5 downto 0) & m00_p(16 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
||||
289
xilinx-mult.vhdl
289
xilinx-mult.vhdl
@ -18,26 +18,32 @@ entity multiply is
|
||||
end entity multiply;
|
||||
|
||||
architecture behaviour of multiply is
|
||||
signal d1sign : std_ulogic_vector(13 downto 0);
|
||||
signal d2sign : std_ulogic_vector(4 downto 0);
|
||||
signal m00_p, m01_p, m02_p, m03_p : std_ulogic_vector(47 downto 0);
|
||||
signal m00_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m00_pc, m02_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m10_p, m11_p, m12_p, m13_p : std_ulogic_vector(47 downto 0);
|
||||
signal m11_pc, m12_pc, m13_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m10_pc, m12_pc : std_ulogic_vector(47 downto 0);
|
||||
signal m20_p, m21_p, m22_p, m23_p : std_ulogic_vector(47 downto 0);
|
||||
signal m20_pc, m22_pc : std_ulogic_vector(47 downto 0);
|
||||
signal pp0, pp1 : std_ulogic_vector(127 downto 0);
|
||||
signal pp23 : std_ulogic_vector(127 downto 0);
|
||||
signal sumlo : std_ulogic_vector(8 downto 0);
|
||||
signal s0_pc, s1_pc : std_ulogic_vector(47 downto 0);
|
||||
signal s0_carry, p0_carry : std_ulogic_vector(3 downto 0);
|
||||
signal product : std_ulogic_vector(127 downto 0);
|
||||
signal addend : std_ulogic_vector(127 downto 0);
|
||||
signal s0_carry, p0_carry : std_ulogic_vector(3 downto 0);
|
||||
signal p0_mask : std_ulogic_vector(47 downto 0);
|
||||
signal p0_pat, p0_patb : std_ulogic;
|
||||
signal p1_pat, p1_patb : std_ulogic;
|
||||
|
||||
signal req_32bit, r32_1 : std_ulogic;
|
||||
signal rnot_1 : std_ulogic;
|
||||
signal valid_1 : std_ulogic;
|
||||
signal overflow, ovf_in : std_ulogic;
|
||||
signal overflow : std_ulogic;
|
||||
|
||||
begin
|
||||
addend <= m_in.addend;
|
||||
addend <= m_in.addend when m_in.subtract = '0' else not m_in.addend;
|
||||
d1sign <= (others => m_in.data1(63) and m_in.is_signed);
|
||||
d2sign <= (others => m_in.data2(63) and m_in.is_signed);
|
||||
|
||||
m00: DSP48E1
|
||||
generic map (
|
||||
@ -55,12 +61,12 @@ begin
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & m_in.data1(22 downto 0),
|
||||
A => 6x"0" & m_in.data1(23 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => "00000000000000" & addend(33 downto 0),
|
||||
C => 14x"0" & addend(33 downto 0),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -106,12 +112,14 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & m_in.data1(22 downto 0),
|
||||
A => 6x"0" & m_in.data1(23 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(33 downto 17),
|
||||
@ -126,7 +134,7 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@ -168,12 +176,12 @@ begin
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & m_in.data1(22 downto 0),
|
||||
A => 6x"0" & m_in.data1(23 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(50 downto 34),
|
||||
BCIN => (others => '0'),
|
||||
C => x"0000000" & "000" & addend(50 downto 34),
|
||||
C => 24x"0" & addend(57 downto 34),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -197,6 +205,7 @@ begin
|
||||
OPMODE => "0110101",
|
||||
P => m02_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m02_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -220,17 +229,17 @@ begin
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 1
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000" & m_in.data1(22 downto 0),
|
||||
A => 6x"0" & m_in.data1(23 downto 0),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => "00000" & m_in.data2(63 downto 51),
|
||||
B => d2sign & m_in.data2(63 downto 51),
|
||||
BCIN => (others => '0'),
|
||||
C => x"000000" & '0' & addend(73 downto 51),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -245,15 +254,15 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => m_in.valid,
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
OPMODE => "1010101",
|
||||
P => m03_p,
|
||||
PCIN => (others => '0'),
|
||||
PCIN => m02_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -277,16 +286,17 @@ begin
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "0000000000000" & m_in.data1(39 downto 23),
|
||||
A => 6x"0" & m_in.data1(47 downto 24),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(16 downto 0),
|
||||
BCIN => (others => '0'),
|
||||
C => x"000" & "00" & m01_p(39 downto 6),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -301,15 +311,16 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CEM => '0',
|
||||
CEP => m_in.valid,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
OPMODE => "0000101",
|
||||
P => m10_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -333,16 +344,17 @@ begin
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000000000" & m_in.data1(39 downto 23),
|
||||
A => 6x"0" & m_in.data1(47 downto 24),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(33 downto 17),
|
||||
BCIN => (others => '0'),
|
||||
C => x"000" & "00" & m02_p(39 downto 6),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -363,10 +375,9 @@ begin
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
OPMODE => "1010101",
|
||||
P => m11_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m11_pc,
|
||||
PCIN => m10_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -390,16 +401,17 @@ begin
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "0000000000000" & m_in.data1(39 downto 23),
|
||||
A => 6x"0" & m_in.data1(47 downto 24),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(50 downto 34),
|
||||
BCIN => (others => '0'),
|
||||
C => x"0000" & '0' & m03_p(36 downto 6),
|
||||
C => 24x"0" & addend(81 downto 58),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -414,8 +426,8 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CEM => '0',
|
||||
CEP => m_in.valid,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
@ -445,17 +457,19 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "0000000000000" & m_in.data1(39 downto 23),
|
||||
A => 6x"0" & m_in.data1(47 downto 24),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => "00000" & m_in.data2(63 downto 51),
|
||||
B => d2sign & m_in.data2(63 downto 51),
|
||||
BCIN => (others => '0'),
|
||||
C => x"0000000" & "000" & addend(90 downto 74),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -465,7 +479,7 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@ -476,10 +490,9 @@ begin
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
OPMODE => "1010101",
|
||||
P => m13_p,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m13_pc,
|
||||
PCIN => m12_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -501,12 +514,14 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "000000" & m_in.data1(63 downto 40),
|
||||
A => d1sign & m_in.data1(63 downto 48),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(16 downto 0),
|
||||
@ -521,20 +536,21 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CEM => '0',
|
||||
CEP => m_in.valid,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0010101",
|
||||
OPMODE => "0000101",
|
||||
P => m20_p,
|
||||
PCIN => m11_pc,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m20_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -556,12 +572,14 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "000000" & m_in.data1(63 downto 40),
|
||||
A => d1sign & m_in.data1(63 downto 48),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(33 downto 17),
|
||||
@ -576,7 +594,7 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@ -587,9 +605,9 @@ begin
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0010101",
|
||||
OPMODE => "1010101",
|
||||
P => m21_p,
|
||||
PCIN => m12_pc,
|
||||
PCIN => m20_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -611,17 +629,19 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
PREG => 1
|
||||
)
|
||||
port map (
|
||||
A => "000000" & m_in.data1(63 downto 40),
|
||||
A => d1sign & m_in.data1(63 downto 48),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => '0' & m_in.data2(50 downto 34),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
C => "00" & addend(127 downto 82),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -631,20 +651,21 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CEM => '0',
|
||||
CEP => m_in.valid,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0010101",
|
||||
OPMODE => "0110101",
|
||||
P => m22_p,
|
||||
PCIN => m13_pc,
|
||||
PCIN => (others => '0'),
|
||||
PCOUT => m22_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -666,17 +687,19 @@ begin
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 1,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0
|
||||
)
|
||||
port map (
|
||||
A => "000000" & m_in.data1(63 downto 40),
|
||||
A => d1sign & m_in.data1(63 downto 48),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => "00000" & m_in.data2(63 downto 51),
|
||||
B => d2sign & m_in.data2(63 downto 51),
|
||||
BCIN => (others => '0'),
|
||||
C => x"00" & "000" & addend(127 downto 91),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -686,7 +709,7 @@ begin
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '0',
|
||||
CEC => '1',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@ -697,9 +720,9 @@ begin
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
MULTSIGNIN => '0',
|
||||
OPMODE => "0110101",
|
||||
OPMODE => "1010101",
|
||||
P => m23_p,
|
||||
PCIN => (others => '0'),
|
||||
PCIN => m22_pc,
|
||||
RSTA => '0',
|
||||
RSTALLCARRYIN => '0',
|
||||
RSTALUMODE => '0',
|
||||
@ -712,6 +735,17 @@ begin
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
pp0 <= std_ulogic_vector(resize(signed(m13_p(37 downto 0) & m12_p(16 downto 0) &
|
||||
m01_p(40 downto 0) & m00_p(16 downto 0)), 128));
|
||||
pp1 <= m23_p(28 downto 0) & m22_p(16 downto 0) & m11_p(40 downto 0) & m10_p(16 downto 0) & 24x"0";
|
||||
-- pp2 <= std_ulogic_vector(resize(signed(m03_p(37 downto 0) & m02_p(16 downto 0) & 34x"0"), 128));
|
||||
-- pp3 <= std_ulogic_vector(resize(signed(m21_p(34 downto 0) & m20_p(16 downto 0) & 48x"0"), 128));
|
||||
|
||||
pp23 <= std_ulogic_vector(resize(resize(signed(m03_p(37 downto 0) & m02_p(16 downto 0) & 34x"0"), 100) +
|
||||
signed(m21_p(34 downto 0) & m20_p(16 downto 0) & 48x"0"), 128));
|
||||
|
||||
sumlo <= std_ulogic_vector(unsigned('0' & pp0(31 downto 24)) + unsigned('0' & pp1(31 downto 24)));
|
||||
|
||||
s0: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 0,
|
||||
@ -725,16 +759,16 @@ begin
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 1,
|
||||
PREG => 0,
|
||||
USE_MULT => "none"
|
||||
)
|
||||
port map (
|
||||
A => m22_p(5 downto 0) & x"0000" & m10_p(34 downto 27),
|
||||
A => pp0(79 downto 50),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => m10_p(26 downto 9),
|
||||
B => pp0(49 downto 32),
|
||||
BCIN => (others => '0'),
|
||||
C => m20_p(39 downto 0) & m02_p(5 downto 0) & "00",
|
||||
C => pp1(79 downto 32),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYINSEL => "000",
|
||||
@ -751,7 +785,7 @@ begin
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => valid_1,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
@ -773,43 +807,43 @@ begin
|
||||
|
||||
s1: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 1,
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 1,
|
||||
BCASCREG => 1,
|
||||
BREG => 1,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 1,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
PREG => 1,
|
||||
USE_MULT => "none"
|
||||
)
|
||||
port map (
|
||||
A => x"000" & m22_p(41 downto 24),
|
||||
A => pp0(127 downto 98),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "0000",
|
||||
B => m22_p(23 downto 6),
|
||||
B => pp0(97 downto 80),
|
||||
BCIN => (others => '0'),
|
||||
C => m23_p(36 downto 0) & x"00" & "0" & m20_p(41 downto 40),
|
||||
C => pp1(127 downto 80),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => s0_carry(3),
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => valid_1,
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => valid_1,
|
||||
CEC => valid_1,
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CEP => valid_1,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
@ -829,52 +863,48 @@ begin
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
-- mask is 0 for 32-bit ops, 0x0000ffffffff for 64-bit
|
||||
p0_mask(47 downto 31) <= (others => '0');
|
||||
p0_mask(30 downto 0) <= (others => not r32_1);
|
||||
|
||||
p0: DSP48E1
|
||||
generic map (
|
||||
ACASCREG => 1,
|
||||
ALUMODEREG => 1,
|
||||
AREG => 1,
|
||||
BCASCREG => 1,
|
||||
BREG => 1,
|
||||
ACASCREG => 0,
|
||||
ALUMODEREG => 0,
|
||||
AREG => 0,
|
||||
BCASCREG => 0,
|
||||
BREG => 0,
|
||||
CARRYINREG => 0,
|
||||
CARRYINSELREG => 0,
|
||||
CREG => 1,
|
||||
CREG => 0,
|
||||
INMODEREG => 0,
|
||||
MASK => x"00007fffffff",
|
||||
MREG => 0,
|
||||
OPMODEREG => 0,
|
||||
PREG => 0,
|
||||
SEL_MASK => "C",
|
||||
PREG => 1,
|
||||
USE_MULT => "none",
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => m21_p(22 downto 0) & m03_p(5 downto 0) & '0',
|
||||
A => pp23(79 downto 50),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "00" & rnot_1 & '0',
|
||||
B => (others => '0'),
|
||||
B => pp23(49 downto 32),
|
||||
BCIN => (others => '0'),
|
||||
C => p0_mask,
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
CARRYIN => '0',
|
||||
CARRYIN => sumlo(8),
|
||||
CARRYINSEL => "000",
|
||||
CARRYOUT => p0_carry,
|
||||
CEA1 => '0',
|
||||
CEA2 => valid_1,
|
||||
CEA2 => '0',
|
||||
CEAD => '0',
|
||||
CEALUMODE => valid_1,
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => valid_1,
|
||||
CEC => valid_1,
|
||||
CEB2 => '0',
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '0',
|
||||
CEP => '0',
|
||||
CEP => valid_1,
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
INMODE => "00000",
|
||||
@ -915,10 +945,10 @@ begin
|
||||
USE_PATTERN_DETECT => "PATDET"
|
||||
)
|
||||
port map (
|
||||
A => x"0000000" & '0' & m21_p(41),
|
||||
A => pp23(127 downto 98),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "00" & rnot_1 & '0',
|
||||
B => m21_p(40 downto 23),
|
||||
B => pp23(97 downto 80),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
CARRYCASCIN => '0',
|
||||
@ -930,7 +960,7 @@ begin
|
||||
CEALUMODE => valid_1,
|
||||
CEB1 => '0',
|
||||
CEB2 => valid_1,
|
||||
CEC => '0',
|
||||
CEC => valid_1,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@ -958,39 +988,26 @@ begin
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
mult_out: process(all)
|
||||
variable ov : std_ulogic;
|
||||
begin
|
||||
-- set overflow if the high bits are neither all zeroes nor all ones
|
||||
if req_32bit = '0' then
|
||||
ov := not ((p1_pat and p0_pat) or (p1_patb and p0_patb));
|
||||
else
|
||||
ov := not ((p1_pat and p0_pat and not product(31)) or
|
||||
(p1_patb and p0_patb and product(31)));
|
||||
end if;
|
||||
ovf_in <= ov;
|
||||
|
||||
m_out.result <= product;
|
||||
m_out.overflow <= overflow;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rnot_1 = '0' then
|
||||
product(31 downto 0) <= m10_p(8 downto 0) & m01_p(5 downto 0) & m00_p(16 downto 0);
|
||||
else
|
||||
product(31 downto 0) <= not (m10_p(8 downto 0) & m01_p(5 downto 0) & m00_p(16 downto 0));
|
||||
if valid_1 = '1' then
|
||||
if rnot_1 = '0' then
|
||||
product(31 downto 0) <= sumlo(7 downto 0) & pp0(23 downto 0);
|
||||
else
|
||||
product(31 downto 0) <= not (sumlo(7 downto 0) & pp0(23 downto 0));
|
||||
end if;
|
||||
end if;
|
||||
m_out.valid <= valid_1;
|
||||
valid_1 <= m_in.valid;
|
||||
req_32bit <= r32_1;
|
||||
r32_1 <= m_in.is_32bit;
|
||||
rnot_1 <= m_in.not_result;
|
||||
overflow <= ovf_in;
|
||||
rnot_1 <= m_in.subtract;
|
||||
overflow <= not ((p1_pat and p0_pat) or (p1_patb and p0_patb));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
m_out.result <= product;
|
||||
m_out.overflow <= overflow;
|
||||
|
||||
end architecture behaviour;
|
||||
|
||||
library ieee;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user