core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \
utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \
- decode1.vhdl helpers.vhdl insn_helpers.vhdl gpr_hazard.vhdl \
+ decode1.vhdl helpers.vhdl insn_helpers.vhdl \
cr_hazard.vhdl control.vhdl decode2.vhdl register_file.vhdl \
cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \
logical.vhdl countzero.vhdl multiply.vhdl divider.vhdl execute1.vhdl \
use ieee.numeric_std.all;
library work;
+use work.utils.all;
use work.decode_types.all;
package common is
constant FPSCR_NI : integer := 63 - 61;
constant FPSCR_RN : integer := 63 - 63;
+ -- Used for tracking instruction completion and pending register writes
+ constant TAG_COUNT : positive := 4;
+ constant TAG_NUMBER_BITS : natural := log2(TAG_COUNT);
+ subtype tag_number_t is integer range 0 to TAG_COUNT - 1;
+ subtype tag_index_t is unsigned(TAG_NUMBER_BITS - 1 downto 0);
+ type instr_tag_t is record
+ tag : tag_number_t;
+ valid : std_ulogic;
+ end record;
+ constant instr_tag_init : instr_tag_t := (tag => 0, valid => '0');
+
type irq_state_t is (WRITE_SRR0, WRITE_SRR1);
-- For now, fixed 16 sources, make this either a parametric
fac : facility_t;
insn_type: insn_type_t;
nia: std_ulogic_vector(63 downto 0);
+ instr_tag : instr_tag_t;
write_reg: gspr_index_t;
write_reg_enable: std_ulogic;
read_reg1: gspr_index_t;
second : std_ulogic; -- set if this is the second op
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
- (valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL,
+ (valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
write_reg_enable => '0', bypass_data1 => '0', bypass_data2 => '0', bypass_data3 => '0',
bypass_cr => '0', lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0',
invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
end record;
type RegisterFileToDecode2Type is record
- read1_data : std_ulogic_vector(63 downto 0);
- read2_data : std_ulogic_vector(63 downto 0);
- read3_data : std_ulogic_vector(63 downto 0);
+ read1_data : std_ulogic_vector(63 downto 0);
+ read2_data : std_ulogic_vector(63 downto 0);
+ read3_data : std_ulogic_vector(63 downto 0);
end record;
type Decode2ToCrFileType is record
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);
addr2 : std_ulogic_vector(63 downto 0);
data : std_ulogic_vector(63 downto 0); -- data to write, unused for read
repeat : std_ulogic;
second : std_ulogic;
end record;
- constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (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'),
- addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
- write_reg => (others => '0'), length => (others => '0'),
- mode_32bit => '0', is_32bit => '0',
- repeat => '0', second => '0');
+ constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type :=
+ (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'),
+ instr_tag => instr_tag_init,
+ addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
+ write_reg => (others => '0'),
+ length => (others => '0'),
+ mode_32bit => '0', is_32bit => '0',
+ repeat => '0', second => '0');
type Loadstore1ToExecute1Type is record
busy : std_ulogic;
type Loadstore1ToWritebackType is record
valid : std_ulogic;
+ instr_tag : instr_tag_t;
write_enable: std_ulogic;
write_reg : gspr_index_t;
write_data : std_ulogic_vector(63 downto 0);
rc : std_ulogic;
store_done : std_ulogic;
end record;
- constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType := (valid => '0', write_enable => '0', xerc => xerc_init,
- rc => '0', store_done => '0', write_data => (others => '0'), others => (others => '0'));
+ constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType :=
+ (valid => '0', instr_tag => instr_tag_init, write_enable => '0', xerc => xerc_init,
+ rc => '0', store_done => '0', write_data => (others => '0'), others => (others => '0'));
type Execute1ToWritebackType is record
valid: std_ulogic;
+ instr_tag : instr_tag_t;
rc : std_ulogic;
mode_32bit : std_ulogic;
write_enable : std_ulogic;
exc_write_reg : gspr_index_t;
exc_write_data : std_ulogic_vector(63 downto 0);
end record;
- constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', mode_32bit => '0', write_enable => '0',
- write_cr_enable => '0', exc_write_enable => '0',
- write_xerc_enable => '0', xerc => xerc_init,
- write_data => (others => '0'), write_cr_mask => (others => '0'),
- write_cr_data => (others => '0'), write_reg => (others => '0'),
- exc_write_reg => (others => '0'), exc_write_data => (others => '0'));
+ constant Execute1ToWritebackInit : Execute1ToWritebackType :=
+ (valid => '0', instr_tag => instr_tag_init, rc => '0', mode_32bit => '0',
+ write_enable => '0', write_cr_enable => '0', exc_write_enable => '0',
+ write_xerc_enable => '0', xerc => xerc_init,
+ write_data => (others => '0'), write_cr_mask => (others => '0'),
+ write_cr_data => (others => '0'), write_reg => (others => '0'),
+ exc_write_reg => (others => '0'), exc_write_data => (others => '0'));
type Execute1ToFPUType is record
valid : std_ulogic;
op : insn_type_t;
nia : std_ulogic_vector(63 downto 0);
+ itag : instr_tag_t;
insn : std_ulogic_vector(31 downto 0);
single : std_ulogic;
fe_mode : std_ulogic_vector(1 downto 0);
out_cr : std_ulogic;
end record;
constant Execute1ToFPUInit : Execute1ToFPUType := (valid => '0', op => OP_ILLEGAL, nia => (others => '0'),
+ itag => instr_tag_init,
insn => (others => '0'), fe_mode => "00", rc => '0',
fra => (others => '0'), frb => (others => '0'),
frc => (others => '0'), frt => (others => '0'),
type FPUToWritebackType is record
valid : std_ulogic;
+ instr_tag : instr_tag_t;
write_enable : std_ulogic;
write_reg : gspr_index_t;
write_data : std_ulogic_vector(63 downto 0);
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
end record;
- constant FPUToWritebackInit : FPUToWritebackType := (valid => '0', write_enable => '0', write_cr_enable => '0', others => (others => '0'));
+ constant FPUToWritebackInit : FPUToWritebackType := (valid => '0', instr_tag => instr_tag_init,
+ write_enable => '0', write_cr_enable => '0',
+ others => (others => '0'));
type DividerToExecute1Type is record
valid: std_ulogic;
write_data : std_ulogic_vector(63 downto 0);
write_enable : std_ulogic;
end record;
- constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', write_data => (others => '0'), others => (others => '0'));
+ constant WritebackToRegisterFileInit : WritebackToRegisterFileType :=
+ (write_enable => '0', write_data => (others => '0'), others => (others => '0'));
type WritebackToCrFileType is record
write_cr_enable : std_ulogic;
clk : in std_ulogic;
rst : in std_ulogic;
- complete_in : in std_ulogic;
+ complete_in : in instr_tag_t;
valid_in : in std_ulogic;
repeated : in std_ulogic;
flush_in : in std_ulogic;
gpr_write_in : in gspr_index_t;
gpr_bypassable : in std_ulogic;
- update_gpr_write_valid : in std_ulogic;
- update_gpr_write_reg : in gspr_index_t;
-
gpr_a_read_valid_in : in std_ulogic;
gpr_a_read_in : in gspr_index_t;
gpr_bypass_a : out std_ulogic;
gpr_bypass_b : out std_ulogic;
gpr_bypass_c : out std_ulogic;
- cr_bypass : out std_ulogic
+ cr_bypass : out std_ulogic;
+
+ instr_tag_out : out instr_tag_t
);
end entity control;
signal gpr_write_valid : std_ulogic := '0';
signal cr_write_valid : std_ulogic := '0';
-begin
- gpr_hazard0: entity work.gpr_hazard
- generic map (
- PIPELINE_DEPTH => PIPELINE_DEPTH
- )
- port map (
- clk => clk,
- busy_in => busy_in,
- deferred => deferred,
- complete_in => complete_in,
- flush_in => flush_in,
- issuing => valid_out,
- repeated => repeated,
-
- gpr_write_valid_in => gpr_write_valid,
- gpr_write_in => gpr_write_in,
- bypass_avail => gpr_bypassable,
- gpr_read_valid_in => gpr_a_read_valid_in,
- gpr_read_in => gpr_a_read_in,
-
- ugpr_write_valid => update_gpr_write_valid,
- ugpr_write_reg => update_gpr_write_reg,
-
- stall_out => stall_a_out,
- use_bypass => gpr_bypass_a
- );
+ type tag_register is record
+ wr_gpr : std_ulogic;
+ reg : gspr_index_t;
+ recent : std_ulogic;
+ end record;
- gpr_hazard1: entity work.gpr_hazard
- generic map (
- PIPELINE_DEPTH => PIPELINE_DEPTH
- )
- port map (
- clk => clk,
- busy_in => busy_in,
- deferred => deferred,
- complete_in => complete_in,
- flush_in => flush_in,
- issuing => valid_out,
- repeated => repeated,
+ type tag_regs_array is array(tag_number_t) of tag_register;
+ signal tag_regs : tag_regs_array;
- gpr_write_valid_in => gpr_write_valid,
- gpr_write_in => gpr_write_in,
- bypass_avail => gpr_bypassable,
- gpr_read_valid_in => gpr_b_read_valid_in,
- gpr_read_in => gpr_b_read_in,
+ signal instr_tag : instr_tag_t;
- ugpr_write_valid => update_gpr_write_valid,
- ugpr_write_reg => update_gpr_write_reg,
+ signal gpr_tag_a : instr_tag_t;
+ signal gpr_tag_b : instr_tag_t;
+ signal gpr_tag_c : instr_tag_t;
+ signal gpr_tag_stall : std_ulogic;
- stall_out => stall_b_out,
- use_bypass => gpr_bypass_b
- );
+ signal curr_tag : tag_number_t;
+ signal next_tag : tag_number_t;
- gpr_hazard2: entity work.gpr_hazard
- generic map (
- PIPELINE_DEPTH => PIPELINE_DEPTH
- )
- port map (
- clk => clk,
- busy_in => busy_in,
- deferred => deferred,
- complete_in => complete_in,
- flush_in => flush_in,
- issuing => valid_out,
- repeated => repeated,
-
- gpr_write_valid_in => gpr_write_valid,
- gpr_write_in => gpr_write_in,
- bypass_avail => gpr_bypassable,
- gpr_read_valid_in => gpr_c_read_valid_in,
- gpr_read_in => gpr_c_read_in,
-
- ugpr_write_valid => update_gpr_write_valid,
- ugpr_write_reg => update_gpr_write_reg,
-
- stall_out => stall_c_out,
- use_bypass => gpr_bypass_c
- );
+ function tag_match(tag1 : instr_tag_t; tag2 : instr_tag_t) return boolean is
+ begin
+ return tag1.valid = '1' and tag2.valid = '1' and tag1.tag = tag2.tag;
+ end;
+begin
cr_hazard0: entity work.cr_hazard
generic map (
PIPELINE_DEPTH => PIPELINE_DEPTH
clk => clk,
busy_in => busy_in,
deferred => deferred,
- complete_in => complete_in,
+ complete_in => complete_in.valid,
flush_in => flush_in,
issuing => valid_out,
use_bypass => cr_bypass
);
+ gpr_bypass_a <= '0';
+ gpr_bypass_b <= '0';
+ gpr_bypass_c <= '0';
+
control0: process(clk)
begin
if rising_edge(clk) then
assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1)
report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure;
r_int <= rin_int;
+ for i in tag_number_t loop
+ if rst = '1' or flush_in = '1' then
+ tag_regs(i).wr_gpr <= '0';
+ else
+ if complete_in.valid = '1' and i = complete_in.tag then
+ tag_regs(i).wr_gpr <= '0';
+ report "tag " & integer'image(i) & " not valid";
+ end if;
+ if gpr_write_valid = '1' and tag_regs(i).reg = gpr_write_in then
+ tag_regs(i).recent <= '0';
+ if tag_regs(i).recent = '1' and tag_regs(i).wr_gpr = '1' then
+ report "tag " & integer'image(i) & " not recent";
+ end if;
+ end if;
+ if instr_tag.valid = '1' and i = instr_tag.tag then
+ tag_regs(i).wr_gpr <= gpr_write_valid;
+ tag_regs(i).reg <= gpr_write_in;
+ tag_regs(i).recent <= gpr_write_valid;
+ if gpr_write_valid = '1' then
+ report "tag " & integer'image(i) & " valid for gpr " & to_hstring(gpr_write_in);
+ end if;
+ end if;
+ end if;
+ end loop;
+ if rst = '1' then
+ curr_tag <= 0;
+ else
+ curr_tag <= next_tag;
+ end if;
end if;
end process;
+ control_hazards : process(all)
+ variable gpr_stall : std_ulogic;
+ variable tag_a : instr_tag_t;
+ variable tag_b : instr_tag_t;
+ variable tag_c : instr_tag_t;
+ variable tag_s : instr_tag_t;
+ variable tag_t : instr_tag_t;
+ variable incr_tag : tag_number_t;
+ begin
+ tag_a := instr_tag_init;
+ for i in tag_number_t loop
+ if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
+ tag_a.valid := gpr_a_read_valid_in;
+ tag_a.tag := i;
+ end if;
+ end loop;
+ if tag_match(tag_a, complete_in) then
+ tag_a.valid := '0';
+ end if;
+ tag_b := instr_tag_init;
+ for i in tag_number_t loop
+ if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then
+ tag_b.valid := gpr_b_read_valid_in;
+ tag_b.tag := i;
+ end if;
+ end loop;
+ if tag_match(tag_b, complete_in) then
+ tag_b.valid := '0';
+ end if;
+ tag_c := instr_tag_init;
+ for i in tag_number_t loop
+ if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
+ tag_c.valid := gpr_c_read_valid_in;
+ tag_c.tag := i;
+ end if;
+ end loop;
+ if tag_match(tag_c, complete_in) then
+ tag_c.valid := '0';
+ end if;
+ gpr_tag_a <= tag_a;
+ gpr_tag_b <= tag_b;
+ gpr_tag_c <= tag_c;
+ gpr_tag_stall <= tag_a.valid or tag_b.valid or tag_c.valid;
+
+ incr_tag := curr_tag;
+ instr_tag.tag <= curr_tag;
+ instr_tag.valid <= valid_out and not deferred;
+ if instr_tag.valid = '1' then
+ incr_tag := (curr_tag + 1) mod TAG_COUNT;
+ end if;
+ next_tag <= incr_tag;
+ instr_tag_out <= instr_tag;
+ end process;
+
control1 : process(all)
variable v_int : reg_internal_type;
variable valid_tmp : std_ulogic;
if flush_in = '1' then
-- expect to see complete_in next cycle
v_int.outstanding := 1;
- elsif complete_in = '1' then
+ elsif complete_in.valid = '1' then
v_int.outstanding := r_int.outstanding - 1;
end if;
v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
end if;
else
- -- let it go out if there are no GPR hazards
- stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
+ -- let it go out if there are no GPR or CR hazards
+ stall_tmp := gpr_tag_stall or cr_stall_out;
end if;
end if;
v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
end if;
else
- -- let it go out if there are no GPR hazards
- stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
+ -- let it go out if there are no GPR or CR hazards
+ stall_tmp := gpr_tag_stall or cr_stall_out;
end if;
end if;
else
valid_tmp := '0';
end if;
- if valid_tmp = '1' then
- if deferred = '0' then
- v_int.outstanding := v_int.outstanding + 1;
- end if;
- gpr_write_valid <= gpr_write_valid_in;
- cr_write_valid <= cr_write_in;
- else
- gpr_write_valid <= '0';
- cr_write_valid <= '0';
+ gpr_write_valid <= gpr_write_valid_in and valid_tmp;
+ cr_write_valid <= cr_write_in and valid_tmp;
+
+ if valid_tmp = '1' and deferred = '0' then
+ v_int.outstanding := v_int.outstanding + 1;
end if;
-- update outputs
signal decode1_flush: std_ulogic;
signal fetch1_flush: std_ulogic;
- signal complete: std_ulogic;
+ signal complete: instr_tag_t;
signal terminate: std_ulogic;
signal core_rst: std_ulogic;
signal icache_inv: std_ulogic;
clk : in std_ulogic;
rst : in std_ulogic;
- complete_in : in std_ulogic;
+ complete_in : in instr_tag_t;
busy_in : in std_ulogic;
stall_out : out std_ulogic;
signal cr_bypass : std_ulogic;
signal cr_bypass_avail : std_ulogic;
+ signal instr_tag : instr_tag_t;
+
begin
control_0: entity work.control
generic map (
gpr_write_in => gpr_write,
gpr_bypassable => gpr_bypassable,
- update_gpr_write_valid => '0',
- update_gpr_write_reg => 7x"00",
-
gpr_a_read_valid_in => gpr_a_read_valid,
gpr_a_read_in => gpr_a_read,
gpr_bypass_a => gpr_a_bypass,
gpr_bypass_b => gpr_b_bypass,
- gpr_bypass_c => gpr_c_bypass
+ gpr_bypass_c => gpr_c_bypass,
+
+ instr_tag_out => instr_tag
);
deferred <= r.e.valid and busy_in;
v.e.nia := d_in.nia;
v.e.unit := d_in.decode.unit;
v.e.fac := d_in.decode.facility;
+ v.e.instr_tag := instr_tag;
v.e.read_reg1 := decoded_reg_a.reg;
v.e.read_data1 := decoded_reg_a.data;
v.e.bypass_data1 := gpr_a_bypass;
ctrl <= ctrl_tmp;
if valid_in = '1' then
report "execute " & to_hstring(e_in.nia) & " op=" & insn_type_t'image(e_in.insn_type) &
- " wr=" & to_hstring(rin.e.write_reg);
+ " wr=" & to_hstring(rin.e.write_reg) & " we=" & std_ulogic'image(rin.e.write_enable) &
+ " tag=" & integer'image(rin.e.instr_tag.tag) & std_ulogic'image(rin.e.instr_tag.valid);
end if;
end if;
end if;
end if;
v.e.mode_32bit := not ctrl.msr(MSR_SF);
+ v.e.instr_tag := current.instr_tag;
do_trace := valid_in and ctrl.msr(MSR_SE);
if valid_in = '1' then
end if;
if valid_in = '1' and exception = '0' and illegal = '0' and e_in.unit = ALU then
- report "execute nia " & to_hstring(e_in.nia);
-
v.cur_instr := e_in;
v.next_lr := next_nia;
v.e.valid := '1';
when OP_ISEL =>
when OP_CROP =>
cr_op := insn_cr(e_in.insn);
- report "CR OP " & to_hstring(cr_op);
if cr_op(0) = '0' then -- MCRF
bf := insn_bf(e_in.insn);
bfa := insn_bfa(e_in.insn);
-- 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;
lv.data := c_in;
fv.op := e_in.insn_type;
fv.nia := e_in.nia;
fv.insn := e_in.insn;
+ fv.itag := e_in.instr_tag;
fv.single := e_in.is_32bit;
fv.fe_mode := ctrl.msr(MSR_FE0) & ctrl.msr(MSR_FE1);
fv.fra := a_in;
do_intr : std_ulogic;
op : insn_type_t;
insn : std_ulogic_vector(31 downto 0);
+ instr_tag : instr_tag_t;
dest_fpr : gspr_index_t;
fe_mode : std_ulogic;
rc : std_ulogic;
e_out.interrupt <= r.do_intr;
w_out.valid <= r.instr_done and not r.do_intr;
+ w_out.instr_tag <= r.instr_tag;
w_out.write_enable <= r.writing_back;
w_out.write_reg <= r.dest_fpr;
w_out.write_data <= fp_result;
if e_in.valid = '1' then
v.insn := e_in.insn;
v.op := e_in.op;
+ v.instr_tag := e_in.itag;
v.fe_mode := or (e_in.fe_mode);
v.dest_fpr := e_in.frt;
v.single_prec := e_in.single;
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.numeric_std.all;
-
-library work;
-use work.common.all;
-
-entity gpr_hazard is
- generic (
- PIPELINE_DEPTH : natural := 1
- );
- port(
- clk : in std_ulogic;
- busy_in : in std_ulogic;
- deferred : in std_ulogic;
- complete_in : in std_ulogic;
- flush_in : in std_ulogic;
- issuing : in std_ulogic;
- repeated : in std_ulogic;
-
- gpr_write_valid_in : in std_ulogic;
- gpr_write_in : in gspr_index_t;
- bypass_avail : in std_ulogic;
- gpr_read_valid_in : in std_ulogic;
- gpr_read_in : in gspr_index_t;
-
- ugpr_write_valid : in std_ulogic;
- ugpr_write_reg : in gspr_index_t;
-
- stall_out : out std_ulogic;
- use_bypass : out std_ulogic
- );
-end entity gpr_hazard;
-architecture behaviour of gpr_hazard is
- type pipeline_entry_type is record
- valid : std_ulogic;
- bypass : std_ulogic;
- gpr : gspr_index_t;
- ugpr_valid : std_ulogic;
- ugpr : gspr_index_t;
- end record;
- constant pipeline_entry_init : pipeline_entry_type := (valid => '0', bypass => '0', gpr => (others => '0'),
- ugpr_valid => '0', ugpr => (others => '0'));
-
- type pipeline_t is array(0 to PIPELINE_DEPTH) of pipeline_entry_type;
- constant pipeline_t_init : pipeline_t := (others => pipeline_entry_init);
-
- signal r, rin : pipeline_t := pipeline_t_init;
-begin
- gpr_hazard0: process(clk)
- begin
- if rising_edge(clk) then
- r <= rin;
- end if;
- end process;
-
- gpr_hazard1: process(all)
- variable v : pipeline_t;
- begin
- v := r;
-
- if complete_in = '1' then
- v(PIPELINE_DEPTH).valid := '0';
- v(PIPELINE_DEPTH).ugpr_valid := '0';
- end if;
-
- stall_out <= '0';
- use_bypass <= '0';
- if repeated = '0' and gpr_read_valid_in = '1' then
- loop_0: for i in 0 to PIPELINE_DEPTH loop
- -- The second half of a split instruction never has GPR
- -- dependencies on the first half's output GPR,
- -- so ignore matches when i = 0 for the second half.
- if v(i).valid = '1' and r(i).gpr = gpr_read_in and
- not (i = 0 and repeated = '1') then
- if r(i).bypass = '1' then
- use_bypass <= '1';
- else
- stall_out <= '1';
- end if;
- end if;
- if v(i).ugpr_valid = '1' and r(i).ugpr = gpr_read_in then
- stall_out <= '1';
- end if;
- end loop;
- end if;
-
- -- XXX assumes PIPELINE_DEPTH = 1
- if busy_in = '0' then
- v(1) := v(0);
- v(0).valid := '0';
- v(0).ugpr_valid := '0';
- end if;
- if deferred = '0' and issuing = '1' then
- v(0).valid := gpr_write_valid_in;
- v(0).bypass := bypass_avail;
- v(0).gpr := gpr_write_in;
- v(0).ugpr_valid := ugpr_write_valid;
- v(0).ugpr := ugpr_write_reg;
- end if;
- if flush_in = '1' then
- v(0).valid := '0';
- v(0).ugpr_valid := '0';
- v(1).valid := '0';
- v(1).ugpr_valid := '0';
- end if;
-
- -- update registers
- rin <= v;
-
- end process;
-end;
addr : std_ulogic_vector(63 downto 0);
store_data : std_ulogic_vector(63 downto 0);
load_data : std_ulogic_vector(63 downto 0);
+ instr_tag : instr_tag_t;
write_reg : gspr_index_t;
length : std_ulogic_vector(3 downto 0);
byte_reverse : std_ulogic;
v.align_intr := '0';
v.dwords_done := '0';
v.last_dword := '1';
+ v.instr_tag := l_in.instr_tag;
v.write_reg := l_in.write_reg;
v.length := l_in.length;
v.byte_reverse := l_in.byte_reverse;
-- Multiplex either cache data to the destination GPR or
-- the address for the rA update.
l_out.valid <= done;
+ l_out.instr_tag <= r.instr_tag;
l_out.write_reg <= r.write_reg;
case r.wr_sel is
when "00" =>
- sim_console.vhdl
- logical.vhdl
- countzero.vhdl
- - gpr_hazard.vhdl
- cr_hazard.vhdl
- control.vhdl
- execute1.vhdl
w_out : out WritebackToRegisterFileType;
c_out : out WritebackToCrFileType;
- complete_out : out std_ulogic
+ complete_out : out instr_tag_t
);
end entity writeback;
y(0) := fp_in.write_cr_enable;
assert (to_integer(unsigned(w)) + to_integer(unsigned(x)) +
to_integer(unsigned(y))) <= 1 severity failure;
+
+ assert not (e_in.valid = '1' and e_in.instr_tag.valid = '0') severity failure;
+ assert not (l_in.valid = '1' and l_in.instr_tag.valid = '0') severity failure;
+ assert not (fp_in.valid = '1' and fp_in.instr_tag.valid = '0') severity failure;
end if;
end process;
w_out <= WritebackToRegisterFileInit;
c_out <= WritebackToCrFileInit;
- complete_out <= '0';
- if e_in.valid = '1' or l_in.valid = '1' or fp_in.valid = '1' then
- complete_out <= '1';
+ complete_out <= instr_tag_init;
+ if e_in.valid = '1' then
+ complete_out <= e_in.instr_tag;
+ elsif l_in.valid = '1' then
+ complete_out <= l_in.instr_tag;
+ elsif fp_in.valid = '1' then
+ complete_out <= fp_in.instr_tag;
end if;
if e_in.exc_write_enable = '1' then