//
|
//
|
// COPYRIGHT 2000 by Bruce L. Jacob
|
// COPYRIGHT 2000 by Bruce L. Jacob
|
// (contact info: http://www.ece.umd.edu/~blj/)
|
// (contact info: http://www.ece.umd.edu/~blj/)
|
//
|
//
|
// You are welcome to use, modify, copy, and/or redistribute this implementation, provided:
|
// You are welcome to use, modify, copy, and/or redistribute this implementation, provided:
|
// 1. you share with the author (Bruce Jacob) any changes you make;
|
// 1. you share with the author (Bruce Jacob) any changes you make;
|
// 2. you properly credit the author (Bruce Jacob) if used within a larger work; and
|
// 2. you properly credit the author (Bruce Jacob) if used within a larger work; and
|
// 3. you do not modify, delete, or in any way obscure the implementation's copyright
|
// 3. you do not modify, delete, or in any way obscure the implementation's copyright
|
// notice or following comments (i.e. the first 3-4 dozen lines of this file).
|
// notice or following comments (i.e. the first 3-4 dozen lines of this file).
|
//
|
//
|
// RiSC-16
|
// RiSC-16
|
//
|
//
|
// This is an out-of-order implementation of the RiSC-16, a teaching instruction-set used by
|
// This is an out-of-order implementation of the RiSC-16, a teaching instruction-set used by
|
// the author at the University of Maryland, and which is a blatant (but sanctioned) rip-off
|
// the author at the University of Maryland, and which is a blatant (but sanctioned) rip-off
|
// of the Little Computer (LC-896) developed by Peter Chen at the University of Michigan.
|
// of the Little Computer (LC-896) developed by Peter Chen at the University of Michigan.
|
// The primary differences include the following:
|
// The primary differences include the following:
|
// 1. a move from 17-bit to 16-bit instructions; and
|
// 1. a move from 17-bit to 16-bit instructions; and
|
// 2. the replacement of the NOP and HALT opcodes by ADDI and LUI ... HALT and NOP are
|
// 2. the replacement of the NOP and HALT opcodes by ADDI and LUI ... HALT and NOP are
|
// now simply special instances of other instructions: NOP is a do-nothing ADD, and
|
// now simply special instances of other instructions: NOP is a do-nothing ADD, and
|
// HALT is a subset of JALR.
|
// HALT is a subset of JALR.
|
//
|
//
|
// RiSC stands for Ridiculously Simple Computer, which makes sense in the context in which
|
// RiSC stands for Ridiculously Simple Computer, which makes sense in the context in which
|
// the instruction-set is normally used -- to teach simple organization and architecture to
|
// the instruction-set is normally used -- to teach simple organization and architecture to
|
// undergraduates who do not yet know how computers work. This implementation was targetted
|
// undergraduates who do not yet know how computers work. This implementation was targetted
|
// towards more advanced undergraduates doing design & implementation and was intended to
|
// towards more advanced undergraduates doing design & implementation and was intended to
|
// demonstrate some high-performance concepts on a small scale -- an 8-entry reorder buffer,
|
// demonstrate some high-performance concepts on a small scale -- an 8-entry reorder buffer,
|
// eight opcodes, two ALUs, two-way issue, two-way commit, etc. However, the out-of-order
|
// eight opcodes, two ALUs, two-way issue, two-way commit, etc. However, the out-of-order
|
// core is much more complex than I anticipated, and I hope that its complexity does not
|
// core is much more complex than I anticipated, and I hope that its complexity does not
|
// obscure its underlying structure. We'll see how well it flies in class ...
|
// obscure its underlying structure. We'll see how well it flies in class ...
|
//
|
//
|
// CAVEAT FREELOADER: This Verilog implementation was developed and debugged in a (somewhat
|
// CAVEAT FREELOADER: This Verilog implementation was developed and debugged in a (somewhat
|
// frantic) 2-week period before the start of the Fall 2000 semester. Not surprisingly, it
|
// frantic) 2-week period before the start of the Fall 2000 semester. Not surprisingly, it
|
// still contains many bugs and some horrible, horrible logic. The logic is also written so
|
// still contains many bugs and some horrible, horrible logic. The logic is also written so
|
// as to be debuggable and/or explain its function, rather than to be efficient -- e.g. in
|
// as to be debuggable and/or explain its function, rather than to be efficient -- e.g. in
|
// several places, signals are over-constrained so that they are easy to read in the debug
|
// several places, signals are over-constrained so that they are easy to read in the debug
|
// output ... also, you will see statements like
|
// output ... also, you will see statements like
|
//
|
//
|
// if (xyz[`INSTRUCTION_OP] == `BEQ || xyz[`INSTRUCTION_OP] == `SW)
|
// if (xyz[`INSTRUCTION_OP] == `BEQ || xyz[`INSTRUCTION_OP] == `SW)
|
//
|
//
|
// instead of and/nand combinations of bits ... sorry; can't be helped. Use at your own risk.
|
// instead of and/nand combinations of bits ... sorry; can't be helped. Use at your own risk.
|
//
|
//
|
// DOCUMENTATION: Documents describing the RiSC-16 in all its forms (sequential, pipelined,
|
// DOCUMENTATION: Documents describing the RiSC-16 in all its forms (sequential, pipelined,
|
// as well as out-of-order) can be found on the author's website at the following URL:
|
// as well as out-of-order) can be found on the author's website at the following URL:
|
//
|
//
|
// http://www.ece.umd.edu/~blj/RiSC/
|
// http://www.ece.umd.edu/~blj/RiSC/
|
//
|
//
|
// If you do not find what you are looking for, please feel free to email me with suggestions
|
// If you do not find what you are looking for, please feel free to email me with suggestions
|
// for more/different/modified documents. Same goes for bug fixes.
|
// for more/different/modified documents. Same goes for bug fixes.
|
//
|
//
|
//
|
//
|
// KNOWN PROBLEMS (i.e., bugs I haven't got around to fixing yet)
|
// KNOWN PROBLEMS (i.e., bugs I haven't got around to fixing yet)
|
//
|
//
|
// - If the target of a backwards branch is a backwards branch, the fetchbuf steering logic
|
// - If the target of a backwards branch is a backwards branch, the fetchbuf steering logic
|
// will get confused. This can be fixed by having a separate did_branchback status register
|
// will get confused. This can be fixed by having a separate did_branchback status register
|
// for each of the fetch buffers.
|
// for each of the fetch buffers.
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford
|
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
// it under the terms of the GNU Lesser General Public License as published
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// This source file is distributed in the hope that it will be useful,
|
// This source file is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
//
|
//
|
// Thor Superscaler
|
// Thor Superscaler
|
//
|
//
|
// This work is starting with the RiSC-16 as noted in the copyright statement
|
// This work is starting with the RiSC-16 as noted in the copyright statement
|
// above. Hopefully it will be possible to run this processor in real hardware
|
// above. Hopefully it will be possible to run this processor in real hardware
|
// (FPGA) as opposed to just simulation. To the RiSC-16 are added:
|
// (FPGA) as opposed to just simulation. To the RiSC-16 are added:
|
//
|
//
|
// 64/32 bit datapath rather than 16 bit
|
// 64/32 bit datapath rather than 16 bit
|
// 64 general purpose registers
|
// 64 general purpose registers
|
// 16 code address registers
|
// 16 code address registers
|
// 16 predicate registers / predicated instruction execution
|
// 16 predicate registers / predicated instruction execution
|
// 8 segment registers
|
// 8 segment registers
|
// A branch history table, and a (2,2) correlating branch predictor added
|
// A branch history table, and a (2,2) correlating branch predictor added
|
// variable length instruction encodings (code density)
|
// variable length instruction encodings (code density)
|
// support for interrupts
|
// support for interrupts
|
// The instruction set is changed completely with many new instructions.
|
// The instruction set is changed completely with many new instructions.
|
// An instruction and data cache were added.
|
// An instruction and data cache were added.
|
// A WISHBONE bus interface was added,
|
// A WISHBONE bus interface was added,
|
//
|
//
|
// 53,950 (86,500 LC's)
|
// 53,950 (86,500 LC's)
|
// with segmentation
|
// with segmentation
|
// no bitfield, stack or FP ops
|
// no bitfield, stack or FP ops
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
`include "Thor_defines.v"
|
`include "Thor_defines.v"
|
|
|
module Thor(corenum, rst_i, clk_i, clk_o, km, nmi_i, irq_i, vec_i, bte_o, cti_o, bl_o, lock_o, resv_o, resv_i, cres_o,
|
module Thor(corenum, rst_i, clk_i, clk_o, km, nmi_i, irq_i, vec_i, bte_o, cti_o, bl_o, lock_o, resv_o, resv_i, cres_o,
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, adr_o, dat_i, dat_o);
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, adr_o, dat_i, dat_o);
|
parameter DBW = 32; // databus width
|
parameter DBW = 32; // databus width
|
parameter ABW = 32; // address bus width
|
parameter ABW = 32; // address bus width
|
parameter RSTCSEG = 52'h0;
|
parameter RSTCSEG = 52'h0;
|
parameter RSTPC = 64'hFFFFFFFFFFFFEFF0;
|
parameter RSTPC = 64'hFFFFFFFFFFFC0000;
|
parameter STARTUP_POWER = 16'hFFFF;
|
parameter STARTUP_POWER = 16'hFFFF;
|
parameter IMCD = 6'h3E;
|
parameter IMCD = 6'h30;
|
localparam AMSB = ABW-1;
|
localparam AMSB = ABW-1;
|
parameter QENTRIES = 8;
|
parameter QENTRIES = 8;
|
parameter ALU1BIG = 0;
|
parameter ALU1BIG = 0;
|
parameter RESET1 = 4'd0;
|
parameter RESET1 = 4'd0;
|
parameter RESET2 = 4'd1;
|
parameter RESET2 = 4'd1;
|
parameter IDLE = 4'd2;
|
parameter IDLE = 4'd2;
|
parameter ICACHE1 = 4'd3;
|
parameter ICACHE1 = 4'd3;
|
parameter DCACHE1 = 4'd4;
|
parameter DCACHE1 = 4'd4;
|
parameter IBUF1 = 4'd5;
|
parameter IBUF1 = 4'd5;
|
parameter IBUF2 = 4'd6;
|
parameter IBUF2 = 4'd6;
|
parameter IBUF3 = 4'd7;
|
parameter IBUF3 = 4'd7;
|
parameter IBUF4 = 4'd8;
|
parameter IBUF4 = 4'd8;
|
parameter IBUF5 = 4'd9;
|
parameter IBUF5 = 4'd9;
|
parameter NREGS = 127;
|
parameter NREGS = 127;
|
parameter PF = 4'd0;
|
parameter PF = 4'd0;
|
parameter PT = 4'd1;
|
parameter PT = 4'd1;
|
parameter PEQ = 4'd2;
|
parameter PEQ = 4'd2;
|
parameter PNE = 4'd3;
|
parameter PNE = 4'd3;
|
parameter PLE = 4'd4;
|
parameter PLE = 4'd4;
|
parameter PGT = 4'd5;
|
parameter PGT = 4'd5;
|
parameter PGE = 4'd6;
|
parameter PGE = 4'd6;
|
parameter PLT = 4'd7;
|
parameter PLT = 4'd7;
|
parameter PLEU = 4'd8;
|
parameter PLEU = 4'd8;
|
parameter PGTU = 4'd9;
|
parameter PGTU = 4'd9;
|
parameter PGEU = 4'd10;
|
parameter PGEU = 4'd10;
|
parameter PLTU = 4'd11;
|
parameter PLTU = 4'd11;
|
input [63:0] corenum;
|
input [63:0] corenum;
|
input rst_i;
|
input rst_i;
|
input clk_i;
|
input clk_i;
|
output clk_o;
|
output clk_o;
|
output km;
|
output km;
|
input nmi_i;
|
input nmi_i;
|
input irq_i;
|
input irq_i;
|
input [7:0] vec_i;
|
input [7:0] vec_i;
|
output reg [1:0] bte_o;
|
output reg [1:0] bte_o;
|
output reg [2:0] cti_o;
|
output reg [2:0] cti_o;
|
output reg [4:0] bl_o;
|
output reg [4:0] bl_o;
|
output reg lock_o;
|
output reg lock_o;
|
output reg resv_o;
|
output reg resv_o;
|
input resv_i;
|
input resv_i;
|
output reg cres_o;
|
output reg cres_o;
|
output reg cyc_o;
|
output reg cyc_o;
|
output reg stb_o;
|
output reg stb_o;
|
input ack_i;
|
input ack_i;
|
input err_i;
|
input err_i;
|
output reg we_o;
|
output reg we_o;
|
output reg [DBW/8-1:0] sel_o;
|
output reg [DBW/8-1:0] sel_o;
|
output reg [ABW-1:0] adr_o;
|
output reg [ABW-1:0] adr_o;
|
input [DBW-1:0] dat_i;
|
input [DBW-1:0] dat_i;
|
output reg [DBW-1:0] dat_o;
|
output reg [DBW-1:0] dat_o;
|
|
|
integer n,i;
|
integer n,i;
|
reg [DBW/8-1:0] rsel;
|
reg [DBW/8-1:0] rsel;
|
reg [3:0] cstate;
|
reg [3:0] cstate;
|
reg [ABW:0] pc; // program counter (virtual)
|
reg [ABW:0] pc; // program counter (virtual)
|
wire [ABW-1:0] ppc; // physical pc address
|
wire [ABW-1:0] ppc; // physical pc address
|
reg [ABW-1:0] interrupt_pc; // working register for interrupt pc
|
reg [ABW-1:0] interrupt_pc; // working register for interrupt pc
|
reg [DBW-1:0] vadr; // data virtual address
|
reg [DBW-1:0] vadr; // data virtual address
|
reg [3:0] panic; // indexes the message structure
|
reg [3:0] panic; // indexes the message structure
|
reg [128:0] message [0:15]; // indexed by panic
|
reg [128:0] message [0:15]; // indexed by panic
|
reg [DBW-1:0] cregs [0:15]; // code address registers
|
reg [DBW-1:0] cregs [0:15]; // code address registers
|
reg [ 3:0] pregs [0:15]; // predicate registers
|
reg [ 3:0] pregs [0:15]; // predicate registers
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
reg [DBW-1:12] sregs [0:7]; // segment registers
|
reg [DBW-1:12] sregs [0:7]; // segment registers
|
reg [DBW-1:12] sregs_lmt [0:7];
|
reg [DBW-1:12] sregs_lmt [0:7];
|
`endif
|
`endif
|
reg [2:0] rrmapno; // register rename map number
|
reg [2:0] rrmapno; // register rename map number
|
wire ITLBMiss;
|
wire ITLBMiss;
|
wire DTLBMiss;
|
wire DTLBMiss;
|
wire uncached;
|
wire uncached;
|
wire [DBW-1:0] cdat;
|
wire [DBW-1:0] cdat;
|
reg pwe;
|
reg pwe;
|
wire [DBW-1:0] pea;
|
wire [DBW-1:0] pea;
|
reg [DBW-1:0] tick;
|
reg [DBW-1:0] tick;
|
reg [DBW-1:0] lc; // loop counter
|
reg [DBW-1:0] lc; // loop counter
|
reg [DBW-1:0] rfoa0,rfoa1;
|
reg [DBW-1:0] rfoa0,rfoa1;
|
reg [DBW-1:0] rfob0,rfob1;
|
reg [DBW-1:0] rfob0,rfob1;
|
reg [DBW-1:0] rfoc0,rfoc1;
|
reg [DBW-1:0] rfoc0,rfoc1;
|
reg [DBW-1:0] rfot0,rfot1;
|
reg [DBW-1:0] rfot0,rfot1;
|
reg ic_invalidate,dc_invalidate;
|
reg ic_invalidate,dc_invalidate;
|
reg ic_invalidate_line,dc_invalidate_line;
|
reg ic_invalidate_line,dc_invalidate_line;
|
reg [ABW-1:0] ic_lineno,dc_lineno;
|
reg [ABW-1:0] ic_lineno,dc_lineno;
|
reg ierr,derr; // err_i during icache load
|
reg ierr,derr; // err_i during icache load
|
wire insnerr; // err_i during icache load
|
wire insnerr; // err_i during icache load
|
wire [127:0] insn;
|
wire [127:0] insn;
|
wire iuncached;
|
wire iuncached;
|
reg [NREGS:0] rf_v;
|
reg [NREGS:0] rf_v;
|
//reg [15:0] pf_v;
|
//reg [15:0] pf_v;
|
reg im,imb;
|
reg im,imb;
|
reg [5:0] imcd;
|
reg [5:0] imcd;
|
reg fxe;
|
reg fxe;
|
reg nmi1,nmi_edge;
|
reg nmi1,nmi_edge;
|
reg StatusHWI;
|
reg StatusHWI;
|
reg StatusDBG;
|
reg StatusDBG;
|
reg [7:0] StatusEXL;
|
reg [7:0] StatusEXL;
|
assign km = StatusHWI | |StatusEXL;
|
assign km = StatusHWI | |StatusEXL;
|
reg [7:0] GM; // register group mask
|
reg [7:0] GM; // register group mask
|
reg [7:0] GMB;
|
reg [7:0] GMB;
|
wire [63:0] sr = {32'd0,imb,7'b0,GMB,im,1'b0,km,fxe,4'b0,GM};
|
wire [63:0] sr = {32'd0,imb,7'b0,GMB,im,1'b0,km,fxe,4'b0,GM};
|
wire int_commit;
|
wire int_commit;
|
wire int_pending;
|
wire int_pending;
|
wire sys_commit;
|
wire sys_commit;
|
wire dbg_commit;
|
wire dbg_commit;
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
wire [DBW-1:0] spc = (pc[ABW]==1'b1) ? pc[ABW-1:0] :
|
wire [DBW-1:0] spc = (pc[ABW]==1'b1) ? pc[ABW-1:0] :
|
(pc[ABW-1:ABW-4]==4'hF) ? pc[ABW-1:0] : {sregs[3'd7],12'h000} + pc[ABW-1:0];
|
(pc[ABW-1:ABW-4]==4'hF) ? pc[ABW-1:0] : {sregs[3'd7],12'h000} + pc[ABW-1:0];
|
`else
|
`else
|
wire [DBW-1:0] spc = pc;
|
wire [DBW-1:0] spc = pc;
|
`endif
|
`endif
|
wire [DBW-1:0] ppcp16 = ppc + 64'd16;
|
wire [DBW-1:0] ppcp16 = ppc + 64'd16;
|
reg [DBW-1:0] string_pc;
|
reg [DBW-1:0] string_pc;
|
reg stmv_flag;
|
reg stmv_flag;
|
reg [7:0] asid;
|
reg [7:0] asid;
|
|
|
wire clk;
|
wire clk;
|
|
|
// Operand registers
|
// Operand registers
|
wire take_branch;
|
wire take_branch;
|
wire take_branch0;
|
wire take_branch0;
|
wire take_branch1;
|
wire take_branch1;
|
|
|
reg [3:0] rf_source [0:NREGS];
|
reg [3:0] rf_source [0:NREGS];
|
//reg [3:0] pf_source [15:0];
|
//reg [3:0] pf_source [15:0];
|
|
|
// instruction queue (ROB)
|
// instruction queue (ROB)
|
reg [7:0] iqentry_v; // entry valid? -- this should be the first bit
|
reg [7:0] iqentry_v; // entry valid? -- this should be the first bit
|
reg iqentry_out [0:7]; // instruction has been issued to an ALU ...
|
reg iqentry_out [0:7]; // instruction has been issued to an ALU ...
|
reg iqentry_done [0:7]; // instruction result valid
|
reg iqentry_done [0:7]; // instruction result valid
|
reg [7:0] iqentry_cmt; // commit result to machine state
|
reg [7:0] iqentry_cmt; // commit result to machine state
|
reg iqentry_bt [0:7]; // branch-taken (used only for branches)
|
reg iqentry_bt [0:7]; // branch-taken (used only for branches)
|
reg iqentry_br [0:7]; // branch instruction decode
|
reg iqentry_br [0:7]; // branch instruction decode
|
reg iqentry_agen [0:7]; // memory address is generated
|
reg iqentry_agen [0:7]; // memory address is generated
|
reg iqentry_mem [0:7]; // touches memory: 1 if LW/SW
|
reg iqentry_mem [0:7]; // touches memory: 1 if LW/SW
|
reg iqentry_ndx [0:7]; // TRUE if indexed memory op
|
reg iqentry_ndx [0:7]; // TRUE if indexed memory op
|
reg iqentry_cas [0:7];
|
reg iqentry_cas [0:7];
|
reg iqentry_pushpop [0:7];
|
reg iqentry_pushpop [0:7];
|
reg iqentry_pea [0:7];
|
reg iqentry_pea [0:7];
|
reg iqentry_cmpmv [0:7];
|
reg iqentry_cmpmv [0:7];
|
reg iqentry_lla [0:7]; // load linear address
|
reg iqentry_lla [0:7]; // load linear address
|
reg iqentry_tlb [0:7];
|
reg iqentry_tlb [0:7];
|
reg iqentry_jmp [0:7]; // changes control flow: 1 if BEQ/JALR
|
reg iqentry_jmp [0:7]; // changes control flow: 1 if BEQ/JALR
|
reg iqentry_jmpi [0:7];
|
reg iqentry_jmpi [0:7];
|
reg iqentry_sync [0:7]; // sync instruction
|
reg iqentry_sync [0:7]; // sync instruction
|
reg iqentry_memsb[0:7];
|
reg iqentry_memsb[0:7];
|
reg iqentry_memdb[0:7];
|
reg iqentry_memdb[0:7];
|
reg iqentry_fp [0:7]; // is an floating point operation
|
reg iqentry_fp [0:7]; // is an floating point operation
|
reg iqentry_rfw [0:7]; // writes to register file
|
reg iqentry_rfw [0:7]; // writes to register file
|
reg [DBW-1:0] iqentry_res [0:7]; // instruction result
|
reg [DBW-1:0] iqentry_res [0:7]; // instruction result
|
reg [3:0] iqentry_insnsz [0:7]; // the size of the instruction
|
reg [3:0] iqentry_insnsz [0:7]; // the size of the instruction
|
reg [3:0] iqentry_cond [0:7]; // predicating condition
|
reg [3:0] iqentry_cond [0:7]; // predicating condition
|
reg [3:0] iqentry_preg [0:7]; // predicate regno
|
reg [3:0] iqentry_preg [0:7]; // predicate regno
|
reg [3:0] iqentry_pred [0:7]; // predicate value
|
reg [3:0] iqentry_pred [0:7]; // predicate value
|
reg iqentry_p_v [0:7]; // predicate is valid
|
reg iqentry_p_v [0:7]; // predicate is valid
|
reg [3:0] iqentry_p_s [0:7]; // predicate source
|
reg [3:0] iqentry_p_s [0:7]; // predicate source
|
reg [7:0] iqentry_op [0:7]; // instruction opcode
|
reg [7:0] iqentry_op [0:7]; // instruction opcode
|
reg [5:0] iqentry_fn [0:7]; // instruction function
|
reg [5:0] iqentry_fn [0:7]; // instruction function
|
reg [2:0] iqentry_renmapno [0:7]; // register rename map number
|
reg [2:0] iqentry_renmapno [0:7]; // register rename map number
|
reg [6:0] iqentry_tgt [0:7]; // Rt field or ZERO -- this is the instruction's target (if any)
|
reg [6:0] iqentry_tgt [0:7]; // Rt field or ZERO -- this is the instruction's target (if any)
|
reg [DBW-1:0] iqentry_a0 [0:7]; // argument 0 (immediate)
|
reg [DBW-1:0] iqentry_a0 [0:7]; // argument 0 (immediate)
|
reg [DBW-1:0] iqentry_a1 [0:7]; // argument 1
|
reg [DBW-1:0] iqentry_a1 [0:7]; // argument 1
|
reg [6:0] iqentry_r1 [0:7];
|
reg [6:0] iqentry_r1 [0:7];
|
reg iqentry_a1_v [0:7]; // arg1 valid
|
reg iqentry_a1_v [0:7]; // arg1 valid
|
reg [3:0] iqentry_a1_s [0:7]; // arg1 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [3:0] iqentry_a1_s [0:7]; // arg1 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [6:0] iqentry_r2 [0:7];
|
reg [6:0] iqentry_r2 [0:7];
|
reg [DBW-1:0] iqentry_a2 [0:7]; // argument 2
|
reg [DBW-1:0] iqentry_a2 [0:7]; // argument 2
|
reg iqentry_a2_v [0:7]; // arg2 valid
|
reg iqentry_a2_v [0:7]; // arg2 valid
|
reg [3:0] iqentry_a2_s [0:7]; // arg2 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [3:0] iqentry_a2_s [0:7]; // arg2 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [6:0] iqentry_r3 [0:7];
|
reg [6:0] iqentry_r3 [0:7];
|
reg [DBW-1:0] iqentry_a3 [0:7]; // argument 3
|
reg [DBW-1:0] iqentry_a3 [0:7]; // argument 3
|
reg iqentry_a3_v [0:7]; // arg3 valid
|
reg iqentry_a3_v [0:7]; // arg3 valid
|
reg [3:0] iqentry_a3_s [0:7]; // arg3 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [3:0] iqentry_a3_s [0:7]; // arg3 source (iq entry # with top bit representing ALU/DRAM bus)
|
reg [6:0] iqentry_rt [0:7];
|
reg [6:0] iqentry_rt [0:7];
|
reg [DBW-1:0] iqentry_T [0:7];
|
reg [DBW-1:0] iqentry_T [0:7];
|
reg iqentry_T_v [0:7];
|
reg iqentry_T_v [0:7];
|
reg [3:0] iqentry_T_s [0:7];
|
reg [3:0] iqentry_T_s [0:7];
|
reg [DBW-1:0] iqentry_pc [0:7]; // program counter for this instruction
|
reg [DBW-1:0] iqentry_pc [0:7]; // program counter for this instruction
|
|
|
reg [7:0] iqentry_source;
|
reg [7:0] iqentry_source;
|
wire iqentry_imm [0:7];
|
wire iqentry_imm [0:7];
|
wire iqentry_memready [0:7];
|
wire iqentry_memready [0:7];
|
wire iqentry_memopsvalid [0:7];
|
wire iqentry_memopsvalid [0:7];
|
reg qstomp;
|
reg qstomp;
|
|
|
wire stomp_all;
|
wire stomp_all;
|
reg [7:0] iqentry_fpissue;
|
reg [7:0] iqentry_fpissue;
|
reg [7:0] iqentry_memissue;
|
reg [7:0] iqentry_memissue;
|
wire iqentry_memissue_head0;
|
wire iqentry_memissue_head0;
|
wire iqentry_memissue_head1;
|
wire iqentry_memissue_head1;
|
wire iqentry_memissue_head2;
|
wire iqentry_memissue_head2;
|
wire iqentry_memissue_head3;
|
wire iqentry_memissue_head3;
|
wire iqentry_memissue_head4;
|
wire iqentry_memissue_head4;
|
wire iqentry_memissue_head5;
|
wire iqentry_memissue_head5;
|
wire iqentry_memissue_head6;
|
wire iqentry_memissue_head6;
|
wire iqentry_memissue_head7;
|
wire iqentry_memissue_head7;
|
wire [7:0] iqentry_stomp;
|
wire [7:0] iqentry_stomp;
|
reg [7:0] iqentry_issue;
|
reg [7:0] iqentry_issue;
|
wire [1:0] iqentry_0_islot;
|
wire [1:0] iqentry_0_islot;
|
wire [1:0] iqentry_1_islot;
|
wire [1:0] iqentry_1_islot;
|
wire [1:0] iqentry_2_islot;
|
wire [1:0] iqentry_2_islot;
|
wire [1:0] iqentry_3_islot;
|
wire [1:0] iqentry_3_islot;
|
wire [1:0] iqentry_4_islot;
|
wire [1:0] iqentry_4_islot;
|
wire [1:0] iqentry_5_islot;
|
wire [1:0] iqentry_5_islot;
|
wire [1:0] iqentry_6_islot;
|
wire [1:0] iqentry_6_islot;
|
wire [1:0] iqentry_7_islot;
|
wire [1:0] iqentry_7_islot;
|
reg [1:0] iqentry_islot[0:7];
|
reg [1:0] iqentry_islot[0:7];
|
reg [1:0] iqentry_fpislot[0:7];
|
reg [1:0] iqentry_fpislot[0:7];
|
|
|
reg queued1,queued2;
|
reg queued1,queued2;
|
reg queued3; // for three-way config
|
reg queued3; // for three-way config
|
reg allowq;
|
reg allowq;
|
|
|
wire [NREGS:1] livetarget;
|
wire [NREGS:1] livetarget;
|
wire [NREGS:1] iqentry_0_livetarget;
|
wire [NREGS:1] iqentry_0_livetarget;
|
wire [NREGS:1] iqentry_1_livetarget;
|
wire [NREGS:1] iqentry_1_livetarget;
|
wire [NREGS:1] iqentry_2_livetarget;
|
wire [NREGS:1] iqentry_2_livetarget;
|
wire [NREGS:1] iqentry_3_livetarget;
|
wire [NREGS:1] iqentry_3_livetarget;
|
wire [NREGS:1] iqentry_4_livetarget;
|
wire [NREGS:1] iqentry_4_livetarget;
|
wire [NREGS:1] iqentry_5_livetarget;
|
wire [NREGS:1] iqentry_5_livetarget;
|
wire [NREGS:1] iqentry_6_livetarget;
|
wire [NREGS:1] iqentry_6_livetarget;
|
wire [NREGS:1] iqentry_7_livetarget;
|
wire [NREGS:1] iqentry_7_livetarget;
|
wire [NREGS:1] iqentry_0_latestID;
|
wire [NREGS:1] iqentry_0_latestID;
|
wire [NREGS:1] iqentry_1_latestID;
|
wire [NREGS:1] iqentry_1_latestID;
|
wire [NREGS:1] iqentry_2_latestID;
|
wire [NREGS:1] iqentry_2_latestID;
|
wire [NREGS:1] iqentry_3_latestID;
|
wire [NREGS:1] iqentry_3_latestID;
|
wire [NREGS:1] iqentry_4_latestID;
|
wire [NREGS:1] iqentry_4_latestID;
|
wire [NREGS:1] iqentry_5_latestID;
|
wire [NREGS:1] iqentry_5_latestID;
|
wire [NREGS:1] iqentry_6_latestID;
|
wire [NREGS:1] iqentry_6_latestID;
|
wire [NREGS:1] iqentry_7_latestID;
|
wire [NREGS:1] iqentry_7_latestID;
|
wire [NREGS:1] iqentry_0_cumulative;
|
wire [NREGS:1] iqentry_0_cumulative;
|
wire [NREGS:1] iqentry_1_cumulative;
|
wire [NREGS:1] iqentry_1_cumulative;
|
wire [NREGS:1] iqentry_2_cumulative;
|
wire [NREGS:1] iqentry_2_cumulative;
|
wire [NREGS:1] iqentry_3_cumulative;
|
wire [NREGS:1] iqentry_3_cumulative;
|
wire [NREGS:1] iqentry_4_cumulative;
|
wire [NREGS:1] iqentry_4_cumulative;
|
wire [NREGS:1] iqentry_5_cumulative;
|
wire [NREGS:1] iqentry_5_cumulative;
|
wire [NREGS:1] iqentry_6_cumulative;
|
wire [NREGS:1] iqentry_6_cumulative;
|
wire [NREGS:1] iqentry_7_cumulative;
|
wire [NREGS:1] iqentry_7_cumulative;
|
|
|
|
|
reg [2:0] tail0;
|
reg [2:0] tail0;
|
reg [2:0] tail1;
|
reg [2:0] tail1;
|
reg [2:0] tail2; // used only for three-way config
|
reg [2:0] tail2; // used only for three-way config
|
reg [2:0] head0;
|
reg [2:0] head0;
|
reg [2:0] head1;
|
reg [2:0] head1;
|
reg [2:0] head2; // used only to determine memory-access ordering
|
reg [2:0] head2; // used only to determine memory-access ordering
|
reg [2:0] head3; // used only to determine memory-access ordering
|
reg [2:0] head3; // used only to determine memory-access ordering
|
reg [2:0] head4; // used only to determine memory-access ordering
|
reg [2:0] head4; // used only to determine memory-access ordering
|
reg [2:0] head5; // used only to determine memory-access ordering
|
reg [2:0] head5; // used only to determine memory-access ordering
|
reg [2:0] head6; // used only to determine memory-access ordering
|
reg [2:0] head6; // used only to determine memory-access ordering
|
reg [2:0] head7; // used only to determine memory-access ordering
|
reg [2:0] head7; // used only to determine memory-access ordering
|
reg [2:0] headinc;
|
reg [2:0] headinc;
|
|
|
wire [2:0] missid;
|
wire [2:0] missid;
|
reg fetchbuf; // determines which pair to read from & write to
|
reg fetchbuf; // determines which pair to read from & write to
|
|
|
reg [63:0] fetchbuf0_instr;
|
reg [63:0] fetchbuf0_instr;
|
reg [DBW-1:0] fetchbuf0_pc;
|
reg [DBW-1:0] fetchbuf0_pc;
|
reg fetchbuf0_v;
|
reg fetchbuf0_v;
|
wire fetchbuf0_mem;
|
wire fetchbuf0_mem;
|
wire fetchbuf0_jmp;
|
wire fetchbuf0_jmp;
|
wire fetchbuf0_fp;
|
wire fetchbuf0_fp;
|
wire fetchbuf0_rfw;
|
wire fetchbuf0_rfw;
|
wire fetchbuf0_pfw;
|
wire fetchbuf0_pfw;
|
reg [63:0] fetchbuf1_instr;
|
reg [63:0] fetchbuf1_instr;
|
reg [DBW-1:0] fetchbuf1_pc;
|
reg [DBW-1:0] fetchbuf1_pc;
|
reg fetchbuf1_v;
|
reg fetchbuf1_v;
|
wire fetchbuf1_mem;
|
wire fetchbuf1_mem;
|
wire fetchbuf1_jmp;
|
wire fetchbuf1_jmp;
|
wire fetchbuf1_fp;
|
wire fetchbuf1_fp;
|
wire fetchbuf1_rfw;
|
wire fetchbuf1_rfw;
|
wire fetchbuf1_pfw;
|
wire fetchbuf1_pfw;
|
wire fetchbuf1_bfw;
|
wire fetchbuf1_bfw;
|
reg [63:0] fetchbuf2_instr;
|
reg [63:0] fetchbuf2_instr;
|
reg [DBW-1:0] fetchbuf2_pc;
|
reg [DBW-1:0] fetchbuf2_pc;
|
reg fetchbuf2_v;
|
reg fetchbuf2_v;
|
wire fetchbuf2_mem;
|
wire fetchbuf2_mem;
|
wire fetchbuf2_jmp;
|
wire fetchbuf2_jmp;
|
wire fetchbuf2_fp;
|
wire fetchbuf2_fp;
|
wire fetchbuf2_rfw;
|
wire fetchbuf2_rfw;
|
wire fetchbuf2_pfw;
|
wire fetchbuf2_pfw;
|
wire fetchbuf2_bfw;
|
wire fetchbuf2_bfw;
|
|
|
reg [63:0] fetchbufA_instr;
|
reg [63:0] fetchbufA_instr;
|
reg [DBW-1:0] fetchbufA_pc;
|
reg [DBW-1:0] fetchbufA_pc;
|
reg fetchbufA_v;
|
reg fetchbufA_v;
|
reg [63:0] fetchbufB_instr;
|
reg [63:0] fetchbufB_instr;
|
reg [DBW-1:0] fetchbufB_pc;
|
reg [DBW-1:0] fetchbufB_pc;
|
reg fetchbufB_v;
|
reg fetchbufB_v;
|
reg [63:0] fetchbufC_instr;
|
reg [63:0] fetchbufC_instr;
|
reg [DBW-1:0] fetchbufC_pc;
|
reg [DBW-1:0] fetchbufC_pc;
|
reg fetchbufC_v;
|
reg fetchbufC_v;
|
reg [63:0] fetchbufD_instr;
|
reg [63:0] fetchbufD_instr;
|
reg [DBW-1:0] fetchbufD_pc;
|
reg [DBW-1:0] fetchbufD_pc;
|
reg fetchbufD_v;
|
reg fetchbufD_v;
|
|
|
reg did_branchback;
|
reg did_branchback;
|
reg did_branchback0;
|
reg did_branchback0;
|
reg did_branchback1;
|
reg did_branchback1;
|
|
|
reg alu0_ld;
|
reg alu0_ld;
|
reg alu0_available;
|
reg alu0_available;
|
reg alu0_dataready;
|
reg alu0_dataready;
|
reg [3:0] alu0_sourceid;
|
reg [3:0] alu0_sourceid;
|
reg [3:0] alu0_insnsz;
|
reg [3:0] alu0_insnsz;
|
reg [7:0] alu0_op;
|
reg [7:0] alu0_op;
|
reg [5:0] alu0_fn;
|
reg [5:0] alu0_fn;
|
reg [3:0] alu0_cond;
|
reg [3:0] alu0_cond;
|
reg alu0_bt;
|
reg alu0_bt;
|
reg alu0_cmt;
|
reg alu0_cmt;
|
reg [DBW-1:0] alu0_argA;
|
reg [DBW-1:0] alu0_argA;
|
reg [DBW-1:0] alu0_argB;
|
reg [DBW-1:0] alu0_argB;
|
reg [DBW-1:0] alu0_argC;
|
reg [DBW-1:0] alu0_argC;
|
reg [DBW-1:0] alu0_argT;
|
reg [DBW-1:0] alu0_argT;
|
reg [DBW-1:0] alu0_argI;
|
reg [DBW-1:0] alu0_argI;
|
reg [3:0] alu0_pred;
|
reg [3:0] alu0_pred;
|
reg [DBW-1:0] alu0_pc;
|
reg [DBW-1:0] alu0_pc;
|
reg [DBW-1:0] alu0_bus;
|
reg [DBW-1:0] alu0_bus;
|
reg [3:0] alu0_id;
|
reg [3:0] alu0_id;
|
wire [3:0] alu0_exc;
|
wire [3:0] alu0_exc;
|
reg alu0_v;
|
reg alu0_v;
|
wire alu0_branchmiss;
|
wire alu0_branchmiss;
|
reg [ABW:0] alu0_misspc;
|
reg [ABW:0] alu0_misspc;
|
|
|
reg alu1_ld;
|
reg alu1_ld;
|
reg alu1_available;
|
reg alu1_available;
|
reg alu1_dataready;
|
reg alu1_dataready;
|
reg [3:0] alu1_sourceid;
|
reg [3:0] alu1_sourceid;
|
reg [3:0] alu1_insnsz;
|
reg [3:0] alu1_insnsz;
|
reg [7:0] alu1_op;
|
reg [7:0] alu1_op;
|
reg [5:0] alu1_fn;
|
reg [5:0] alu1_fn;
|
reg [3:0] alu1_cond;
|
reg [3:0] alu1_cond;
|
reg alu1_bt;
|
reg alu1_bt;
|
reg alu1_cmt;
|
reg alu1_cmt;
|
reg [DBW-1:0] alu1_argA;
|
reg [DBW-1:0] alu1_argA;
|
reg [DBW-1:0] alu1_argB;
|
reg [DBW-1:0] alu1_argB;
|
reg [DBW-1:0] alu1_argC;
|
reg [DBW-1:0] alu1_argC;
|
reg [DBW-1:0] alu1_argT;
|
reg [DBW-1:0] alu1_argT;
|
reg [DBW-1:0] alu1_argI;
|
reg [DBW-1:0] alu1_argI;
|
reg [3:0] alu1_pred;
|
reg [3:0] alu1_pred;
|
reg [DBW-1:0] alu1_pc;
|
reg [DBW-1:0] alu1_pc;
|
reg [DBW-1:0] alu1_bus;
|
reg [DBW-1:0] alu1_bus;
|
reg [3:0] alu1_id;
|
reg [3:0] alu1_id;
|
wire [3:0] alu1_exc;
|
wire [3:0] alu1_exc;
|
reg alu1_v;
|
reg alu1_v;
|
wire alu1_branchmiss;
|
wire alu1_branchmiss;
|
reg [ABW:0] alu1_misspc;
|
reg [ABW:0] alu1_misspc;
|
|
|
wire jmpi_miss;
|
wire jmpi_miss;
|
reg [ABW-1:0] jmpi_misspc;
|
reg [ABW-1:0] jmpi_misspc;
|
wire mem_stringmissx;
|
wire mem_stringmissx;
|
reg mem_stringmiss;
|
reg mem_stringmiss;
|
wire branchmiss;
|
wire branchmiss;
|
wire [ABW:0] misspc;
|
wire [ABW:0] misspc;
|
|
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
reg fp0_ld;
|
reg fp0_ld;
|
reg fp0_available;
|
reg fp0_available;
|
reg fp0_dataready;
|
reg fp0_dataready;
|
reg [3:0] fp0_sourceid;
|
reg [3:0] fp0_sourceid;
|
reg [7:0] fp0_op;
|
reg [7:0] fp0_op;
|
reg [5:0] fp0_fn;
|
reg [5:0] fp0_fn;
|
reg [3:0] fp0_cond;
|
reg [3:0] fp0_cond;
|
wire fp0_cmt;
|
wire fp0_cmt;
|
reg fp0_done;
|
reg fp0_done;
|
reg [DBW-1:0] fp0_argA;
|
reg [DBW-1:0] fp0_argA;
|
reg [DBW-1:0] fp0_argB;
|
reg [DBW-1:0] fp0_argB;
|
reg [DBW-1:0] fp0_argC;
|
reg [DBW-1:0] fp0_argC;
|
reg [DBW-1:0] fp0_argI;
|
reg [DBW-1:0] fp0_argI;
|
reg [3:0] fp0_pred;
|
reg [3:0] fp0_pred;
|
reg [DBW-1:0] fp0_pc;
|
reg [DBW-1:0] fp0_pc;
|
wire [DBW-1:0] fp0_bus;
|
wire [DBW-1:0] fp0_bus;
|
wire [3:0] fp0_id;
|
wire [3:0] fp0_id;
|
wire [7:0] fp0_exc;
|
wire [7:0] fp0_exc;
|
wire fp0_v;
|
wire fp0_v;
|
`endif
|
`endif
|
|
|
wire dram_avail;
|
wire dram_avail;
|
reg [2:0] dram0; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] dram0; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] dram1; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] dram1; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] dram2; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] dram2; // state of the DRAM request (latency = 4; can have three in pipeline)
|
reg [2:0] tlb_state;
|
reg [2:0] tlb_state;
|
reg [3:0] tlb_id;
|
reg [3:0] tlb_id;
|
reg [3:0] tlb_op;
|
reg [3:0] tlb_op;
|
reg [3:0] tlb_regno;
|
reg [3:0] tlb_regno;
|
reg [8:0] tlb_tgt;
|
reg [8:0] tlb_tgt;
|
reg [DBW-1:0] tlb_data;
|
reg [DBW-1:0] tlb_data;
|
|
|
wire [DBW-1:0] tlb_dato;
|
wire [DBW-1:0] tlb_dato;
|
reg dram0_owns_bus;
|
reg dram0_owns_bus;
|
reg [DBW-1:0] dram0_data;
|
reg [DBW-1:0] dram0_data;
|
reg [DBW-1:0] dram0_datacmp;
|
reg [DBW-1:0] dram0_datacmp;
|
reg [DBW-1:0] dram0_addr;
|
reg [DBW-1:0] dram0_addr;
|
reg [DBW-1:0] dram0_seg; // value of segment register associated with memory operation
|
reg [DBW-1:0] dram0_seg; // value of segment register associated with memory operation
|
reg [ABW-1:12] dram0_lmt; // value of segment limit associated with memory operation
|
reg [ABW-1:12] dram0_lmt; // value of segment limit associated with memory operation
|
reg [7:0] dram0_op;
|
reg [7:0] dram0_op;
|
reg [5:0] dram0_fn;
|
reg [5:0] dram0_fn;
|
reg [8:0] dram0_tgt;
|
reg [8:0] dram0_tgt;
|
reg [3:0] dram0_id;
|
reg [3:0] dram0_id;
|
reg [3:0] dram0_exc;
|
reg [3:0] dram0_exc;
|
reg [ABW-1:0] dram0_misspc;
|
reg [ABW-1:0] dram0_misspc;
|
reg dram1_owns_bus;
|
reg dram1_owns_bus;
|
reg [DBW-1:0] dram1_data;
|
reg [DBW-1:0] dram1_data;
|
reg [DBW-1:0] dram1_datacmp;
|
reg [DBW-1:0] dram1_datacmp;
|
reg [DBW-1:0] dram1_addr;
|
reg [DBW-1:0] dram1_addr;
|
reg [7:0] dram1_op;
|
reg [7:0] dram1_op;
|
reg [5:0] dram1_fn;
|
reg [5:0] dram1_fn;
|
reg [6:0] dram1_tgt;
|
reg [6:0] dram1_tgt;
|
reg [3:0] dram1_id;
|
reg [3:0] dram1_id;
|
reg [3:0] dram1_exc;
|
reg [3:0] dram1_exc;
|
reg [DBW-1:0] dram2_data;
|
reg [DBW-1:0] dram2_data;
|
reg [DBW-1:0] dram2_datacmp;
|
reg [DBW-1:0] dram2_datacmp;
|
reg [DBW-1:0] dram2_addr;
|
reg [DBW-1:0] dram2_addr;
|
reg [7:0] dram2_op;
|
reg [7:0] dram2_op;
|
reg [5:0] dram2_fn;
|
reg [5:0] dram2_fn;
|
reg [6:0] dram2_tgt;
|
reg [6:0] dram2_tgt;
|
reg [3:0] dram2_id;
|
reg [3:0] dram2_id;
|
reg [3:0] dram2_exc;
|
reg [3:0] dram2_exc;
|
|
|
reg [DBW-1:0] dram_bus;
|
reg [DBW-1:0] dram_bus;
|
reg [6:0] dram_tgt;
|
reg [6:0] dram_tgt;
|
reg [3:0] dram_id;
|
reg [3:0] dram_id;
|
reg [3:0] dram_exc;
|
reg [3:0] dram_exc;
|
reg dram_v;
|
reg dram_v;
|
|
|
reg [DBW-1:0] index;
|
reg [DBW-1:0] index;
|
reg [DBW-1:0] src_addr,dst_addr;
|
reg [DBW-1:0] src_addr,dst_addr;
|
wire mem_issue;
|
wire mem_issue;
|
|
|
wire outstanding_stores;
|
wire outstanding_stores;
|
reg [DBW-1:0] I; // instruction count
|
reg [DBW-1:0] I; // instruction count
|
|
|
wire commit0_v;
|
wire commit0_v;
|
wire [3:0] commit0_id;
|
wire [3:0] commit0_id;
|
wire [6:0] commit0_tgt;
|
wire [6:0] commit0_tgt;
|
wire [DBW-1:0] commit0_bus;
|
wire [DBW-1:0] commit0_bus;
|
wire commit1_v;
|
wire commit1_v;
|
wire [3:0] commit1_id;
|
wire [3:0] commit1_id;
|
wire [6:0] commit1_tgt;
|
wire [6:0] commit1_tgt;
|
wire [DBW-1:0] commit1_bus;
|
wire [DBW-1:0] commit1_bus;
|
wire limit_cmt;
|
wire limit_cmt;
|
wire committing2;
|
wire committing2;
|
|
|
wire [63:0] alu0_divq;
|
wire [63:0] alu0_divq;
|
wire [63:0] alu0_rem;
|
wire [63:0] alu0_rem;
|
wire alu0_div_done;
|
wire alu0_div_done;
|
|
|
wire [63:0] alu1_divq;
|
wire [63:0] alu1_divq;
|
wire [63:0] alu1_rem;
|
wire [63:0] alu1_rem;
|
wire alu1_div_done;
|
wire alu1_div_done;
|
|
|
wire [127:0] alu0_prod;
|
wire [127:0] alu0_prod;
|
wire alu0_mult_done;
|
wire alu0_mult_done;
|
wire [127:0] alu1_prod;
|
wire [127:0] alu1_prod;
|
wire alu1_mult_done;
|
wire alu1_mult_done;
|
|
|
reg exception_set;
|
reg exception_set;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Debug
|
// Debug
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
wire [DBW-1:0] dbg_stat1x;
|
wire [DBW-1:0] dbg_stat1x;
|
reg [DBW-1:0] dbg_stat;
|
reg [DBW-1:0] dbg_stat;
|
reg [DBW-1:0] dbg_ctrl;
|
reg [DBW-1:0] dbg_ctrl;
|
reg [ABW-1:0] dbg_adr0;
|
reg [ABW-1:0] dbg_adr0;
|
reg [ABW-1:0] dbg_adr1;
|
reg [ABW-1:0] dbg_adr1;
|
reg [ABW-1:0] dbg_adr2;
|
reg [ABW-1:0] dbg_adr2;
|
reg [ABW-1:0] dbg_adr3;
|
reg [ABW-1:0] dbg_adr3;
|
reg dbg_imatchA0,dbg_imatchA1,dbg_imatchA2,dbg_imatchA3,dbg_imatchA;
|
reg dbg_imatchA0,dbg_imatchA1,dbg_imatchA2,dbg_imatchA3,dbg_imatchA;
|
reg dbg_imatchB0,dbg_imatchB1,dbg_imatchB2,dbg_imatchB3,dbg_imatchB;
|
reg dbg_imatchB0,dbg_imatchB1,dbg_imatchB2,dbg_imatchB3,dbg_imatchB;
|
|
|
wire dbg_lmatch0 =
|
wire dbg_lmatch0 =
|
dbg_ctrl[0] && dbg_ctrl[17:16]==2'b11 && dram0_addr[AMSB:3]==dbg_adr0[AMSB:3] &&
|
dbg_ctrl[0] && dbg_ctrl[17:16]==2'b11 && dram0_addr[AMSB:3]==dbg_adr0[AMSB:3] &&
|
((dbg_ctrl[19:18]==2'b00 && dram0_addr[2:0]==dbg_adr0[2:0]) ||
|
((dbg_ctrl[19:18]==2'b00 && dram0_addr[2:0]==dbg_adr0[2:0]) ||
|
(dbg_ctrl[19:18]==2'b01 && dram0_addr[2:1]==dbg_adr0[2:1]) ||
|
(dbg_ctrl[19:18]==2'b01 && dram0_addr[2:1]==dbg_adr0[2:1]) ||
|
(dbg_ctrl[19:18]==2'b10 && dram0_addr[2]==dbg_adr0[2]) ||
|
(dbg_ctrl[19:18]==2'b10 && dram0_addr[2]==dbg_adr0[2]) ||
|
dbg_ctrl[19:18]==2'b11)
|
dbg_ctrl[19:18]==2'b11)
|
;
|
;
|
wire dbg_lmatch1 =
|
wire dbg_lmatch1 =
|
dbg_ctrl[1] && dbg_ctrl[21:20]==2'b11 && dram0_addr[AMSB:3]==dbg_adr1[AMSB:3] &&
|
dbg_ctrl[1] && dbg_ctrl[21:20]==2'b11 && dram0_addr[AMSB:3]==dbg_adr1[AMSB:3] &&
|
((dbg_ctrl[23:22]==2'b00 && dram0_addr[2:0]==dbg_adr1[2:0]) ||
|
((dbg_ctrl[23:22]==2'b00 && dram0_addr[2:0]==dbg_adr1[2:0]) ||
|
(dbg_ctrl[23:22]==2'b01 && dram0_addr[2:1]==dbg_adr1[2:1]) ||
|
(dbg_ctrl[23:22]==2'b01 && dram0_addr[2:1]==dbg_adr1[2:1]) ||
|
(dbg_ctrl[23:22]==2'b10 && dram0_addr[2]==dbg_adr1[2]) ||
|
(dbg_ctrl[23:22]==2'b10 && dram0_addr[2]==dbg_adr1[2]) ||
|
dbg_ctrl[23:22]==2'b11)
|
dbg_ctrl[23:22]==2'b11)
|
;
|
;
|
wire dbg_lmatch2 =
|
wire dbg_lmatch2 =
|
dbg_ctrl[2] && dbg_ctrl[25:24]==2'b11 && dram0_addr[AMSB:3]==dbg_adr2[AMSB:3] &&
|
dbg_ctrl[2] && dbg_ctrl[25:24]==2'b11 && dram0_addr[AMSB:3]==dbg_adr2[AMSB:3] &&
|
((dbg_ctrl[27:26]==2'b00 && dram0_addr[2:0]==dbg_adr2[2:0]) ||
|
((dbg_ctrl[27:26]==2'b00 && dram0_addr[2:0]==dbg_adr2[2:0]) ||
|
(dbg_ctrl[27:26]==2'b01 && dram0_addr[2:1]==dbg_adr2[2:1]) ||
|
(dbg_ctrl[27:26]==2'b01 && dram0_addr[2:1]==dbg_adr2[2:1]) ||
|
(dbg_ctrl[27:26]==2'b10 && dram0_addr[2]==dbg_adr2[2]) ||
|
(dbg_ctrl[27:26]==2'b10 && dram0_addr[2]==dbg_adr2[2]) ||
|
dbg_ctrl[27:26]==2'b11)
|
dbg_ctrl[27:26]==2'b11)
|
;
|
;
|
wire dbg_lmatch3 =
|
wire dbg_lmatch3 =
|
dbg_ctrl[3] && dbg_ctrl[29:28]==2'b11 && dram0_addr[AMSB:3]==dbg_adr3[AMSB:3] &&
|
dbg_ctrl[3] && dbg_ctrl[29:28]==2'b11 && dram0_addr[AMSB:3]==dbg_adr3[AMSB:3] &&
|
((dbg_ctrl[31:30]==2'b00 && dram0_addr[2:0]==dbg_adr3[2:0]) ||
|
((dbg_ctrl[31:30]==2'b00 && dram0_addr[2:0]==dbg_adr3[2:0]) ||
|
(dbg_ctrl[31:30]==2'b01 && dram0_addr[2:1]==dbg_adr3[2:1]) ||
|
(dbg_ctrl[31:30]==2'b01 && dram0_addr[2:1]==dbg_adr3[2:1]) ||
|
(dbg_ctrl[31:30]==2'b10 && dram0_addr[2]==dbg_adr3[2]) ||
|
(dbg_ctrl[31:30]==2'b10 && dram0_addr[2]==dbg_adr3[2]) ||
|
dbg_ctrl[31:30]==2'b11)
|
dbg_ctrl[31:30]==2'b11)
|
;
|
;
|
wire dbg_lmatch = dbg_lmatch0|dbg_lmatch1|dbg_lmatch2|dbg_lmatch3;
|
wire dbg_lmatch = dbg_lmatch0|dbg_lmatch1|dbg_lmatch2|dbg_lmatch3;
|
|
|
wire dbg_smatch0 =
|
wire dbg_smatch0 =
|
dbg_ctrl[0] && dbg_ctrl[17:16]==2'b11 && dram0_addr[AMSB:3]==dbg_adr0[AMSB:3] &&
|
dbg_ctrl[0] && dbg_ctrl[17:16]==2'b11 && dram0_addr[AMSB:3]==dbg_adr0[AMSB:3] &&
|
((dbg_ctrl[19:18]==2'b00 && dram0_addr[2:0]==dbg_adr0[2:0]) ||
|
((dbg_ctrl[19:18]==2'b00 && dram0_addr[2:0]==dbg_adr0[2:0]) ||
|
(dbg_ctrl[19:18]==2'b01 && dram0_addr[2:1]==dbg_adr0[2:1]) ||
|
(dbg_ctrl[19:18]==2'b01 && dram0_addr[2:1]==dbg_adr0[2:1]) ||
|
(dbg_ctrl[19:18]==2'b10 && dram0_addr[2]==dbg_adr0[2]) ||
|
(dbg_ctrl[19:18]==2'b10 && dram0_addr[2]==dbg_adr0[2]) ||
|
dbg_ctrl[19:18]==2'b11)
|
dbg_ctrl[19:18]==2'b11)
|
;
|
;
|
wire dbg_smatch1 =
|
wire dbg_smatch1 =
|
dbg_ctrl[1] && dbg_ctrl[21:20]==2'b11 && dram0_addr[AMSB:3]==dbg_adr1[AMSB:3] &&
|
dbg_ctrl[1] && dbg_ctrl[21:20]==2'b11 && dram0_addr[AMSB:3]==dbg_adr1[AMSB:3] &&
|
((dbg_ctrl[23:22]==2'b00 && dram0_addr[2:0]==dbg_adr1[2:0]) ||
|
((dbg_ctrl[23:22]==2'b00 && dram0_addr[2:0]==dbg_adr1[2:0]) ||
|
(dbg_ctrl[23:22]==2'b01 && dram0_addr[2:1]==dbg_adr1[2:1]) ||
|
(dbg_ctrl[23:22]==2'b01 && dram0_addr[2:1]==dbg_adr1[2:1]) ||
|
(dbg_ctrl[23:22]==2'b10 && dram0_addr[2]==dbg_adr1[2]) ||
|
(dbg_ctrl[23:22]==2'b10 && dram0_addr[2]==dbg_adr1[2]) ||
|
dbg_ctrl[23:22]==2'b11)
|
dbg_ctrl[23:22]==2'b11)
|
;
|
;
|
wire dbg_smatch2 =
|
wire dbg_smatch2 =
|
dbg_ctrl[2] && dbg_ctrl[25:24]==2'b11 && dram0_addr[AMSB:3]==dbg_adr2[AMSB:3] &&
|
dbg_ctrl[2] && dbg_ctrl[25:24]==2'b11 && dram0_addr[AMSB:3]==dbg_adr2[AMSB:3] &&
|
((dbg_ctrl[27:26]==2'b00 && dram0_addr[2:0]==dbg_adr2[2:0]) ||
|
((dbg_ctrl[27:26]==2'b00 && dram0_addr[2:0]==dbg_adr2[2:0]) ||
|
(dbg_ctrl[27:26]==2'b01 && dram0_addr[2:1]==dbg_adr2[2:1]) ||
|
(dbg_ctrl[27:26]==2'b01 && dram0_addr[2:1]==dbg_adr2[2:1]) ||
|
(dbg_ctrl[27:26]==2'b10 && dram0_addr[2]==dbg_adr2[2]) ||
|
(dbg_ctrl[27:26]==2'b10 && dram0_addr[2]==dbg_adr2[2]) ||
|
dbg_ctrl[27:26]==2'b11)
|
dbg_ctrl[27:26]==2'b11)
|
;
|
;
|
wire dbg_smatch3 =
|
wire dbg_smatch3 =
|
dbg_ctrl[3] && dbg_ctrl[29:28]==2'b11 && dram0_addr[AMSB:3]==dbg_adr3[AMSB:3] &&
|
dbg_ctrl[3] && dbg_ctrl[29:28]==2'b11 && dram0_addr[AMSB:3]==dbg_adr3[AMSB:3] &&
|
((dbg_ctrl[31:30]==2'b00 && dram0_addr[2:0]==dbg_adr3[2:0]) ||
|
((dbg_ctrl[31:30]==2'b00 && dram0_addr[2:0]==dbg_adr3[2:0]) ||
|
(dbg_ctrl[31:30]==2'b01 && dram0_addr[2:1]==dbg_adr3[2:1]) ||
|
(dbg_ctrl[31:30]==2'b01 && dram0_addr[2:1]==dbg_adr3[2:1]) ||
|
(dbg_ctrl[31:30]==2'b10 && dram0_addr[2]==dbg_adr3[2]) ||
|
(dbg_ctrl[31:30]==2'b10 && dram0_addr[2]==dbg_adr3[2]) ||
|
dbg_ctrl[31:30]==2'b11)
|
dbg_ctrl[31:30]==2'b11)
|
;
|
;
|
wire dbg_smatch = dbg_smatch0|dbg_smatch1|dbg_smatch2|dbg_smatch3;
|
wire dbg_smatch = dbg_smatch0|dbg_smatch1|dbg_smatch2|dbg_smatch3;
|
|
|
wire dbg_stat0 = dbg_imatchA0 | dbg_imatchB0 | dbg_lmatch0 | dbg_smatch0;
|
wire dbg_stat0 = dbg_imatchA0 | dbg_imatchB0 | dbg_lmatch0 | dbg_smatch0;
|
wire dbg_stat1 = dbg_imatchA1 | dbg_imatchB1 | dbg_lmatch1 | dbg_smatch1;
|
wire dbg_stat1 = dbg_imatchA1 | dbg_imatchB1 | dbg_lmatch1 | dbg_smatch1;
|
wire dbg_stat2 = dbg_imatchA2 | dbg_imatchB2 | dbg_lmatch2 | dbg_smatch2;
|
wire dbg_stat2 = dbg_imatchA2 | dbg_imatchB2 | dbg_lmatch2 | dbg_smatch2;
|
wire dbg_stat3 = dbg_imatchA3 | dbg_imatchB3 | dbg_lmatch3 | dbg_smatch3;
|
wire dbg_stat3 = dbg_imatchA3 | dbg_imatchB3 | dbg_lmatch3 | dbg_smatch3;
|
assign dbg_stat1x = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0};
|
assign dbg_stat1x = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0};
|
wire debug_on = |dbg_ctrl[3:0]|dbg_ctrl[7];
|
wire debug_on = |dbg_ctrl[3:0]|dbg_ctrl[7];
|
|
|
reg [11:0] spr_bir;
|
reg [11:0] spr_bir;
|
|
|
//
|
//
|
// BRANCH-MISS LOGIC: livetarget
|
// BRANCH-MISS LOGIC: livetarget
|
//
|
//
|
// livetarget implies that there is a not-to-be-stomped instruction that targets the register in question
|
// livetarget implies that there is a not-to-be-stomped instruction that targets the register in question
|
// therefore, if it is zero it implies the rf_v value should become VALID on a branchmiss
|
// therefore, if it is zero it implies the rf_v value should become VALID on a branchmiss
|
//
|
//
|
/*
|
/*
|
Thor_livetarget #(NREGS) ultgt1
|
Thor_livetarget #(NREGS) ultgt1
|
(
|
(
|
iqentry_v,
|
iqentry_v,
|
iqentry_stomp,
|
iqentry_stomp,
|
iqentry_cmt,
|
iqentry_cmt,
|
iqentry_tgt[0],
|
iqentry_tgt[0],
|
iqentry_tgt[1],
|
iqentry_tgt[1],
|
iqentry_tgt[2],
|
iqentry_tgt[2],
|
iqentry_tgt[3],
|
iqentry_tgt[3],
|
iqentry_tgt[4],
|
iqentry_tgt[4],
|
iqentry_tgt[5],
|
iqentry_tgt[5],
|
iqentry_tgt[6],
|
iqentry_tgt[6],
|
iqentry_tgt[7],
|
iqentry_tgt[7],
|
livetarget,
|
livetarget,
|
iqentry_0_livetarget,
|
iqentry_0_livetarget,
|
iqentry_1_livetarget,
|
iqentry_1_livetarget,
|
iqentry_2_livetarget,
|
iqentry_2_livetarget,
|
iqentry_3_livetarget,
|
iqentry_3_livetarget,
|
iqentry_4_livetarget,
|
iqentry_4_livetarget,
|
iqentry_5_livetarget,
|
iqentry_5_livetarget,
|
iqentry_6_livetarget,
|
iqentry_6_livetarget,
|
iqentry_7_livetarget
|
iqentry_7_livetarget
|
);
|
);
|
|
|
//
|
//
|
// BRANCH-MISS LOGIC: latestID
|
// BRANCH-MISS LOGIC: latestID
|
//
|
//
|
// latestID is the instruction queue ID of the newest instruction (latest) that targets
|
// latestID is the instruction queue ID of the newest instruction (latest) that targets
|
// a particular register. looks a lot like scheduling logic, but in reverse.
|
// a particular register. looks a lot like scheduling logic, but in reverse.
|
//
|
//
|
|
|
assign iqentry_0_latestID = ((missid == 3'd0)|| ((iqentry_0_livetarget & iqentry_1_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_0_latestID = ((missid == 3'd0)|| ((iqentry_0_livetarget & iqentry_1_cumulative) == {NREGS{1'b0}}))
|
? iqentry_0_livetarget
|
? iqentry_0_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_0_cumulative = (missid == 3'd0)
|
assign iqentry_0_cumulative = (missid == 3'd0)
|
? iqentry_0_livetarget
|
? iqentry_0_livetarget
|
: iqentry_0_livetarget | iqentry_1_cumulative;
|
: iqentry_0_livetarget | iqentry_1_cumulative;
|
|
|
assign iqentry_1_latestID = ((missid == 3'd1)|| ((iqentry_1_livetarget & iqentry_2_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_1_latestID = ((missid == 3'd1)|| ((iqentry_1_livetarget & iqentry_2_cumulative) == {NREGS{1'b0}}))
|
? iqentry_1_livetarget
|
? iqentry_1_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_1_cumulative = (missid == 3'd1)
|
assign iqentry_1_cumulative = (missid == 3'd1)
|
? iqentry_1_livetarget
|
? iqentry_1_livetarget
|
: iqentry_1_livetarget | iqentry_2_cumulative;
|
: iqentry_1_livetarget | iqentry_2_cumulative;
|
|
|
assign iqentry_2_latestID = ((missid == 3'd2) || ((iqentry_2_livetarget & iqentry_3_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_2_latestID = ((missid == 3'd2) || ((iqentry_2_livetarget & iqentry_3_cumulative) == {NREGS{1'b0}}))
|
? iqentry_2_livetarget
|
? iqentry_2_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_2_cumulative = (missid == 3'd2)
|
assign iqentry_2_cumulative = (missid == 3'd2)
|
? iqentry_2_livetarget
|
? iqentry_2_livetarget
|
: iqentry_2_livetarget | iqentry_3_cumulative;
|
: iqentry_2_livetarget | iqentry_3_cumulative;
|
|
|
assign iqentry_3_latestID = ((missid == 3'd3)|| ((iqentry_3_livetarget & iqentry_4_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_3_latestID = ((missid == 3'd3)|| ((iqentry_3_livetarget & iqentry_4_cumulative) == {NREGS{1'b0}}))
|
? iqentry_3_livetarget
|
? iqentry_3_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_3_cumulative = (missid == 3'd3)
|
assign iqentry_3_cumulative = (missid == 3'd3)
|
? iqentry_3_livetarget
|
? iqentry_3_livetarget
|
: iqentry_3_livetarget | iqentry_4_cumulative;
|
: iqentry_3_livetarget | iqentry_4_cumulative;
|
|
|
assign iqentry_4_latestID = ((missid == 3'd4) || ((iqentry_4_livetarget & iqentry_5_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_4_latestID = ((missid == 3'd4) || ((iqentry_4_livetarget & iqentry_5_cumulative) == {NREGS{1'b0}}))
|
? iqentry_4_livetarget
|
? iqentry_4_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_4_cumulative = (missid == 3'd4)
|
assign iqentry_4_cumulative = (missid == 3'd4)
|
? iqentry_4_livetarget
|
? iqentry_4_livetarget
|
: iqentry_4_livetarget | iqentry_5_cumulative;
|
: iqentry_4_livetarget | iqentry_5_cumulative;
|
|
|
assign iqentry_5_latestID = ((missid == 3'd5)|| ((iqentry_5_livetarget & iqentry_6_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_5_latestID = ((missid == 3'd5)|| ((iqentry_5_livetarget & iqentry_6_cumulative) == {NREGS{1'b0}}))
|
? iqentry_5_livetarget
|
? iqentry_5_livetarget
|
: 287'd0;
|
: 287'd0;
|
assign iqentry_5_cumulative = (missid == 3'd5)
|
assign iqentry_5_cumulative = (missid == 3'd5)
|
? iqentry_5_livetarget
|
? iqentry_5_livetarget
|
: iqentry_5_livetarget | iqentry_6_cumulative;
|
: iqentry_5_livetarget | iqentry_6_cumulative;
|
|
|
assign iqentry_6_latestID = ((missid == 3'd6) || ((iqentry_6_livetarget & iqentry_7_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_6_latestID = ((missid == 3'd6) || ((iqentry_6_livetarget & iqentry_7_cumulative) == {NREGS{1'b0}}))
|
? iqentry_6_livetarget
|
? iqentry_6_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_6_cumulative = (missid == 3'd6)
|
assign iqentry_6_cumulative = (missid == 3'd6)
|
? iqentry_6_livetarget
|
? iqentry_6_livetarget
|
: iqentry_6_livetarget | iqentry_7_cumulative;
|
: iqentry_6_livetarget | iqentry_7_cumulative;
|
|
|
assign iqentry_7_latestID = ((missid == 3'd7) || ((iqentry_7_livetarget & iqentry_0_cumulative) == {NREGS{1'b0}}))
|
assign iqentry_7_latestID = ((missid == 3'd7) || ((iqentry_7_livetarget & iqentry_0_cumulative) == {NREGS{1'b0}}))
|
? iqentry_7_livetarget
|
? iqentry_7_livetarget
|
: {NREGS{1'b0}};
|
: {NREGS{1'b0}};
|
assign iqentry_7_cumulative = (missid==3'd7)
|
assign iqentry_7_cumulative = (missid==3'd7)
|
? iqentry_7_livetarget
|
? iqentry_7_livetarget
|
: iqentry_7_livetarget | iqentry_0_cumulative;
|
: iqentry_7_livetarget | iqentry_0_cumulative;
|
|
|
assign
|
assign
|
iqentry_source[0] = | iqentry_0_latestID,
|
iqentry_source[0] = | iqentry_0_latestID,
|
iqentry_source[1] = | iqentry_1_latestID,
|
iqentry_source[1] = | iqentry_1_latestID,
|
iqentry_source[2] = | iqentry_2_latestID,
|
iqentry_source[2] = | iqentry_2_latestID,
|
iqentry_source[3] = | iqentry_3_latestID,
|
iqentry_source[3] = | iqentry_3_latestID,
|
iqentry_source[4] = | iqentry_4_latestID,
|
iqentry_source[4] = | iqentry_4_latestID,
|
iqentry_source[5] = | iqentry_5_latestID,
|
iqentry_source[5] = | iqentry_5_latestID,
|
iqentry_source[6] = | iqentry_6_latestID,
|
iqentry_source[6] = | iqentry_6_latestID,
|
iqentry_source[7] = | iqentry_7_latestID;
|
iqentry_source[7] = | iqentry_7_latestID;
|
*/
|
*/
|
always @*
|
always @*
|
begin
|
begin
|
iqentry_source = 8'h00;
|
iqentry_source = 8'h00;
|
if (missid==head0) begin
|
if (missid==head0) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
end
|
end
|
else if (missid==head1) begin
|
else if (missid==head1) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
end
|
end
|
else if (missid==head2) begin
|
else if (missid==head2) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
end
|
end
|
else if (missid==head3) begin
|
else if (missid==head3) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
end
|
end
|
else if (missid==head4) begin
|
else if (missid==head4) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
end
|
end
|
else if (missid==head5) begin
|
else if (missid==head5) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
end
|
end
|
else if (missid==head6) begin
|
else if (missid==head6) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
if (iqentry_v[head6] && !iqentry_stomp[head6])
|
if (iqentry_v[head6] && !iqentry_stomp[head6])
|
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
|
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
|
end
|
end
|
else if (missid==head7) begin
|
else if (missid==head7) begin
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
if (iqentry_v[head0] && !iqentry_stomp[head0])
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
if (iqentry_v[head1] && !iqentry_stomp[head1])
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
if (iqentry_v[head2] && !iqentry_stomp[head2])
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
if (iqentry_v[head3] && !iqentry_stomp[head3])
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
if (iqentry_v[head4] && !iqentry_stomp[head4])
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
if (iqentry_v[head5] && !iqentry_stomp[head5])
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
|
if (iqentry_v[head6] && !iqentry_stomp[head6])
|
if (iqentry_v[head6] && !iqentry_stomp[head6])
|
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
|
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
|
if (iqentry_v[head7] && !iqentry_stomp[head7])
|
if (iqentry_v[head7] && !iqentry_stomp[head7])
|
iqentry_source[head7] = !fnRegIsAutoValid(iqentry_tgt[head7]);
|
iqentry_source[head7] = !fnRegIsAutoValid(iqentry_tgt[head7]);
|
end
|
end
|
end
|
end
|
|
|
//assign iqentry_0_islot = iqentry_islot[0];
|
//assign iqentry_0_islot = iqentry_islot[0];
|
//assign iqentry_1_islot = iqentry_islot[1];
|
//assign iqentry_1_islot = iqentry_islot[1];
|
//assign iqentry_2_islot = iqentry_islot[2];
|
//assign iqentry_2_islot = iqentry_islot[2];
|
//assign iqentry_3_islot = iqentry_islot[3];
|
//assign iqentry_3_islot = iqentry_islot[3];
|
//assign iqentry_4_islot = iqentry_islot[4];
|
//assign iqentry_4_islot = iqentry_islot[4];
|
//assign iqentry_5_islot = iqentry_islot[5];
|
//assign iqentry_5_islot = iqentry_islot[5];
|
//assign iqentry_6_islot = iqentry_islot[6];
|
//assign iqentry_6_islot = iqentry_islot[6];
|
//assign iqentry_7_islot = iqentry_islot[7];
|
//assign iqentry_7_islot = iqentry_islot[7];
|
|
|
// A single instruction can require 3 read ports. Only a total of four read
|
// A single instruction can require 3 read ports. Only a total of four read
|
// ports are supported because most of the time that's enough.
|
// ports are supported because most of the time that's enough.
|
// If there aren't enough read ports available then the second instruction
|
// If there aren't enough read ports available then the second instruction
|
// isn't enqueued (it'll be enqueued in the next cycle).
|
// isn't enqueued (it'll be enqueued in the next cycle).
|
reg [1:0] ports_avail; // available read ports for instruction #3.
|
reg [1:0] ports_avail; // available read ports for instruction #3.
|
reg [6:0] pRa0,pRb0,pRa1,pRb1,pRt0,pRt1;
|
reg [6:0] pRa0,pRb0,pRa1,pRb1,pRt0,pRt1;
|
wire [DBW-1:0] prfoa0,prfob0,prfoa1,prfob1;
|
wire [DBW-1:0] prfoa0,prfob0,prfoa1,prfob1;
|
wire [DBW-1:0] prfot0,prfot1;
|
wire [DBW-1:0] prfot0,prfot1;
|
|
|
wire [6:0] Ra0 = fnRa(fetchbuf0_instr);
|
wire [6:0] Ra0 = fnRa(fetchbuf0_instr);
|
wire [6:0] Rb0 = fnRb(fetchbuf0_instr);
|
wire [6:0] Rb0 = fnRb(fetchbuf0_instr);
|
wire [6:0] Rc0 = fnRc(fetchbuf0_instr);
|
wire [6:0] Rc0 = fnRc(fetchbuf0_instr);
|
wire [6:0] Ra1 = fnRa(fetchbuf1_instr);
|
wire [6:0] Ra1 = fnRa(fetchbuf1_instr);
|
wire [6:0] Rb1 = fnRb(fetchbuf1_instr);
|
wire [6:0] Rb1 = fnRb(fetchbuf1_instr);
|
wire [6:0] Rc1 = fnRc(fetchbuf1_instr);
|
wire [6:0] Rc1 = fnRc(fetchbuf1_instr);
|
wire [6:0] Rt0 = fnTargetReg(fetchbuf0_instr);
|
wire [6:0] Rt0 = fnTargetReg(fetchbuf0_instr);
|
wire [6:0] Rt1 = fnTargetReg(fetchbuf1_instr);
|
wire [6:0] Rt1 = fnTargetReg(fetchbuf1_instr);
|
always @*
|
always @*
|
begin
|
begin
|
pRt0 = Rt0;
|
pRt0 = Rt0;
|
pRt1 = Rt1;
|
pRt1 = Rt1;
|
rfot0 = prfot0;
|
rfot0 = prfot0;
|
rfot1 = prfot1;
|
rfot1 = prfot1;
|
case(fetchbuf0_v ? fnNumReadPorts(fetchbuf0_instr) : 2'd0)
|
case(fetchbuf0_v ? fnNumReadPorts(fetchbuf0_instr) : 2'd0)
|
2'd0: begin
|
2'd0: begin
|
pRa0 = 7'd0;
|
pRa0 = 7'd0;
|
pRb0 = Rc1;
|
pRb0 = Rc1;
|
pRa1 = Ra1;
|
pRa1 = Ra1;
|
pRb1 = Rb1;
|
pRb1 = Rb1;
|
rfoa0 = 64'd0;
|
rfoa0 = 64'd0;
|
rfob0 = 64'd0;
|
rfob0 = 64'd0;
|
rfoc0 = 64'd0;
|
rfoc0 = 64'd0;
|
rfoa1 = prfoa1;
|
rfoa1 = prfoa1;
|
rfob1 = prfob1;
|
rfob1 = prfob1;
|
rfoc1 = prfob0;
|
rfoc1 = prfob0;
|
ports_avail = 2'd3;
|
ports_avail = 2'd3;
|
end
|
end
|
2'd1: begin
|
2'd1: begin
|
pRa0 = Ra0;
|
pRa0 = Ra0;
|
pRb0 = Rc1;
|
pRb0 = Rc1;
|
pRa1 = Ra1;
|
pRa1 = Ra1;
|
pRb1 = Rb1;
|
pRb1 = Rb1;
|
rfoa0 = prfoa0;
|
rfoa0 = prfoa0;
|
rfob0 = 64'd0;
|
rfob0 = 64'd0;
|
rfoc0 = 64'd0;
|
rfoc0 = 64'd0;
|
rfoa1 = prfoa1;
|
rfoa1 = prfoa1;
|
rfob1 = prfob1;
|
rfob1 = prfob1;
|
rfoc1 = prfob0;
|
rfoc1 = prfob0;
|
ports_avail = 2'd3;
|
ports_avail = 2'd3;
|
end
|
end
|
2'd2: begin
|
2'd2: begin
|
pRa0 = Ra0;
|
pRa0 = Ra0;
|
pRb0 = Rb0;
|
pRb0 = Rb0;
|
pRa1 = Ra1;
|
pRa1 = Ra1;
|
pRb1 = Rb1;
|
pRb1 = Rb1;
|
rfoa0 = prfoa0;
|
rfoa0 = prfoa0;
|
rfob0 = prfob0;
|
rfob0 = prfob0;
|
rfoc0 = 64'd0;
|
rfoc0 = 64'd0;
|
rfoa1 = prfoa1;
|
rfoa1 = prfoa1;
|
rfob1 = prfob1;
|
rfob1 = prfob1;
|
rfoc1 = 64'd0;
|
rfoc1 = 64'd0;
|
ports_avail = 2'd2;
|
ports_avail = 2'd2;
|
end
|
end
|
2'd3: begin
|
2'd3: begin
|
pRa0 = Ra0;
|
pRa0 = Ra0;
|
pRb0 = Rb0;
|
pRb0 = Rb0;
|
pRa1 = Rc0;
|
pRa1 = Rc0;
|
pRb1 = Ra1;
|
pRb1 = Ra1;
|
rfoa0 = prfoa0;
|
rfoa0 = prfoa0;
|
rfob0 = prfob0;
|
rfob0 = prfob0;
|
rfoc0 = prfoa1;
|
rfoc0 = prfoa1;
|
rfoa1 = prfob1;
|
rfoa1 = prfob1;
|
rfob1 = 64'd0;
|
rfob1 = 64'd0;
|
rfoc1 = 64'd0;
|
rfoc1 = 64'd0;
|
ports_avail = 2'd1;
|
ports_avail = 2'd1;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
/*
|
/*
|
wire [8:0] Rb0 = ((fnNumReadPorts(fetchbuf0_instr) < 3'd2) || !fetchbuf0_v) ? {1'b0,fetchbuf1_instr[`INSTRUCTION_RC]} :
|
wire [8:0] Rb0 = ((fnNumReadPorts(fetchbuf0_instr) < 3'd2) || !fetchbuf0_v) ? {1'b0,fetchbuf1_instr[`INSTRUCTION_RC]} :
|
fnRb(fetchbuf0_instr);
|
fnRb(fetchbuf0_instr);
|
wire [8:0] Ra1 = (!fetchbuf0_v || fnNumReadPorts(fetchbuf0_instr) < 3'd3) ? fnRa(fetchbuf1_instr) :
|
wire [8:0] Ra1 = (!fetchbuf0_v || fnNumReadPorts(fetchbuf0_instr) < 3'd3) ? fnRa(fetchbuf1_instr) :
|
fetchbuf0_instr[`INSTRUCTION_RC];
|
fetchbuf0_instr[`INSTRUCTION_RC];
|
wire [8:0] Rb1 = (fnNumReadPorts(fetchbuf1_instr) < 3'd2 && fetchbuf0_v) ? fnRa(fetchbuf1_instr):fnRb(fetchbuf1_instr);
|
wire [8:0] Rb1 = (fnNumReadPorts(fetchbuf1_instr) < 3'd2 && fetchbuf0_v) ? fnRa(fetchbuf1_instr):fnRb(fetchbuf1_instr);
|
*/
|
*/
|
function [7:0] fnOpcode;
|
function [7:0] fnOpcode;
|
input [63:0] ins;
|
input [63:0] ins;
|
fnOpcode = (ins[3:0]==4'h0 && ins[7:4] > 4'h1 && ins[7:4] < 4'h9) ? `IMM :
|
fnOpcode = (ins[3:0]==4'h0 && ins[7:4] > 4'h1 && ins[7:4] < 4'h9) ? `IMM :
|
ins[7:0]==8'h10 ? `NOP : ins[15:8];
|
ins[7:0]==8'h10 ? `NOP : ins[15:8];
|
endfunction
|
endfunction
|
|
|
wire [7:0] opcode0 = fnOpcode(fetchbuf0_instr);
|
wire [7:0] opcode0 = fnOpcode(fetchbuf0_instr);
|
wire [7:0] opcode1 = fnOpcode(fetchbuf1_instr);
|
wire [7:0] opcode1 = fnOpcode(fetchbuf1_instr);
|
wire [3:0] cond0 = fetchbuf0_instr[3:0];
|
wire [3:0] cond0 = fetchbuf0_instr[3:0];
|
wire [3:0] cond1 = fetchbuf1_instr[3:0];
|
wire [3:0] cond1 = fetchbuf1_instr[3:0];
|
wire [3:0] Pn0 = fetchbuf0_instr[7:4];
|
wire [3:0] Pn0 = fetchbuf0_instr[7:4];
|
wire [3:0] Pt0 = fetchbuf0_instr[11:8];
|
wire [3:0] Pt0 = fetchbuf0_instr[11:8];
|
wire [3:0] Pn1 = fetchbuf1_instr[7:4];
|
wire [3:0] Pn1 = fetchbuf1_instr[7:4];
|
wire [3:0] Pt1 = fetchbuf1_instr[11:8];
|
wire [3:0] Pt1 = fetchbuf1_instr[11:8];
|
|
|
function [6:0] fnRa;
|
function [6:0] fnRa;
|
input [63:0] isn;
|
input [63:0] isn;
|
case(isn[15:8])
|
case(isn[15:8])
|
`RTS2: fnRa = 7'h51;
|
`RTS2: fnRa = 7'h51;
|
`RTI: fnRa = 7'h5E;
|
`RTI: fnRa = 7'h5E;
|
`RTD: fnRa = 7'h5B;
|
`RTD: fnRa = 7'h5B;
|
`RTE: fnRa = 7'h5D;
|
`RTE: fnRa = 7'h5D;
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
|
fnRa = {3'h5,isn[23:20]};
|
fnRa = {3'h5,isn[23:20]};
|
`TLB: fnRa = {1'b0,isn[29:24]};
|
`TLB: fnRa = {1'b0,isn[29:24]};
|
`P: fnRa = 7'h70;
|
`P: fnRa = 7'h70;
|
`LOOP: fnRa = 7'h73;
|
`LOOP: fnRa = 7'h73;
|
`PUSH: fnRa = km ? 7'd31 : 7'd27;
|
`PUSH: fnRa = km ? 7'd31 : 7'd27;
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
`PEA,`POP,`LINK: fnRa = km ? 7'd31 : 7'd27;
|
`PEA,`POP,`LINK: fnRa = km ? 7'd31 : 7'd27;
|
`endif
|
`endif
|
`MFSPR,`MOVS: fnRa = {1'b1,isn[`INSTRUCTION_RA]};
|
`MFSPR,`MOVS: fnRa = {1'b1,isn[`INSTRUCTION_RA]};
|
default: fnRa = {1'b0,isn[`INSTRUCTION_RA]};
|
default: fnRa = {1'b0,isn[`INSTRUCTION_RA]};
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [6:0] fnRb;
|
function [6:0] fnRb;
|
input [63:0] isn;
|
input [63:0] isn;
|
case(isn[15:8])
|
case(isn[15:8])
|
// `LOOP: fnRb = 7'h73;
|
// `LOOP: fnRb = 7'h73;
|
// `RTS,`STP,`TLB,`POP: fnRb = 7'd0;
|
// `RTS,`STP,`TLB,`POP: fnRb = 7'd0;
|
`JSR,`JSRS,`JSRZ,`SYS,`INT:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT:
|
fnRb = {3'h5,isn[23:20]};
|
fnRb = {3'h5,isn[23:20]};
|
`SWS: fnRb = {1'b1,isn[27:22]};
|
`SWS: fnRb = {1'b1,isn[27:22]};
|
`PUSH: fnRb = isn[22:16];
|
`PUSH: fnRb = isn[22:16];
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
`LINK: fnRb = {1'b0,isn[27:22]};
|
`LINK: fnRb = {1'b0,isn[27:22]};
|
`PEA: fnRb = {1'b0,isn[21:16]};
|
`PEA: fnRb = {1'b0,isn[21:16]};
|
`endif
|
`endif
|
default: fnRb = {1'b0,isn[`INSTRUCTION_RB]};
|
default: fnRb = {1'b0,isn[`INSTRUCTION_RB]};
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [6:0] fnRc;
|
function [6:0] fnRc;
|
input [63:0] isn;
|
input [63:0] isn;
|
fnRc = {1'b0,isn[`INSTRUCTION_RC]};
|
fnRc = {1'b0,isn[`INSTRUCTION_RC]};
|
endfunction
|
endfunction
|
|
|
function [3:0] fnCar;
|
function [3:0] fnCar;
|
input [63:0] isn;
|
input [63:0] isn;
|
case(isn[15:8])
|
case(isn[15:8])
|
`RTS2: fnCar = 4'h1;
|
`RTS2: fnCar = 4'h1;
|
`RTI: fnCar = 4'hE;
|
`RTI: fnCar = 4'hE;
|
`RTD: fnCar = 4'hB;
|
`RTD: fnCar = 4'hB;
|
`RTE: fnCar = 4'hD;
|
`RTE: fnCar = 4'hD;
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
|
fnCar = {isn[23:20]};
|
fnCar = {isn[23:20]};
|
default: fnCar = 4'h0;
|
default: fnCar = 4'h0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [5:0] fnFunc;
|
function [5:0] fnFunc;
|
input [63:0] isn;
|
input [63:0] isn;
|
case(isn[15:8])
|
case(isn[15:8])
|
`BITFIELD: fnFunc = isn[43:40];
|
`BITFIELD: fnFunc = isn[43:40];
|
`R: fnFunc = isn[31:28];
|
`R: fnFunc = isn[31:28];
|
`R2: fnFunc = isn[31:28];
|
`R2: fnFunc = isn[31:28];
|
`DOUBLE_R: fnFunc = isn[31:28];
|
`DOUBLE_R: fnFunc = isn[31:28];
|
`SINGLE_R: fnFunc = isn[31:28];
|
`SINGLE_R: fnFunc = isn[31:28];
|
8'h10: fnFunc = isn[31:28];
|
8'h10: fnFunc = isn[31:28];
|
8'h11: fnFunc = isn[31:28];
|
8'h11: fnFunc = isn[31:28];
|
8'h12: fnFunc = isn[31:28];
|
8'h12: fnFunc = isn[31:28];
|
8'h13: fnFunc = isn[31:28];
|
8'h13: fnFunc = isn[31:28];
|
8'h14: fnFunc = isn[31:28];
|
8'h14: fnFunc = isn[31:28];
|
8'h15: fnFunc = isn[31:28];
|
8'h15: fnFunc = isn[31:28];
|
8'h16: fnFunc = isn[31:28];
|
8'h16: fnFunc = isn[31:28];
|
8'h17: fnFunc = isn[31:28];
|
8'h17: fnFunc = isn[31:28];
|
8'h18: fnFunc = isn[31:28];
|
8'h18: fnFunc = isn[31:28];
|
8'h19: fnFunc = isn[31:28];
|
8'h19: fnFunc = isn[31:28];
|
8'h1A: fnFunc = isn[31:28];
|
8'h1A: fnFunc = isn[31:28];
|
8'h1B: fnFunc = isn[31:28];
|
8'h1B: fnFunc = isn[31:28];
|
8'h1C: fnFunc = isn[31:28];
|
8'h1C: fnFunc = isn[31:28];
|
8'h1D: fnFunc = isn[31:28];
|
8'h1D: fnFunc = isn[31:28];
|
8'h1E: fnFunc = isn[31:28];
|
8'h1E: fnFunc = isn[31:28];
|
8'h1F: fnFunc = isn[31:28];
|
8'h1F: fnFunc = isn[31:28];
|
8'h00: fnFunc = isn[23:22];
|
8'h00: fnFunc = isn[23:22];
|
8'h01: fnFunc = isn[23:22];
|
8'h01: fnFunc = isn[23:22];
|
8'h02: fnFunc = isn[23:22];
|
8'h02: fnFunc = isn[23:22];
|
8'h03: fnFunc = isn[23:22];
|
8'h03: fnFunc = isn[23:22];
|
8'h04: fnFunc = isn[23:22];
|
8'h04: fnFunc = isn[23:22];
|
8'h05: fnFunc = isn[23:22];
|
8'h05: fnFunc = isn[23:22];
|
8'h06: fnFunc = isn[23:22];
|
8'h06: fnFunc = isn[23:22];
|
8'h07: fnFunc = isn[23:22];
|
8'h07: fnFunc = isn[23:22];
|
8'h08: fnFunc = isn[23:22];
|
8'h08: fnFunc = isn[23:22];
|
8'h09: fnFunc = isn[23:22];
|
8'h09: fnFunc = isn[23:22];
|
8'h0A: fnFunc = isn[23:22];
|
8'h0A: fnFunc = isn[23:22];
|
8'h0B: fnFunc = isn[23:22];
|
8'h0B: fnFunc = isn[23:22];
|
8'h0C: fnFunc = isn[23:22];
|
8'h0C: fnFunc = isn[23:22];
|
8'h0D: fnFunc = isn[23:22];
|
8'h0D: fnFunc = isn[23:22];
|
8'h0E: fnFunc = isn[23:22];
|
8'h0E: fnFunc = isn[23:22];
|
8'h0F: fnFunc = isn[23:22];
|
8'h0F: fnFunc = isn[23:22];
|
`INC: fnFunc = isn[24:22];
|
`INC: fnFunc = {isn[39:37],isn[24:22]};
|
`TLB: fnFunc = isn[19:16];
|
`TLB: fnFunc = isn[19:16];
|
`RTS: fnFunc = isn[19:16]; // used to pass a small immediate
|
`RTS: fnFunc = isn[19:16]; // used to pass a small immediate
|
`CACHE: fnFunc = isn[31:26];
|
`CACHE: fnFunc = isn[31:26];
|
`PUSH,`PEA: fnFunc = km ? 6'b0 : 6'b110000; // select segment register #6
|
`PUSH,`PEA: fnFunc = km ? 6'b0 : 6'b110000; // select segment register #6
|
`JMPI: fnFunc = {isn[39:37],1'b0,isn[27:26]};
|
`JMPI: fnFunc = {isn[39:37],1'b0,isn[27:26]};
|
`JMPIX: fnFunc = {isn[39:37],1'b0,isn[33:32]};
|
`JMPIX: fnFunc = {isn[39:37],1'b0,isn[33:32]};
|
default:
|
default:
|
fnFunc = isn[39:34];
|
fnFunc = isn[39:34];
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// Returns true if the operation is limited to ALU #0
|
// Returns true if the operation is limited to ALU #0
|
function fnIsAlu0Op;
|
function fnIsAlu0Op;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] func;
|
input [5:0] func;
|
case(opcode)
|
case(opcode)
|
`R:
|
`R:
|
case(func)
|
case(func)
|
`CNTLZ,`CNTLO,`CNTPOP: fnIsAlu0Op = `TRUE;
|
`CNTLZ,`CNTLO,`CNTPOP: fnIsAlu0Op = `TRUE;
|
`ABS,`SGN,`ZXB,`ZXC,`ZXH,`SXB,`SXC,`SXH: fnIsAlu0Op = `TRUE;
|
`ABS,`SGN,`ZXB,`ZXC,`ZXH,`SXB,`SXC,`SXH: fnIsAlu0Op = `TRUE;
|
default: fnIsAlu0Op = `FALSE;
|
default: fnIsAlu0Op = `FALSE;
|
endcase
|
endcase
|
`RR:
|
`RR:
|
case(func)
|
case(func)
|
`DIV,`DIVU: fnIsAlu0Op = `TRUE;
|
`DIV,`DIVU: fnIsAlu0Op = `TRUE;
|
`MOD,`MODU: fnIsAlu0Op = `TRUE;
|
`MOD,`MODU: fnIsAlu0Op = `TRUE;
|
`MIN,`MAX: fnIsAlu0Op = `TRUE;
|
`MIN,`MAX: fnIsAlu0Op = `TRUE;
|
default: fnIsAlu0Op = `FALSE;
|
default: fnIsAlu0Op = `FALSE;
|
endcase
|
endcase
|
`BCD: fnIsAlu0Op = `TRUE;
|
`BCD: fnIsAlu0Op = `TRUE;
|
`DIVI,`DIVUI: fnIsAlu0Op = `TRUE;
|
`DIVI,`DIVUI: fnIsAlu0Op = `TRUE;
|
`MODI,`MODUI: fnIsAlu0Op = `TRUE;
|
`MODI,`MODUI: fnIsAlu0Op = `TRUE;
|
//`DOUBLE: fnIsAlu0Op = `TRUE;
|
//`DOUBLE: fnIsAlu0Op = `TRUE;
|
`SHIFT: fnIsAlu0Op = `TRUE;
|
`SHIFT: fnIsAlu0Op = `TRUE;
|
`BITFIELD: fnIsAlu0Op = `TRUE;
|
`BITFIELD: fnIsAlu0Op = `TRUE;
|
default: fnIsAlu0Op = `FALSE;
|
default: fnIsAlu0Op = `FALSE;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// Returns TRUE if the alu will be valid immediately
|
// Returns TRUE if the alu will be valid immediately
|
//
|
//
|
function fnAluValid;
|
function fnAluValid;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] func;
|
input [5:0] func;
|
case(opcode)
|
case(opcode)
|
`R: fnAluValid = `TRUE;
|
`R: fnAluValid = `TRUE;
|
`RR:
|
`RR:
|
case(func)
|
case(func)
|
`MUL,`MULU,`DIV,`DIVU,`MOD,`MODU: fnAluValid = `FALSE;
|
`MUL,`MULU,`DIV,`DIVU,`MOD,`MODU: fnAluValid = `FALSE;
|
default: fnAluValid = `TRUE;
|
default: fnAluValid = `TRUE;
|
endcase
|
endcase
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI: fnAluValid = `FALSE;
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI: fnAluValid = `FALSE;
|
default: fnAluValid = `TRUE;
|
default: fnAluValid = `TRUE;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
Thor_regfile2w6r #(DBW) urf1
|
Thor_regfile2w6r #(DBW) urf1
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.rclk(~clk),
|
.rclk(~clk),
|
.wr0(commit0_v && ~commit0_tgt[6]),
|
.wr0(commit0_v && ~commit0_tgt[6]),
|
.wr1(commit1_v && ~commit1_tgt[6]),
|
.wr1(commit1_v && ~commit1_tgt[6]),
|
.wa0(commit0_tgt[5:0]),
|
.wa0(commit0_tgt[5:0]),
|
.wa1(commit1_tgt[5:0]),
|
.wa1(commit1_tgt[5:0]),
|
.ra0(pRa0[5:0]),
|
.ra0(pRa0[5:0]),
|
.ra1(pRb0[5:0]),
|
.ra1(pRb0[5:0]),
|
.ra2(pRa1[5:0]),
|
.ra2(pRa1[5:0]),
|
.ra3(pRb1[5:0]),
|
.ra3(pRb1[5:0]),
|
.ra4(pRt0[5:0]),
|
.ra4(pRt0[5:0]),
|
.ra5(pRt1[5:0]),
|
.ra5(pRt1[5:0]),
|
.i0(commit0_bus),
|
.i0(commit0_bus),
|
.i1(commit1_bus),
|
.i1(commit1_bus),
|
.o0(prfoa0),
|
.o0(prfoa0),
|
.o1(prfob0),
|
.o1(prfob0),
|
.o2(prfoa1),
|
.o2(prfoa1),
|
.o3(prfob1),
|
.o3(prfob1),
|
.o4(prfot0),
|
.o4(prfot0),
|
.o5(prfot1)
|
.o5(prfot1)
|
);
|
);
|
|
|
wire [63:0] cregs0 = fnCar(fetchbuf0_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf0_instr)==4'hF ? fetchbuf0_pc : cregs[fnCar(fetchbuf0_instr)];
|
wire [63:0] cregs0 = fnCar(fetchbuf0_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf0_instr)==4'hF ? fetchbuf0_pc : cregs[fnCar(fetchbuf0_instr)];
|
wire [63:0] cregs1 = fnCar(fetchbuf1_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf1_instr)==4'hF ? fetchbuf1_pc : cregs[fnCar(fetchbuf1_instr)];
|
wire [63:0] cregs1 = fnCar(fetchbuf1_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf1_instr)==4'hF ? fetchbuf1_pc : cregs[fnCar(fetchbuf1_instr)];
|
//
|
//
|
// 1 if the the operand is automatically valid,
|
// 1 if the the operand is automatically valid,
|
// 0 if we need a RF value
|
// 0 if we need a RF value
|
function fnSource1_v;
|
function fnSource1_v;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
case(opcode)
|
case(opcode)
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP:
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP:
|
fnSource1_v = 1'b1;
|
fnSource1_v = 1'b1;
|
`LDI,`LDIS,`IMM: fnSource1_v = 1'b1;
|
`LDI,`LDIS,`IMM: fnSource1_v = 1'b1;
|
default:
|
default:
|
case(opcode[7:4])
|
case(opcode[7:4])
|
`BR: fnSource1_v = 1'b1;
|
`BR: fnSource1_v = 1'b1;
|
default: fnSource1_v = 1'b0;
|
default: fnSource1_v = 1'b0;
|
endcase
|
endcase
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
//
|
//
|
// 1 if the the operand is automatically valid,
|
// 1 if the the operand is automatically valid,
|
// 0 if we need a RF value
|
// 0 if we need a RF value
|
function fnSource2_v;
|
function fnSource2_v;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] func;
|
input [5:0] func;
|
case(opcode)
|
case(opcode)
|
`R,`P: fnSource2_v = 1'b1;
|
`R,`P: fnSource2_v = 1'b1;
|
`LDI,`LDIS,`IMM,`NOP,`STP: fnSource2_v = 1'b1;
|
`LDI,`LDIS,`IMM,`NOP,`STP: fnSource2_v = 1'b1;
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC:
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`RTI,`RTD,`RTE,`JMPI: fnSource2_v = 1'b1;
|
`RTI,`RTD,`RTE,`JMPI: fnSource2_v = 1'b1;
|
// TST
|
// TST
|
8'h00: fnSource2_v = 1'b1;
|
8'h00: fnSource2_v = 1'b1;
|
8'h01: fnSource2_v = 1'b1;
|
8'h01: fnSource2_v = 1'b1;
|
8'h02: fnSource2_v = 1'b1;
|
8'h02: fnSource2_v = 1'b1;
|
8'h03: fnSource2_v = 1'b1;
|
8'h03: fnSource2_v = 1'b1;
|
8'h04: fnSource2_v = 1'b1;
|
8'h04: fnSource2_v = 1'b1;
|
8'h05: fnSource2_v = 1'b1;
|
8'h05: fnSource2_v = 1'b1;
|
8'h06: fnSource2_v = 1'b1;
|
8'h06: fnSource2_v = 1'b1;
|
8'h07: fnSource2_v = 1'b1;
|
8'h07: fnSource2_v = 1'b1;
|
8'h08: fnSource2_v = 1'b1;
|
8'h08: fnSource2_v = 1'b1;
|
8'h09: fnSource2_v = 1'b1;
|
8'h09: fnSource2_v = 1'b1;
|
8'h0A: fnSource2_v = 1'b1;
|
8'h0A: fnSource2_v = 1'b1;
|
8'h0B: fnSource2_v = 1'b1;
|
8'h0B: fnSource2_v = 1'b1;
|
8'h0C: fnSource2_v = 1'b1;
|
8'h0C: fnSource2_v = 1'b1;
|
8'h0D: fnSource2_v = 1'b1;
|
8'h0D: fnSource2_v = 1'b1;
|
8'h0E: fnSource2_v = 1'b1;
|
8'h0E: fnSource2_v = 1'b1;
|
8'h0F: fnSource2_v = 1'b1;
|
8'h0F: fnSource2_v = 1'b1;
|
`ADDI,`ADDUI,`ADDUIS:
|
`ADDI,`ADDUI,`ADDUIS:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`SUBI,`SUBUI: fnSource2_v = 1'b1;
|
`SUBI,`SUBUI: fnSource2_v = 1'b1;
|
// CMPI
|
// CMPI
|
8'h20: fnSource2_v = 1'b1;
|
8'h20: fnSource2_v = 1'b1;
|
8'h21: fnSource2_v = 1'b1;
|
8'h21: fnSource2_v = 1'b1;
|
8'h22: fnSource2_v = 1'b1;
|
8'h22: fnSource2_v = 1'b1;
|
8'h23: fnSource2_v = 1'b1;
|
8'h23: fnSource2_v = 1'b1;
|
8'h24: fnSource2_v = 1'b1;
|
8'h24: fnSource2_v = 1'b1;
|
8'h25: fnSource2_v = 1'b1;
|
8'h25: fnSource2_v = 1'b1;
|
8'h26: fnSource2_v = 1'b1;
|
8'h26: fnSource2_v = 1'b1;
|
8'h27: fnSource2_v = 1'b1;
|
8'h27: fnSource2_v = 1'b1;
|
8'h28: fnSource2_v = 1'b1;
|
8'h28: fnSource2_v = 1'b1;
|
8'h29: fnSource2_v = 1'b1;
|
8'h29: fnSource2_v = 1'b1;
|
8'h2A: fnSource2_v = 1'b1;
|
8'h2A: fnSource2_v = 1'b1;
|
8'h2B: fnSource2_v = 1'b1;
|
8'h2B: fnSource2_v = 1'b1;
|
8'h2C: fnSource2_v = 1'b1;
|
8'h2C: fnSource2_v = 1'b1;
|
8'h2D: fnSource2_v = 1'b1;
|
8'h2D: fnSource2_v = 1'b1;
|
8'h2E: fnSource2_v = 1'b1;
|
8'h2E: fnSource2_v = 1'b1;
|
8'h2F: fnSource2_v = 1'b1;
|
8'h2F: fnSource2_v = 1'b1;
|
// BR
|
// BR
|
8'h30: fnSource2_v = 1'b1;
|
8'h30: fnSource2_v = 1'b1;
|
8'h31: fnSource2_v = 1'b1;
|
8'h31: fnSource2_v = 1'b1;
|
8'h32: fnSource2_v = 1'b1;
|
8'h32: fnSource2_v = 1'b1;
|
8'h33: fnSource2_v = 1'b1;
|
8'h33: fnSource2_v = 1'b1;
|
8'h34: fnSource2_v = 1'b1;
|
8'h34: fnSource2_v = 1'b1;
|
8'h35: fnSource2_v = 1'b1;
|
8'h35: fnSource2_v = 1'b1;
|
8'h36: fnSource2_v = 1'b1;
|
8'h36: fnSource2_v = 1'b1;
|
8'h37: fnSource2_v = 1'b1;
|
8'h37: fnSource2_v = 1'b1;
|
8'h38: fnSource2_v = 1'b1;
|
8'h38: fnSource2_v = 1'b1;
|
8'h39: fnSource2_v = 1'b1;
|
8'h39: fnSource2_v = 1'b1;
|
8'h3A: fnSource2_v = 1'b1;
|
8'h3A: fnSource2_v = 1'b1;
|
8'h3B: fnSource2_v = 1'b1;
|
8'h3B: fnSource2_v = 1'b1;
|
8'h3C: fnSource2_v = 1'b1;
|
8'h3C: fnSource2_v = 1'b1;
|
8'h3D: fnSource2_v = 1'b1;
|
8'h3D: fnSource2_v = 1'b1;
|
8'h3E: fnSource2_v = 1'b1;
|
8'h3E: fnSource2_v = 1'b1;
|
8'h3F: fnSource2_v = 1'b1;
|
8'h3F: fnSource2_v = 1'b1;
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`ANDI,`BITI: fnSource2_v = 1'b1;
|
`ANDI,`BITI: fnSource2_v = 1'b1;
|
`ORI: fnSource2_v = 1'b1;
|
`ORI: fnSource2_v = 1'b1;
|
`EORI: fnSource2_v = 1'b1;
|
`EORI: fnSource2_v = 1'b1;
|
`SHIFT:
|
`SHIFT:
|
if (func>=6'h10)
|
if (func>=6'h10)
|
fnSource2_v = `TRUE;
|
fnSource2_v = `TRUE;
|
else
|
else
|
fnSource2_v = `FALSE;
|
fnSource2_v = `FALSE;
|
`CACHE,`LCL,`TLB,`LLA,
|
`CACHE,`LCL,`TLB,`LLA,`LEA,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`STI,`INC:
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`STI,`INC:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`MTSPR,`MFSPR,`POP,`UNLINK:
|
`MTSPR,`MFSPR,`POP,`UNLINK:
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`BITFIELD:
|
`BITFIELD:
|
if (func==`BFINS)
|
if (func==`BFINS)
|
fnSource2_v = 1'b0;
|
fnSource2_v = 1'b0;
|
else
|
else
|
fnSource2_v = 1'b1;
|
fnSource2_v = 1'b1;
|
`LOOP: fnSource2_v = 1'b1;
|
`LOOP: fnSource2_v = 1'b1;
|
default: fnSource2_v = 1'b0;
|
default: fnSource2_v = 1'b0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
|
|
// Source #3 valid
|
// Source #3 valid
|
// Since most instructions don't use a third source the default it to return
|
// Since most instructions don't use a third source the default it to return
|
// a valid status.
|
// a valid status.
|
// 1 if the the operand is automatically valid,
|
// 1 if the the operand is automatically valid,
|
// 0 if we need a RF value
|
// 0 if we need a RF value
|
function fnSource3_v;
|
function fnSource3_v;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
case(opcode)
|
case(opcode)
|
`SBX,`SCX,`SHX,`SWX,`CAS,`STMV,`STCMP,`STFND: fnSource3_v = 1'b0;
|
`SBX,`SCX,`SHX,`SWX,`CAS,`STMV,`STCMP,`STFND: fnSource3_v = 1'b0;
|
`MUX: fnSource3_v = 1'b0;
|
`MUX: fnSource3_v = 1'b0;
|
default: fnSource3_v = 1'b1;
|
default: fnSource3_v = 1'b1;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function fnSourceT_v;
|
function fnSourceT_v;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
case(opcode)
|
case(opcode)
|
// BR
|
// BR
|
8'h30,8'h31,8'h32,8'h33,
|
8'h30,8'h31,8'h32,8'h33,
|
8'h34,8'h35,8'h36,8'h37,
|
8'h34,8'h35,8'h36,8'h37,
|
8'h38,8'h39,8'h3A,8'h3B,
|
8'h38,8'h39,8'h3A,8'h3B,
|
8'h3C,8'h3D,8'h3E,8'h3F,
|
8'h3C,8'h3D,8'h3E,8'h3F,
|
`SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS,
|
`SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS,
|
`CACHE,
|
`CACHE,
|
`SEI,`CLI,`NOP,`STP,`RTI,`RTD,`RTE,
|
`SEI,`CLI,`NOP,`STP,`RTI,`RTD,`RTE,
|
`MEMSB,`MEMDB,`SYNC:
|
`MEMSB,`MEMDB,`SYNC:
|
fnSourceT_v = 1'b1;
|
fnSourceT_v = 1'b1;
|
default: fnSourceT_v = 1'b0;
|
default: fnSourceT_v = 1'b0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// Return the number of register read ports required for an instruction.
|
// Return the number of register read ports required for an instruction.
|
function [2:0] fnNumReadPorts;
|
function [2:0] fnNumReadPorts;
|
input [63:0] ins;
|
input [63:0] ins;
|
case(fnOpcode(ins))
|
case(fnOpcode(ins))
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`MOVS,`STP:
|
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`MOVS,`STP:
|
fnNumReadPorts = 3'd0;
|
fnNumReadPorts = 3'd0;
|
`LDI,`LDIS,`IMM: fnNumReadPorts = 3'd0;
|
`LDI,`LDIS,`IMM: fnNumReadPorts = 3'd0;
|
`R,`P,`STI,`LOOP,`JMPI: fnNumReadPorts = 3'd1;
|
`R,`P,`STI,`LOOP,`JMPI: fnNumReadPorts = 3'd1;
|
`RTI,`RTD,`RTE: fnNumReadPorts = 3'd1;
|
`RTI,`RTD,`RTE: fnNumReadPorts = 3'd1;
|
`ADDI,`ADDUI,`ADDUIS:
|
`ADDI,`ADDUI,`ADDUIS:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`SUBI,`SUBUI: fnNumReadPorts = 3'd1;
|
`SUBI,`SUBUI: fnNumReadPorts = 3'd1;
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`BITI,
|
`BITI,
|
`ANDI,`ORI,`EORI: fnNumReadPorts = 3'd1;
|
`ANDI,`ORI,`EORI: fnNumReadPorts = 3'd1;
|
`SHIFT:
|
`SHIFT:
|
if (ins[39:38]==2'h1) // shift immediate
|
if (ins[39:38]==2'h1) // shift immediate
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
else
|
else
|
fnNumReadPorts = 3'd2;
|
fnNumReadPorts = 3'd2;
|
`CACHE,`LCL,`TLB,`LLA,
|
`CACHE,`LCL,`TLB,`LLA,`LEA,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`INC:
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`INC:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2,`BR:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2,`BR:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`SBX,`SCX,`SHX,`SWX,
|
`SBX,`SCX,`SHX,`SWX,
|
`MUX,`CAS,`STMV,`STCMP:
|
`MUX,`CAS,`STMV,`STCMP:
|
fnNumReadPorts = 3'd3;
|
fnNumReadPorts = 3'd3;
|
`MTSPR,`MFSPR,`POP,`UNLINK: fnNumReadPorts = 3'd1;
|
`MTSPR,`MFSPR,`POP,`UNLINK: fnNumReadPorts = 3'd1;
|
`STFND: fnNumReadPorts = 3'd2; // *** TLB reads on Rb we say 2 for simplicity
|
`STFND: fnNumReadPorts = 3'd2; // *** TLB reads on Rb we say 2 for simplicity
|
`BITFIELD:
|
`BITFIELD:
|
case(ins[43:40])
|
case(ins[43:40])
|
`BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU,`BFINSI:
|
`BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU,`BFINSI:
|
fnNumReadPorts = 3'd1;
|
fnNumReadPorts = 3'd1;
|
`BFINS: fnNumReadPorts = 3'd2;
|
`BFINS: fnNumReadPorts = 3'd2;
|
default: fnNumReadPorts = 3'd0;
|
default: fnNumReadPorts = 3'd0;
|
endcase
|
endcase
|
default:
|
default:
|
case(ins[15:12])
|
case(ins[15:12])
|
`TST: fnNumReadPorts = 3'd1;
|
`TST: fnNumReadPorts = 3'd1;
|
`CMPI: fnNumReadPorts = 3'd1;
|
`CMPI: fnNumReadPorts = 3'd1;
|
`CMP: fnNumReadPorts = 3'd2;
|
`CMP: fnNumReadPorts = 3'd2;
|
`BR: fnNumReadPorts = 3'd0;
|
`BR: fnNumReadPorts = 3'd0;
|
default: fnNumReadPorts = 3'd2;
|
default: fnNumReadPorts = 3'd2;
|
endcase
|
endcase
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function fnIsBranch;
|
function fnIsBranch;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
case(opcode[7:4])
|
case(opcode[7:4])
|
`BR: fnIsBranch = `TRUE;
|
`BR: fnIsBranch = `TRUE;
|
default: fnIsBranch = `FALSE;
|
default: fnIsBranch = `FALSE;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function fnIsPush;
|
function fnIsPush;
|
input [63:0] isn;
|
input [63:0] isn;
|
fnIsPush = isn[15:8]==`PUSH || isn[15:8]==`PEA;
|
fnIsPush = isn[15:8]==`PUSH || isn[15:8]==`PEA;
|
endfunction
|
endfunction
|
|
|
function fnIsPop;
|
function fnIsPop;
|
input [63:0] isn;
|
input [63:0] isn;
|
fnIsPop = isn[15:8]==`POP;
|
fnIsPop = isn[15:8]==`POP;
|
endfunction
|
endfunction
|
|
|
function fnIsStoreString;
|
function fnIsStoreString;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsStoreString =
|
fnIsStoreString =
|
opcode==`STS;
|
opcode==`STS;
|
endfunction
|
endfunction
|
|
|
reg [DBW-1:0] branch_pc;
|
reg [DBW-1:0] branch_pc;
|
wire xbr = iqentry_br[head0] | iqentry_br[head1];
|
wire xbr = iqentry_br[head0] | iqentry_br[head1];
|
wire takb = iqentry_br[head0] ? commit0_v : commit1_v;
|
wire takb = iqentry_br[head0] ? commit0_v : commit1_v;
|
wire [DBW-1:0] xbrpc = iqentry_br[head0] ? iqentry_pc[head0] : iqentry_pc[head1];
|
wire [DBW-1:0] xbrpc = iqentry_br[head0] ? iqentry_pc[head0] : iqentry_pc[head1];
|
|
|
wire predict_taken0;
|
wire predict_taken0;
|
wire predict_taken1;
|
wire predict_taken1;
|
|
|
// This is really just a single history table with three read ports.
|
// This is really just a single history table with three read ports.
|
// One for fetchbuf0, one for fetchbuf1 and one for the branch_pc.
|
// One for fetchbuf0, one for fetchbuf1 and one for the branch_pc.
|
// Ideally, there really needs to be two write ports as well (for
|
// Ideally, there really needs to be two write ports as well (for
|
// head0 and head1).
|
// head0 and head1).
|
// There is only a single write port for branches committing at
|
// There is only a single write port for branches committing at
|
// head0 or head1. If there are two branches one after the other
|
// head0 or head1. If there are two branches one after the other
|
// in code, then the prediction will be off because the taken/
|
// in code, then the prediction will be off because the taken/
|
// not taken status for the second branch won't be updated. It
|
// not taken status for the second branch won't be updated. It
|
// doesn't happen that often that branches are piled together and
|
// doesn't happen that often that branches are piled together and
|
// executing during the same clock cycle.
|
// executing during the same clock cycle.
|
// There's usually at least an intervening compare operation.
|
// There's usually at least an intervening compare operation.
|
// Needs more work yet.
|
// Needs more work yet.
|
//
|
//
|
// ToDo: add return address stack predictor.
|
// ToDo: add return address stack predictor.
|
//
|
//
|
Thor_BranchHistory #(DBW) ubhtA
|
Thor_BranchHistory #(DBW) ubhtA
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(xbr),
|
.advanceX(xbr),
|
.xisBranch(xbr),
|
.xisBranch(xbr),
|
.pc(branch_pc),
|
.pc(branch_pc),
|
.xpc(xbrpc),
|
.xpc(xbrpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_takenBr)
|
.predict_taken(predict_takenBr)
|
);
|
);
|
|
|
Thor_BranchHistory #(DBW) ubhtB
|
Thor_BranchHistory #(DBW) ubhtB
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(xbr),
|
.advanceX(xbr),
|
.xisBranch(xbr),
|
.xisBranch(xbr),
|
.pc(fetchbuf0_pc),
|
.pc(fetchbuf0_pc),
|
.xpc(xbrpc),
|
.xpc(xbrpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_taken0)
|
.predict_taken(predict_taken0)
|
);
|
);
|
|
|
Thor_BranchHistory #(DBW) ubhtC
|
Thor_BranchHistory #(DBW) ubhtC
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(xbr),
|
.advanceX(xbr),
|
.xisBranch(xbr),
|
.xisBranch(xbr),
|
.pc(fetchbuf1_pc),
|
.pc(fetchbuf1_pc),
|
.xpc(xbrpc),
|
.xpc(xbrpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_taken1)
|
.predict_taken(predict_taken1)
|
);
|
);
|
|
|
/*
|
/*
|
Thor_BranchHistory #(DBW) ubhtC
|
Thor_BranchHistory #(DBW) ubhtC
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(xbr),
|
.advanceX(xbr),
|
.xisBranch(xbr),
|
.xisBranch(xbr),
|
.pc(pc),
|
.pc(pc),
|
.xpc(xbrpc),
|
.xpc(xbrpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_takenC)
|
.predict_taken(predict_takenC)
|
);
|
);
|
|
|
Thor_BranchHistory #(DBW) ubhtD
|
Thor_BranchHistory #(DBW) ubhtD
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(xbr),
|
.advanceX(xbr),
|
.xisBranch(xbr),
|
.xisBranch(xbr),
|
.pc(pc+fnInsnLength(insn)),
|
.pc(pc+fnInsnLength(insn)),
|
.xpc(xbrpc),
|
.xpc(xbrpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_takenD)
|
.predict_taken(predict_takenD)
|
);
|
);
|
*/
|
*/
|
`ifdef PCHIST
|
`ifdef PCHIST
|
wire [63:0] pc_histo;
|
wire [63:0] pc_histo;
|
reg pc_cap;
|
reg pc_cap;
|
reg [5:0] pc_ndx;
|
reg [5:0] pc_ndx;
|
vtdl #(.WID(64),.DEP(64)) uvtl1
|
vtdl #(.WID(64),.DEP(64)) uvtl1
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.ce(pc_cap),
|
.ce(pc_cap),
|
.a(pc_ndx),
|
.a(pc_ndx),
|
.d({fetchbuf1_pc,fetcbuf0_pc}),
|
.d({fetchbuf1_pc,fetcbuf0_pc}),
|
.q(pc_histo)
|
.q(pc_histo)
|
);
|
);
|
`endif
|
`endif
|
|
|
Thor_icachemem #(DBW) uicm1
|
Thor_icachemem #(.DBW(DBW),.ABW(ABW)) uicm1
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.wce(cstate==ICACHE1),
|
.wce(cstate==ICACHE1),
|
.wr(ack_i|err_i),
|
.wr(ack_i|err_i),
|
.wa(adr_o),
|
.wa(adr_o),
|
.wd({err_i,dat_i}),
|
.wd({err_i,dat_i}),
|
.rclk(~clk),
|
.rclk(~clk),
|
.pc(ppc),
|
.pc(ppc),
|
.insn(insn)
|
.insn(insn)
|
);
|
);
|
|
|
wire hit0,hit1;
|
wire hit0,hit1;
|
reg ic_ld;
|
reg ic_ld;
|
reg [31:0] ic_ld_cntr;
|
reg [31:0] ic_ld_cntr;
|
Thor_itagmem #(DBW-1) uitm1
|
Thor_itagmem #(DBW-1) uitm1
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.wce((cstate==ICACHE1 && cti_o==3'b111)|ic_ld),
|
.wce((cstate==ICACHE1 && cti_o==3'b111)|ic_ld),
|
.wr(ack_i|err_i|ic_ld),
|
.wr(ack_i|err_i|ic_ld),
|
.wa(adr_o|ic_ld_cntr),
|
.wa(adr_o|ic_ld_cntr),
|
.err_i(err_i|ierr),
|
.err_i(err_i|ierr),
|
.invalidate(ic_invalidate),
|
.invalidate(ic_invalidate),
|
.invalidate_line(ic_invalidate_line),
|
.invalidate_line(ic_invalidate_line),
|
.invalidate_lineno(ic_lineno),
|
.invalidate_lineno(ic_lineno),
|
.rclk(~clk),
|
.rclk(~clk),
|
.rce(1'b1),
|
.rce(1'b1),
|
.pc(ppc),
|
.pc(ppc),
|
.hit0(hit0),
|
.hit0(hit0),
|
.hit1(hit1),
|
.hit1(hit1),
|
.err_o(insnerr)
|
.err_o(insnerr)
|
);
|
);
|
|
|
wire ihit = hit0 & hit1;
|
wire ihit = hit0 & hit1;
|
wire do_pcinc = ihit;// && !((nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit));
|
wire do_pcinc = ihit;// && !((nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit));
|
wire ld_fetchbuf = ihit || (nmi_edge & !StatusHWI)||(irq_i & ~im & !StatusHWI);
|
wire ld_fetchbuf = ihit || (nmi_edge & !StatusHWI)||(irq_i & ~im & !StatusHWI);
|
|
|
wire whit;
|
wire whit;
|
|
|
Thor_dcachemem_1w1r #(DBW) udcm1
|
Thor_dcachemem_1w1r #(DBW) udcm1
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.wce(whit || cstate==DCACHE1),
|
.wce(whit || cstate==DCACHE1),
|
.wr(ack_i|err_i),
|
.wr(ack_i|err_i),
|
.sel(whit ? sel_o : 8'hFF),
|
.sel(whit ? sel_o : 8'hFF),
|
.wa(adr_o),
|
.wa(adr_o),
|
.wd(whit ? dat_o : dat_i),
|
.wd(whit ? dat_o : dat_i),
|
.rclk(~clk),
|
.rclk(~clk),
|
.rce(1'b1),
|
.rce(1'b1),
|
.ra(pea),
|
.ra(pea),
|
.o(cdat)
|
.o(cdat)
|
);
|
);
|
|
|
Thor_dtagmem #(DBW-1) udtm1
|
Thor_dtagmem #(DBW-1) udtm1
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.wce(cstate==DCACHE1 && cti_o==3'b111),
|
.wce(cstate==DCACHE1 && cti_o==3'b111),
|
.wr(ack_i|err_i),
|
.wr(ack_i|err_i),
|
.wa(adr_o),
|
.wa(adr_o),
|
.err_i(err_i|derr),
|
.err_i(err_i|derr),
|
.invalidate(dc_invalidate),
|
.invalidate(dc_invalidate),
|
.invalidate_line(dc_invalidate_line),
|
.invalidate_line(dc_invalidate_line),
|
.invalidate_lineno(dc_lineno),
|
.invalidate_lineno(dc_lineno),
|
.rclk(~clk),
|
.rclk(~clk),
|
.rce(1'b1),
|
.rce(1'b1),
|
.ra(pea),
|
.ra(pea),
|
.whit(whit),
|
.whit(whit),
|
.rhit(rhit),
|
.rhit(rhit),
|
.err_o()
|
.err_o()
|
);
|
);
|
|
|
wire [DBW-1:0] shfto0,shfto1;
|
wire [DBW-1:0] shfto0,shfto1;
|
|
|
function fnIsShiftiop;
|
function fnIsShiftiop;
|
input [63:0] isn;
|
input [63:0] isn;
|
fnIsShiftiop = isn[15:8]==`SHIFT && (
|
fnIsShiftiop = isn[15:8]==`SHIFT && (
|
isn[39:34]==`SHLI || isn[39:34]==`SHLUI ||
|
isn[39:34]==`SHLI || isn[39:34]==`SHLUI ||
|
isn[39:34]==`SHRI || isn[39:34]==`SHRUI ||
|
isn[39:34]==`SHRI || isn[39:34]==`SHRUI ||
|
isn[39:34]==`ROLI || isn[39:34]==`RORI
|
isn[39:34]==`ROLI || isn[39:34]==`RORI
|
)
|
)
|
;
|
;
|
endfunction
|
endfunction
|
|
|
function fnIsShiftop;
|
function fnIsShiftop;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsShiftop = opcode==`SHL || opcode==`SHLI || opcode==`SHLU || opcode==`SHLUI ||
|
fnIsShiftop = opcode==`SHL || opcode==`SHLI || opcode==`SHLU || opcode==`SHLUI ||
|
opcode==`SHR || opcode==`SHRI || opcode==`SHRU || opcode==`SHRUI ||
|
opcode==`SHR || opcode==`SHRI || opcode==`SHRU || opcode==`SHRUI ||
|
opcode==`ROL || opcode==`ROLI || opcode==`ROR || opcode==`RORI
|
opcode==`ROL || opcode==`ROLI || opcode==`ROR || opcode==`RORI
|
;
|
;
|
endfunction
|
endfunction
|
|
|
function fnIsFP;
|
function fnIsFP;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsFP = opcode==`DOUBLE_R||opcode==`FLOAT||opcode==`SINGLE_R;
|
fnIsFP = opcode==`DOUBLE_R||opcode==`FLOAT||opcode==`SINGLE_R;
|
// opcode==`ITOF || opcode==`FTOI || opcode==`FNEG || opcode==`FSIGN || /*opcode==`FCMP || */ opcode==`FABS ||
|
// opcode==`ITOF || opcode==`FTOI || opcode==`FNEG || opcode==`FSIGN || /*opcode==`FCMP || */ opcode==`FABS ||
|
// opcode==`FADD || opcode==`FSUB || opcode==`FMUL || opcode==`FDIV
|
// opcode==`FADD || opcode==`FSUB || opcode==`FMUL || opcode==`FDIV
|
// ;
|
// ;
|
endfunction
|
endfunction
|
|
|
function fnIsFPCtrl;
|
function fnIsFPCtrl;
|
input [63:0] isn;
|
input [63:0] isn;
|
fnIsFPCtrl = (isn[15:8]==`SINGLE_R && (isn[31:28]==`FTX||isn[31:28]==`FCX||isn[31:28]==`FDX||isn[31:28]==`FEX)) ||
|
fnIsFPCtrl = (isn[15:8]==`SINGLE_R && (isn[31:28]==`FTX||isn[31:28]==`FCX||isn[31:28]==`FDX||isn[31:28]==`FEX)) ||
|
(isn[15:8]==`DOUBLE_R && (isn[31:28]==`FRM))
|
(isn[15:8]==`DOUBLE_R && (isn[31:28]==`FRM))
|
;
|
;
|
endfunction
|
endfunction
|
|
|
function fnIsBitfield;
|
function fnIsBitfield;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsBitfield = opcode==`BITFIELD;
|
fnIsBitfield = opcode==`BITFIELD;
|
endfunction
|
endfunction
|
|
|
//wire [3:0] Pn = ir[7:4];
|
//wire [3:0] Pn = ir[7:4];
|
|
|
// Set the target register
|
// Set the target register
|
// 00-3F = general register file
|
// 00-3F = general register file
|
// 40-4F = predicate register
|
// 40-4F = predicate register
|
// 50-5F = code address register
|
// 50-5F = code address register
|
// 60-67 = segment base register
|
// 60-67 = segment base register
|
// 68-6F = segment limit register
|
// 68-6F = segment limit register
|
// 70 = predicate register horizontal
|
// 70 = predicate register horizontal
|
// 73 = loop counter
|
// 73 = loop counter
|
// 7C = breakout index register
|
// 7C = breakout index register
|
// 7D = broken out register
|
// 7D = broken out register
|
// 7F = power shift register
|
// 7F = power shift register
|
function [6:0] fnTargetReg;
|
function [6:0] fnTargetReg;
|
input [63:0] ir;
|
input [63:0] ir;
|
begin
|
begin
|
// Process special predicates (NOP, IMM)
|
// Process special predicates (NOP, IMM)
|
// Note that BRK (00) is already translated to a SYS instruction
|
// Note that BRK (00) is already translated to a SYS instruction
|
if (ir[3:0]==4'h0)
|
if (ir[3:0]==4'h0)
|
fnTargetReg = 7'h000;
|
fnTargetReg = 7'h000;
|
else
|
else
|
case(fnOpcode(ir))
|
case(fnOpcode(ir))
|
`POP: fnTargetReg = ir[22:16];
|
`POP: fnTargetReg = ir[22:16];
|
`LDI,`ADDUIS,`STS,`LINK,`UNLINK:
|
`LDI,`ADDUIS,`STS,`LINK,`UNLINK:
|
fnTargetReg = {1'b0,ir[21:16]};
|
fnTargetReg = {1'b0,ir[21:16]};
|
`LDIS:
|
`LDIS:
|
fnTargetReg = {1'b1,ir[21:16]};
|
fnTargetReg = {1'b1,ir[21:16]};
|
`RR:
|
`RR:
|
fnTargetReg = {1'b0,ir[33:28]};
|
fnTargetReg = {1'b0,ir[33:28]};
|
`BCD,
|
`BCD,
|
`LOGIC,`FLOAT,
|
`LOGIC,`FLOAT,
|
`LWX,`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`STMV,`STCMP,`STFND:
|
`LWX,`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`STMV,`STCMP,`STFND:
|
fnTargetReg = {1'b0,ir[33:28]};
|
fnTargetReg = {1'b0,ir[33:28]};
|
`SHIFT:
|
`SHIFT:
|
fnTargetReg = {1'b0,ir[33:28]};
|
fnTargetReg = {1'b0,ir[33:28]};
|
`R,`R2,`DOUBLE_R,`SINGLE_R,
|
`R,`R2,`DOUBLE_R,`SINGLE_R,
|
`ADDI,`ADDUI,`SUBI,`SUBUI,
|
`ADDI,`ADDUI,`SUBI,`SUBUI,
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
|
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,
|
`ANDI,`ORI,`EORI,`LLA,
|
`ANDI,`ORI,`EORI,`LLA,`LEA,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LINK:
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LINK:
|
fnTargetReg = {1'b0,ir[27:22]};
|
fnTargetReg = {1'b0,ir[27:22]};
|
`CAS:
|
`CAS:
|
fnTargetReg = {1'b0,ir[39:34]};
|
fnTargetReg = {1'b0,ir[39:34]};
|
`BITFIELD:
|
`BITFIELD:
|
fnTargetReg = {1'b0,ir[27:22]};
|
fnTargetReg = {1'b0,ir[27:22]};
|
`TLB:
|
`TLB:
|
if (ir[19:16]==`TLB_RDREG)
|
if (ir[19:16]==`TLB_RDREG)
|
fnTargetReg = {1'b0,ir[29:24]};
|
fnTargetReg = {1'b0,ir[29:24]};
|
else
|
else
|
fnTargetReg = 7'h00;
|
fnTargetReg = 7'h00;
|
`MFSPR:
|
`MFSPR:
|
fnTargetReg = {1'b0,ir[27:22]};
|
fnTargetReg = {1'b0,ir[27:22]};
|
`BITI:
|
`BITI:
|
fnTargetReg = {3'h4,ir[25:22]};
|
fnTargetReg = {3'h4,ir[25:22]};
|
// TST
|
// TST
|
8'h00,8'h01,8'h02,8'h03,
|
8'h00,8'h01,8'h02,8'h03,
|
8'h04,8'h05,8'h06,8'h07,
|
8'h04,8'h05,8'h06,8'h07,
|
8'h08,8'h09,8'h0A,8'h0B,
|
8'h08,8'h09,8'h0A,8'h0B,
|
8'h0C,8'h0D,8'h0E,8'h0F,
|
8'h0C,8'h0D,8'h0E,8'h0F,
|
// CMP
|
// CMP
|
8'h10,8'h11,8'h12,8'h13,
|
8'h10,8'h11,8'h12,8'h13,
|
8'h14,8'h15,8'h16,8'h17,
|
8'h14,8'h15,8'h16,8'h17,
|
8'h18,8'h19,8'h1A,8'h1B,
|
8'h18,8'h19,8'h1A,8'h1B,
|
8'h1C,8'h1D,8'h1E,8'h1F,
|
8'h1C,8'h1D,8'h1E,8'h1F,
|
// CMPI
|
// CMPI
|
8'h20,8'h21,8'h22,8'h23,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h2C,8'h2D,8'h2E,8'h2F:
|
8'h2C,8'h2D,8'h2E,8'h2F:
|
begin
|
begin
|
fnTargetReg = {3'h4,ir[11:8]};
|
fnTargetReg = {3'h4,ir[11:8]};
|
end
|
end
|
`SWCR: fnTargetReg = {3'h4,4'h0};
|
`SWCR: fnTargetReg = {3'h4,4'h0};
|
`JSR,`JSRZ,`JSRS,`SYS,`INT:
|
`JSR,`JSRZ,`JSRS,`SYS,`INT:
|
fnTargetReg = {3'h5,ir[19:16]};
|
fnTargetReg = {3'h5,ir[19:16]};
|
`JMPI:
|
`JMPI:
|
fnTargetReg = {3'h5,ir[25:22]};
|
fnTargetReg = {3'h5,ir[25:22]};
|
`JMPIX:
|
`JMPIX:
|
fnTargetReg = {3'h5,ir[31:28]};
|
fnTargetReg = {3'h5,ir[31:28]};
|
`MTSPR,`MOVS,`LWS:
|
`MTSPR,`MOVS,`LWS:
|
fnTargetReg = {1'b1,ir[27:22]};
|
fnTargetReg = {1'b1,ir[27:22]};
|
/*
|
/*
|
if (ir[27:26]==2'h1) // Move to code address register
|
if (ir[27:26]==2'h1) // Move to code address register
|
fnTargetReg = {3'h5,ir[25:22]};
|
fnTargetReg = {3'h5,ir[25:22]};
|
else if (ir[27:26]==2'h2) // Move to seg. reg.
|
else if (ir[27:26]==2'h2) // Move to seg. reg.
|
fnTargetReg = {3'h6,ir[25:22]};
|
fnTargetReg = {3'h6,ir[25:22]};
|
else if (ir[27:22]==6'h04)
|
else if (ir[27:22]==6'h04)
|
fnTargetReg = 7'h70;
|
fnTargetReg = 7'h70;
|
else
|
else
|
fnTargetReg = 7'h00;
|
fnTargetReg = 7'h00;
|
*/
|
*/
|
`PUSH: fnTargetReg = km ? 7'd31 : 7'd27;
|
`PUSH: fnTargetReg = km ? 7'd31 : 7'd27;
|
`LOOP: fnTargetReg = 7'h73;
|
`LOOP: fnTargetReg = 7'h73;
|
`STP: fnTargetReg = 7'h7F;
|
`STP: fnTargetReg = 7'h7F;
|
`P: fnTargetReg = 7'h70;
|
`P: fnTargetReg = 7'h70;
|
default: fnTargetReg = 7'h00;
|
default: fnTargetReg = 7'h00;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
/*
|
/*
|
function fnAllowedReg;
|
function fnAllowedReg;
|
input [8:0] regno;
|
input [8:0] regno;
|
fnAllowedReg = allowedRegs[regno] ? regno : 9'h000;
|
fnAllowedReg = allowedRegs[regno] ? regno : 9'h000;
|
endfunction
|
endfunction
|
*/
|
*/
|
function fnTargetsCa;
|
function fnTargetsCa;
|
input [63:0] ir;
|
input [63:0] ir;
|
begin
|
begin
|
if (ir[3:0]==4'h0)
|
if (ir[3:0]==4'h0)
|
fnTargetsCa = `FALSE;
|
fnTargetsCa = `FALSE;
|
else begin
|
else begin
|
case(fnOpcode(ir))
|
case(fnOpcode(ir))
|
`JSR,`JSRZ,`JSRS,`SYS,`INT:
|
`JSR,`JSRZ,`JSRS,`SYS,`INT:
|
fnTargetsCa = `TRUE;
|
fnTargetsCa = `TRUE;
|
`JMPI,`JMPIX:
|
`JMPI,`JMPIX:
|
fnTargetsCa = `TRUE;
|
fnTargetsCa = `TRUE;
|
`LWS:
|
`LWS:
|
if (ir[27:26]==2'h1)
|
if (ir[27:26]==2'h1)
|
fnTargetsCa = `TRUE;
|
fnTargetsCa = `TRUE;
|
else
|
else
|
fnTargetsCa = `FALSE;
|
fnTargetsCa = `FALSE;
|
`LDIS:
|
`LDIS:
|
if (ir[21:20]==2'h1)
|
if (ir[21:20]==2'h1)
|
fnTargetsCa = `TRUE;
|
fnTargetsCa = `TRUE;
|
else
|
else
|
fnTargetsCa = `FALSE;
|
fnTargetsCa = `FALSE;
|
`MTSPR,`MOVS:
|
`MTSPR,`MOVS:
|
begin
|
begin
|
if (ir[27:26]==2'h1)
|
if (ir[27:26]==2'h1)
|
fnTargetsCa = `TRUE;
|
fnTargetsCa = `TRUE;
|
else
|
else
|
fnTargetsCa = `FALSE;
|
fnTargetsCa = `FALSE;
|
end
|
end
|
default: fnTargetsCa = `FALSE;
|
default: fnTargetsCa = `FALSE;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function fnTargetsSegreg;
|
function fnTargetsSegreg;
|
input [63:0] ir;
|
input [63:0] ir;
|
if (ir[3:0]==4'h0)
|
if (ir[3:0]==4'h0)
|
fnTargetsSegreg = `FALSE;
|
fnTargetsSegreg = `FALSE;
|
else
|
else
|
case(fnOpcode(ir))
|
case(fnOpcode(ir))
|
`LWS:
|
`LWS:
|
if (ir[27:26]==2'h2)
|
if (ir[27:26]==2'h2)
|
fnTargetsSegreg = `TRUE;
|
fnTargetsSegreg = `TRUE;
|
else
|
else
|
fnTargetsSegreg = `FALSE;
|
fnTargetsSegreg = `FALSE;
|
`LDIS:
|
`LDIS:
|
if (ir[21:20]==2'h2)
|
if (ir[21:20]==2'h2)
|
fnTargetsSegreg = `TRUE;
|
fnTargetsSegreg = `TRUE;
|
else
|
else
|
fnTargetsSegreg = `FALSE;
|
fnTargetsSegreg = `FALSE;
|
`MTSPR,`MOVS:
|
`MTSPR,`MOVS:
|
if (ir[27:26]==2'h2)
|
if (ir[27:26]==2'h2)
|
fnTargetsSegreg = `TRUE;
|
fnTargetsSegreg = `TRUE;
|
else
|
else
|
fnTargetsSegreg = `FALSE;
|
fnTargetsSegreg = `FALSE;
|
default: fnTargetsSegreg = `FALSE;
|
default: fnTargetsSegreg = `FALSE;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function fnHasConst;
|
function fnHasConst;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
case(opcode)
|
case(opcode)
|
`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS,
|
`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS,
|
`LDI,`LDIS,`ADDUIS,
|
`LDI,`LDIS,`ADDUIS,
|
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
|
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,
|
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,
|
// CMPI
|
// CMPI
|
8'h20,8'h21,8'h22,8'h23,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
// BR
|
// BR
|
8'h30,8'h31,8'h32,8'h33,
|
8'h30,8'h31,8'h32,8'h33,
|
8'h34,8'h35,8'h36,8'h37,
|
8'h34,8'h35,8'h36,8'h37,
|
8'h38,8'h39,8'h3A,8'h3B,
|
8'h38,8'h39,8'h3A,8'h3B,
|
8'h3C,8'h3D,8'h3E,8'h3F,
|
8'h3C,8'h3D,8'h3E,8'h3F,
|
`ANDI,`ORI,`EORI,`BITI,
|
`ANDI,`ORI,`EORI,`BITI,
|
// `SHLI,`SHLUI,`SHRI,`SHRUI,`ROLI,`RORI,
|
// `SHLI,`SHLUI,`SHRI,`SHRUI,`ROLI,`RORI,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`INC,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`INC,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,`STI,`JMPI,
|
`LVB,`LVC,`LVH,`LVW,`LVWAR,`STI,`JMPI,
|
`SB,`SC,`SH,`SW,`SWCR,`CAS,`SWS,
|
`SB,`SC,`SH,`SW,`SWCR,`CAS,`SWS,
|
`RTI,`RTD,`RTE,`LLA,
|
`RTI,`RTD,`RTE,`LLA,
|
`JSR,`JSRS,`SYS,`INT,`LOOP,`PEA,`LINK,`UNLINK:
|
`JSR,`JSRS,`SYS,`INT,`LOOP,`PEA,`LINK,`UNLINK:
|
fnHasConst = 1'b1;
|
fnHasConst = 1'b1;
|
default:
|
default:
|
fnHasConst = 1'b0;
|
fnHasConst = 1'b0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// Used by memory issue logic.
|
// Used by memory issue logic.
|
function fnIsFlowCtrl;
|
function fnIsFlowCtrl;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
begin
|
begin
|
case(opcode)
|
case(opcode)
|
`JMPI,`JMPIX,
|
`JMPI,`JMPIX,
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE:
|
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE:
|
fnIsFlowCtrl = 1'b1;
|
fnIsFlowCtrl = 1'b1;
|
default:
|
default:
|
if (opcode[7:4]==`BR)
|
if (opcode[7:4]==`BR)
|
fnIsFlowCtrl = 1'b1;
|
fnIsFlowCtrl = 1'b1;
|
else
|
else
|
fnIsFlowCtrl = 1'b0;
|
fnIsFlowCtrl = 1'b0;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
// fnCanException
|
// fnCanException
|
//
|
//
|
// Used by memory issue logic.
|
// Used by memory issue logic.
|
// Returns TRUE if the instruction can cause an exception.
|
// Returns TRUE if the instruction can cause an exception.
|
// In debug mode any instruction could potentially cause a breakpoint exception.
|
// In debug mode any instruction could potentially cause a breakpoint exception.
|
// Rather than check all the addresses for potential debug exceptions it's
|
// Rather than check all the addresses for potential debug exceptions it's
|
// simpler to just have it so that all instructions could exception. This will
|
// simpler to just have it so that all instructions could exception. This will
|
// slow processing down somewhat as stores will only be done at the head of the
|
// slow processing down somewhat as stores will only be done at the head of the
|
// instruction queue, but it's debug mode so we probably don't care.
|
// instruction queue, but it's debug mode so we probably don't care.
|
//
|
//
|
function fnCanException;
|
function fnCanException;
|
input [7:0] op;
|
input [7:0] op;
|
input [5:0] func;
|
input [5:0] func;
|
if (debug_on)
|
if (debug_on)
|
fnCanException = `TRUE;
|
fnCanException = `TRUE;
|
else
|
else
|
case(op)
|
case(op)
|
`FLOAT:
|
`FLOAT:
|
case(func)
|
case(func)
|
`FDIVS,`FMULS,`FADDS,`FSUBS,
|
`FDIVS,`FMULS,`FADDS,`FSUBS,
|
`FDIV,`FMUL,`FADD,`FSUB:
|
`FDIV,`FMUL,`FADD,`FSUB:
|
fnCanException = `TRUE;
|
fnCanException = `TRUE;
|
default: fnCanException = `FALSE;
|
default: fnCanException = `FALSE;
|
endcase
|
endcase
|
`SINGLE_R:
|
`SINGLE_R:
|
if (func==`FTX) fnCanException = `TRUE;
|
if (func==`FTX) fnCanException = `TRUE;
|
else fnCanException = `FALSE;
|
else fnCanException = `FALSE;
|
`ADDI,`SUBI,`DIVI,`MODI,`MULI:
|
`ADDI,`SUBI,`DIVI,`MODI,`MULI:
|
fnCanException = `TRUE;
|
fnCanException = `TRUE;
|
`RR:
|
`RR:
|
if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD)
|
if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD)
|
fnCanException = `TRUE;
|
fnCanException = `TRUE;
|
else
|
else
|
fnCanException = `FALSE;
|
fnCanException = `FALSE;
|
`TLB,`RTI,`RTD,`RTE,`CLI,`SEI:
|
`TLB,`RTI,`RTD,`RTE,`CLI,`SEI:
|
fnCanException = `TRUE;
|
fnCanException = `TRUE;
|
default:
|
default:
|
fnCanException = fnIsMem(op);
|
fnCanException = fnIsMem(op);
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// fnInsnLength
|
// fnInsnLength
|
// Used by fetch logic.
|
// Used by fetch logic.
|
// Return the length of an instruction.
|
// Return the length of an instruction.
|
//
|
//
|
function [3:0] fnInsnLength;
|
function [3:0] fnInsnLength;
|
input [127:0] isn;
|
input [127:0] isn;
|
case(isn[7:0])
|
case(isn[7:0])
|
8'b00000000: fnInsnLength = 4'd1; // BRK
|
8'b00000000: fnInsnLength = 4'd1; // BRK
|
8'b00010000: fnInsnLength = 4'd1; // NOP
|
8'b00010000: fnInsnLength = 4'd1; // NOP
|
8'b00100000: fnInsnLength = 4'd2;
|
8'b00100000: fnInsnLength = 4'd2;
|
8'b00110000: fnInsnLength = 4'd3;
|
8'b00110000: fnInsnLength = 4'd3;
|
8'b01000000: fnInsnLength = 4'd4;
|
8'b01000000: fnInsnLength = 4'd4;
|
8'b01010000: fnInsnLength = 4'd5;
|
8'b01010000: fnInsnLength = 4'd5;
|
8'b01100000: fnInsnLength = 4'd6;
|
8'b01100000: fnInsnLength = 4'd6;
|
8'b01110000: fnInsnLength = 4'd7;
|
8'b01110000: fnInsnLength = 4'd7;
|
8'b10000000: fnInsnLength = 4'd8;
|
8'b10000000: fnInsnLength = 4'd8;
|
default:
|
default:
|
case(isn[15:8])
|
case(isn[15:8])
|
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`MEMSB,`MEMDB,`SYNC:
|
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`MEMSB,`MEMDB,`SYNC:
|
fnInsnLength = 4'd2;
|
fnInsnLength = 4'd2;
|
`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK:
|
`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK:
|
fnInsnLength = 4'd3;
|
fnInsnLength = 4'd3;
|
`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`STP:
|
`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`STP:
|
fnInsnLength = 4'd4;
|
fnInsnLength = 4'd4;
|
`BITFIELD,`JSR,`MUX,`BCD,`INC:
|
`BITFIELD,`JSR,`MUX,`BCD,`INC:
|
fnInsnLength = 4'd6;
|
fnInsnLength = 4'd6;
|
`CAS:
|
`CAS:
|
fnInsnLength = 4'd6;
|
fnInsnLength = 4'd6;
|
default:
|
default:
|
begin
|
begin
|
case(isn[15:12])
|
case(isn[15:12])
|
`TST: fnInsnLength = 4'd3;
|
`TST: fnInsnLength = 4'd3;
|
`BR: fnInsnLength = 4'd3;
|
`BR: fnInsnLength = 4'd3;
|
`CMP,`CMPI: fnInsnLength = 4'd4;
|
`CMP,`CMPI: fnInsnLength = 4'd4;
|
default: fnInsnLength = 4'd5;
|
default: fnInsnLength = 4'd5;
|
endcase
|
endcase
|
end
|
end
|
endcase
|
endcase
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [3:0] fnInsnLength1;
|
function [3:0] fnInsnLength1;
|
input [127:0] isn;
|
input [127:0] isn;
|
case(fnInsnLength(isn))
|
case(fnInsnLength(isn))
|
4'd1: fnInsnLength1 = fnInsnLength(isn[127: 8]);
|
4'd1: fnInsnLength1 = fnInsnLength(isn[127: 8]);
|
4'd2: fnInsnLength1 = fnInsnLength(isn[127:16]);
|
4'd2: fnInsnLength1 = fnInsnLength(isn[127:16]);
|
4'd3: fnInsnLength1 = fnInsnLength(isn[127:24]);
|
4'd3: fnInsnLength1 = fnInsnLength(isn[127:24]);
|
4'd4: fnInsnLength1 = fnInsnLength(isn[127:32]);
|
4'd4: fnInsnLength1 = fnInsnLength(isn[127:32]);
|
4'd5: fnInsnLength1 = fnInsnLength(isn[127:40]);
|
4'd5: fnInsnLength1 = fnInsnLength(isn[127:40]);
|
4'd6: fnInsnLength1 = fnInsnLength(isn[127:48]);
|
4'd6: fnInsnLength1 = fnInsnLength(isn[127:48]);
|
4'd7: fnInsnLength1 = fnInsnLength(isn[127:56]);
|
4'd7: fnInsnLength1 = fnInsnLength(isn[127:56]);
|
4'd8: fnInsnLength1 = fnInsnLength(isn[127:64]);
|
4'd8: fnInsnLength1 = fnInsnLength(isn[127:64]);
|
default: fnInsnLength1 = 4'd0;
|
default: fnInsnLength1 = 4'd0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [3:0] fnInsnLength2;
|
function [3:0] fnInsnLength2;
|
input [127:0] isn;
|
input [127:0] isn;
|
case(fnInsnLength(isn)+fnInsnLength1(isn))
|
case(fnInsnLength(isn)+fnInsnLength1(isn))
|
4'd2: fnInsnLength2 = fnInsnLength(isn[127:16]);
|
4'd2: fnInsnLength2 = fnInsnLength(isn[127:16]);
|
4'd3: fnInsnLength2 = fnInsnLength(isn[127:24]);
|
4'd3: fnInsnLength2 = fnInsnLength(isn[127:24]);
|
4'd4: fnInsnLength2 = fnInsnLength(isn[127:32]);
|
4'd4: fnInsnLength2 = fnInsnLength(isn[127:32]);
|
4'd5: fnInsnLength2 = fnInsnLength(isn[127:40]);
|
4'd5: fnInsnLength2 = fnInsnLength(isn[127:40]);
|
4'd6: fnInsnLength2 = fnInsnLength(isn[127:48]);
|
4'd6: fnInsnLength2 = fnInsnLength(isn[127:48]);
|
4'd7: fnInsnLength2 = fnInsnLength(isn[127:56]);
|
4'd7: fnInsnLength2 = fnInsnLength(isn[127:56]);
|
4'd8: fnInsnLength2 = fnInsnLength(isn[127:64]);
|
4'd8: fnInsnLength2 = fnInsnLength(isn[127:64]);
|
4'd9: fnInsnLength2 = fnInsnLength(isn[127:72]);
|
4'd9: fnInsnLength2 = fnInsnLength(isn[127:72]);
|
4'd10: fnInsnLength2 = fnInsnLength(isn[127:80]);
|
4'd10: fnInsnLength2 = fnInsnLength(isn[127:80]);
|
4'd11: fnInsnLength2 = fnInsnLength(isn[127:88]);
|
4'd11: fnInsnLength2 = fnInsnLength(isn[127:88]);
|
4'd12: fnInsnLength2 = fnInsnLength(isn[127:96]);
|
4'd12: fnInsnLength2 = fnInsnLength(isn[127:96]);
|
4'd13: fnInsnLength2 = fnInsnLength(isn[127:104]);
|
4'd13: fnInsnLength2 = fnInsnLength(isn[127:104]);
|
4'd14: fnInsnLength2 = fnInsnLength(isn[127:112]);
|
4'd14: fnInsnLength2 = fnInsnLength(isn[127:112]);
|
4'd15: fnInsnLength2 = fnInsnLength(isn[127:120]);
|
4'd15: fnInsnLength2 = fnInsnLength(isn[127:120]);
|
default: fnInsnLength2 = 4'd0;
|
default: fnInsnLength2 = 4'd0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
wire [5:0] total_insn_length = fnInsnLength(insn) + fnInsnLength1(insn) + fnInsnLength2(insn);
|
wire [5:0] total_insn_length = fnInsnLength(insn) + fnInsnLength1(insn) + fnInsnLength2(insn);
|
wire [5:0] insn_length12 = fnInsnLength(insn) + fnInsnLength1(insn);
|
wire [5:0] insn_length12 = fnInsnLength(insn) + fnInsnLength1(insn);
|
wire insn3_will_fit = total_insn_length < 6'd16;
|
wire insn3_will_fit = total_insn_length < 6'd16;
|
|
|
always @(fetchbuf or fetchbufA_instr or fetchbufA_v or fetchbufA_pc
|
always @(fetchbuf or fetchbufA_instr or fetchbufA_v or fetchbufA_pc
|
or fetchbufB_instr or fetchbufB_v or fetchbufB_pc
|
or fetchbufB_instr or fetchbufB_v or fetchbufB_pc
|
or fetchbufC_instr or fetchbufC_v or fetchbufC_pc
|
or fetchbufC_instr or fetchbufC_v or fetchbufC_pc
|
or fetchbufD_instr or fetchbufD_v or fetchbufD_pc
|
or fetchbufD_instr or fetchbufD_v or fetchbufD_pc
|
)
|
)
|
begin
|
begin
|
fetchbuf0_instr <= (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr;
|
fetchbuf0_instr <= (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr;
|
fetchbuf0_v <= (fetchbuf == 1'b0) ? fetchbufA_v : fetchbufC_v ;
|
fetchbuf0_v <= (fetchbuf == 1'b0) ? fetchbufA_v : fetchbufC_v ;
|
|
|
if (int_pending && string_pc!=64'd0)
|
if (int_pending && string_pc!=64'd0)
|
fetchbuf0_pc <= string_pc;
|
fetchbuf0_pc <= string_pc;
|
else
|
else
|
fetchbuf0_pc <= (fetchbuf == 1'b0) ? fetchbufA_pc : fetchbufC_pc ;
|
fetchbuf0_pc <= (fetchbuf == 1'b0) ? fetchbufA_pc : fetchbufC_pc ;
|
|
|
fetchbuf1_instr <= (fetchbuf == 1'b0) ? fetchbufB_instr : fetchbufD_instr;
|
fetchbuf1_instr <= (fetchbuf == 1'b0) ? fetchbufB_instr : fetchbufD_instr;
|
fetchbuf1_v <= (fetchbuf == 1'b0) ? fetchbufB_v : fetchbufD_v ;
|
fetchbuf1_v <= (fetchbuf == 1'b0) ? fetchbufB_v : fetchbufD_v ;
|
|
|
if (int_pending && string_pc != 64'd0)
|
if (int_pending && string_pc != 64'd0)
|
fetchbuf1_pc <= string_pc;
|
fetchbuf1_pc <= string_pc;
|
else
|
else
|
fetchbuf1_pc <= (fetchbuf == 1'b0) ? fetchbufB_pc : fetchbufD_pc ;
|
fetchbuf1_pc <= (fetchbuf == 1'b0) ? fetchbufB_pc : fetchbufD_pc ;
|
end
|
end
|
|
|
wire [7:0] opcodeA = fnOpcode(fetchbufA_instr);
|
wire [7:0] opcodeA = fnOpcode(fetchbufA_instr);
|
wire [7:0] opcodeB = fnOpcode(fetchbufB_instr);
|
wire [7:0] opcodeB = fnOpcode(fetchbufB_instr);
|
wire [7:0] opcodeC = fnOpcode(fetchbufC_instr);
|
wire [7:0] opcodeC = fnOpcode(fetchbufC_instr);
|
wire [7:0] opcodeD = fnOpcode(fetchbufD_instr);
|
wire [7:0] opcodeD = fnOpcode(fetchbufD_instr);
|
|
|
function fnIsMem;
|
function fnIsMem;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsMem = opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
fnIsMem = opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
opcode==`LBX || opcode==`LWX || opcode==`LBUX || opcode==`LHX || opcode==`LHUX || opcode==`LCX || opcode==`LCUX ||
|
opcode==`LBX || opcode==`LWX || opcode==`LBUX || opcode==`LHX || opcode==`LHUX || opcode==`LCX || opcode==`LCUX ||
|
opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
|
opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
|
opcode==`STS || opcode==`LCL ||
|
opcode==`STS || opcode==`LCL ||
|
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
|
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
|
opcode==`TLB || opcode==`CAS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
|
opcode==`TLB || opcode==`CAS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
|
opcode==`LWS || opcode==`SWS || opcode==`STI ||
|
opcode==`LWS || opcode==`SWS || opcode==`STI ||
|
opcode==`INC ||
|
opcode==`INC ||
|
opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`PUSH || opcode==`POP || opcode==`PEA || opcode==`LINK || opcode==`UNLINK
|
opcode==`PUSH || opcode==`POP || opcode==`PEA || opcode==`LINK || opcode==`UNLINK
|
;
|
;
|
endfunction
|
endfunction
|
|
|
// Determines which instruction write to the register file
|
// Determines which instruction write to the register file
|
function fnIsRFW;
|
function fnIsRFW;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [63:0] ir;
|
input [63:0] ir;
|
begin
|
begin
|
fnIsRFW = // General registers
|
fnIsRFW = // General registers
|
opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
opcode==`LVB || opcode==`LVH || opcode==`LVC || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
|
opcode==`LVB || opcode==`LVH || opcode==`LVC || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
|
opcode==`STP || opcode==`LLA || opcode==`LLAX ||
|
opcode==`STP || opcode==`LLA || opcode==`LLAX || opcode==`LEA ||
|
opcode==`CAS || opcode==`LWS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
|
opcode==`CAS || opcode==`LWS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
|
opcode==`STS || opcode==`PUSH || opcode==`POP || opcode==`LINK || opcode==`UNLINK ||
|
opcode==`STS || opcode==`PUSH || opcode==`POP || opcode==`LINK || opcode==`UNLINK ||
|
opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`ADDI || opcode==`SUBI || opcode==`ADDUI || opcode==`SUBUI ||
|
opcode==`ADDI || opcode==`SUBI || opcode==`ADDUI || opcode==`SUBUI ||
|
opcode==`MULI || opcode==`MULUI || opcode==`DIVI || opcode==`DIVUI || opcode==`MODI || opcode==`MODUI ||
|
opcode==`MULI || opcode==`MULUI || opcode==`DIVI || opcode==`DIVUI || opcode==`MODI || opcode==`MODUI ||
|
opcode==`_2ADDUI || opcode==`_4ADDUI || opcode==`_8ADDUI || opcode==`_16ADDUI ||
|
opcode==`_2ADDUI || opcode==`_4ADDUI || opcode==`_8ADDUI || opcode==`_16ADDUI ||
|
opcode==`ANDI || opcode==`ORI || opcode==`EORI ||
|
opcode==`ANDI || opcode==`ORI || opcode==`EORI ||
|
opcode==`SHIFT || opcode==`LOGIC ||
|
opcode==`SHIFT || opcode==`LOGIC ||
|
opcode==`R || opcode==`R2 || opcode==`RR || opcode==`P || opcode==`LOOP ||
|
opcode==`R || opcode==`R2 || opcode==`RR || opcode==`P || opcode==`LOOP ||
|
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST ||
|
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST ||
|
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR ||
|
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR ||
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
opcode==`DOUBLE_R || opcode==`FLOAT_RR || opcode==`SINGLE_R ||
|
opcode==`DOUBLE_R || opcode==`FLOAT_RR || opcode==`SINGLE_R ||
|
`endif
|
`endif
|
// Branch registers / Segment registers
|
// Branch registers / Segment registers
|
((opcode==`MTSPR || opcode==`MOVS) /*&& (fnTargetsCa(ir) || fnTargetsSegreg(ir))*/) ||
|
((opcode==`MTSPR || opcode==`MOVS) /*&& (fnTargetsCa(ir) || fnTargetsSegreg(ir))*/) ||
|
opcode==`JSR || opcode==`JSRS || opcode==`JSRZ || opcode==`SYS || opcode==`INT ||
|
opcode==`JSR || opcode==`JSRS || opcode==`JSRZ || opcode==`SYS || opcode==`INT ||
|
// predicate registers
|
// predicate registers
|
(opcode[7:4] < 4'h3) ||
|
(opcode[7:4] < 4'h3) ||
|
(opcode==`TLB && ir[19:16]==`TLB_RDREG) ||
|
(opcode==`TLB && ir[19:16]==`TLB_RDREG) ||
|
opcode==`BCD
|
opcode==`BCD
|
;
|
;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function fnIsStore;
|
function fnIsStore;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsStore = opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
|
fnIsStore = opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
|
opcode==`STS || opcode==`SWCR ||
|
opcode==`STS || opcode==`SWCR ||
|
opcode==`SWS || opcode==`STI ||
|
opcode==`SWS || opcode==`STI ||
|
opcode==`PUSH || opcode==`PEA || opcode==`LINK;
|
opcode==`PUSH || opcode==`PEA || opcode==`LINK;
|
endfunction
|
endfunction
|
|
|
function fnIsLoad;
|
function fnIsLoad;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsLoad = opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
fnIsLoad = opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW ||
|
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL ||
|
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL ||
|
opcode==`LWS || opcode==`UNLINK || opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`LWS || opcode==`UNLINK || opcode==`JMPI || opcode==`JMPIX ||
|
opcode==`POP;
|
opcode==`POP;
|
endfunction
|
endfunction
|
|
|
function fnIsLoadV;
|
function fnIsLoadV;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsLoadV = opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL;
|
fnIsLoadV = opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL;
|
endfunction
|
endfunction
|
|
|
function fnIsIndexed;
|
function fnIsIndexed;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsIndexed = opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
fnIsIndexed = opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX ||
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || opcode==`JMPIX;
|
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || opcode==`JMPIX;
|
endfunction
|
endfunction
|
|
|
//
|
//
|
function fnIsPFW;
|
function fnIsPFW;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
fnIsPFW = opcode[7:4]<4'h3 || opcode==`BITI || opcode==`P;//opcode==`CMP || opcode==`CMPI || opcode==`TST;
|
fnIsPFW = opcode[7:4]<4'h3 || opcode==`BITI || opcode==`P;//opcode==`CMP || opcode==`CMPI || opcode==`TST;
|
endfunction
|
endfunction
|
|
|
// Decoding for illegal opcodes
|
// Decoding for illegal opcodes
|
function fnIsIllegal;
|
function fnIsIllegal;
|
input [7:0] op;
|
input [7:0] op;
|
input [5:0] fn;
|
input [5:0] fn;
|
casex(op)
|
casex(op)
|
8'h40:
|
8'h40:
|
if (fn > 6'h17)
|
if (fn > 6'h17)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h14 || fn==6'h15 || fn==6'h16)
|
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h14 || fn==6'h15 || fn==6'h16)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else fnIsIllegal = `FALSE;
|
else fnIsIllegal = `FALSE;
|
8'h41:
|
8'h41:
|
if (fn > 6'd3) fnIsIllegal = `TRUE;
|
if (fn > 6'd3) fnIsIllegal = `TRUE;
|
else fnIsIllegal = `FALSE;
|
else fnIsIllegal = `FALSE;
|
8'h42:
|
8'h42:
|
if (fn > 6'd7) fnIsIllegal = `TRUE;
|
if (fn > 6'd7) fnIsIllegal = `TRUE;
|
else fnIsIllegal = `FALSE;
|
else fnIsIllegal = `FALSE;
|
8'h50:
|
8'h50:
|
if (fn > 6'd7) fnIsIllegal = `TRUE;
|
if (fn > 6'd7) fnIsIllegal = `TRUE;
|
else fnIsIllegal = `FALSE;
|
else fnIsIllegal = `FALSE;
|
8'h58:
|
8'h58:
|
if (fn > 6'h15 || (fn > 6'h5 && fn < 6'h10))
|
if (fn > 6'h15 || (fn > 6'h5 && fn < 6'h10))
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else
|
else
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
8'h77:
|
8'h77:
|
if (fn==8'h99 || fn==8'h9A || fn==8'h9B || fn==8'h9E || fn==8'h9F)
|
if (fn==8'h99 || fn==8'h9A || fn==8'h9B || fn==8'h9E || fn==8'h9F)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else
|
else
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
8'h78:
|
8'h78:
|
if ((fn >= 8'h07 && fn <= 8'h0B) || (fn >= 8'h17 && fn <= 8'h1B))
|
if ((fn >= 8'h07 && fn <= 8'h0B) || (fn >= 8'h17 && fn <= 8'h1B))
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
else
|
else
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'h79:
|
8'h79:
|
if (fn==8'h99 || fn==8'h9A || fn==8'h9B)
|
if (fn==8'h99 || fn==8'h9A || fn==8'h9B)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else
|
else
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
8'hAA:
|
8'hAA:
|
if (fn > 4'd6)
|
if (fn > 4'd6)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else
|
else
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
8'hF5:
|
8'hF5:
|
if (fn > 4'd2)
|
if (fn > 4'd2)
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
else
|
else
|
fnIsIllegal = `FALSE;
|
fnIsIllegal = `FALSE;
|
8'h43,8'h44,8'h45: fnIsIllegal = `TRUE;
|
8'h43,8'h44,8'h45: fnIsIllegal = `TRUE;
|
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5C,8'h5D,8'h5E:
|
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5D,8'h5E:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69:
|
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'h73,8'h74,8'h75,8'h76,8'h7A,8'h7B,8'h7C,8'h7D,8'h7E,8'h7F:
|
8'h73,8'h74,8'h75,8'h76,8'h7A,8'h7B,8'h7C,8'h7D,8'h7E,8'h7F:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'h87,8'h88,8'h89,8'h8A:
|
8'h87,8'h88,8'h89,8'h8A:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'h94,8'h95,8'h9C:
|
8'h94,8'h95,8'h9C:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'hB9,8'hBA,8'hBB,8'hBC,8'hBD,8'hBE,8'hBF:
|
8'hB9,8'hBA,8'hBB,8'hBC,8'hBD,8'hBE,8'hBF:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'hC4,8'hC5,8'b11001xxx:
|
8'hC4,8'hC5,8'b11001xxx:
|
fnIsIllegal = `TRUE;
|
fnIsIllegal = `TRUE;
|
8'hDx: fnIsIllegal = `TRUE;
|
8'hDx: fnIsIllegal = `TRUE;
|
8'hEx: fnIsIllegal = `TRUE;
|
8'hEx: fnIsIllegal = `TRUE;
|
8'hFD,8'hFE: fnIsIllegal = `TRUE;
|
8'hFD,8'hFE: fnIsIllegal = `TRUE;
|
default: fnIsIllegal = `FALSE;
|
default: fnIsIllegal = `FALSE;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
function [7:0] fnSelect;
|
function [7:0] fnSelect;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] fn;
|
input [5:0] fn;
|
input [DBW-1:0] adr;
|
input [DBW-1:0] adr;
|
begin
|
begin
|
if (DBW==32)
|
if (DBW==32)
|
case(opcode)
|
case(opcode)
|
`STS,`STMV,`STCMP,`STFND,`INC:
|
`STS,`STMV,`STCMP,`STFND,`INC:
|
case(fn[2:0])
|
case(fn[2:0])
|
3'd0:
|
3'd0:
|
case(adr[1:0])
|
case(adr[1:0])
|
3'd0: fnSelect = 8'h11;
|
3'd0: fnSelect = 8'h11;
|
3'd1: fnSelect = 8'h22;
|
3'd1: fnSelect = 8'h22;
|
3'd2: fnSelect = 8'h44;
|
3'd2: fnSelect = 8'h44;
|
3'd3: fnSelect = 8'h88;
|
3'd3: fnSelect = 8'h88;
|
endcase
|
endcase
|
3'd1:
|
3'd1:
|
case(adr[1])
|
case(adr[1])
|
1'd0: fnSelect = 8'h33;
|
1'd0: fnSelect = 8'h33;
|
1'd1: fnSelect = 8'hCC;
|
1'd1: fnSelect = 8'hCC;
|
endcase
|
endcase
|
3'd2:
|
3'd2:
|
fnSelect = 8'hFF;
|
fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
`JMPI,`JMPIX:
|
`JMPI,`JMPIX:
|
case(fn[1:0])
|
case(fn[1:0])
|
2'd1:
|
2'd1:
|
case(adr[1])
|
case(adr[1])
|
1'b0: fnSelect = 8'h33;
|
1'b0: fnSelect = 8'h33;
|
1'b1: fnSelect = 8'hCC;
|
1'b1: fnSelect = 8'hCC;
|
endcase
|
endcase
|
2'd2: fnSelect = 8'hFF;
|
2'd2: fnSelect = 8'hFF;
|
2'd3: fnSelect = 8'hFF;
|
2'd3: fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
`LB,`LBU,`LBX,`LBUX,`SB,`SBX,`LVB:
|
`LB,`LBU,`LBX,`LBUX,`SB,`SBX,`LVB:
|
case(adr[1:0])
|
case(adr[1:0])
|
3'd0: fnSelect = 8'h11;
|
3'd0: fnSelect = 8'h11;
|
3'd1: fnSelect = 8'h22;
|
3'd1: fnSelect = 8'h22;
|
3'd2: fnSelect = 8'h44;
|
3'd2: fnSelect = 8'h44;
|
3'd3: fnSelect = 8'h88;
|
3'd3: fnSelect = 8'h88;
|
endcase
|
endcase
|
`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
|
`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
|
case(adr[1])
|
case(adr[1])
|
1'd0: fnSelect = 8'h33;
|
1'd0: fnSelect = 8'h33;
|
1'd1: fnSelect = 8'hCC;
|
1'd1: fnSelect = 8'hCC;
|
endcase
|
endcase
|
`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
|
`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
|
fnSelect = 8'hFF;
|
fnSelect = 8'hFF;
|
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
|
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
|
`PUSH,`PEA,`POP,`LINK,`UNLINK:
|
`PUSH,`PEA,`POP,`LINK,`UNLINK:
|
fnSelect = 8'hFF;
|
fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
else
|
else
|
case(opcode)
|
case(opcode)
|
`STS,`STMV,`STCMP,`STFND,`INC:
|
`STS,`STMV,`STCMP,`STFND,`INC:
|
case(fn[2:0])
|
case(fn[2:0])
|
3'd0:
|
3'd0:
|
case(adr[2:0])
|
case(adr[2:0])
|
3'd0: fnSelect = 8'h01;
|
3'd0: fnSelect = 8'h01;
|
3'd1: fnSelect = 8'h02;
|
3'd1: fnSelect = 8'h02;
|
3'd2: fnSelect = 8'h04;
|
3'd2: fnSelect = 8'h04;
|
3'd3: fnSelect = 8'h08;
|
3'd3: fnSelect = 8'h08;
|
3'd4: fnSelect = 8'h10;
|
3'd4: fnSelect = 8'h10;
|
3'd5: fnSelect = 8'h20;
|
3'd5: fnSelect = 8'h20;
|
3'd6: fnSelect = 8'h40;
|
3'd6: fnSelect = 8'h40;
|
3'd7: fnSelect = 8'h80;
|
3'd7: fnSelect = 8'h80;
|
endcase
|
endcase
|
3'd1:
|
3'd1:
|
case(adr[2:1])
|
case(adr[2:1])
|
2'd0: fnSelect = 8'h03;
|
2'd0: fnSelect = 8'h03;
|
2'd1: fnSelect = 8'h0C;
|
2'd1: fnSelect = 8'h0C;
|
2'd2: fnSelect = 8'h30;
|
2'd2: fnSelect = 8'h30;
|
2'd3: fnSelect = 8'hC0;
|
2'd3: fnSelect = 8'hC0;
|
endcase
|
endcase
|
3'd2:
|
3'd2:
|
case(adr[2])
|
case(adr[2])
|
1'b0: fnSelect = 8'h0F;
|
1'b0: fnSelect = 8'h0F;
|
1'b1: fnSelect = 8'hF0;
|
1'b1: fnSelect = 8'hF0;
|
endcase
|
endcase
|
3'd3:
|
3'd3:
|
fnSelect = 8'hFF;
|
fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
`JMPI,`JMPIX:
|
`JMPI,`JMPIX:
|
case(fn[1:0])
|
case(fn[1:0])
|
2'd1:
|
2'd1:
|
case(adr[2:1])
|
case(adr[2:1])
|
2'd0: fnSelect = 8'h03;
|
2'd0: fnSelect = 8'h03;
|
2'd1: fnSelect = 8'h0C;
|
2'd1: fnSelect = 8'h0C;
|
2'd2: fnSelect = 8'h30;
|
2'd2: fnSelect = 8'h30;
|
2'd3: fnSelect = 8'hC0;
|
2'd3: fnSelect = 8'hC0;
|
endcase
|
endcase
|
2'd2:
|
2'd2:
|
case(adr[2])
|
case(adr[2])
|
1'b0: fnSelect = 8'h0F;
|
1'b0: fnSelect = 8'h0F;
|
1'b1: fnSelect = 8'hF0;
|
1'b1: fnSelect = 8'hF0;
|
endcase
|
endcase
|
2'd3: fnSelect = 8'hFF;
|
2'd3: fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
`LB,`LBU,`LBX,`SB,`LVB,`LBUX,`SBX:
|
`LB,`LBU,`LBX,`SB,`LVB,`LBUX,`SBX:
|
case(adr[2:0])
|
case(adr[2:0])
|
3'd0: fnSelect = 8'h01;
|
3'd0: fnSelect = 8'h01;
|
3'd1: fnSelect = 8'h02;
|
3'd1: fnSelect = 8'h02;
|
3'd2: fnSelect = 8'h04;
|
3'd2: fnSelect = 8'h04;
|
3'd3: fnSelect = 8'h08;
|
3'd3: fnSelect = 8'h08;
|
3'd4: fnSelect = 8'h10;
|
3'd4: fnSelect = 8'h10;
|
3'd5: fnSelect = 8'h20;
|
3'd5: fnSelect = 8'h20;
|
3'd6: fnSelect = 8'h40;
|
3'd6: fnSelect = 8'h40;
|
3'd7: fnSelect = 8'h80;
|
3'd7: fnSelect = 8'h80;
|
endcase
|
endcase
|
`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
|
`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
|
case(adr[2:1])
|
case(adr[2:1])
|
2'd0: fnSelect = 8'h03;
|
2'd0: fnSelect = 8'h03;
|
2'd1: fnSelect = 8'h0C;
|
2'd1: fnSelect = 8'h0C;
|
2'd2: fnSelect = 8'h30;
|
2'd2: fnSelect = 8'h30;
|
2'd3: fnSelect = 8'hC0;
|
2'd3: fnSelect = 8'hC0;
|
endcase
|
endcase
|
`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
|
`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
|
case(adr[2])
|
case(adr[2])
|
1'b0: fnSelect = 8'h0F;
|
1'b0: fnSelect = 8'h0F;
|
1'b1: fnSelect = 8'hF0;
|
1'b1: fnSelect = 8'hF0;
|
endcase
|
endcase
|
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
|
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
|
`PUSH,`PEA,`POP,`LINK,`UNLINK:
|
`PUSH,`PEA,`POP,`LINK,`UNLINK:
|
fnSelect = 8'hFF;
|
fnSelect = 8'hFF;
|
default: fnSelect = 8'h00;
|
default: fnSelect = 8'h00;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [DBW-1:0] fnDatai;
|
function [DBW-1:0] fnDatai;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] func;
|
input [5:0] func;
|
input [DBW-1:0] dat;
|
input [DBW-1:0] dat;
|
input [7:0] sel;
|
input [7:0] sel;
|
begin
|
begin
|
if (DBW==32)
|
if (DBW==32)
|
case(opcode)
|
case(opcode)
|
`STMV,`STCMP,`STFND,`INC:
|
`STMV,`STCMP,`STFND,`INC:
|
case(func[2:0])
|
case(func[2:0])
|
3'd0,3'd4:
|
3'd0,3'd4:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h1: fnDatai = dat[7:0];
|
4'h1: fnDatai = dat[7:0];
|
4'h2: fnDatai = dat[15:8];
|
4'h2: fnDatai = dat[15:8];
|
4'h4: fnDatai = dat[23:16];
|
4'h4: fnDatai = dat[23:16];
|
4'h8: fnDatai = dat[31:24];
|
4'h8: fnDatai = dat[31:24];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
3'd1,3'd5:
|
3'd1,3'd5:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h3: fnDatai = dat[15:0];
|
4'h3: fnDatai = dat[15:0];
|
4'hC: fnDatai = dat[31:16];
|
4'hC: fnDatai = dat[31:16];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
default:
|
default:
|
fnDatai = dat[31:0];
|
fnDatai = dat[31:0];
|
endcase
|
endcase
|
`JMPI,`JMPIX:
|
`JMPI,`JMPIX:
|
case(func[1:0])
|
case(func[1:0])
|
2'd1:
|
2'd1:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h3: fnDatai = dat[15:0];
|
4'h3: fnDatai = dat[15:0];
|
4'hC: fnDatai = dat[31:16];
|
4'hC: fnDatai = dat[31:16];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
2'd2: fnDatai = dat[31:0];
|
2'd2: fnDatai = dat[31:0];
|
default: fnDatai = dat[31:0];
|
default: fnDatai = dat[31:0];
|
endcase
|
endcase
|
`LB,`LBX,`LVB:
|
`LB,`LBX,`LVB:
|
case(sel[3:0])
|
case(sel[3:0])
|
8'h1: fnDatai = {{24{dat[7]}},dat[7:0]};
|
8'h1: fnDatai = {{24{dat[7]}},dat[7:0]};
|
8'h2: fnDatai = {{24{dat[15]}},dat[15:8]};
|
8'h2: fnDatai = {{24{dat[15]}},dat[15:8]};
|
8'h4: fnDatai = {{24{dat[23]}},dat[23:16]};
|
8'h4: fnDatai = {{24{dat[23]}},dat[23:16]};
|
8'h8: fnDatai = {{24{dat[31]}},dat[31:24]};
|
8'h8: fnDatai = {{24{dat[31]}},dat[31:24]};
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LBU,`LBUX:
|
`LBU,`LBUX:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h1: fnDatai = dat[7:0];
|
4'h1: fnDatai = dat[7:0];
|
4'h2: fnDatai = dat[15:8];
|
4'h2: fnDatai = dat[15:8];
|
4'h4: fnDatai = dat[23:16];
|
4'h4: fnDatai = dat[23:16];
|
4'h8: fnDatai = dat[31:24];
|
4'h8: fnDatai = dat[31:24];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LC,`LVC,`LCX:
|
`LC,`LVC,`LCX:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h3: fnDatai = {{16{dat[15]}},dat[15:0]};
|
4'h3: fnDatai = {{16{dat[15]}},dat[15:0]};
|
4'hC: fnDatai = {{16{dat[31]}},dat[31:16]};
|
4'hC: fnDatai = {{16{dat[31]}},dat[31:16]};
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LCU,`LCUX:
|
`LCU,`LCUX:
|
case(sel[3:0])
|
case(sel[3:0])
|
4'h3: fnDatai = dat[15:0];
|
4'h3: fnDatai = dat[15:0];
|
4'hC: fnDatai = dat[31:16];
|
4'hC: fnDatai = dat[31:16];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LCL,`LWS,`POP,`UNLINK:
|
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LCL,`LWS,`POP,`UNLINK:
|
fnDatai = dat[31:0];
|
fnDatai = dat[31:0];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
else
|
else
|
case(opcode)
|
case(opcode)
|
`STMV,`STCMP,`STFND,`INC:
|
`STMV,`STCMP,`STFND,`INC:
|
case(func[2:0])
|
case(func[2:0])
|
3'd0,3'd4:
|
3'd0,3'd4:
|
case(sel)
|
case(sel)
|
8'h01: fnDatai = dat[DBW*1/8-1:0];
|
8'h01: fnDatai = dat[DBW*1/8-1:0];
|
8'h02: fnDatai = dat[DBW*2/8-1:DBW*1/8];
|
8'h02: fnDatai = dat[DBW*2/8-1:DBW*1/8];
|
8'h04: fnDatai = dat[DBW*3/8-1:DBW*2/8];
|
8'h04: fnDatai = dat[DBW*3/8-1:DBW*2/8];
|
8'h08: fnDatai = dat[DBW*4/8-1:DBW*3/8];
|
8'h08: fnDatai = dat[DBW*4/8-1:DBW*3/8];
|
8'h10: fnDatai = dat[DBW*5/8-1:DBW*4/8];
|
8'h10: fnDatai = dat[DBW*5/8-1:DBW*4/8];
|
8'h20: fnDatai = dat[DBW*6/8-1:DBW*5/8];
|
8'h20: fnDatai = dat[DBW*6/8-1:DBW*5/8];
|
8'h40: fnDatai = dat[DBW*7/8-1:DBW*6/8];
|
8'h40: fnDatai = dat[DBW*7/8-1:DBW*6/8];
|
8'h80: fnDatai = dat[DBW-1:DBW*7/8];
|
8'h80: fnDatai = dat[DBW-1:DBW*7/8];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
3'd1,3'd5:
|
3'd1,3'd5:
|
case(sel)
|
case(sel)
|
8'h03: fnDatai = dat[DBW/4-1:0];
|
8'h03: fnDatai = dat[DBW/4-1:0];
|
8'h0C: fnDatai = dat[DBW/2-1:DBW/4];
|
8'h0C: fnDatai = dat[DBW/2-1:DBW/4];
|
8'h30: fnDatai = dat[DBW*3/4-1:DBW/2];
|
8'h30: fnDatai = dat[DBW*3/4-1:DBW/2];
|
8'hC0: fnDatai = dat[DBW-1:DBW*3/4];
|
8'hC0: fnDatai = dat[DBW-1:DBW*3/4];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
3'd2,3'd6:
|
3'd2,3'd6:
|
case(sel)
|
case(sel)
|
8'h0F: fnDatai = dat[DBW/2-1:0];
|
8'h0F: fnDatai = dat[DBW/2-1:0];
|
8'hF0: fnDatai = dat[DBW-1:DBW/2];
|
8'hF0: fnDatai = dat[DBW-1:DBW/2];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
3'd3,3'd7: fnDatai = dat;
|
3'd3,3'd7: fnDatai = dat;
|
endcase
|
endcase
|
`JMPI,`JMPIX:
|
`JMPI,`JMPIX:
|
case(func[1:0])
|
case(func[1:0])
|
2'd1:
|
2'd1:
|
case(sel[7:0])
|
case(sel[7:0])
|
8'h03: fnDatai = dat[15:0];
|
8'h03: fnDatai = dat[15:0];
|
8'h0C: fnDatai = dat[31:16];
|
8'h0C: fnDatai = dat[31:16];
|
8'h30: fnDatai = dat[47:32];
|
8'h30: fnDatai = dat[47:32];
|
8'hC0: fnDatai = dat[63:48];
|
8'hC0: fnDatai = dat[63:48];
|
default: fnDatai = dat[15:0];
|
default: fnDatai = dat[15:0];
|
endcase
|
endcase
|
2'd2:
|
2'd2:
|
case(sel[7:0])
|
case(sel[7:0])
|
8'h0F: fnDatai = dat[31:0];
|
8'h0F: fnDatai = dat[31:0];
|
8'hF0: fnDatai = dat[63:32];
|
8'hF0: fnDatai = dat[63:32];
|
default: fnDatai = dat[31:0];
|
default: fnDatai = dat[31:0];
|
endcase
|
endcase
|
2'd3: fnDatai = dat;
|
2'd3: fnDatai = dat;
|
default: fnDatai = dat;
|
default: fnDatai = dat;
|
endcase
|
endcase
|
`LB,`LBX,`LVB:
|
`LB,`LBX,`LVB:
|
case(sel)
|
case(sel)
|
8'h01: fnDatai = {{DBW*7/8{dat[DBW*1/8-1]}},dat[DBW*1/8-1:0]};
|
8'h01: fnDatai = {{DBW*7/8{dat[DBW*1/8-1]}},dat[DBW*1/8-1:0]};
|
8'h02: fnDatai = {{DBW*7/8{dat[DBW*2/8-1]}},dat[DBW*2/8-1:DBW*1/8]};
|
8'h02: fnDatai = {{DBW*7/8{dat[DBW*2/8-1]}},dat[DBW*2/8-1:DBW*1/8]};
|
8'h04: fnDatai = {{DBW*7/8{dat[DBW*3/8-1]}},dat[DBW*3/8-1:DBW*2/8]};
|
8'h04: fnDatai = {{DBW*7/8{dat[DBW*3/8-1]}},dat[DBW*3/8-1:DBW*2/8]};
|
8'h08: fnDatai = {{DBW*7/8{dat[DBW*4/8-1]}},dat[DBW*4/8-1:DBW*3/8]};
|
8'h08: fnDatai = {{DBW*7/8{dat[DBW*4/8-1]}},dat[DBW*4/8-1:DBW*3/8]};
|
8'h10: fnDatai = {{DBW*7/8{dat[DBW*5/8-1]}},dat[DBW*5/8-1:DBW*4/8]};
|
8'h10: fnDatai = {{DBW*7/8{dat[DBW*5/8-1]}},dat[DBW*5/8-1:DBW*4/8]};
|
8'h20: fnDatai = {{DBW*7/8{dat[DBW*6/8-1]}},dat[DBW*6/8-1:DBW*5/8]};
|
8'h20: fnDatai = {{DBW*7/8{dat[DBW*6/8-1]}},dat[DBW*6/8-1:DBW*5/8]};
|
8'h40: fnDatai = {{DBW*7/8{dat[DBW*7/8-1]}},dat[DBW*7/8-1:DBW*6/8]};
|
8'h40: fnDatai = {{DBW*7/8{dat[DBW*7/8-1]}},dat[DBW*7/8-1:DBW*6/8]};
|
8'h80: fnDatai = {{DBW*7/8{dat[DBW-1]}},dat[DBW-1:DBW*7/8]};
|
8'h80: fnDatai = {{DBW*7/8{dat[DBW-1]}},dat[DBW-1:DBW*7/8]};
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LBU,`LBUX:
|
`LBU,`LBUX:
|
case(sel)
|
case(sel)
|
8'h01: fnDatai = dat[DBW*1/8-1:0];
|
8'h01: fnDatai = dat[DBW*1/8-1:0];
|
8'h02: fnDatai = dat[DBW*2/8-1:DBW*1/8];
|
8'h02: fnDatai = dat[DBW*2/8-1:DBW*1/8];
|
8'h04: fnDatai = dat[DBW*3/8-1:DBW*2/8];
|
8'h04: fnDatai = dat[DBW*3/8-1:DBW*2/8];
|
8'h08: fnDatai = dat[DBW*4/8-1:DBW*3/8];
|
8'h08: fnDatai = dat[DBW*4/8-1:DBW*3/8];
|
8'h10: fnDatai = dat[DBW*5/8-1:DBW*4/8];
|
8'h10: fnDatai = dat[DBW*5/8-1:DBW*4/8];
|
8'h20: fnDatai = dat[DBW*6/8-1:DBW*5/8];
|
8'h20: fnDatai = dat[DBW*6/8-1:DBW*5/8];
|
8'h40: fnDatai = dat[DBW*7/8-1:DBW*6/8];
|
8'h40: fnDatai = dat[DBW*7/8-1:DBW*6/8];
|
8'h80: fnDatai = dat[DBW-1:DBW*7/8];
|
8'h80: fnDatai = dat[DBW-1:DBW*7/8];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LC,`LVC,`LCX:
|
`LC,`LVC,`LCX:
|
case(sel)
|
case(sel)
|
8'h03: fnDatai = {{DBW*3/4{dat[DBW/4-1]}},dat[DBW/4-1:0]};
|
8'h03: fnDatai = {{DBW*3/4{dat[DBW/4-1]}},dat[DBW/4-1:0]};
|
8'h0C: fnDatai = {{DBW*3/4{dat[DBW/2-1]}},dat[DBW/2-1:DBW/4]};
|
8'h0C: fnDatai = {{DBW*3/4{dat[DBW/2-1]}},dat[DBW/2-1:DBW/4]};
|
8'h30: fnDatai = {{DBW*3/4{dat[DBW*3/4-1]}},dat[DBW*3/4-1:DBW/2]};
|
8'h30: fnDatai = {{DBW*3/4{dat[DBW*3/4-1]}},dat[DBW*3/4-1:DBW/2]};
|
8'hC0: fnDatai = {{DBW*3/4{dat[DBW-1]}},dat[DBW-1:DBW*3/4]};
|
8'hC0: fnDatai = {{DBW*3/4{dat[DBW-1]}},dat[DBW-1:DBW*3/4]};
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LCU,`LCUX:
|
`LCU,`LCUX:
|
case(sel)
|
case(sel)
|
8'h03: fnDatai = dat[DBW/4-1:0];
|
8'h03: fnDatai = dat[DBW/4-1:0];
|
8'h0C: fnDatai = dat[DBW/2-1:DBW/4];
|
8'h0C: fnDatai = dat[DBW/2-1:DBW/4];
|
8'h30: fnDatai = dat[DBW*3/4-1:DBW/2];
|
8'h30: fnDatai = dat[DBW*3/4-1:DBW/2];
|
8'hC0: fnDatai = dat[DBW-1:DBW*3/4];
|
8'hC0: fnDatai = dat[DBW-1:DBW*3/4];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LH,`LVH,`LHX:
|
`LH,`LVH,`LHX:
|
case(sel)
|
case(sel)
|
8'h0F: fnDatai = {{DBW/2{dat[DBW/2-1]}},dat[DBW/2-1:0]};
|
8'h0F: fnDatai = {{DBW/2{dat[DBW/2-1]}},dat[DBW/2-1:0]};
|
8'hF0: fnDatai = {{DBW/2{dat[DBW-1]}},dat[DBW-1:DBW/2]};
|
8'hF0: fnDatai = {{DBW/2{dat[DBW-1]}},dat[DBW-1:DBW/2]};
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LHU,`LHUX:
|
`LHU,`LHUX:
|
case(sel)
|
case(sel)
|
8'h0F: fnDatai = dat[DBW/2-1:0];
|
8'h0F: fnDatai = dat[DBW/2-1:0];
|
8'hF0: fnDatai = dat[DBW-1:DBW/2];
|
8'hF0: fnDatai = dat[DBW-1:DBW/2];
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
`LW,`LWX,`LVW,`LVWAR,`CAS,`LCL,`LWS,`POP,`UNLINK:
|
`LW,`LWX,`LVW,`LVWAR,`CAS,`LCL,`LWS,`POP,`UNLINK:
|
case(sel)
|
case(sel)
|
8'hFF: fnDatai = dat;
|
8'hFF: fnDatai = dat;
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
default: fnDatai = {DBW{1'b1}};
|
default: fnDatai = {DBW{1'b1}};
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [DBW-1:0] fnDatao;
|
function [DBW-1:0] fnDatao;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [5:0] func;
|
input [5:0] func;
|
input [DBW-1:0] dat;
|
input [DBW-1:0] dat;
|
if (DBW==32)
|
if (DBW==32)
|
case(opcode)
|
case(opcode)
|
`STMV,`INC:
|
`STMV,`INC:
|
case(func[2:0])
|
case(func[2:0])
|
3'd0,3'd4: fnDatao = {4{dat[7:0]}};
|
3'd0,3'd4: fnDatao = {4{dat[7:0]}};
|
3'd1,3'd5: fnDatao = {2{dat[15:8]}};
|
3'd1,3'd5: fnDatao = {2{dat[15:8]}};
|
default: fnDatao = dat;
|
default: fnDatao = dat;
|
endcase
|
endcase
|
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
|
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
|
`PUSH,`PEA,`LINK: fnDatao = dat;
|
`PUSH,`PEA,`LINK: fnDatao = dat;
|
`SH,`SHX: fnDatao = dat;
|
`SH,`SHX: fnDatao = dat;
|
`SC,`SCX: fnDatao = {2{dat[15:0]}};
|
`SC,`SCX: fnDatao = {2{dat[15:0]}};
|
`SB,`SBX: fnDatao = {4{dat[7:0]}};
|
`SB,`SBX: fnDatao = {4{dat[7:0]}};
|
default: fnDatao = dat;
|
default: fnDatao = dat;
|
endcase
|
endcase
|
else
|
else
|
case(opcode)
|
case(opcode)
|
`STMV,`INC:
|
`STMV,`INC:
|
case(func[2:0])
|
case(func[2:0])
|
3'd0,3'd4: fnDatao = {8{dat[DBW/8-1:0]}};
|
3'd0,3'd4: fnDatao = {8{dat[DBW/8-1:0]}};
|
3'd1,3'd5: fnDatao = {4{dat[DBW/4-1:0]}};
|
3'd1,3'd5: fnDatao = {4{dat[DBW/4-1:0]}};
|
3'd2,3'd6: fnDatao = {2{dat[DBW/2-1:0]}};
|
3'd2,3'd6: fnDatao = {2{dat[DBW/2-1:0]}};
|
3'd3,3'd7: fnDatao = dat;
|
3'd3,3'd7: fnDatao = dat;
|
endcase
|
endcase
|
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
|
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
|
`PUSH,`PEA,`LINK: fnDatao = dat;
|
`PUSH,`PEA,`LINK: fnDatao = dat;
|
`SH,`SHX: fnDatao = {2{dat[DBW/2-1:0]}};
|
`SH,`SHX: fnDatao = {2{dat[DBW/2-1:0]}};
|
`SC,`SCX: fnDatao = {4{dat[DBW/4-1:0]}};
|
`SC,`SCX: fnDatao = {4{dat[DBW/4-1:0]}};
|
`SB,`SBX: fnDatao = {8{dat[DBW/8-1:0]}};
|
`SB,`SBX: fnDatao = {8{dat[DBW/8-1:0]}};
|
default: fnDatao = dat;
|
default: fnDatao = dat;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
assign fetchbuf0_mem = fnIsMem(opcode0);
|
assign fetchbuf0_mem = fnIsMem(opcode0);
|
assign fetchbuf0_jmp = fnIsFlowCtrl(opcode0);
|
assign fetchbuf0_jmp = fnIsFlowCtrl(opcode0);
|
assign fetchbuf0_fp = fnIsFP(opcode0);
|
assign fetchbuf0_fp = fnIsFP(opcode0);
|
assign fetchbuf0_rfw = fnIsRFW(opcode0,fetchbuf0_instr);
|
assign fetchbuf0_rfw = fnIsRFW(opcode0,fetchbuf0_instr);
|
assign fetchbuf0_pfw = fnIsPFW(opcode0);
|
assign fetchbuf0_pfw = fnIsPFW(opcode0);
|
assign fetchbuf1_mem = fnIsMem(opcode1);
|
assign fetchbuf1_mem = fnIsMem(opcode1);
|
assign fetchbuf1_jmp = fnIsFlowCtrl(opcode1);
|
assign fetchbuf1_jmp = fnIsFlowCtrl(opcode1);
|
assign fetchbuf1_fp = fnIsFP(opcode1);
|
assign fetchbuf1_fp = fnIsFP(opcode1);
|
assign fetchbuf1_rfw = fnIsRFW(opcode1,fetchbuf1_instr);
|
assign fetchbuf1_rfw = fnIsRFW(opcode1,fetchbuf1_instr);
|
assign fetchbuf1_pfw = fnIsPFW(opcode1);
|
assign fetchbuf1_pfw = fnIsPFW(opcode1);
|
|
|
//
|
//
|
// set branchback and backpc values ... ignore branches in fetchbuf slots not ready for enqueue yet
|
// set branchback and backpc values ... ignore branches in fetchbuf slots not ready for enqueue yet
|
//
|
//
|
assign take_branch0 = ({fetchbuf0_v, fnIsBranch(opcode0), predict_taken0} == {`VAL, `TRUE, `TRUE}) ||
|
assign take_branch0 = ({fetchbuf0_v, fnIsBranch(opcode0), predict_taken0} == {`VAL, `TRUE, `TRUE}) ||
|
({fetchbuf0_v, opcode0==`LOOP} == {`VAL, `TRUE})
|
({fetchbuf0_v, opcode0==`LOOP} == {`VAL, `TRUE})
|
;
|
;
|
assign take_branch1 = ({fetchbuf1_v, fnIsBranch(opcode1), predict_taken1} == {`VAL, `TRUE, `TRUE}) ||
|
assign take_branch1 = ({fetchbuf1_v, fnIsBranch(opcode1), predict_taken1} == {`VAL, `TRUE, `TRUE}) ||
|
({fetchbuf1_v, opcode1==`LOOP} == {`VAL, `TRUE})
|
({fetchbuf1_v, opcode1==`LOOP} == {`VAL, `TRUE})
|
;
|
;
|
assign take_branch = take_branch0 || take_branch1
|
assign take_branch = take_branch0 || take_branch1
|
;
|
;
|
|
|
always @*
|
always @*
|
if (fnIsBranch(opcode0) && fetchbuf0_v && predict_taken0) begin
|
if (fnIsBranch(opcode0) && fetchbuf0_v && predict_taken0) begin
|
branch_pc <= fetchbuf0_pc + {{ABW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3;
|
branch_pc <= fetchbuf0_pc + {{ABW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3;
|
end
|
end
|
else if (opcode0==`LOOP && fetchbuf0_v) begin
|
else if (opcode0==`LOOP && fetchbuf0_v) begin
|
branch_pc <= fetchbuf0_pc + {{ABW-8{fetchbuf0_instr[23]}},fetchbuf0_instr[23:16]} + 64'd3;
|
branch_pc <= fetchbuf0_pc + {{ABW-8{fetchbuf0_instr[23]}},fetchbuf0_instr[23:16]} + 64'd3;
|
end
|
end
|
else if (fnIsBranch(opcode1) && fetchbuf1_v && predict_taken1) begin
|
else if (fnIsBranch(opcode1) && fetchbuf1_v && predict_taken1) begin
|
branch_pc <= fetchbuf1_pc + {{ABW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} + 64'd3;
|
branch_pc <= fetchbuf1_pc + {{ABW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} + 64'd3;
|
end
|
end
|
else if (opcode1==`LOOP && fetchbuf1_v) begin
|
else if (opcode1==`LOOP && fetchbuf1_v) begin
|
branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3;
|
branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3;
|
end
|
end
|
else begin
|
else begin
|
branch_pc <= RSTPC; // set to something to prevent a latch
|
branch_pc <= RSTPC; // set to something to prevent a latch
|
end
|
end
|
|
|
assign int_pending = (nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit);
|
assign int_pending = (nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit);
|
|
|
assign mem_stringmissx = ((dram0_op==`STS || dram0_op==`STFND) && int_pending && lc != 0 && !mem_stringmiss) ||
|
assign mem_stringmissx = ((dram0_op==`STS || dram0_op==`STFND) && int_pending && lc != 0 && !mem_stringmiss) ||
|
((dram0_op==`STMV || dram0_op==`STCMP) && int_pending && lc != 0 && !mem_stringmiss && stmv_flag);
|
((dram0_op==`STMV || dram0_op==`STCMP) && int_pending && lc != 0 && !mem_stringmiss && stmv_flag);
|
|
|
assign jmpi_miss = dram_v && (dram0_op==`JMPI || dram0_op==`JMPIX);
|
assign jmpi_miss = dram_v && (dram0_op==`JMPI || dram0_op==`JMPIX);
|
|
|
// "Stream" interrupt instructions into the instruction stream until an INT
|
// "Stream" interrupt instructions into the instruction stream until an INT
|
// instruction commits. This avoids the problem of an INT instruction being
|
// instruction commits. This avoids the problem of an INT instruction being
|
// stomped on by a previous branch instruction.
|
// stomped on by a previous branch instruction.
|
// Populate the instruction buffers with INT instructions for a hardware interrupt
|
// Populate the instruction buffers with INT instructions for a hardware interrupt
|
// Also populate the instruction buffers with a call to the instruction error vector
|
// Also populate the instruction buffers with a call to the instruction error vector
|
// if an error occurred during instruction load time.
|
// if an error occurred during instruction load time.
|
// Translate the BRK opcode to a syscall.
|
// Translate the BRK opcode to a syscall.
|
|
|
// There is a one cycle delay in setting the StatusHWI that allowed an extra INT
|
// There is a one cycle delay in setting the StatusHWI that allowed an extra INT
|
// instruction to sneek into the queue. This is NOPped out by the int_commit
|
// instruction to sneek into the queue. This is NOPped out by the int_commit
|
// signal.
|
// signal.
|
|
|
// On a cache miss the instruction buffers are loaded with NOPs this prevents
|
// On a cache miss the instruction buffers are loaded with NOPs this prevents
|
// the PC from being trashed by invalid branch instructions.
|
// the PC from being trashed by invalid branch instructions.
|
reg [63:0] insn1a,insn2a;
|
reg [63:0] insn1a,insn2a;
|
reg [63:0] insn0,insn1,insn2;
|
reg [63:0] insn0,insn1,insn2;
|
always @*
|
always @*
|
//if (int_commit)
|
//if (int_commit)
|
// insn0 <= {8{8'h10}}; // load with NOPs
|
// insn0 <= {8{8'h10}}; // load with NOPs
|
//else
|
//else
|
if (nmi_edge & ~StatusHWI & ~int_commit)
|
if (nmi_edge & ~StatusHWI & ~int_commit)
|
insn0 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
|
insn0 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
|
else if (ITLBMiss)
|
else if (ITLBMiss)
|
insn0 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
|
insn0 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
|
else if (insnerr)
|
else if (insnerr)
|
insn0 <= {8'hFC,8'hCE,8'hA6,8'h01,8'hFC,8'hCE,8'hA6,8'h01};
|
insn0 <= {8'hFC,8'hCE,8'hA6,8'h01,8'hFC,8'hCE,8'hA6,8'h01};
|
else if (irq_i & ~im & ~StatusHWI & ~int_commit)
|
else if (irq_i & ~im & ~StatusHWI & ~int_commit)
|
insn0 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
|
insn0 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
|
else if (ihit) begin
|
else if (ihit) begin
|
if (insn[7:0]==8'h00)
|
if (insn[7:0]==8'h00)
|
insn0 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
|
insn0 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
|
else
|
else
|
insn0 <= insn[63:0];
|
insn0 <= insn[63:0];
|
end
|
end
|
else
|
else
|
insn0 <= {8{8'h10}}; // load with NOPs
|
insn0 <= {8{8'h10}}; // load with NOPs
|
|
|
|
|
always @*
|
always @*
|
//if (int_commit)
|
//if (int_commit)
|
// insn1 <= {8{8'h10}}; // load with NOPs
|
// insn1 <= {8{8'h10}}; // load with NOPs
|
//else
|
//else
|
if (nmi_edge & ~StatusHWI & ~int_commit)
|
if (nmi_edge & ~StatusHWI & ~int_commit)
|
insn1 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
|
insn1 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
|
else if (ITLBMiss)
|
else if (ITLBMiss)
|
insn1 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
|
insn1 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
|
else if (insnerr)
|
else if (insnerr)
|
insn1 <= {8'hFC,8'hCE,8'hA6,8'h01,8'hFC,8'hCE,8'hA6,8'h01};
|
insn1 <= {8'hFC,8'hCE,8'hA6,8'h01,8'hFC,8'hCE,8'hA6,8'h01};
|
else if (irq_i & ~im & ~StatusHWI & ~int_commit)
|
else if (irq_i & ~im & ~StatusHWI & ~int_commit)
|
insn1 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
|
insn1 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
|
else if (ihit) begin
|
else if (ihit) begin
|
if (insn1a[7:0]==8'h00)
|
if (insn1a[7:0]==8'h00)
|
insn1 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
|
insn1 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
|
else
|
else
|
insn1 <= insn1a;
|
insn1 <= insn1a;
|
end
|
end
|
else
|
else
|
insn1 <= {8{8'h10}}; // load with NOPs
|
insn1 <= {8{8'h10}}; // load with NOPs
|
|
|
|
|
// Find the second instruction in the instruction line.
|
// Find the second instruction in the instruction line.
|
always @(insn)
|
always @(insn)
|
case(fnInsnLength(insn))
|
case(fnInsnLength(insn))
|
4'd1: insn1a <= insn[71: 8];
|
4'd1: insn1a <= insn[71: 8];
|
4'd2: insn1a <= insn[79:16];
|
4'd2: insn1a <= insn[79:16];
|
4'd3: insn1a <= insn[87:24];
|
4'd3: insn1a <= insn[87:24];
|
4'd4: insn1a <= insn[95:32];
|
4'd4: insn1a <= insn[95:32];
|
4'd5: insn1a <= insn[103:40];
|
4'd5: insn1a <= insn[103:40];
|
4'd6: insn1a <= insn[111:48];
|
4'd6: insn1a <= insn[111:48];
|
4'd7: insn1a <= insn[119:56];
|
4'd7: insn1a <= insn[119:56];
|
4'd8: insn1a <= insn[127:64];
|
4'd8: insn1a <= insn[127:64];
|
default: insn1a <= {8{8'h10}}; // NOPs
|
default: insn1a <= {8{8'h10}}; // NOPs
|
endcase
|
endcase
|
|
|
// Return the immediate field of an instruction
|
// Return the immediate field of an instruction
|
function [63:0] fnImm;
|
function [63:0] fnImm;
|
input [127:0] insn;
|
input [127:0] insn;
|
case(insn[15:8])
|
case(insn[15:8])
|
`P: fnImm = insn[33:16];
|
`P: fnImm = insn[33:16];
|
`CAS: fnImm = {{56{insn[47]}},insn[47:40]};
|
`CAS: fnImm = {{56{insn[47]}},insn[47:40]};
|
`BCD: fnImm = insn[47:40];
|
`BCD: fnImm = insn[47:40];
|
`TLB: fnImm = insn[23:16];
|
`TLB: fnImm = insn[23:16];
|
`LOOP: fnImm = {{56{insn[23]}},insn[23:16]};
|
`LOOP: fnImm = {{56{insn[23]}},insn[23:16]};
|
`STP: fnImm = insn[31:16];
|
`STP: fnImm = insn[31:16];
|
`JSR: fnImm = {{40{insn[47]}},insn[47:24]};
|
`JSR: fnImm = {{40{insn[47]}},insn[47:24]};
|
`JSRS: fnImm = {{48{insn[39]}},insn[39:24]};
|
`JSRS: fnImm = {{48{insn[39]}},insn[39:24]};
|
`BITFIELD: fnImm = insn[47:32];
|
`BITFIELD: fnImm = insn[47:32];
|
`SYS,`INT: fnImm = {insn[31:24],4'h0};
|
`SYS,`INT: fnImm = {insn[31:24],4'h0};
|
//`CMPI,
|
//`CMPI,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
`LDI,`LDIS,`ADDUIS:
|
`LDI,`LDIS,`ADDUIS:
|
fnImm = {{54{insn[31]}},insn[31:22]};
|
fnImm = {{54{insn[31]}},insn[31:22]};
|
`RTS: fnImm = insn[19:16];
|
`RTS: fnImm = insn[19:16];
|
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm = 64'h0;
|
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm = 64'h0;
|
`STI: fnImm = {{58{insn[33]}},insn[33:28]};
|
`STI: fnImm = {{58{insn[33]}},insn[33:28]};
|
`PUSH: fnImm = 64'hFFFFFFFFFFFFFFF8; //-8
|
`PUSH: fnImm = 64'hFFFFFFFFFFFFFFF8; //-8
|
//`LINK: fnImm = {insn[39:28],3'b000};
|
//`LINK: fnImm = {insn[39:28],3'b000};
|
`JMPI,`LLA,
|
`JMPI,`LLA,`LEA,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
|
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
|
fnImm = {{55{insn[36]}},insn[36:28]};
|
fnImm = {{55{insn[36]}},insn[36:28]};
|
default:
|
default:
|
fnImm = {{52{insn[39]}},insn[39:28]};
|
fnImm = {{52{insn[39]}},insn[39:28]};
|
endcase
|
endcase
|
|
|
endfunction
|
endfunction
|
|
|
function [7:0] fnImm8;
|
function [7:0] fnImm8;
|
input [127:0] insn;
|
input [127:0] insn;
|
case(insn[15:8])
|
case(insn[15:8])
|
`CAS: fnImm8 = insn[47:40];
|
`CAS: fnImm8 = insn[47:40];
|
`BCD: fnImm8 = insn[47:40];
|
`BCD: fnImm8 = insn[47:40];
|
`TLB: fnImm8 = insn[23:16];
|
`TLB: fnImm8 = insn[23:16];
|
`LOOP: fnImm8 = insn[23:16];
|
`LOOP: fnImm8 = insn[23:16];
|
`STP: fnImm8 = insn[23:16];
|
`STP: fnImm8 = insn[23:16];
|
`JSR,`JSRS: fnImm8 = insn[31:24];
|
`JSR,`JSRS: fnImm8 = insn[31:24];
|
`BITFIELD: fnImm8 = insn[39:32];
|
`BITFIELD: fnImm8 = insn[39:32];
|
`SYS,`INT: fnImm8 = {insn[27:24],4'h0};
|
`SYS,`INT: fnImm8 = {insn[27:24],4'h0};
|
//`CMPI,
|
//`CMPI,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22];
|
`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22];
|
`RTS: fnImm8 = insn[19:16];
|
`RTS: fnImm8 = insn[19:16];
|
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm8 = 8'h00;
|
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm8 = 8'h00;
|
`STI: fnImm8 = insn[35:28];
|
`STI: fnImm8 = insn[35:28];
|
`PUSH: fnImm8 = 8'hF8;
|
`PUSH: fnImm8 = 8'hF8;
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
`LINK: fnImm8 = {insn[32:28],3'b000};
|
`LINK: fnImm8 = {insn[32:28],3'b000};
|
`endif
|
`endif
|
`JMPI,`LLA,
|
`JMPI,`LLA,`LEA,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
|
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
|
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
|
fnImm8 = insn[35:28];
|
fnImm8 = insn[35:28];
|
default: fnImm8 = insn[35:28];
|
default: fnImm8 = insn[35:28];
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
// Return MSB of immediate value for instruction
|
// Return MSB of immediate value for instruction
|
function fnImmMSB;
|
function fnImmMSB;
|
input [127:0] insn;
|
input [127:0] insn;
|
case(insn[15:8])
|
case(insn[15:8])
|
`CAS: fnImmMSB = insn[47];
|
`CAS: fnImmMSB = insn[47];
|
`TLB,`BCD,`STP:
|
`TLB,`BCD,`STP:
|
fnImmMSB = 1'b0; // TLB regno is unsigned
|
fnImmMSB = 1'b0; // TLB regno is unsigned
|
`LOOP:
|
`LOOP:
|
fnImmMSB = insn[23];
|
fnImmMSB = insn[23];
|
`JSR:
|
`JSR:
|
fnImmMSB = insn[47];
|
fnImmMSB = insn[47];
|
`JSRS:
|
`JSRS:
|
fnImmMSB = insn[39];
|
fnImmMSB = insn[39];
|
//`CMPI,
|
//`CMPI,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h20,8'h21,8'h22,8'h23,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h24,8'h25,8'h26,8'h27,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h28,8'h29,8'h2A,8'h2B,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
8'h2C,8'h2D,8'h2E,8'h2F,
|
`LDI,`LDIS,`ADDUIS:
|
`LDI,`LDIS,`ADDUIS:
|
fnImmMSB = insn[31];
|
fnImmMSB = insn[31];
|
`SYS,`INT,`CACHE,`LINK:
|
`SYS,`INT,`CACHE,`LINK:
|
fnImmMSB = 1'b0; // SYS,INT are unsigned
|
fnImmMSB = 1'b0; // SYS,INT are unsigned
|
`RTS,`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`RTS2,`STS:
|
`RTS,`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`RTS2,`STS:
|
fnImmMSB = 1'b0; // RTS is unsigned
|
fnImmMSB = 1'b0; // RTS is unsigned
|
`PUSH: fnImmMSB = 1'b1;
|
`PUSH: fnImmMSB = 1'b1;
|
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX,
|
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX,
|
`SBX,`SCX,`SHX,`SWX:
|
`SBX,`SCX,`SHX,`SWX:
|
fnImmMSB = insn[47];
|
fnImmMSB = insn[47];
|
`JMPI,`LLA,
|
`JMPI,`LLA,`LEA,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,
|
`SB,`SC,`SH,`SW,`SWCR,`STI,`LWS,`SWS,`INC,`LCL,`PEA:
|
`SB,`SC,`SH,`SW,`SWCR,`STI,`LWS,`SWS,`INC,`LCL,`PEA:
|
fnImmMSB = insn[36];
|
fnImmMSB = insn[36];
|
default:
|
default:
|
fnImmMSB = insn[39];
|
fnImmMSB = insn[39];
|
endcase
|
endcase
|
|
|
endfunction
|
endfunction
|
|
|
function [63:0] fnImmImm;
|
function [63:0] fnImmImm;
|
input [63:0] insn;
|
input [63:0] insn;
|
case(insn[7:4])
|
case(insn[7:4])
|
4'd2: fnImmImm = {{48{insn[15]}},insn[15:8],8'h00};
|
4'd2: fnImmImm = {{48{insn[15]}},insn[15:8],8'h00};
|
4'd3: fnImmImm = {{40{insn[23]}},insn[23:8],8'h00};
|
4'd3: fnImmImm = {{40{insn[23]}},insn[23:8],8'h00};
|
4'd4: fnImmImm = {{32{insn[31]}},insn[31:8],8'h00};
|
4'd4: fnImmImm = {{32{insn[31]}},insn[31:8],8'h00};
|
4'd5: fnImmImm = {{24{insn[39]}},insn[39:8],8'h00};
|
4'd5: fnImmImm = {{24{insn[39]}},insn[39:8],8'h00};
|
4'd6: fnImmImm = {{16{insn[47]}},insn[47:8],8'h00};
|
4'd6: fnImmImm = {{16{insn[47]}},insn[47:8],8'h00};
|
4'd7: fnImmImm = {{ 8{insn[55]}},insn[55:8],8'h00};
|
4'd7: fnImmImm = {{ 8{insn[55]}},insn[55:8],8'h00};
|
4'd8: fnImmImm = {insn[63:8],8'h00};
|
4'd8: fnImmImm = {insn[63:8],8'h00};
|
default: fnImmImm = 64'd0;
|
default: fnImmImm = 64'd0;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
|
|
// Used during enque
|
// Used during enque
|
// Operand A is a little more work than B or C as it may read from special
|
// Operand A is a little more work than B or C as it may read from special
|
// purpose registers.
|
// purpose registers.
|
function [63:0] fnOpa;
|
function [63:0] fnOpa;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [6:0] Ra;
|
input [6:0] Ra;
|
input [63:0] ins;
|
input [63:0] ins;
|
input [63:0] rfo;
|
input [63:0] rfo;
|
input [63:0] epc;
|
input [63:0] epc;
|
begin
|
begin
|
`ifdef BITFIELDOPS
|
`ifdef BITFIELDOPS
|
if (opcode==`BITFIELD && ins[43:40]==`BFINSI)
|
if (opcode==`BITFIELD && ins[43:40]==`BFINSI)
|
fnOpa = ins[21:16];
|
fnOpa = ins[21:16];
|
else
|
else
|
`endif
|
`endif
|
if (Ra[6])
|
if (Ra[6])
|
fnOpa = fnSpr(Ra[5:0],epc);
|
fnOpa = fnSpr(Ra[5:0],epc);
|
else
|
else
|
fnOpa = rfo;
|
fnOpa = rfo;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [DBW-1:0] fnOpb;
|
function [DBW-1:0] fnOpb;
|
input [7:0] opcode;
|
input [7:0] opcode;
|
input [6:0] Rb;
|
input [6:0] Rb;
|
input [63:0] ins;
|
input [63:0] ins;
|
input [63:0] rfo;
|
input [63:0] rfo;
|
input [63:0] epc;
|
input [63:0] epc;
|
begin
|
begin
|
fnOpb = fnIsShiftiop(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} :
|
fnOpb = fnIsShiftiop(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} :
|
fnIsFPCtrl(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} :
|
fnIsFPCtrl(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} :
|
opcode==`INC ? {{56{ins[47]}},ins[47:40]} :
|
opcode==`INC ? {{56{ins[47]}},ins[47:40]} :
|
opcode==`STI ? ins[27:22] :
|
opcode==`STI ? ins[27:22] :
|
Rb[6] ? fnSpr(Rb[5:0],epc) :
|
Rb[6] ? fnSpr(Rb[5:0],epc) :
|
rfo;
|
rfo;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
// Used during enque
|
// Used during enque
|
function [63:0] fnOpt;
|
function [63:0] fnOpt;
|
input [6:0] tgt;
|
input [6:0] tgt;
|
input [63:0] rfo;
|
input [63:0] rfo;
|
input [63:0] epc;
|
input [63:0] epc;
|
begin
|
begin
|
if (tgt[6])
|
if (tgt[6])
|
fnOpt = fnSpr(tgt[5:0],epc);
|
fnOpt = fnSpr(tgt[5:0],epc);
|
else
|
else
|
fnOpt = rfo;
|
fnOpt = rfo;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
// Returns TRUE if instruction is only allowed in kernel mode.
|
// Returns TRUE if instruction is only allowed in kernel mode.
|
function fnIsKMOnly;
|
function fnIsKMOnly;
|
input [7:0] op;
|
input [7:0] op;
|
`ifdef PRIVCHKS
|
`ifdef PRIVCHKS
|
fnIsKMOnly = op==`RTI || op==`RTE || op==`RTD || op==`TLB || op==`CLI || op==`SEI ||
|
fnIsKMOnly = op==`RTI || op==`RTE || op==`RTD || op==`TLB || op==`CLI || op==`SEI ||
|
op==`STP
|
op==`STP
|
;
|
;
|
`else
|
`else
|
fnIsKMOnly = `FALSE;
|
fnIsKMOnly = `FALSE;
|
`endif
|
`endif
|
endfunction
|
endfunction
|
|
|
function fnIsKMOnlyReg;
|
function fnIsKMOnlyReg;
|
input [6:0] regx;
|
input [6:0] regx;
|
`ifdef PRIVCHKS
|
`ifdef PRIVCHKS
|
fnIsKMOnlyReg = regx==7'd28 || regx==7'd29 || regx==7'd30 || regx==7'd31 ||
|
fnIsKMOnlyReg = regx==7'd28 || regx==7'd29 || regx==7'd30 || regx==7'd31 ||
|
regx==7'h5B || regx==7'h5C || regx==7'h5D || regx==7'h5E ||
|
regx==7'h5B || regx==7'h5C || regx==7'h5D || regx==7'h5E ||
|
regx==7'h60 || regx==7'h68;
|
regx==7'h60 || regx==7'h68;
|
`else
|
`else
|
fnIsKMOnlyReg = `FALSE;
|
fnIsKMOnlyReg = `FALSE;
|
`endif
|
`endif
|
endfunction
|
endfunction
|
|
|
// Returns TRUE if the register is automatically valid.
|
// Returns TRUE if the register is automatically valid.
|
function fnRegIsAutoValid;
|
function fnRegIsAutoValid;
|
input [6:0] regno; // r0, c0, c15, tick
|
input [6:0] regno; // r0, c0, c15, tick
|
fnRegIsAutoValid = regno==7'h00 || regno==7'h50 || regno==7'h5F || regno==7'h72;
|
fnRegIsAutoValid = regno==7'h00 || regno==7'h50 || regno==7'h5F || regno==7'h72;
|
endfunction
|
endfunction
|
|
|
function [15:0] fnRegstrGrp;
|
function [15:0] fnRegstrGrp;
|
input [6:0] Rn;
|
input [6:0] Rn;
|
if (!Rn[6]) begin
|
if (!Rn[6]) begin
|
fnRegstrGrp="GP";
|
fnRegstrGrp="GP";
|
end
|
end
|
else
|
else
|
case(Rn[5:4])
|
case(Rn[5:4])
|
2'h0: fnRegstrGrp="PR";
|
2'h0: fnRegstrGrp="PR";
|
2'h1: fnRegstrGrp="CA";
|
2'h1: fnRegstrGrp="CA";
|
2'h2: fnRegstrGrp="SG";
|
2'h2: fnRegstrGrp="SG";
|
2'h3:
|
2'h3:
|
case(Rn[3:0])
|
case(Rn[3:0])
|
3'h0: fnRegstrGrp="PA";
|
3'h0: fnRegstrGrp="PA";
|
3'h3: fnRegstrGrp="LC";
|
3'h3: fnRegstrGrp="LC";
|
endcase
|
endcase
|
endcase
|
endcase
|
|
|
endfunction
|
endfunction
|
|
|
function [7:0] fnRegstr;
|
function [7:0] fnRegstr;
|
input [6:0] Rn;
|
input [6:0] Rn;
|
begin
|
begin
|
if (!Rn[6]) begin
|
if (!Rn[6]) begin
|
fnRegstr = Rn[5:0];
|
fnRegstr = Rn[5:0];
|
end
|
end
|
else
|
else
|
fnRegstr = Rn[3:0];
|
fnRegstr = Rn[3:0];
|
end
|
end
|
endfunction
|
endfunction
|
|
|
initial begin
|
initial begin
|
//
|
//
|
// set up panic messages
|
// set up panic messages
|
message[ `PANIC_NONE ] = "NONE ";
|
message[ `PANIC_NONE ] = "NONE ";
|
message[ `PANIC_FETCHBUFBEQ ] = "FETCHBUFBEQ ";
|
message[ `PANIC_FETCHBUFBEQ ] = "FETCHBUFBEQ ";
|
message[ `PANIC_INVALIDISLOT ] = "INVALIDISLOT ";
|
message[ `PANIC_INVALIDISLOT ] = "INVALIDISLOT ";
|
message[ `PANIC_IDENTICALDRAMS ] = "IDENTICALDRAMS ";
|
message[ `PANIC_IDENTICALDRAMS ] = "IDENTICALDRAMS ";
|
message[ `PANIC_OVERRUN ] = "OVERRUN ";
|
message[ `PANIC_OVERRUN ] = "OVERRUN ";
|
message[ `PANIC_HALTINSTRUCTION ] = "HALTINSTRUCTION ";
|
message[ `PANIC_HALTINSTRUCTION ] = "HALTINSTRUCTION ";
|
message[ `PANIC_INVALIDMEMOP ] = "INVALIDMEMOP ";
|
message[ `PANIC_INVALIDMEMOP ] = "INVALIDMEMOP ";
|
message[ `PANIC_INVALIDFBSTATE ] = "INVALIDFBSTATE ";
|
message[ `PANIC_INVALIDFBSTATE ] = "INVALIDFBSTATE ";
|
message[ `PANIC_INVALIDIQSTATE ] = "INVALIDIQSTATE ";
|
message[ `PANIC_INVALIDIQSTATE ] = "INVALIDIQSTATE ";
|
message[ `PANIC_BRANCHBACK ] = "BRANCHBACK ";
|
message[ `PANIC_BRANCHBACK ] = "BRANCHBACK ";
|
message[ `PANIC_MEMORYRACE ] = "MEMORYRACE ";
|
message[ `PANIC_MEMORYRACE ] = "MEMORYRACE ";
|
end
|
end
|
|
|
//`include "Thor_issue_combo.v"
|
//`include "Thor_issue_combo.v"
|
/*
|
/*
|
assign iqentry_imm[0] = fnHasConst(iqentry_op[0]),
|
assign iqentry_imm[0] = fnHasConst(iqentry_op[0]),
|
iqentry_imm[1] = fnHasConst(iqentry_op[1]),
|
iqentry_imm[1] = fnHasConst(iqentry_op[1]),
|
iqentry_imm[2] = fnHasConst(iqentry_op[2]),
|
iqentry_imm[2] = fnHasConst(iqentry_op[2]),
|
iqentry_imm[3] = fnHasConst(iqentry_op[3]),
|
iqentry_imm[3] = fnHasConst(iqentry_op[3]),
|
iqentry_imm[4] = fnHasConst(iqentry_op[4]),
|
iqentry_imm[4] = fnHasConst(iqentry_op[4]),
|
iqentry_imm[5] = fnHasConst(iqentry_op[5]),
|
iqentry_imm[5] = fnHasConst(iqentry_op[5]),
|
iqentry_imm[6] = fnHasConst(iqentry_op[6]),
|
iqentry_imm[6] = fnHasConst(iqentry_op[6]),
|
iqentry_imm[7] = fnHasConst(iqentry_op[7]);
|
iqentry_imm[7] = fnHasConst(iqentry_op[7]);
|
*/
|
*/
|
//
|
//
|
// additional logic for ISSUE
|
// additional logic for ISSUE
|
//
|
//
|
// for the moment, we look at ALU-input buffers to allow back-to-back issue of
|
// for the moment, we look at ALU-input buffers to allow back-to-back issue of
|
// dependent instructions ... we do not, however, look ahead for DRAM requests
|
// dependent instructions ... we do not, however, look ahead for DRAM requests
|
// that will become valid in the next cycle. instead, these have to propagate
|
// that will become valid in the next cycle. instead, these have to propagate
|
// their results into the IQ entry directly, at which point it becomes issue-able
|
// their results into the IQ entry directly, at which point it becomes issue-able
|
//
|
//
|
/*
|
/*
|
always @*
|
always @*
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
iq_cmt[n] <= fnPredicate(iqentry_pred[n], iqentry_cond[n]) ||
|
iq_cmt[n] <= fnPredicate(iqentry_pred[n], iqentry_cond[n]) ||
|
(iqentry_cond[n] < 4'h2 && ({iqentry_pred[n],iqentry_cond[n]}!=8'h90));
|
(iqentry_cond[n] < 4'h2 && ({iqentry_pred[n],iqentry_cond[n]}!=8'h90));
|
*/
|
*/
|
wire [QENTRIES-1:0] args_valid;
|
wire [QENTRIES-1:0] args_valid;
|
wire [QENTRIES-1:0] could_issue;
|
wire [QENTRIES-1:0] could_issue;
|
|
|
genvar g;
|
genvar g;
|
generate
|
generate
|
begin : argsv
|
begin : argsv
|
|
|
for (g = 0; g < QENTRIES; g = g + 1)
|
for (g = 0; g < QENTRIES; g = g + 1)
|
begin
|
begin
|
assign iqentry_imm[g] = fnHasConst(iqentry_op[g]);
|
assign iqentry_imm[g] = fnHasConst(iqentry_op[g]);
|
|
|
assign args_valid[g] =
|
assign args_valid[g] =
|
(iqentry_p_v[g]
|
(iqentry_p_v[g]
|
|| (iqentry_p_s[g]==alu0_sourceid && alu0_v)
|
|| (iqentry_p_s[g]==alu0_sourceid && alu0_v)
|
|| (iqentry_p_s[g]==alu1_sourceid && alu1_v))
|
|| (iqentry_p_s[g]==alu1_sourceid && alu1_v))
|
&& (iqentry_a1_v[g]
|
&& (iqentry_a1_v[g]
|
// || (iqentry_mem[g] && !iqentry_agen[g] && iqentry_op[g]!=`TLB)
|
// || (iqentry_mem[g] && !iqentry_agen[g] && iqentry_op[g]!=`TLB)
|
|| (iqentry_a1_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a1_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a1_s[g] == alu1_sourceid && alu1_v))
|
|| (iqentry_a1_s[g] == alu1_sourceid && alu1_v))
|
&& (iqentry_a2_v[g]
|
&& (iqentry_a2_v[g]
|
|| (iqentry_a2_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a2_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a2_s[g] == alu1_sourceid && alu1_v))
|
|| (iqentry_a2_s[g] == alu1_sourceid && alu1_v))
|
&& (iqentry_a3_v[g]
|
&& (iqentry_a3_v[g]
|
|| (iqentry_a3_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a3_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_a3_s[g] == alu1_sourceid && alu1_v))
|
|| (iqentry_a3_s[g] == alu1_sourceid && alu1_v))
|
&& (iqentry_T_v[g]
|
&& (iqentry_T_v[g]
|
|| (iqentry_T_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_T_s[g] == alu0_sourceid && alu0_v)
|
|| (iqentry_T_s[g] == alu1_sourceid && alu1_v))
|
|| (iqentry_T_s[g] == alu1_sourceid && alu1_v))
|
;
|
;
|
|
|
assign could_issue[g] = iqentry_v[g] && !iqentry_done[g] && !iqentry_out[g] && args_valid[g] &&
|
assign could_issue[g] = iqentry_v[g] && !iqentry_done[g] && !iqentry_out[g] && args_valid[g] &&
|
(iqentry_mem[g] ? !iqentry_agen[g] : 1'b1);
|
(iqentry_mem[g] ? !iqentry_agen[g] : 1'b1);
|
|
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
// The (old) simulator didn't handle the asynchronous race loop properly in the
|
// The (old) simulator didn't handle the asynchronous race loop properly in the
|
// original code. It would issue two instructions to the same islot. So the
|
// original code. It would issue two instructions to the same islot. So the
|
// issue logic has been re-written to eliminate the asynchronous loop.
|
// issue logic has been re-written to eliminate the asynchronous loop.
|
// Can't issue to the ALU if it's busy doing a long running operation like a
|
// Can't issue to the ALU if it's busy doing a long running operation like a
|
// divide.
|
// divide.
|
always @*//(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
|
always @*//(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
|
begin
|
begin
|
iqentry_issue = 8'h00;
|
iqentry_issue = 8'h00;
|
iqentry_islot[0] = 2'b00;
|
iqentry_islot[0] = 2'b00;
|
iqentry_islot[1] = 2'b00;
|
iqentry_islot[1] = 2'b00;
|
iqentry_islot[2] = 2'b00;
|
iqentry_islot[2] = 2'b00;
|
iqentry_islot[3] = 2'b00;
|
iqentry_islot[3] = 2'b00;
|
iqentry_islot[4] = 2'b00;
|
iqentry_islot[4] = 2'b00;
|
iqentry_islot[5] = 2'b00;
|
iqentry_islot[5] = 2'b00;
|
iqentry_islot[6] = 2'b00;
|
iqentry_islot[6] = 2'b00;
|
iqentry_islot[7] = 2'b00;
|
iqentry_islot[7] = 2'b00;
|
if (could_issue[head0] & !iqentry_fp[head0] & alu0_idle) begin
|
if (could_issue[head0] & !iqentry_fp[head0] & alu0_idle) begin
|
iqentry_issue[head0] = `TRUE;
|
iqentry_issue[head0] = `TRUE;
|
iqentry_islot[head0] = 2'b00;
|
iqentry_islot[head0] = 2'b00;
|
end
|
end
|
else if (could_issue[head1] & !iqentry_fp[head1] & alu0_idle
|
else if (could_issue[head1] & !iqentry_fp[head1] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
begin
|
begin
|
iqentry_issue[head1] = `TRUE;
|
iqentry_issue[head1] = `TRUE;
|
iqentry_islot[head1] = 2'b00;
|
iqentry_islot[head1] = 2'b00;
|
end
|
end
|
else if (could_issue[head2] & !iqentry_fp[head2] & alu0_idle
|
else if (could_issue[head2] & !iqentry_fp[head2] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
)
|
)
|
begin
|
begin
|
iqentry_issue[head2] = `TRUE;
|
iqentry_issue[head2] = `TRUE;
|
iqentry_islot[head2] = 2'b00;
|
iqentry_islot[head2] = 2'b00;
|
end
|
end
|
else if (could_issue[head3] & !iqentry_fp[head3] & alu0_idle
|
else if (could_issue[head3] & !iqentry_fp[head3] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
) begin
|
) begin
|
iqentry_issue[head3] = `TRUE;
|
iqentry_issue[head3] = `TRUE;
|
iqentry_islot[head3] = 2'b00;
|
iqentry_islot[head3] = 2'b00;
|
end
|
end
|
else if (could_issue[head4] & !iqentry_fp[head4] & alu0_idle
|
else if (could_issue[head4] & !iqentry_fp[head4] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
) begin
|
) begin
|
iqentry_issue[head4] = `TRUE;
|
iqentry_issue[head4] = `TRUE;
|
iqentry_islot[head4] = 2'b00;
|
iqentry_islot[head4] = 2'b00;
|
end
|
end
|
else if (could_issue[head5] & !iqentry_fp[head5] & alu0_idle
|
else if (could_issue[head5] & !iqentry_fp[head5] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
) begin
|
) begin
|
iqentry_issue[head5] = `TRUE;
|
iqentry_issue[head5] = `TRUE;
|
iqentry_islot[head5] = 2'b00;
|
iqentry_islot[head5] = 2'b00;
|
end
|
end
|
else if (could_issue[head6] & !iqentry_fp[head6] & alu0_idle
|
else if (could_issue[head6] & !iqentry_fp[head6] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
) begin
|
) begin
|
iqentry_issue[head6] = `TRUE;
|
iqentry_issue[head6] = `TRUE;
|
iqentry_islot[head6] = 2'b00;
|
iqentry_islot[head6] = 2'b00;
|
end
|
end
|
else if (could_issue[head7] & !iqentry_fp[head7] & alu0_idle
|
else if (could_issue[head7] & !iqentry_fp[head7] & alu0_idle
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
) begin
|
) begin
|
iqentry_issue[head7] = `TRUE;
|
iqentry_issue[head7] = `TRUE;
|
iqentry_islot[head7] = 2'b00;
|
iqentry_islot[head7] = 2'b00;
|
end
|
end
|
|
|
// Don't bother checking head0, it should have issued to the first
|
// Don't bother checking head0, it should have issued to the first
|
// instruction.
|
// instruction.
|
if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] & alu1_idle
|
if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1])
|
&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1])
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
begin
|
begin
|
iqentry_issue[head1] = `TRUE;
|
iqentry_issue[head1] = `TRUE;
|
iqentry_islot[head1] = 2'b01;
|
iqentry_islot[head1] = 2'b01;
|
end
|
end
|
else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] & alu1_idle
|
else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2])
|
&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
)
|
)
|
begin
|
begin
|
iqentry_issue[head2] = `TRUE;
|
iqentry_issue[head2] = `TRUE;
|
iqentry_islot[head2] = 2'b01;
|
iqentry_islot[head2] = 2'b01;
|
end
|
end
|
else if (could_issue[head3] & !iqentry_fp[head3] && !iqentry_issue[head3] & alu1_idle
|
else if (could_issue[head3] & !iqentry_fp[head3] && !iqentry_issue[head3] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3])
|
&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
) begin
|
) begin
|
iqentry_issue[head3] = `TRUE;
|
iqentry_issue[head3] = `TRUE;
|
iqentry_islot[head3] = 2'b01;
|
iqentry_islot[head3] = 2'b01;
|
end
|
end
|
else if (could_issue[head4] & !iqentry_fp[head4] && !iqentry_issue[head4] & alu1_idle
|
else if (could_issue[head4] & !iqentry_fp[head4] && !iqentry_issue[head4] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4])
|
&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
) begin
|
) begin
|
iqentry_issue[head4] = `TRUE;
|
iqentry_issue[head4] = `TRUE;
|
iqentry_islot[head4] = 2'b01;
|
iqentry_islot[head4] = 2'b01;
|
end
|
end
|
else if (could_issue[head5] & !iqentry_fp[head5] && !iqentry_issue[head5] & alu1_idle
|
else if (could_issue[head5] & !iqentry_fp[head5] && !iqentry_issue[head5] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5])
|
&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
) begin
|
) begin
|
iqentry_issue[head5] = `TRUE;
|
iqentry_issue[head5] = `TRUE;
|
iqentry_islot[head5] = 2'b01;
|
iqentry_islot[head5] = 2'b01;
|
end
|
end
|
else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] & alu1_idle
|
else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6])
|
&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
) begin
|
) begin
|
iqentry_issue[head6] = `TRUE;
|
iqentry_issue[head6] = `TRUE;
|
iqentry_islot[head6] = 2'b01;
|
iqentry_islot[head6] = 2'b01;
|
end
|
end
|
else if (could_issue[head7] & !iqentry_fp[head7] && !iqentry_issue[head7] & alu1_idle
|
else if (could_issue[head7] & !iqentry_fp[head7] && !iqentry_issue[head7] & alu1_idle
|
&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7])
|
&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
) begin
|
) begin
|
iqentry_issue[head7] = `TRUE;
|
iqentry_issue[head7] = `TRUE;
|
iqentry_islot[head7] = 2'b01;
|
iqentry_islot[head7] = 2'b01;
|
end
|
end
|
end
|
end
|
|
|
|
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
reg [3:0] fpispot;
|
reg [3:0] fpispot;
|
always @(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
|
always @(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
|
begin
|
begin
|
iqentry_fpissue = 8'h00;
|
iqentry_fpissue = 8'h00;
|
iqentry_fpislot[0] = 2'b00;
|
iqentry_fpislot[0] = 2'b00;
|
iqentry_fpislot[1] = 2'b00;
|
iqentry_fpislot[1] = 2'b00;
|
iqentry_fpislot[2] = 2'b00;
|
iqentry_fpislot[2] = 2'b00;
|
iqentry_fpislot[3] = 2'b00;
|
iqentry_fpislot[3] = 2'b00;
|
iqentry_fpislot[4] = 2'b00;
|
iqentry_fpislot[4] = 2'b00;
|
iqentry_fpislot[5] = 2'b00;
|
iqentry_fpislot[5] = 2'b00;
|
iqentry_fpislot[6] = 2'b00;
|
iqentry_fpislot[6] = 2'b00;
|
iqentry_fpislot[7] = 2'b00;
|
iqentry_fpislot[7] = 2'b00;
|
fpispot = head0;
|
fpispot = head0;
|
if (could_issue[head0] & iqentry_fp[head0]) begin
|
if (could_issue[head0] & iqentry_fp[head0]) begin
|
iqentry_fpissue[head0] = `TRUE;
|
iqentry_fpissue[head0] = `TRUE;
|
iqentry_fpislot[head0] = 2'b00;
|
iqentry_fpislot[head0] = 2'b00;
|
fpispot = head0;
|
fpispot = head0;
|
end
|
end
|
else if (could_issue[head1] & iqentry_fp[head1]
|
else if (could_issue[head1] & iqentry_fp[head1]
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
&& !(iqentry_v[head0] && iqentry_sync[head0]))
|
begin
|
begin
|
iqentry_fpissue[head1] = `TRUE;
|
iqentry_fpissue[head1] = `TRUE;
|
iqentry_fpislot[head1] = 2'b00;
|
iqentry_fpislot[head1] = 2'b00;
|
fpispot = head1;
|
fpispot = head1;
|
end
|
end
|
else if (could_issue[head2] & iqentry_fp[head2]
|
else if (could_issue[head2] & iqentry_fp[head2]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
)
|
)
|
begin
|
begin
|
iqentry_fpissue[head2] = `TRUE;
|
iqentry_fpissue[head2] = `TRUE;
|
iqentry_fpislot[head2] = 2'b00;
|
iqentry_fpislot[head2] = 2'b00;
|
fpispot = head2;
|
fpispot = head2;
|
end
|
end
|
else if (could_issue[head3] & iqentry_fp[head3]
|
else if (could_issue[head3] & iqentry_fp[head3]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
) begin
|
) begin
|
iqentry_fpissue[head3] = `TRUE;
|
iqentry_fpissue[head3] = `TRUE;
|
iqentry_fpislot[head3] = 2'b00;
|
iqentry_fpislot[head3] = 2'b00;
|
fpispot = head3;
|
fpispot = head3;
|
end
|
end
|
else if (could_issue[head4] & iqentry_fp[head4]
|
else if (could_issue[head4] & iqentry_fp[head4]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
) begin
|
) begin
|
iqentry_fpissue[head4] = `TRUE;
|
iqentry_fpissue[head4] = `TRUE;
|
iqentry_fpislot[head4] = 2'b00;
|
iqentry_fpislot[head4] = 2'b00;
|
fpispot = head4;
|
fpispot = head4;
|
end
|
end
|
else if (could_issue[head5] & iqentry_fp[head5]
|
else if (could_issue[head5] & iqentry_fp[head5]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
) begin
|
) begin
|
iqentry_fpissue[head5] = `TRUE;
|
iqentry_fpissue[head5] = `TRUE;
|
iqentry_fpislot[head5] = 2'b00;
|
iqentry_fpislot[head5] = 2'b00;
|
fpispot = head5;
|
fpispot = head5;
|
end
|
end
|
else if (could_issue[head6] & iqentry_fp[head6]
|
else if (could_issue[head6] & iqentry_fp[head6]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
) begin
|
) begin
|
iqentry_fpissue[head6] = `TRUE;
|
iqentry_fpissue[head6] = `TRUE;
|
iqentry_fpislot[head6] = 2'b00;
|
iqentry_fpislot[head6] = 2'b00;
|
fpispot = head6;
|
fpispot = head6;
|
end
|
end
|
else if (could_issue[head7] & iqentry_fp[head7]
|
else if (could_issue[head7] & iqentry_fp[head7]
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head0] && iqentry_sync[head0])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head1] && iqentry_sync[head1])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head2] && iqentry_sync[head2])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head3] && iqentry_sync[head3])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head4] && iqentry_sync[head4])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head5] && iqentry_sync[head5])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
&& !(iqentry_v[head6] && iqentry_sync[head6])
|
) begin
|
) begin
|
iqentry_fpissue[head7] = `TRUE;
|
iqentry_fpissue[head7] = `TRUE;
|
iqentry_fpislot[head7] = 2'b00;
|
iqentry_fpislot[head7] = 2'b00;
|
fpispot = head7;
|
fpispot = head7;
|
end
|
end
|
else
|
else
|
fpispot = 4'd8;
|
fpispot = 4'd8;
|
|
|
end
|
end
|
`endif
|
`endif
|
|
|
//
|
//
|
// additional logic for handling a branch miss (STOMP logic)
|
// additional logic for handling a branch miss (STOMP logic)
|
//
|
//
|
wire [QENTRIES-1:0] alu0_issue_;
|
wire [QENTRIES-1:0] alu0_issue_;
|
wire [QENTRIES-1:0] alu1_issue_;
|
wire [QENTRIES-1:0] alu1_issue_;
|
wire [QENTRIES-1:0] fp0_issue_;
|
wire [QENTRIES-1:0] fp0_issue_;
|
generate
|
generate
|
begin : stomp_logic
|
begin : stomp_logic
|
assign iqentry_stomp[0] = branchmiss & (iqentry_v[0] && head0 != 3'd0 && ((missid == QENTRIES-1) || iqentry_stomp[QENTRIES-1]));
|
assign iqentry_stomp[0] = branchmiss & (iqentry_v[0] && head0 != 3'd0 && ((missid == QENTRIES-1) || iqentry_stomp[QENTRIES-1]));
|
for (g = 1; g < QENTRIES; g = g + 1)
|
for (g = 1; g < QENTRIES; g = g + 1)
|
assign iqentry_stomp[g] = branchmiss & (iqentry_v[g] && head0 != g && ((missid == g-1) || iqentry_stomp[g-1]));
|
assign iqentry_stomp[g] = branchmiss & (iqentry_v[g] && head0 != g && ((missid == g-1) || iqentry_stomp[g-1]));
|
for (g = 0; g < QENTRIES; g = g + 1)
|
for (g = 0; g < QENTRIES; g = g + 1)
|
begin
|
begin
|
assign alu0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd0);
|
assign alu0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd0);
|
assign alu1_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd1);
|
assign alu1_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd1);
|
assign fp0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_fpissue[g] && iqentry_islot[g]==2'd0);
|
assign fp0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_fpissue[g] && iqentry_islot[g]==2'd0);
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
assign alu0_issue = |alu0_issue_;
|
assign alu0_issue = |alu0_issue_;
|
assign alu1_issue = |alu1_issue_;
|
assign alu1_issue = |alu1_issue_;
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
assign fp0_issue = |fp0_issue_;
|
assign fp0_issue = |fp0_issue_;
|
`endif
|
`endif
|
|
|
wire dcache_access_pending = dram0 == 3'd6 && (!rhit || (dram0_op==`LCL && dram0_tgt==7'd1));
|
wire dcache_access_pending = dram0 == 3'd6 && (!rhit || (dram0_op==`LCL && dram0_tgt==7'd1));
|
|
|
//
|
//
|
// determine if the instructions ready to issue can, in fact, issue.
|
// determine if the instructions ready to issue can, in fact, issue.
|
// "ready" means that the instruction has valid operands but has not gone yet
|
// "ready" means that the instruction has valid operands but has not gone yet
|
//
|
//
|
// Stores can only issue if there is no possibility of a change of program flow.
|
// Stores can only issue if there is no possibility of a change of program flow.
|
// That means no flow control operations or instructions that can cause an
|
// That means no flow control operations or instructions that can cause an
|
// exception can be before the store.
|
// exception can be before the store.
|
|
|
// ToDo: if debugging matches are enabled in theory any instruction could cause
|
// ToDo: if debugging matches are enabled in theory any instruction could cause
|
// a debug exception. The memory issue logic should check to see a debug address
|
// a debug exception. The memory issue logic should check to see a debug address
|
// match will occur, and avoid a store operation. It may be simpler to have stores
|
// match will occur, and avoid a store operation. It may be simpler to have stores
|
// only occur if they are at the head of the queue if debugging matches are turned
|
// only occur if they are at the head of the queue if debugging matches are turned
|
// on.
|
// on.
|
assign iqentry_memissue_head0 = iqentry_memready[ head0 ] && cstate==IDLE && !dcache_access_pending && dram0==0; // first in line ... go as soon as ready
|
assign iqentry_memissue_head0 = iqentry_memready[ head0 ] && cstate==IDLE && !dcache_access_pending && dram0==0; // first in line ... go as soon as ready
|
|
|
assign iqentry_memissue_head1 = ~iqentry_stomp[head1] && iqentry_memready[ head1 ] // addr and data are valid
|
assign iqentry_memissue_head1 = ~iqentry_stomp[head1] && iqentry_memready[ head1 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head1][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head1][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head1]) ? !fnIsFlowCtrl(iqentry_op[head0])
|
&& (fnIsStore(iqentry_op[head1]) ? !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnCanException(iqentry_op[head0],iqentry_fn[head0]) : `TRUE)
|
&& !fnCanException(iqentry_op[head0],iqentry_fn[head0]) : `TRUE)
|
&& (!iqentry_cas[head1])
|
&& (!iqentry_cas[head1])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
|
|
assign iqentry_memissue_head2 = ~iqentry_stomp[head2] && iqentry_memready[ head2 ] // addr and data are valid
|
assign iqentry_memissue_head2 = ~iqentry_stomp[head2] && iqentry_memready[ head2 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head2][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head2][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head2][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head2][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head2]) ?
|
&& (fnIsStore(iqentry_op[head2]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1])
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head2])
|
&& (!iqentry_cas[head2])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
// ( !fnIsFlowCtrl(iqentry_op[head0])
|
// ( !fnIsFlowCtrl(iqentry_op[head0])
|
// && !fnIsFlowCtrl(iqentry_op[head1])));
|
// && !fnIsFlowCtrl(iqentry_op[head1])));
|
|
|
assign iqentry_memissue_head3 = ~iqentry_stomp[head3] && iqentry_memready[ head3 ] // addr and data are valid
|
assign iqentry_memissue_head3 = ~iqentry_stomp[head3] && iqentry_memready[ head3 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head2]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
|| (iqentry_a1_v[head2] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
|| (iqentry_a1_v[head2] && iqentry_a1[head3][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head3]) ?
|
&& (fnIsStore(iqentry_op[head3]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2])
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head3])
|
&& (!iqentry_cas[head3])
|
// ... and there is no memory barrier
|
// ... and there is no memory barrier
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
/* ( !fnIsFlowCtrl(iqentry_op[head0])
|
/* ( !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head2])));
|
&& !fnIsFlowCtrl(iqentry_op[head2])));
|
*/
|
*/
|
assign iqentry_memissue_head4 = ~iqentry_stomp[head4] && iqentry_memready[ head4 ] // addr and data are valid
|
assign iqentry_memissue_head4 = ~iqentry_stomp[head4] && iqentry_memready[ head4 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head3]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
|| (iqentry_a1_v[head2] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
|| (iqentry_a1_v[head2] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
|| (iqentry_a1_v[head3] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
|| (iqentry_a1_v[head3] && iqentry_a1[head4][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head4]) ?
|
&& (fnIsStore(iqentry_op[head4]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3])
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head4])
|
&& (!iqentry_cas[head4])
|
// ... and there is no memory barrier
|
// ... and there is no memory barrier
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
/* ||
|
/* ||
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head3])));
|
&& !fnIsFlowCtrl(iqentry_op[head3])));
|
*/
|
*/
|
assign iqentry_memissue_head5 = ~iqentry_stomp[head5] && iqentry_memready[ head5 ] // addr and data are valid
|
assign iqentry_memissue_head5 = ~iqentry_stomp[head5] && iqentry_memready[ head5 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head4]
|
&& ~iqentry_memready[head4]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
|| (iqentry_a1_v[head2] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
|| (iqentry_a1_v[head2] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
|| (iqentry_a1_v[head3] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
|| (iqentry_a1_v[head3] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
|| (iqentry_a1_v[head4] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
|| (iqentry_a1_v[head4] && iqentry_a1[head5][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head5]) ?
|
&& (fnIsStore(iqentry_op[head5]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4])
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head5])
|
&& (!iqentry_cas[head5])
|
// ... and there is no memory barrier
|
// ... and there is no memory barrier
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
/*||
|
/*||
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head4])));
|
&& !fnIsFlowCtrl(iqentry_op[head4])));
|
*/
|
*/
|
assign iqentry_memissue_head6 = ~iqentry_stomp[head6] && iqentry_memready[ head6 ] // addr and data are valid
|
assign iqentry_memissue_head6 = ~iqentry_stomp[head6] && iqentry_memready[ head6 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head4]
|
&& ~iqentry_memready[head4]
|
&& ~iqentry_memready[head5]
|
&& ~iqentry_memready[head5]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
|| (iqentry_a1_v[head2] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
|| (iqentry_a1_v[head2] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
|| (iqentry_a1_v[head3] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
|| (iqentry_a1_v[head3] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
|| (iqentry_a1_v[head4] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
|| (iqentry_a1_v[head4] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
&& (!iqentry_mem[head5] || (iqentry_agen[head5] & iqentry_out[head5])
|
&& (!iqentry_mem[head5] || (iqentry_agen[head5] & iqentry_out[head5])
|
|| (iqentry_a1_v[head5] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head5][DBW-1:3]))
|
|| (iqentry_a1_v[head5] && iqentry_a1[head6][DBW-1:3] != iqentry_a1[head5][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head6]) ?
|
&& (fnIsStore(iqentry_op[head6]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) &&
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) &&
|
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5])
|
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head6])
|
&& (!iqentry_cas[head6])
|
// ... and there is no memory barrier
|
// ... and there is no memory barrier
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
|
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& !(iqentry_v[head5] && iqentry_memsb[head5])
|
&& !(iqentry_v[head5] && iqentry_memsb[head5])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
/*||
|
/*||
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head4])
|
&& !fnIsFlowCtrl(iqentry_op[head4])
|
&& !fnIsFlowCtrl(iqentry_op[head5])));
|
&& !fnIsFlowCtrl(iqentry_op[head5])));
|
*/
|
*/
|
assign iqentry_memissue_head7 = ~iqentry_stomp[head7] && iqentry_memready[ head7 ] // addr and data are valid
|
assign iqentry_memissue_head7 = ~iqentry_stomp[head7] && iqentry_memready[ head7 ] // addr and data are valid
|
// ... and no preceding instruction is ready to go
|
// ... and no preceding instruction is ready to go
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head0]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head1]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head2]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head3]
|
&& ~iqentry_memready[head4]
|
&& ~iqentry_memready[head4]
|
&& ~iqentry_memready[head5]
|
&& ~iqentry_memready[head5]
|
&& ~iqentry_memready[head6]
|
&& ~iqentry_memready[head6]
|
// ... and there is no address-overlap with any preceding instruction
|
// ... and there is no address-overlap with any preceding instruction
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
&& (!iqentry_mem[head0] || (iqentry_agen[head0] & iqentry_out[head0])
|
|| (iqentry_a1_v[head0] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
|| (iqentry_a1_v[head0] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head0][DBW-1:3]))
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
&& (!iqentry_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1])
|
|| (iqentry_a1_v[head1] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
|| (iqentry_a1_v[head1] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head1][DBW-1:3]))
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
&& (!iqentry_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2])
|
|| (iqentry_a1_v[head2] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
|| (iqentry_a1_v[head2] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head2][DBW-1:3]))
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
&& (!iqentry_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3])
|
|| (iqentry_a1_v[head3] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
|| (iqentry_a1_v[head3] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head3][DBW-1:3]))
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
&& (!iqentry_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4])
|
|| (iqentry_a1_v[head4] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
|| (iqentry_a1_v[head4] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head4][DBW-1:3]))
|
&& (!iqentry_mem[head5] || (iqentry_agen[head5] & iqentry_out[head5])
|
&& (!iqentry_mem[head5] || (iqentry_agen[head5] & iqentry_out[head5])
|
|| (iqentry_a1_v[head5] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head5][DBW-1:3]))
|
|| (iqentry_a1_v[head5] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head5][DBW-1:3]))
|
&& (!iqentry_mem[head6] || (iqentry_agen[head6] & iqentry_out[head6])
|
&& (!iqentry_mem[head6] || (iqentry_agen[head6] & iqentry_out[head6])
|
|| (iqentry_a1_v[head6] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head6][DBW-1:3]))
|
|| (iqentry_a1_v[head6] && iqentry_a1[head7][DBW-1:3] != iqentry_a1[head6][DBW-1:3]))
|
// ... and, if it is a SW, there is no chance of it being undone
|
// ... and, if it is a SW, there is no chance of it being undone
|
&& (fnIsStore(iqentry_op[head7]) ?
|
&& (fnIsStore(iqentry_op[head7]) ?
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) &&
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) &&
|
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) &&
|
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) &&
|
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) &&
|
!fnIsFlowCtrl(iqentry_op[head6]) && !fnCanException(iqentry_op[head6],iqentry_fn[head6])
|
!fnIsFlowCtrl(iqentry_op[head6]) && !fnCanException(iqentry_op[head6],iqentry_fn[head6])
|
: `TRUE)
|
: `TRUE)
|
&& (!iqentry_cas[head7])
|
&& (!iqentry_cas[head7])
|
// ... and there is no memory barrier
|
// ... and there is no memory barrier
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
|
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
|
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
|
&& !(iqentry_v[head6] && fnIsMem(iqentry_op[head6]) && iqentry_memdb[head6])
|
&& !(iqentry_v[head6] && fnIsMem(iqentry_op[head6]) && iqentry_memdb[head6])
|
// ... and there is no instruction barrier
|
// ... and there is no instruction barrier
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head0] && iqentry_memsb[head0])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head1] && iqentry_memsb[head1])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head2] && iqentry_memsb[head2])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head3] && iqentry_memsb[head3])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& !(iqentry_v[head4] && iqentry_memsb[head4])
|
&& !(iqentry_v[head5] && iqentry_memsb[head5])
|
&& !(iqentry_v[head5] && iqentry_memsb[head5])
|
&& !(iqentry_v[head6] && iqentry_memsb[head6])
|
&& !(iqentry_v[head6] && iqentry_memsb[head6])
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
&& cstate==IDLE && !dcache_access_pending && dram0==0
|
;
|
;
|
|
|
`include "Thor_execute_combo.v"
|
`include "Thor_execute_combo.v"
|
//`include "Thor_memory_combo.v"
|
//`include "Thor_memory_combo.v"
|
// additional DRAM-enqueue logic
|
// additional DRAM-enqueue logic
|
|
|
Thor_TLB #(DBW) utlb1
|
Thor_TLB #(DBW) utlb1
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.km(km),
|
.km(km),
|
.pc(spc),
|
.pc(spc),
|
.ea(dram0_addr),
|
.ea(dram0_addr),
|
.ppc(ppc),
|
.ppc(ppc),
|
.pea(pea),
|
.pea(pea),
|
.iuncached(iuncached),
|
.iuncached(iuncached),
|
.uncached(uncached),
|
.uncached(uncached),
|
.m1IsStore(we_o),
|
.m1IsStore(we_o),
|
.ASID(asid),
|
.ASID(asid),
|
.op(tlb_op),
|
.op(tlb_op),
|
.state(tlb_state),
|
.state(tlb_state),
|
.regno(tlb_regno),
|
.regno(tlb_regno),
|
.dati(tlb_data),
|
.dati(tlb_data),
|
.dato(tlb_dato),
|
.dato(tlb_dato),
|
.ITLBMiss(ITLBMiss),
|
.ITLBMiss(ITLBMiss),
|
.DTLBMiss(DTLBMiss),
|
.DTLBMiss(DTLBMiss),
|
.HTLBVirtPageo()
|
.HTLBVirtPageo()
|
);
|
);
|
|
|
assign dram_avail = (dram0 == `DRAMSLOT_AVAIL || dram1 == `DRAMSLOT_AVAIL || dram2 == `DRAMSLOT_AVAIL);
|
assign dram_avail = (dram0 == `DRAMSLOT_AVAIL || dram1 == `DRAMSLOT_AVAIL || dram2 == `DRAMSLOT_AVAIL);
|
|
|
generate
|
generate
|
begin : memr
|
begin : memr
|
for (g = 0; g < QENTRIES; g = g + 1)
|
for (g = 0; g < QENTRIES; g = g + 1)
|
begin
|
begin
|
assign iqentry_memopsvalid[g] = (iqentry_mem[g] & iqentry_a2_v[g] & iqentry_a3_v[g] & iqentry_agen[g] & iqentry_T_v[g]);
|
assign iqentry_memopsvalid[g] = (iqentry_mem[g] & iqentry_a2_v[g] & iqentry_a3_v[g] & iqentry_agen[g] & iqentry_T_v[g]);
|
assign iqentry_memready[g] = (iqentry_v[g] & iqentry_memopsvalid[g] & ~iqentry_memissue[g] /*& !iqentry_issue[g]*/ & ~iqentry_done[g] & ~iqentry_out[g] & ~iqentry_stomp[g]);
|
assign iqentry_memready[g] = (iqentry_v[g] & iqentry_memopsvalid[g] & ~iqentry_memissue[g] /*& !iqentry_issue[g]*/ & ~iqentry_done[g] & ~iqentry_out[g] & ~iqentry_stomp[g]);
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
/*
|
/*
|
assign
|
assign
|
iqentry_memready[0] = (iqentry_v[0] & iqentry_memopsvalid[0] & ~iqentry_memissue[0] & ~iqentry_done[0] & ~iqentry_out[0] & ~iqentry_stomp[0]),
|
iqentry_memready[0] = (iqentry_v[0] & iqentry_memopsvalid[0] & ~iqentry_memissue[0] & ~iqentry_done[0] & ~iqentry_out[0] & ~iqentry_stomp[0]),
|
*/
|
*/
|
assign outstanding_stores = (dram0 && fnIsStore(dram0_op)) || (dram1 && fnIsStore(dram1_op)) || (dram2 && fnIsStore(dram2_op));
|
assign outstanding_stores = (dram0 && fnIsStore(dram0_op)) || (dram1 && fnIsStore(dram1_op)) || (dram2 && fnIsStore(dram2_op));
|
|
|
// This signal needed to stave off an instruction cache access.
|
// This signal needed to stave off an instruction cache access.
|
assign mem_issue =
|
assign mem_issue =
|
iqentry_memissue_head0 |
|
iqentry_memissue_head0 |
|
iqentry_memissue_head1 |
|
iqentry_memissue_head1 |
|
iqentry_memissue_head2 |
|
iqentry_memissue_head2 |
|
iqentry_memissue_head3 |
|
iqentry_memissue_head3 |
|
iqentry_memissue_head4 |
|
iqentry_memissue_head4 |
|
iqentry_memissue_head5 |
|
iqentry_memissue_head5 |
|
iqentry_memissue_head6 |
|
iqentry_memissue_head6 |
|
iqentry_memissue_head7
|
iqentry_memissue_head7
|
;
|
;
|
|
|
// Nybble slices for predicate register forwarding
|
// Nybble slices for predicate register forwarding
|
wire [3:0] alu0nyb[0:15];
|
wire [3:0] alu0nyb[0:15];
|
wire [3:0] alu1nyb[0:15];
|
wire [3:0] alu1nyb[0:15];
|
wire [3:0] cmt0nyb[0:15];
|
wire [3:0] cmt0nyb[0:15];
|
wire [3:0] cmt1nyb[0:15];
|
wire [3:0] cmt1nyb[0:15];
|
|
|
generate
|
generate
|
begin : nybs
|
begin : nybs
|
for (g = 0; g < DBW/4; g = g + 1)
|
for (g = 0; g < DBW/4; g = g + 1)
|
begin
|
begin
|
assign alu0nyb[g] = alu0_bus[g*4+3:g*4];
|
assign alu0nyb[g] = alu0_bus[g*4+3:g*4];
|
assign alu1nyb[g] = alu1_bus[g*4+3:g*4];
|
assign alu1nyb[g] = alu1_bus[g*4+3:g*4];
|
assign cmt0nyb[g] = commit0_bus[g*4+3:g*4];
|
assign cmt0nyb[g] = commit0_bus[g*4+3:g*4];
|
assign cmt1nyb[g] = commit1_bus[g*4+3:g*4];
|
assign cmt1nyb[g] = commit1_bus[g*4+3:g*4];
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
//`include "Thor_commit_combo.v"
|
//`include "Thor_commit_combo.v"
|
|
|
assign commit0_v = ({iqentry_v[head0], iqentry_done[head0]} == 2'b11 && ~|panic);
|
assign commit0_v = ({iqentry_v[head0], iqentry_done[head0]} == 2'b11 && ~|panic);
|
assign commit1_v = ({iqentry_v[head0], iqentry_done[head0]} != 2'b10
|
assign commit1_v = ({iqentry_v[head0], iqentry_done[head0]} != 2'b10
|
&& {iqentry_v[head1], iqentry_done[head1]} == 2'b11 && ~|panic);
|
&& {iqentry_v[head1], iqentry_done[head1]} == 2'b11 && ~|panic);
|
|
|
assign commit0_id = {iqentry_mem[head0], head0}; // if a memory op, it has a DRAM-bus id
|
assign commit0_id = {iqentry_mem[head0], head0}; // if a memory op, it has a DRAM-bus id
|
assign commit1_id = {iqentry_mem[head1], head1}; // if a memory op, it has a DRAM-bus id
|
assign commit1_id = {iqentry_mem[head1], head1}; // if a memory op, it has a DRAM-bus id
|
|
|
assign commit0_tgt = iqentry_tgt[head0];
|
assign commit0_tgt = iqentry_tgt[head0];
|
assign commit1_tgt = iqentry_tgt[head1];
|
assign commit1_tgt = iqentry_tgt[head1];
|
|
|
assign commit0_bus = iqentry_res[head0];
|
assign commit0_bus = iqentry_res[head0];
|
assign commit1_bus = iqentry_res[head1];
|
assign commit1_bus = iqentry_res[head1];
|
|
|
// If the target register is code address register #13 or #11 (0Dh) then we really wanted a SYS not an INT.
|
// If the target register is code address register #13 or #11 (0Dh) then we really wanted a SYS not an INT.
|
// The difference is that and INT returns to the interrupted instruction, and a SYS returns to the
|
// The difference is that and INT returns to the interrupted instruction, and a SYS returns to the
|
// next instruction. In the case of hardware determined software exceptions we want to be able to
|
// next instruction. In the case of hardware determined software exceptions we want to be able to
|
// return to the interrupted instruction, hence an INT is forced targeting code address reg #13.
|
// return to the interrupted instruction, hence an INT is forced targeting code address reg #13.
|
assign int_commit = (iqentry_op[head0]==`INT && commit0_v && iqentry_tgt[head0][3:0]==4'hE) ||
|
assign int_commit = (iqentry_op[head0]==`INT && commit0_v && iqentry_tgt[head0][3:0]==4'hE) ||
|
(commit0_v && iqentry_op[head1]==`INT && commit1_v && iqentry_tgt[head1][3:0]==4'hE);
|
(commit0_v && iqentry_op[head1]==`INT && commit1_v && iqentry_tgt[head1][3:0]==4'hE);
|
assign sys_commit = ((iqentry_op[head0]==`SYS || (iqentry_op[head0]==`INT &&
|
assign sys_commit = ((iqentry_op[head0]==`SYS || (iqentry_op[head0]==`INT &&
|
(iqentry_tgt[head0][3:0]==4'hD || iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) ||
|
(iqentry_tgt[head0][3:0]==4'hD || iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) ||
|
(commit0_v && (iqentry_op[head1]==`SYS || (iqentry_op[head1]==`INT &&
|
(commit0_v && (iqentry_op[head1]==`SYS || (iqentry_op[head1]==`INT &&
|
(iqentry_tgt[head1][3:0]==4'hD || iqentry_tgt[head1][3:0]==4'hB))) && commit1_v);
|
(iqentry_tgt[head1][3:0]==4'hD || iqentry_tgt[head1][3:0]==4'hB))) && commit1_v);
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
assign dbg_commit = (((iqentry_op[head0]==`SYS && iqentry_tgt[head0][3:0]==4'hB) ||
|
assign dbg_commit = (((iqentry_op[head0]==`SYS && iqentry_tgt[head0][3:0]==4'hB) ||
|
(iqentry_op[head0]==`INT && (iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) ||
|
(iqentry_op[head0]==`INT && (iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) ||
|
(commit0_v && ((iqentry_op[head1]==`SYS && iqentry_tgt[head1][3:0]==4'hB)||
|
(commit0_v && ((iqentry_op[head1]==`SYS && iqentry_tgt[head1][3:0]==4'hB)||
|
(iqentry_op[head1]==`INT && (iqentry_tgt[head1][3:0]==4'hB))) && commit1_v);
|
(iqentry_op[head1]==`INT && (iqentry_tgt[head1][3:0]==4'hB))) && commit1_v);
|
`endif
|
`endif
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst_i)
|
if (rst_i)
|
tick <= 64'd0;
|
tick <= 64'd0;
|
else
|
else
|
tick <= tick + 64'd1;
|
tick <= tick + 64'd1;
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst_i)
|
if (rst_i)
|
nmi1 <= 1'b0;
|
nmi1 <= 1'b0;
|
else
|
else
|
nmi1 <= nmi_i;
|
nmi1 <= nmi_i;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Clock control
|
// Clock control
|
// - reset or NMI reenables the clock
|
// - reset or NMI reenables the clock
|
// - this circuit must be under the clk_i domain
|
// - this circuit must be under the clk_i domain
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//
|
//
|
reg cpu_clk_en;
|
reg cpu_clk_en;
|
reg [15:0] clk_throttle;
|
reg [15:0] clk_throttle;
|
reg [15:0] clk_throttle_new;
|
reg [15:0] clk_throttle_new;
|
reg ld_clk_throttle;
|
reg ld_clk_throttle;
|
|
|
//BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
|
//BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
|
|
|
reg lct1;
|
reg lct1;
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (rst_i) begin
|
if (rst_i) begin
|
cpu_clk_en <= 1'b1;
|
cpu_clk_en <= 1'b1;
|
lct1 <= 1'b0;
|
lct1 <= 1'b0;
|
clk_throttle <= STARTUP_POWER; // 50% power
|
clk_throttle <= STARTUP_POWER; // 50% power
|
end
|
end
|
else begin
|
else begin
|
lct1 <= ld_clk_throttle;
|
lct1 <= ld_clk_throttle;
|
clk_throttle <= {clk_throttle[14:0],clk_throttle[15]};
|
clk_throttle <= {clk_throttle[14:0],clk_throttle[15]};
|
if (ld_clk_throttle && !lct1) begin
|
if (ld_clk_throttle && !lct1) begin
|
clk_throttle <= clk_throttle_new;
|
clk_throttle <= clk_throttle_new;
|
end
|
end
|
if (nmi_i)
|
if (nmi_i)
|
clk_throttle <= STARTUP_POWER;
|
clk_throttle <= STARTUP_POWER;
|
cpu_clk_en <= clk_throttle[15];
|
cpu_clk_en <= clk_throttle[15];
|
end
|
end
|
|
|
// Clock throttling bypassed for now
|
// Clock throttling bypassed for now
|
assign clk_o = clk;
|
assign clk_o = clk;
|
assign clk = clk_i;
|
assign clk = clk_i;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Note that everything clocked has to be in the same always block. This is a
|
// Note that everything clocked has to be in the same always block. This is a
|
// limitation of some toolsets. Simulation / synthesis may get confused if the
|
// limitation of some toolsets. Simulation / synthesis may get confused if the
|
// logic isn't placed in the same always block.
|
// logic isn't placed in the same always block.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
|
|
if (nmi_i & !nmi1)
|
if (nmi_i & !nmi1)
|
nmi_edge <= 1'b1;
|
nmi_edge <= 1'b1;
|
|
|
ld_clk_throttle <= `FALSE;
|
ld_clk_throttle <= `FALSE;
|
dram_v <= `INV;
|
dram_v <= `INV;
|
alu0_ld <= 1'b0;
|
alu0_ld <= 1'b0;
|
alu1_ld <= 1'b0;
|
alu1_ld <= 1'b0;
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
fp0_ld <= 1'b0;
|
fp0_ld <= 1'b0;
|
`endif
|
`endif
|
|
|
// Interrupt enable countdown delay.
|
// Interrupt enable countdown delay.
|
if (imcd!=6'h3f)
|
if (imcd!=6'h3f)
|
imcd <= {imcd[4:0],1'b0};
|
imcd <= {imcd[4:0],1'b0};
|
if (imcd==6'd0) begin
|
if (imcd==6'd0) begin
|
im <= 1'b0;
|
im <= 1'b0;
|
imcd <= 6'h3f;
|
imcd <= 6'h3f;
|
end
|
end
|
|
|
mem_stringmiss <= `FALSE;
|
mem_stringmiss <= `FALSE;
|
if (mem_stringmissx) begin
|
if (mem_stringmissx) begin
|
mem_stringmiss <= `TRUE;
|
mem_stringmiss <= `TRUE;
|
// dram0_op <= `NOP; // clears string miss
|
// dram0_op <= `NOP; // clears string miss
|
end
|
end
|
ic_invalidate <= `FALSE;
|
ic_invalidate <= `FALSE;
|
dc_invalidate <= `FALSE;
|
dc_invalidate <= `FALSE;
|
ic_invalidate_line <= `FALSE;
|
ic_invalidate_line <= `FALSE;
|
dc_invalidate_line <= `FALSE;
|
dc_invalidate_line <= `FALSE;
|
alu0_dataready <= `FALSE;
|
alu0_dataready <= `FALSE;
|
alu1_dataready <= `FALSE;
|
alu1_dataready <= `FALSE;
|
|
|
// Reset segmentation flag once operating in non-segmented area.
|
// Reset segmentation flag once operating in non-segmented area.
|
if (pc[ABW-1:ABW-4]==4'hF)
|
if (pc[ABW-1:ABW-4]==4'hF)
|
pc[ABW] <= 1'b0;
|
pc[ABW] <= 1'b0;
|
|
|
if (rst_i)
|
if (rst_i)
|
cstate <= RESET1;
|
cstate <= RESET1;
|
if (rst_i||cstate==RESET1||cstate==RESET2) begin
|
if (rst_i||cstate==RESET1||cstate==RESET2) begin
|
imcd <= 6'h3F;
|
imcd <= 6'h3F;
|
wb_nack();
|
wb_nack();
|
`ifdef PCHIST
|
`ifdef PCHIST
|
pc_cap <= `TRUE;
|
pc_cap <= `TRUE;
|
`endif
|
`endif
|
ierr <= 1'b0;
|
ierr <= 1'b0;
|
GM <= 8'hFF;
|
GM <= 8'hFF;
|
nmi_edge <= 1'b0;
|
nmi_edge <= 1'b0;
|
pc <= RSTPC[ABW-1:0];
|
pc <= RSTPC[ABW-1:0];
|
StatusHWI <= `TRUE; // disables interrupts at startup until an RTI instruction is executed.
|
StatusHWI <= `TRUE; // disables interrupts at startup until an RTI instruction is executed.
|
im <= 1'b1;
|
im <= 1'b1;
|
imb <= 1'b1;
|
imb <= 1'b1;
|
ic_invalidate <= `TRUE;
|
ic_invalidate <= `TRUE;
|
dc_invalidate <= `TRUE;
|
dc_invalidate <= `TRUE;
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
fetchbufA_v <= `INV;
|
fetchbufA_v <= `INV;
|
fetchbufB_v <= `INV;
|
fetchbufB_v <= `INV;
|
fetchbufC_v <= `INV;
|
fetchbufC_v <= `INV;
|
fetchbufD_v <= `INV;
|
fetchbufD_v <= `INV;
|
fetchbufA_instr <= {8{8'h10}};
|
fetchbufA_instr <= {8{8'h10}};
|
fetchbufB_instr <= {8{8'h10}};
|
fetchbufB_instr <= {8{8'h10}};
|
fetchbufC_instr <= {8{8'h10}};
|
fetchbufC_instr <= {8{8'h10}};
|
fetchbufD_instr <= {8{8'h10}};
|
fetchbufD_instr <= {8{8'h10}};
|
fetchbufA_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufA_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufB_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufB_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufC_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufC_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufD_pc <= {{DBW-4{1'b1}},4'h0};
|
fetchbufD_pc <= {{DBW-4{1'b1}},4'h0};
|
for (i=0; i< QENTRIES; i=i+1) begin
|
for (i=0; i< QENTRIES; i=i+1) begin
|
iqentry_v[i] <= `INV;
|
iqentry_v[i] <= `INV;
|
iqentry_agen[i] <= `FALSE;
|
iqentry_agen[i] <= `FALSE;
|
iqentry_op[i] <= `NOP;
|
iqentry_op[i] <= `NOP;
|
iqentry_memissue[i] <= `FALSE;
|
iqentry_memissue[i] <= `FALSE;
|
iqentry_a1[i] <= 64'd0;
|
iqentry_a1[i] <= 64'd0;
|
iqentry_a2[i] <= 64'd0;
|
iqentry_a2[i] <= 64'd0;
|
iqentry_a3[i] <= 64'd0;
|
iqentry_a3[i] <= 64'd0;
|
iqentry_T[i] <= 64'd0;
|
iqentry_T[i] <= 64'd0;
|
iqentry_a1_v[i] <= `INV;
|
iqentry_a1_v[i] <= `INV;
|
iqentry_a2_v[i] <= `INV;
|
iqentry_a2_v[i] <= `INV;
|
iqentry_a3_v[i] <= `INV;
|
iqentry_a3_v[i] <= `INV;
|
iqentry_T_v[i] <= `INV;
|
iqentry_T_v[i] <= `INV;
|
iqentry_a1_s[i] <= 4'd0;
|
iqentry_a1_s[i] <= 4'd0;
|
iqentry_a2_s[i] <= 4'd0;
|
iqentry_a2_s[i] <= 4'd0;
|
iqentry_a3_s[i] <= 4'd0;
|
iqentry_a3_s[i] <= 4'd0;
|
iqentry_T_s[i] <= 4'd0;
|
iqentry_T_s[i] <= 4'd0;
|
end
|
end
|
// All the register are flagged as valid on startup even though they
|
// All the register are flagged as valid on startup even though they
|
// may not contain valid data. Otherwise the processor will stall
|
// may not contain valid data. Otherwise the processor will stall
|
// waiting for the registers to become valid. Ideally the registers
|
// waiting for the registers to become valid. Ideally the registers
|
// should be initialized with valid values before use. But who knows
|
// should be initialized with valid values before use. But who knows
|
// what someone will do in boot code and we don't want the processor
|
// what someone will do in boot code and we don't want the processor
|
// to stall.
|
// to stall.
|
for (n = 1; n < NREGS; n = n + 1) begin
|
for (n = 1; n < NREGS; n = n + 1) begin
|
rf_v[n] = `VAL;
|
rf_v[n] = `VAL;
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
rf_source[n] <= 4'd0;
|
rf_source[n] <= 4'd0;
|
`endif
|
`endif
|
dbg_ctrl <= {DBW{1'b0}};
|
dbg_ctrl <= {DBW{1'b0}};
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
dbg_adr0 <= 0;
|
dbg_adr0 <= 0;
|
dbg_adr1 <= 0;
|
dbg_adr1 <= 0;
|
dbg_adr2 <= 0;
|
dbg_adr2 <= 0;
|
dbg_adr3 <= 0;
|
dbg_adr3 <= 0;
|
`endif
|
`endif
|
end
|
end
|
if (ABW==32)
|
if (ABW==32)
|
sregs_lmt[7] = 20'hFFFFF;
|
sregs_lmt[7] = 20'hFFFFF;
|
else
|
else
|
sregs_lmt[7] = 52'hFFFFFFFFFFFFF;
|
sregs_lmt[7] = 52'hFFFFFFFFFFFFF;
|
rf_source[0] <= 4'd0;
|
rf_source[0] <= 4'd0;
|
// rf_v[0] = `VAL;
|
// rf_v[0] = `VAL;
|
// rf_v[7'h50] = `VAL;
|
// rf_v[7'h50] = `VAL;
|
// rf_v[7'h5F] = `VAL;
|
// rf_v[7'h5F] = `VAL;
|
alu0_available <= `TRUE;
|
alu0_available <= `TRUE;
|
alu1_available <= `TRUE;
|
alu1_available <= `TRUE;
|
reset_tail_pointers(1);
|
reset_tail_pointers(1);
|
head0 <= 3'd0;
|
head0 <= 3'd0;
|
head1 <= 3'd1;
|
head1 <= 3'd1;
|
head2 <= 3'd2;
|
head2 <= 3'd2;
|
head3 <= 3'd3;
|
head3 <= 3'd3;
|
head4 <= 3'd4;
|
head4 <= 3'd4;
|
head5 <= 3'd5;
|
head5 <= 3'd5;
|
head6 <= 3'd6;
|
head6 <= 3'd6;
|
head7 <= 3'd7;
|
head7 <= 3'd7;
|
dram0 <= 3'b00;
|
dram0 <= 3'b00;
|
dram1 <= 3'b00;
|
dram1 <= 3'b00;
|
dram2 <= 3'b00;
|
dram2 <= 3'b00;
|
tlb_state <= 3'd0;
|
tlb_state <= 3'd0;
|
panic <= `PANIC_NONE;
|
panic <= `PANIC_NONE;
|
string_pc <= 64'd0;
|
string_pc <= 64'd0;
|
// The pc wraps around to address zero while fetching the reset vector.
|
// The pc wraps around to address zero while fetching the reset vector.
|
// This causes the processor to use the code segement register so the
|
// This causes the processor to use the code segement register so the
|
// CS has to be defined for reset.
|
// CS has to be defined for reset.
|
sregs[7] <= RSTCSEG;
|
sregs[7] <= RSTCSEG;
|
for (i=0; i < 16; i=i+1)
|
for (i=0; i < 16; i=i+1)
|
pregs[i] <= 4'd0;
|
pregs[i] <= 4'd0;
|
asid <= 8'h00;
|
asid <= 8'h00;
|
rrmapno <= 3'd0;
|
rrmapno <= 3'd0;
|
dram0_id <= 0;
|
dram0_id <= 0;
|
alu1_sourceid <= 0;
|
alu1_sourceid <= 0;
|
end
|
end
|
|
|
// The following registers are always valid
|
// The following registers are always valid
|
rf_v[7'h00] = `VAL;
|
rf_v[7'h00] = `VAL;
|
rf_v[7'h50] = `VAL; // C0
|
rf_v[7'h50] = `VAL; // C0
|
rf_v[7'h5F] = `VAL; // C15 (PC)
|
rf_v[7'h5F] = `VAL; // C15 (PC)
|
rf_v[7'h72] = `VAL; // tick
|
rf_v[7'h72] = `VAL; // tick
|
queued1 = `FALSE;
|
queued1 = `FALSE;
|
queued2 = `FALSE;
|
queued2 = `FALSE;
|
allowq = `TRUE;
|
allowq = `TRUE;
|
dbg_stat <= dbg_stat | dbg_stat1x;
|
dbg_stat <= dbg_stat | dbg_stat1x;
|
|
|
did_branchback <= take_branch;
|
did_branchback <= take_branch;
|
did_branchback0 <= take_branch0;
|
did_branchback0 <= take_branch0;
|
did_branchback1 <= take_branch1;
|
did_branchback1 <= take_branch1;
|
|
|
`include "Thor_Retarget.v"
|
`include "Thor_Retarget.v"
|
/*
|
/*
|
if (branchmiss) begin
|
if (branchmiss) begin
|
for (n = 1; n < NREGS; n = n + 1)
|
for (n = 1; n < NREGS; n = n + 1)
|
if (rf_v[n] == `INV && ~livetarget[n]) begin
|
if (rf_v[n] == `INV && ~livetarget[n]) begin
|
$display("brmiss: rf_v[%d] <= VAL",n);
|
$display("brmiss: rf_v[%d] <= VAL",n);
|
rf_v[n] = `VAL;
|
rf_v[n] = `VAL;
|
end
|
end
|
|
|
if (|iqentry_0_latestID[NREGS:1]) rf_source[ iqentry_tgt[0] ] <= { iqentry_mem[0], 3'd0 };
|
if (|iqentry_0_latestID[NREGS:1]) rf_source[ iqentry_tgt[0] ] <= { iqentry_mem[0], 3'd0 };
|
if (|iqentry_1_latestID[NREGS:1]) rf_source[ iqentry_tgt[1] ] <= { iqentry_mem[1], 3'd1 };
|
if (|iqentry_1_latestID[NREGS:1]) rf_source[ iqentry_tgt[1] ] <= { iqentry_mem[1], 3'd1 };
|
if (|iqentry_2_latestID[NREGS:1]) rf_source[ iqentry_tgt[2] ] <= { iqentry_mem[2], 3'd2 };
|
if (|iqentry_2_latestID[NREGS:1]) rf_source[ iqentry_tgt[2] ] <= { iqentry_mem[2], 3'd2 };
|
if (|iqentry_3_latestID[NREGS:1]) rf_source[ iqentry_tgt[3] ] <= { iqentry_mem[3], 3'd3 };
|
if (|iqentry_3_latestID[NREGS:1]) rf_source[ iqentry_tgt[3] ] <= { iqentry_mem[3], 3'd3 };
|
if (|iqentry_4_latestID[NREGS:1]) rf_source[ iqentry_tgt[4] ] <= { iqentry_mem[4], 3'd4 };
|
if (|iqentry_4_latestID[NREGS:1]) rf_source[ iqentry_tgt[4] ] <= { iqentry_mem[4], 3'd4 };
|
if (|iqentry_5_latestID[NREGS:1]) rf_source[ iqentry_tgt[5] ] <= { iqentry_mem[5], 3'd5 };
|
if (|iqentry_5_latestID[NREGS:1]) rf_source[ iqentry_tgt[5] ] <= { iqentry_mem[5], 3'd5 };
|
if (|iqentry_6_latestID[NREGS:1]) rf_source[ iqentry_tgt[6] ] <= { iqentry_mem[6], 3'd6 };
|
if (|iqentry_6_latestID[NREGS:1]) rf_source[ iqentry_tgt[6] ] <= { iqentry_mem[6], 3'd6 };
|
if (|iqentry_7_latestID[NREGS:1]) rf_source[ iqentry_tgt[7] ] <= { iqentry_mem[7], 3'd7 };
|
if (|iqentry_7_latestID[NREGS:1]) rf_source[ iqentry_tgt[7] ] <= { iqentry_mem[7], 3'd7 };
|
|
|
end
|
end
|
*/
|
*/
|
if (ihit) begin
|
if (ihit) begin
|
$display("\r\n");
|
$display("\r\n");
|
$display("TIME %0d", $time);
|
$display("TIME %0d", $time);
|
end
|
end
|
|
|
// COMMIT PHASE (register-file update only ... dequeue is elsewhere)
|
// COMMIT PHASE (register-file update only ... dequeue is elsewhere)
|
//
|
//
|
// look at head0 and head1 and let 'em write the register file if they are ready
|
// look at head0 and head1 and let 'em write the register file if they are ready
|
//
|
//
|
// why is it happening here and not in another phase?
|
// why is it happening here and not in another phase?
|
// want to emulate a pass-through register file ... i.e. if we are reading
|
// want to emulate a pass-through register file ... i.e. if we are reading
|
// out of r3 while writing to r3, the value read is the value written.
|
// out of r3 while writing to r3, the value read is the value written.
|
// requires BLOCKING assignments, so that we can read from rf[i] later.
|
// requires BLOCKING assignments, so that we can read from rf[i] later.
|
//
|
//
|
if (commit0_v) begin
|
if (commit0_v) begin
|
if (!rf_v[ commit0_tgt ]) begin
|
if (!rf_v[ commit0_tgt ]) begin
|
rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || ((branchmiss) && iqentry_source[ commit0_id[2:0] ]);
|
rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || ((branchmiss) && iqentry_source[ commit0_id[2:0] ]);
|
end
|
end
|
if (commit0_tgt != 7'd0) $display("r%d <- %h", commit0_tgt, commit0_bus);
|
if (commit0_tgt != 7'd0) $display("r%d <- %h", commit0_tgt, commit0_bus);
|
end
|
end
|
if (commit1_v) begin
|
if (commit1_v) begin
|
if (!rf_v[ commit1_tgt ]) begin
|
if (!rf_v[ commit1_tgt ]) begin
|
rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| ((branchmiss) && iqentry_source[ commit1_id[2:0] ]);
|
rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| ((branchmiss) && iqentry_source[ commit1_id[2:0] ]);
|
end
|
end
|
if (commit1_tgt != 7'd0) $display("r%d <- %h", commit1_tgt, commit1_bus);
|
if (commit1_tgt != 7'd0) $display("r%d <- %h", commit1_tgt, commit1_bus);
|
end
|
end
|
|
|
// This chunk of code has to be before the enqueue stage so that the agen bit
|
// This chunk of code has to be before the enqueue stage so that the agen bit
|
// can be reset to zero by enqueue.
|
// can be reset to zero by enqueue.
|
// put results into the appropriate instruction entries
|
// put results into the appropriate instruction entries
|
//
|
//
|
if ((alu0_op==`RR && (alu0_fn==`MUL || alu0_fn==`MULU)) || alu0_op==`MULI || alu0_op==`MULUI) begin
|
if ((alu0_op==`RR && (alu0_fn==`MUL || alu0_fn==`MULU)) || alu0_op==`MULI || alu0_op==`MULUI) begin
|
if (alu0_done) begin
|
if (alu0_done) begin
|
alu0_dataready <= `TRUE;
|
alu0_dataready <= `TRUE;
|
end
|
end
|
end
|
end
|
else if ((alu0_op==`RR && (alu0_fn==`DIV || alu0_fn==`DIVU || alu0_fn==`MOD || alu0_fn==`MODU)) ||
|
else if ((alu0_op==`RR && (alu0_fn==`DIV || alu0_fn==`DIVU || alu0_fn==`MOD || alu0_fn==`MODU)) ||
|
alu0_op==`DIVI || alu0_op==`DIVUI || alu0_op==`MODI || alu0_op==`MODUI) begin
|
alu0_op==`DIVI || alu0_op==`DIVUI || alu0_op==`MODI || alu0_op==`MODUI) begin
|
if (alu0_done) begin
|
if (alu0_done) begin
|
alu0_dataready <= `TRUE;
|
alu0_dataready <= `TRUE;
|
end
|
end
|
end
|
end
|
|
|
if (alu0_v) begin
|
if (alu0_v) begin
|
if (|alu0_exc)
|
if (|alu0_exc)
|
set_exception(alu0_id, alu0_exc==`EXC_DBZ ? 8'd241 : 8'h00);
|
set_exception(alu0_id, alu0_exc==`EXC_DBZ ? 8'd241 : 8'h00);
|
else begin
|
else begin
|
if (iqentry_op[alu0_id[2:0]]!=`IMM)
|
if (iqentry_op[alu0_id[2:0]]!=`IMM)
|
iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ alu0_id[2:0] ] || !alu0_cmt);
|
iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ alu0_id[2:0] ] || !alu0_cmt);
|
if (iqentry_jmpi[alu0_id[2:0]] && alu0_cmt)
|
if (iqentry_jmpi[alu0_id[2:0]] && alu0_cmt)
|
iqentry_res [alu0_id[2:0]] <= alu0_pc + alu0_insnsz;
|
iqentry_res [alu0_id[2:0]] <= alu0_pc + alu0_insnsz;
|
else
|
else
|
iqentry_res [ alu0_id[2:0] ] <= alu0_bus;
|
iqentry_res [ alu0_id[2:0] ] <= alu0_bus;
|
iqentry_out [ alu0_id[2:0] ] <= `FALSE;
|
iqentry_out [ alu0_id[2:0] ] <= `FALSE;
|
iqentry_cmt [ alu0_id[2:0] ] <= alu0_cmt;
|
iqentry_cmt [ alu0_id[2:0] ] <= alu0_cmt;
|
iqentry_agen[ alu0_id[2:0] ] <= `TRUE;
|
iqentry_agen[ alu0_id[2:0] ] <= `TRUE;
|
end
|
end
|
end
|
end
|
|
|
|
|
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI) && ALU1BIG) begin
|
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI) && ALU1BIG) begin
|
if (alu1_done) begin
|
if (alu1_done) begin
|
alu1_dataready <= `TRUE;
|
alu1_dataready <= `TRUE;
|
end
|
end
|
end
|
end
|
else if (((alu1_op==`RR && (alu1_fn==`DIV || alu1_fn==`DIVU || alu1_fn==`MOD || alu1_fn==`MODU)) ||
|
else if (((alu1_op==`RR && (alu1_fn==`DIV || alu1_fn==`DIVU || alu1_fn==`MOD || alu1_fn==`MODU)) ||
|
alu1_op==`DIVI || alu1_op==`DIVUI || alu1_op==`MODI || alu1_op==`MODUI) && ALU1BIG) begin
|
alu1_op==`DIVI || alu1_op==`DIVUI || alu1_op==`MODI || alu1_op==`MODUI) && ALU1BIG) begin
|
if (alu1_done) begin
|
if (alu1_done) begin
|
alu1_dataready <= `TRUE;
|
alu1_dataready <= `TRUE;
|
end
|
end
|
end
|
end
|
|
|
if (alu1_v) begin
|
if (alu1_v) begin
|
if (|alu1_exc)
|
if (|alu1_exc)
|
set_exception(alu1_id, alu1_exc==`EXC_DBZ ? 8'd241 : 8'h00);
|
set_exception(alu1_id, alu1_exc==`EXC_DBZ ? 8'd241 : 8'h00);
|
else begin
|
else begin
|
if (iqentry_op[alu1_id[2:0]]!=`IMM)
|
if (iqentry_op[alu1_id[2:0]]!=`IMM)
|
iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ alu1_id[2:0] ] || !alu1_cmt);
|
iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ alu1_id[2:0] ] || !alu1_cmt);
|
if (iqentry_jmpi[alu1_id[2:0]] && alu1_cmt)
|
if (iqentry_jmpi[alu1_id[2:0]] && alu1_cmt)
|
iqentry_res [alu1_id[2:0]] <= alu1_pc + alu1_insnsz;
|
iqentry_res [alu1_id[2:0]] <= alu1_pc + alu1_insnsz;
|
else
|
else
|
iqentry_res [ alu1_id[2:0] ] <= alu1_bus;
|
iqentry_res [ alu1_id[2:0] ] <= alu1_bus;
|
iqentry_out [ alu1_id[2:0] ] <= `FALSE;
|
iqentry_out [ alu1_id[2:0] ] <= `FALSE;
|
iqentry_cmt [ alu1_id[2:0] ] <= alu1_cmt;
|
iqentry_cmt [ alu1_id[2:0] ] <= alu1_cmt;
|
iqentry_agen[ alu1_id[2:0] ] <= `TRUE;
|
iqentry_agen[ alu1_id[2:0] ] <= `TRUE;
|
end
|
end
|
end
|
end
|
|
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
if (fp0_v) begin
|
if (fp0_v) begin
|
$display("0results to iq[%d]=%h", fp0_id[2:0],fp0_bus);
|
$display("0results to iq[%d]=%h", fp0_id[2:0],fp0_bus);
|
if (|fp0_exc)
|
if (|fp0_exc)
|
set_exception(fp0_id, fp0_exc);
|
set_exception(fp0_id, fp0_exc);
|
else begin
|
else begin
|
iqentry_res [ fp0_id[2:0] ] <= fp0_bus;
|
iqentry_res [ fp0_id[2:0] ] <= fp0_bus;
|
iqentry_done[ fp0_id[2:0] ] <= fp0_done || !fp0_cmt;
|
iqentry_done[ fp0_id[2:0] ] <= fp0_done || !fp0_cmt;
|
iqentry_out [ fp0_id[2:0] ] <= `FALSE;
|
iqentry_out [ fp0_id[2:0] ] <= `FALSE;
|
iqentry_cmt [ fp0_id[2:0] ] <= fp0_cmt;
|
iqentry_cmt [ fp0_id[2:0] ] <= fp0_cmt;
|
iqentry_agen[ fp0_id[2:0] ] <= `TRUE;
|
iqentry_agen[ fp0_id[2:0] ] <= `TRUE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
|
|
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
// ENQUEUE
|
// ENQUEUE
|
//
|
//
|
// place up to three instructions from the fetch buffer into slots in the IQ.
|
// place up to three instructions from the fetch buffer into slots in the IQ.
|
// note: they are placed in-order, and they are expected to be executed
|
// note: they are placed in-order, and they are expected to be executed
|
// 0, 1, or 2 of the fetch buffers may have valid data
|
// 0, 1, or 2 of the fetch buffers may have valid data
|
// 0, 1, or 2 slots in the instruction queue may be available.
|
// 0, 1, or 2 slots in the instruction queue may be available.
|
// if we notice that one of the instructions in the fetch buffer is a predicted
|
// if we notice that one of the instructions in the fetch buffer is a predicted
|
// branch, (set branchback/backpc and delete any instructions after it in
|
// branch, (set branchback/backpc and delete any instructions after it in
|
// fetchbuf)
|
// fetchbuf)
|
//
|
//
|
// We place the queue logic before the fetch to allow the tools to do the work
|
// We place the queue logic before the fetch to allow the tools to do the work
|
// for us. The fetch logic needs to know how many entries were queued, this is
|
// for us. The fetch logic needs to know how many entries were queued, this is
|
// tracked in the queue stage by variables queued1,queued2,queued3. Blocking
|
// tracked in the queue stage by variables queued1,queued2,queued3. Blocking
|
// assignments are used for these vars.
|
// assignments are used for these vars.
|
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
//
|
//
|
exception_set = `FALSE;
|
exception_set = `FALSE;
|
queued1 = `FALSE;
|
queued1 = `FALSE;
|
queued2 = `FALSE;
|
queued2 = `FALSE;
|
allowq = `TRUE;
|
allowq = `TRUE;
|
qstomp = `FALSE;
|
qstomp = `FALSE;
|
if (branchmiss) // don't bother doing anything if there's been a branch miss
|
if (branchmiss) // don't bother doing anything if there's been a branch miss
|
reset_tail_pointers(0);
|
reset_tail_pointers(0);
|
else begin
|
else begin
|
case ({fetchbuf0_v, fetchbuf1_v && fnNumReadPorts(fetchbuf1_instr) <= ports_avail})
|
case ({fetchbuf0_v, fetchbuf1_v && fnNumReadPorts(fetchbuf1_instr) <= ports_avail})
|
2'b00: ; // do nothing
|
2'b00: ; // do nothing
|
2'b01: enque1(tail0,1,0,1);
|
2'b01: enque1(tail0,1,0,1);
|
2'b10: enque0(tail0,1,0,1);
|
2'b10: enque0(tail0,1,0,1);
|
2'b11: begin
|
2'b11: begin
|
enque0(tail0,1,1,1);
|
enque0(tail0,1,1,1);
|
if (allowq)
|
if (allowq)
|
enque1(tail1,2,0,0);
|
enque1(tail1,2,0,0);
|
validate_args();
|
validate_args();
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
// FETCH
|
// FETCH
|
//
|
//
|
// fetch at least two instructions from memory into the fetch buffer unless
|
// fetch at least two instructions from memory into the fetch buffer unless
|
// either one of the buffers is still full, in which case we do nothing (kinda
|
// either one of the buffers is still full, in which case we do nothing (kinda
|
// like alpha approach)
|
// like alpha approach)
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
//
|
//
|
if (branchmiss) begin
|
if (branchmiss) begin
|
$display("pc <= %h", misspc);
|
$display("pc <= %h", misspc);
|
pc <= misspc;
|
pc <= misspc;
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
fetchbufA_v <= 1'b0;
|
fetchbufA_v <= 1'b0;
|
fetchbufB_v <= 1'b0;
|
fetchbufB_v <= 1'b0;
|
fetchbufC_v <= 1'b0;
|
fetchbufC_v <= 1'b0;
|
fetchbufD_v <= 1'b0;
|
fetchbufD_v <= 1'b0;
|
end
|
end
|
else if (take_branch) begin
|
else if (take_branch) begin
|
if (fetchbuf == 1'b0) begin
|
if (fetchbuf == 1'b0) begin
|
case ({fetchbufA_v,fetchbufB_v,fetchbufC_v,fetchbufD_v})
|
case ({fetchbufA_v,fetchbufB_v,fetchbufC_v,fetchbufD_v})
|
4'b0000:
|
4'b0000:
|
begin
|
begin
|
fetchCD();
|
fetchCD();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
end
|
end
|
4'b0100:
|
4'b0100:
|
begin
|
begin
|
fetchCD();
|
fetchCD();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufB_v <= !queued1;
|
fetchbufB_v <= !queued1;
|
if (queued1) begin
|
if (queued1) begin
|
fetchbufB_instr <= 64'd0;
|
fetchbufB_instr <= 64'd0;
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
end
|
end
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b0111:
|
4'b0111:
|
begin
|
begin
|
fetchbufB_v <= !queued1;
|
fetchbufB_v <= !queued1;
|
if (queued1) begin
|
if (queued1) begin
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
fetchbufB_instr <= 64'd0;
|
fetchbufB_instr <= 64'd0;
|
end
|
end
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1000:
|
4'b1000:
|
begin
|
begin
|
fetchCD();
|
fetchCD();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufA_v <= !queued1;
|
fetchbufA_v <= !queued1;
|
if (queued1) begin
|
if (queued1) begin
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
fetchbufA_instr <= 64'd0;
|
fetchbufA_instr <= 64'd0;
|
end
|
end
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1011:
|
4'b1011:
|
begin
|
begin
|
fetchbufA_v <= !queued1;
|
fetchbufA_v <= !queued1;
|
if (queued1) begin
|
if (queued1) begin
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
fetchbufB_instr <= 64'd0;
|
fetchbufB_instr <= 64'd0;
|
end
|
end
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1100:
|
4'b1100:
|
// Note that there is no point to loading C,D here because
|
// Note that there is no point to loading C,D here because
|
// there is a predicted taken branch that would stomp on the
|
// there is a predicted taken branch that would stomp on the
|
// instructions anyways.
|
// instructions anyways.
|
if ((fnIsBranch(opcodeA) && predict_takenBr)||opcodeA==`LOOP) begin
|
if ((fnIsBranch(opcodeA) && predict_takenBr)||opcodeA==`LOOP) begin
|
pc <= branch_pc;
|
pc <= branch_pc;
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufB_v <= `INV; // stomp on it
|
fetchbufB_v <= `INV; // stomp on it
|
// may as well stick with same fetchbuf
|
// may as well stick with same fetchbuf
|
end
|
end
|
else begin
|
else begin
|
if (did_branchback0) begin
|
if (did_branchback0) begin
|
fetchCD();
|
fetchCD();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufB_v <= !queued2;
|
fetchbufB_v <= !queued2;
|
if (queued2)
|
if (queued2)
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
end
|
end
|
else begin
|
else begin
|
pc[ABW-1:0] <= branch_pc;
|
pc[ABW-1:0] <= branch_pc;
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufB_v <= !queued2;
|
fetchbufB_v <= !queued2;
|
// may as well keep the same fetchbuffer
|
// may as well keep the same fetchbuffer
|
end
|
end
|
end
|
end
|
4'b1111:
|
4'b1111:
|
begin
|
begin
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufB_v <= !queued2;
|
fetchbufB_v <= !queued2;
|
if (queued2) begin
|
if (queued2) begin
|
fetchbuf <= 1'b1;
|
fetchbuf <= 1'b1;
|
fetchbufA_instr <= 64'd0;
|
fetchbufA_instr <= 64'd0;
|
fetchbufB_instr <= 64'd0;
|
fetchbufB_instr <= 64'd0;
|
end
|
end
|
end
|
end
|
default: panic <= `PANIC_INVALIDFBSTATE;
|
default: panic <= `PANIC_INVALIDFBSTATE;
|
endcase
|
endcase
|
end
|
end
|
else begin // fetchbuf==1'b1
|
else begin // fetchbuf==1'b1
|
case ({fetchbufC_v,fetchbufD_v,fetchbufA_v,fetchbufB_v})
|
case ({fetchbufC_v,fetchbufD_v,fetchbufA_v,fetchbufB_v})
|
4'b0000:
|
4'b0000:
|
begin
|
begin
|
fetchAB();
|
fetchAB();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
end
|
end
|
4'b0100:
|
4'b0100:
|
begin
|
begin
|
fetchAB();
|
fetchAB();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufD_v <= !queued1;
|
fetchbufD_v <= !queued1;
|
if (queued1)
|
if (queued1)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b0111:
|
4'b0111:
|
begin
|
begin
|
fetchbufD_v <= !queued1;
|
fetchbufD_v <= !queued1;
|
if (queued1)
|
if (queued1)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1000:
|
4'b1000:
|
begin
|
begin
|
fetchAB();
|
fetchAB();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufC_v <= !queued1;
|
fetchbufC_v <= !queued1;
|
if (queued1)
|
if (queued1)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1011:
|
4'b1011:
|
begin
|
begin
|
fetchbufC_v <= !queued1;
|
fetchbufC_v <= !queued1;
|
if (queued1)
|
if (queued1)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
if (queued2|queued3)
|
if (queued2|queued3)
|
panic <= `PANIC_INVALIDIQSTATE;
|
panic <= `PANIC_INVALIDIQSTATE;
|
end
|
end
|
4'b1100:
|
4'b1100:
|
if ((fnIsBranch(opcodeC) && predict_takenBr)||opcodeC==`LOOP) begin
|
if ((fnIsBranch(opcodeC) && predict_takenBr)||opcodeC==`LOOP) begin
|
pc <= branch_pc;
|
pc <= branch_pc;
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufD_v <= `INV; // stomp on it
|
fetchbufD_v <= `INV; // stomp on it
|
// may as well stick with same fetchbuf
|
// may as well stick with same fetchbuf
|
end
|
end
|
else begin
|
else begin
|
if (did_branchback1) begin
|
if (did_branchback1) begin
|
fetchAB();
|
fetchAB();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufD_v <= !queued2;
|
fetchbufD_v <= !queued2;
|
if (queued2)
|
if (queued2)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
end
|
end
|
else begin
|
else begin
|
pc[ABW-1:0] <= branch_pc;
|
pc[ABW-1:0] <= branch_pc;
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufD_v <= !queued2;
|
fetchbufD_v <= !queued2;
|
// may as well keep the same fetchbuffer
|
// may as well keep the same fetchbuffer
|
end
|
end
|
end
|
end
|
4'b1111:
|
4'b1111:
|
begin
|
begin
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufC_v <= !(queued1|queued2);
|
fetchbufD_v <= !queued2;
|
fetchbufD_v <= !queued2;
|
if (queued2)
|
if (queued2)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
end
|
end
|
default: panic <= `PANIC_INVALIDFBSTATE;
|
default: panic <= `PANIC_INVALIDFBSTATE;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (fetchbuf == 1'b0)
|
if (fetchbuf == 1'b0)
|
case ({fetchbufA_v, fetchbufB_v})
|
case ({fetchbufA_v, fetchbufB_v})
|
2'b00: ;
|
2'b00: ;
|
2'b01: begin
|
2'b01: begin
|
fetchbufB_v <= !(queued2|queued1);
|
fetchbufB_v <= !(queued2|queued1);
|
fetchbuf <= queued2|queued1;
|
fetchbuf <= queued2|queued1;
|
end
|
end
|
2'b10: begin
|
2'b10: begin
|
fetchbufA_v <= !(queued2|queued1);
|
fetchbufA_v <= !(queued2|queued1);
|
fetchbuf <= queued2|queued1;
|
fetchbuf <= queued2|queued1;
|
end
|
end
|
2'b11: begin
|
2'b11: begin
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufA_v <= !(queued1|queued2);
|
fetchbufB_v <= !queued2;
|
fetchbufB_v <= !queued2;
|
fetchbuf <= queued2;
|
fetchbuf <= queued2;
|
end
|
end
|
endcase
|
endcase
|
else
|
else
|
case ({fetchbufC_v, fetchbufD_v})
|
case ({fetchbufC_v, fetchbufD_v})
|
2'b00: ;
|
2'b00: ;
|
2'b01: begin
|
2'b01: begin
|
fetchbufD_v <= !(queued2|queued1);
|
fetchbufD_v <= !(queued2|queued1);
|
fetchbuf <= !(queued2|queued1);
|
fetchbuf <= !(queued2|queued1);
|
end
|
end
|
2'b10: begin
|
2'b10: begin
|
fetchbufC_v <= !(queued2|queued1);
|
fetchbufC_v <= !(queued2|queued1);
|
fetchbuf <= !(queued2|queued1);
|
fetchbuf <= !(queued2|queued1);
|
end
|
end
|
2'b11: begin
|
2'b11: begin
|
fetchbufC_v <= !(queued2|queued1);
|
fetchbufC_v <= !(queued2|queued1);
|
fetchbufD_v <= !queued2;
|
fetchbufD_v <= !queued2;
|
fetchbuf <= !queued2;
|
fetchbuf <= !queued2;
|
end
|
end
|
endcase
|
endcase
|
if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
|
if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
|
fetchAB();
|
fetchAB();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
// fetchbuf steering logic correction
|
// fetchbuf steering logic correction
|
if (fetchbufC_v==`INV && fetchbufD_v==`INV && do_pcinc)
|
if (fetchbufC_v==`INV && fetchbufD_v==`INV && do_pcinc)
|
fetchbuf <= 1'b0;
|
fetchbuf <= 1'b0;
|
$display("hit %b 1pc <= %h", do_pcinc, pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
|
$display("hit %b 1pc <= %h", do_pcinc, pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
|
end
|
end
|
else if (fetchbufC_v == `INV && fetchbufD_v == `INV) begin
|
else if (fetchbufC_v == `INV && fetchbufD_v == `INV) begin
|
fetchCD();
|
fetchCD();
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
|
$display("2pc <= %h", pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
|
$display("2pc <= %h", pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
|
end
|
end
|
end
|
end
|
|
|
if (ihit) begin
|
if (ihit) begin
|
$display("%h %h hit0=%b hit1=%b#", spc, pc, hit0, hit1);
|
$display("%h %h hit0=%b hit1=%b#", spc, pc, hit0, hit1);
|
$display("insn=%h", insn);
|
$display("insn=%h", insn);
|
$display("%c insn0=%h insn1=%h", nmi_edge ? "*" : " ",insn0, insn1);
|
$display("%c insn0=%h insn1=%h", nmi_edge ? "*" : " ",insn0, insn1);
|
$display("takb=%d br_pc=%h #", take_branch, branch_pc);
|
$display("takb=%d br_pc=%h #", take_branch, branch_pc);
|
$display("%c%c A: %d %h %h # %d",
|
$display("%c%c A: %d %h %h # %d",
|
45, fetchbuf?45:62, fetchbufA_v, fetchbufA_instr, fetchbufA_pc, fnInsnLength(fetchbufA_instr));
|
45, fetchbuf?45:62, fetchbufA_v, fetchbufA_instr, fetchbufA_pc, fnInsnLength(fetchbufA_instr));
|
$display("%c%c B: %d %h %h # %d",
|
$display("%c%c B: %d %h %h # %d",
|
45, fetchbuf?45:62, fetchbufB_v, fetchbufB_instr, fetchbufB_pc, fnInsnLength(fetchbufB_instr));
|
45, fetchbuf?45:62, fetchbufB_v, fetchbufB_instr, fetchbufB_pc, fnInsnLength(fetchbufB_instr));
|
$display("%c%c C: %d %h %h # %d",
|
$display("%c%c C: %d %h %h # %d",
|
45, fetchbuf?62:45, fetchbufC_v, fetchbufC_instr, fetchbufC_pc, fnInsnLength(fetchbufC_instr));
|
45, fetchbuf?62:45, fetchbufC_v, fetchbufC_instr, fetchbufC_pc, fnInsnLength(fetchbufC_instr));
|
$display("%c%c D: %d %h %h # %d",
|
$display("%c%c D: %d %h %h # %d",
|
45, fetchbuf?62:45, fetchbufD_v, fetchbufD_instr, fetchbufD_pc, fnInsnLength(fetchbufD_instr));
|
45, fetchbuf?62:45, fetchbufD_v, fetchbufD_instr, fetchbufD_pc, fnInsnLength(fetchbufD_instr));
|
$display("fetchbuf=%d",fetchbuf);
|
$display("fetchbuf=%d",fetchbuf);
|
end
|
end
|
|
|
// if (ihit) begin
|
// if (ihit) begin
|
for (i=0; i<QENTRIES; i=i+1)
|
for (i=0; i<QENTRIES; i=i+1)
|
$display("%c%c %d: %c%c%c%c%c%c%c%c %d %c %c%h %d%s %h %h %h %c %o %h %c %o %h %c %o %h %c %o %h #",
|
$display("%c%c %d: %c%c%c%c%c%c%c%c %d %c %c%h %d%s %h %h %h %c %o %h %c %o %h %c %o %h %c %o %h #",
|
(i[2:0]==head0)?72:46, (i[2:0]==tail0)?84:46, i,
|
(i[2:0]==head0)?72:46, (i[2:0]==tail0)?84:46, i,
|
iqentry_v[i]?"v":"-", iqentry_done[i]?"d":"-",
|
iqentry_v[i]?"v":"-", iqentry_done[i]?"d":"-",
|
iqentry_cmt[i]?"c":"-", iqentry_out[i]?"o":"-", iqentry_bt[i]?"b":"-", iqentry_memissue[i]?"m":"-",
|
iqentry_cmt[i]?"c":"-", iqentry_out[i]?"o":"-", iqentry_bt[i]?"b":"-", iqentry_memissue[i]?"m":"-",
|
iqentry_agen[i]?"a":"-", iqentry_issue[i]?"i":"-",
|
iqentry_agen[i]?"a":"-", iqentry_issue[i]?"i":"-",
|
iqentry_islot[i],
|
iqentry_islot[i],
|
// ((i==0) ? iqentry_0_islot : (i==1) ? iqentry_1_islot : (i==2) ? iqentry_2_islot : (i==3) ? iqentry_3_islot :
|
// ((i==0) ? iqentry_0_islot : (i==1) ? iqentry_1_islot : (i==2) ? iqentry_2_islot : (i==3) ? iqentry_3_islot :
|
// (i==4) ? iqentry_4_islot : (i==5) ? iqentry_5_islot : (i==6) ? iqentry_6_islot : iqentry_7_islot),
|
// (i==4) ? iqentry_4_islot : (i==5) ? iqentry_5_islot : (i==6) ? iqentry_6_islot : iqentry_7_islot),
|
iqentry_stomp[i] ? "s" : "-",
|
iqentry_stomp[i] ? "s" : "-",
|
(fnIsFlowCtrl(iqentry_op[i]) ? 98 : fnIsMem(iqentry_op[i]) ? 109 : 97),
|
(fnIsFlowCtrl(iqentry_op[i]) ? 98 : fnIsMem(iqentry_op[i]) ? 109 : 97),
|
iqentry_op[i],
|
iqentry_op[i],
|
fnRegstr(iqentry_tgt[i]),fnRegstrGrp(iqentry_tgt[i]),
|
fnRegstr(iqentry_tgt[i]),fnRegstrGrp(iqentry_tgt[i]),
|
iqentry_res[i], iqentry_a0[i],
|
iqentry_res[i], iqentry_a0[i],
|
iqentry_a1[i], iqentry_a1_v[i]?"v":"-", iqentry_a1_s[i],
|
iqentry_a1[i], iqentry_a1_v[i]?"v":"-", iqentry_a1_s[i],
|
iqentry_a2[i], iqentry_a2_v[i]?"v":"-", iqentry_a2_s[i],
|
iqentry_a2[i], iqentry_a2_v[i]?"v":"-", iqentry_a2_s[i],
|
iqentry_a3[i], iqentry_a3_v[i]?"v":"-", iqentry_a3_s[i],
|
iqentry_a3[i], iqentry_a3_v[i]?"v":"-", iqentry_a3_s[i],
|
iqentry_pred[i], iqentry_p_v[i]?"v":"-", iqentry_p_s[i],
|
iqentry_pred[i], iqentry_p_v[i]?"v":"-", iqentry_p_s[i],
|
iqentry_pc[i]);
|
iqentry_pc[i]);
|
$display("com0:%c%c %d r%d %h", commit0_v?"v":"-", iqentry_cmt[head0]?"c":"-", commit0_id, commit0_tgt, commit0_bus);
|
$display("com0:%c%c %d r%d %h", commit0_v?"v":"-", iqentry_cmt[head0]?"c":"-", commit0_id, commit0_tgt, commit0_bus);
|
$display("com1:%c%c %d r%d %h", commit1_v?"v":"-", iqentry_cmt[head1]?"c":"-", commit1_id, commit1_tgt, commit1_bus);
|
$display("com1:%c%c %d r%d %h", commit1_v?"v":"-", iqentry_cmt[head1]?"c":"-", commit1_id, commit1_tgt, commit1_bus);
|
|
|
// end
|
// end
|
//`include "Thor_dataincoming.v"
|
//`include "Thor_dataincoming.v"
|
// DATAINCOMING
|
// DATAINCOMING
|
//
|
//
|
// wait for operand/s to appear on alu busses and puts them into
|
// wait for operand/s to appear on alu busses and puts them into
|
// the iqentry_a1 and iqentry_a2 slots (if appropriate)
|
// the iqentry_a1 and iqentry_a2 slots (if appropriate)
|
// as well as the appropriate iqentry_res slots (and setting valid bits)
|
// as well as the appropriate iqentry_res slots (and setting valid bits)
|
//
|
//
|
//
|
//
|
if (dram_v && iqentry_v[ dram_id[2:0] ] && iqentry_mem[ dram_id[2:0] ] ) begin // if data for stomped instruction, ignore
|
if (dram_v && iqentry_v[ dram_id[2:0] ] && iqentry_mem[ dram_id[2:0] ] ) begin // if data for stomped instruction, ignore
|
$display("dram results to iq[%d]=%h", dram_id[2:0],dram_bus);
|
$display("dram results to iq[%d]=%h", dram_id[2:0],dram_bus);
|
if (!iqentry_jmpi[dram_id[2:0]])
|
if (!iqentry_jmpi[dram_id[2:0]])
|
iqentry_res [ dram_id[2:0] ] <= dram_bus;
|
iqentry_res [ dram_id[2:0] ] <= dram_bus;
|
// If an exception occurred, stuff an interrupt instruction into the queue
|
// If an exception occurred, stuff an interrupt instruction into the queue
|
// slot. The instruction will re-issue as an ALU operation. We can change
|
// slot. The instruction will re-issue as an ALU operation. We can change
|
// the queued instruction because it isn't finished yet.
|
// the queued instruction because it isn't finished yet.
|
if (|dram_exc) begin
|
if (|dram_exc) begin
|
set_exception(dram_id,
|
set_exception(dram_id,
|
dram_exc==`EXC_DBE ? 8'hFB :
|
dram_exc==`EXC_DBE ? 8'hFB :
|
dram_exc==`EXC_DBG ? 8'd243 :
|
dram_exc==`EXC_DBG ? 8'd243 :
|
dram_exc==`EXC_SEGV ? 8'd244 :
|
dram_exc==`EXC_SEGV ? 8'd244 :
|
8'hF8); // F8 = TLBMiss exception 243 = debug
|
8'hF8); // F8 = TLBMiss exception 243 = debug
|
$stop;
|
$stop;
|
end
|
end
|
else begin
|
else begin
|
// Note that the predicate was already evaluated to TRUE before the
|
// Note that the predicate was already evaluated to TRUE before the
|
// dram operation started.
|
// dram operation started.
|
iqentry_cmt[dram_id[2:0]] <= `TRUE;
|
iqentry_cmt[dram_id[2:0]] <= `TRUE;
|
iqentry_done[ dram_id[2:0] ] <= `TRUE;
|
iqentry_done[ dram_id[2:0] ] <= `TRUE;
|
if ((iqentry_op[dram_id[2:0]]==`STS ||
|
if ((iqentry_op[dram_id[2:0]]==`STS ||
|
iqentry_op[dram_id[2:0]]==`STCMP ||
|
iqentry_op[dram_id[2:0]]==`STCMP ||
|
iqentry_op[dram_id[2:0]]==`STMV ||
|
iqentry_op[dram_id[2:0]]==`STMV ||
|
iqentry_op[dram_id[2:0]]==`STFND
|
iqentry_op[dram_id[2:0]]==`STFND
|
) && lc==64'd0) begin
|
) && lc==64'd0) begin
|
string_pc <= 64'd0;
|
string_pc <= 64'd0;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
// What if there's a databus error during the store ?
|
// What if there's a databus error during the store ?
|
// set the IQ entry == DONE as soon as the SW is let loose to the memory system
|
// set the IQ entry == DONE as soon as the SW is let loose to the memory system
|
//
|
//
|
if (dram0 == 2'd2 && fnIsStore(dram0_op) && dram0_op != `STS && dram0_op != `STMV) begin
|
if (dram0 == 2'd2 && fnIsStore(dram0_op) && dram0_op != `STS && dram0_op != `STMV && dram0_op != `SWCR) begin
|
if ((alu0_v && dram0_id[2:0] == alu0_id[2:0]) || (alu1_v && dram0_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
if ((alu0_v && dram0_id[2:0] == alu0_id[2:0]) || (alu1_v && dram0_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
iqentry_done[ dram0_id[2:0] ] <= `TRUE;
|
iqentry_done[ dram0_id[2:0] ] <= `TRUE;
|
iqentry_cmt [ dram0_id[2:0]] <= `TRUE;
|
iqentry_cmt [ dram0_id[2:0]] <= `TRUE;
|
iqentry_out[ dram0_id[2:0] ] <= `FALSE;
|
iqentry_out[ dram0_id[2:0] ] <= `FALSE;
|
end
|
end
|
if (dram1 == 2'd2 && fnIsStore(dram1_op) && dram1_op != `STS && dram1_op != `STMV) begin
|
if (dram1 == 2'd2 && fnIsStore(dram1_op) && dram1_op != `STS && dram1_op != `STMV && dram1_op != `SWCR) begin
|
if ((alu0_v && dram1_id[2:0] == alu0_id[2:0]) || (alu1_v && dram1_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
if ((alu0_v && dram1_id[2:0] == alu0_id[2:0]) || (alu1_v && dram1_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
iqentry_done[ dram1_id[2:0] ] <= `TRUE;
|
iqentry_done[ dram1_id[2:0] ] <= `TRUE;
|
iqentry_cmt [ dram1_id[2:0]] <= `TRUE;
|
iqentry_cmt [ dram1_id[2:0]] <= `TRUE;
|
iqentry_out[ dram1_id[2:0] ] <= `FALSE;
|
iqentry_out[ dram1_id[2:0] ] <= `FALSE;
|
end
|
end
|
if (dram2 == 2'd2 && fnIsStore(dram2_op) && dram2_op != `STS && dram2_op != `STMV) begin
|
if (dram2 == 2'd2 && fnIsStore(dram2_op) && dram2_op != `STS && dram2_op != `STMV && dram2_op != `SWCR) begin
|
if ((alu0_v && dram2_id[2:0] == alu0_id[2:0]) || (alu1_v && dram2_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
if ((alu0_v && dram2_id[2:0] == alu0_id[2:0]) || (alu1_v && dram2_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE;
|
iqentry_done[ dram2_id[2:0] ] <= `TRUE;
|
iqentry_done[ dram2_id[2:0] ] <= `TRUE;
|
iqentry_cmt [ dram2_id[2:0]] <= `TRUE;
|
iqentry_cmt [ dram2_id[2:0]] <= `TRUE;
|
iqentry_out[ dram2_id[2:0] ] <= `FALSE;
|
iqentry_out[ dram2_id[2:0] ] <= `FALSE;
|
end
|
end
|
|
|
//
|
//
|
// see if anybody else wants the results ... look at lots of buses:
|
// see if anybody else wants the results ... look at lots of buses:
|
// - alu0_bus
|
// - alu0_bus
|
// - alu1_bus
|
// - alu1_bus
|
// - fp0_bus
|
// - fp0_bus
|
// - mem_bus
|
// - mem_bus
|
// - commit0_bus
|
// - commit0_bus
|
// - commit1_bus
|
// - commit1_bus
|
//
|
//
|
|
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
begin
|
begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
iqentry_pred[n] <= alu0nyb[iqentry_preg[n]];
|
iqentry_pred[n] <= alu0nyb[iqentry_preg[n]];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
iqentry_a1[n] <= alu0_bus;
|
iqentry_a1[n] <= alu0_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
iqentry_a2[n] <= alu0_bus;
|
iqentry_a2[n] <= alu0_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
iqentry_a3[n] <= alu0_bus;
|
iqentry_a3[n] <= alu0_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin
|
iqentry_T[n] <= alu0_bus;
|
iqentry_T[n] <= alu0_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
iqentry_pred[n] <= alu1nyb[iqentry_preg[n]];
|
iqentry_pred[n] <= alu1nyb[iqentry_preg[n]];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
iqentry_a1[n] <= alu1_bus;
|
iqentry_a1[n] <= alu1_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
iqentry_a2[n] <= alu1_bus;
|
iqentry_a2[n] <= alu1_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
iqentry_a3[n] <= alu1_bus;
|
iqentry_a3[n] <= alu1_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin
|
iqentry_T[n] <= alu1_bus;
|
iqentry_T[n] <= alu1_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
/*
|
/*
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
iqentry_pred[n] <= fp0_bus[3:0];
|
iqentry_pred[n] <= fp0_bus[3:0];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
*/
|
*/
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
iqentry_a1[n] <= fp0_bus;
|
iqentry_a1[n] <= fp0_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
iqentry_a2[n] <= fp0_bus;
|
iqentry_a2[n] <= fp0_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
iqentry_a3[n] <= fp0_bus;
|
iqentry_a3[n] <= fp0_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin
|
iqentry_T[n] <= fp0_bus;
|
iqentry_T[n] <= fp0_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
`endif
|
`endif
|
// For SWCR
|
// For SWCR
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
iqentry_pred[n] <= dram_bus[3:0];
|
iqentry_pred[n] <= dram_bus[3:0];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
iqentry_a1[n] <= dram_bus;
|
iqentry_a1[n] <= dram_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
iqentry_a2[n] <= dram_bus;
|
iqentry_a2[n] <= dram_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
iqentry_a3[n] <= dram_bus;
|
iqentry_a3[n] <= dram_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin
|
iqentry_T[n] <= dram_bus;
|
iqentry_T[n] <= dram_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
iqentry_pred[n] <= cmt0nyb[iqentry_preg[n]];
|
iqentry_pred[n] <= cmt0nyb[iqentry_preg[n]];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
iqentry_a1[n] <= commit0_bus;
|
iqentry_a1[n] <= commit0_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
iqentry_a2[n] <= commit0_bus;
|
iqentry_a2[n] <= commit0_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
iqentry_a3[n] <= commit0_bus;
|
iqentry_a3[n] <= commit0_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin
|
iqentry_T[n] <= commit0_bus;
|
iqentry_T[n] <= commit0_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
iqentry_pred[n] <= cmt1nyb[iqentry_preg[n]];
|
iqentry_pred[n] <= cmt1nyb[iqentry_preg[n]];
|
iqentry_p_v[n] <= `VAL;
|
iqentry_p_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
iqentry_a1[n] <= commit1_bus;
|
iqentry_a1[n] <= commit1_bus;
|
iqentry_a1_v[n] <= `VAL;
|
iqentry_a1_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
iqentry_a2[n] <= commit1_bus;
|
iqentry_a2[n] <= commit1_bus;
|
iqentry_a2_v[n] <= `VAL;
|
iqentry_a2_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
iqentry_a3[n] <= commit1_bus;
|
iqentry_a3[n] <= commit1_bus;
|
iqentry_a3_v[n] <= `VAL;
|
iqentry_a3_v[n] <= `VAL;
|
end
|
end
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin
|
iqentry_T[n] <= commit1_bus;
|
iqentry_T[n] <= commit1_bus;
|
iqentry_T_v[n] <= `VAL;
|
iqentry_T_v[n] <= `VAL;
|
end
|
end
|
end
|
end
|
|
|
//`include "Thor_issue.v"
|
//`include "Thor_issue.v"
|
// ISSUE
|
// ISSUE
|
//
|
//
|
// determines what instructions are ready to go, then places them
|
// determines what instructions are ready to go, then places them
|
// in the various ALU queues.
|
// in the various ALU queues.
|
// also invalidates instructions following a branch-miss BEQ or any JALR (STOMP logic)
|
// also invalidates instructions following a branch-miss BEQ or any JALR (STOMP logic)
|
//
|
//
|
//alu0_dataready <= alu0_available && alu0_issue;
|
//alu0_dataready <= alu0_available && alu0_issue;
|
/*
|
/*
|
&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
|
&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
|
|| (iqentry_issue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
|
|| (iqentry_issue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
|
|| (iqentry_issue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
|
|| (iqentry_issue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
|
|| (iqentry_issue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
|
|| (iqentry_issue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
|
|| (iqentry_issue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
|
|| (iqentry_issue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
|
|| (iqentry_issue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
|
|| (iqentry_issue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
|
|| (iqentry_issue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
|
|| (iqentry_issue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
|
|| (iqentry_issue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
|
|| (iqentry_issue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
|
*/
|
*/
|
//alu1_dataready <= alu1_available && alu1_issue;
|
//alu1_dataready <= alu1_available && alu1_issue;
|
/*
|
/*
|
&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd1 && !iqentry_stomp[0])
|
&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd1 && !iqentry_stomp[0])
|
|| (iqentry_issue[1] && iqentry_islot[1] == 4'd1 && !iqentry_stomp[1])
|
|| (iqentry_issue[1] && iqentry_islot[1] == 4'd1 && !iqentry_stomp[1])
|
|| (iqentry_issue[2] && iqentry_islot[2] == 4'd1 && !iqentry_stomp[2])
|
|| (iqentry_issue[2] && iqentry_islot[2] == 4'd1 && !iqentry_stomp[2])
|
|| (iqentry_issue[3] && iqentry_islot[3] == 4'd1 && !iqentry_stomp[3])
|
|| (iqentry_issue[3] && iqentry_islot[3] == 4'd1 && !iqentry_stomp[3])
|
|| (iqentry_issue[4] && iqentry_islot[4] == 4'd1 && !iqentry_stomp[4])
|
|| (iqentry_issue[4] && iqentry_islot[4] == 4'd1 && !iqentry_stomp[4])
|
|| (iqentry_issue[5] && iqentry_islot[5] == 4'd1 && !iqentry_stomp[5])
|
|| (iqentry_issue[5] && iqentry_islot[5] == 4'd1 && !iqentry_stomp[5])
|
|| (iqentry_issue[6] && iqentry_islot[6] == 4'd1 && !iqentry_stomp[6])
|
|| (iqentry_issue[6] && iqentry_islot[6] == 4'd1 && !iqentry_stomp[6])
|
|| (iqentry_issue[7] && iqentry_islot[7] == 4'd1 && !iqentry_stomp[7]));
|
|| (iqentry_issue[7] && iqentry_islot[7] == 4'd1 && !iqentry_stomp[7]));
|
*/
|
*/
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
fp0_dataready <= 1'b1
|
fp0_dataready <= 1'b1
|
&& ((iqentry_fpissue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
|
&& ((iqentry_fpissue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
|
|| (iqentry_fpissue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
|
|| (iqentry_fpissue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
|
|| (iqentry_fpissue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
|
|| (iqentry_fpissue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
|
|| (iqentry_fpissue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
|
|| (iqentry_fpissue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
|
|| (iqentry_fpissue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
|
|| (iqentry_fpissue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
|
|| (iqentry_fpissue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
|
|| (iqentry_fpissue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
|
|| (iqentry_fpissue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
|
|| (iqentry_fpissue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
|
|| (iqentry_fpissue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
|
|| (iqentry_fpissue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
|
`endif
|
`endif
|
|
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
begin
|
begin
|
if (iqentry_v[n] && iqentry_stomp[n]) begin
|
if (iqentry_v[n] && iqentry_stomp[n]) begin
|
iqentry_v[n] <= `INV;
|
iqentry_v[n] <= `INV;
|
if (dram0_id[2:0] == n[2:0]) dram0 <= `DRAMSLOT_AVAIL;
|
if (dram0_id[2:0] == n[2:0]) dram0 <= `DRAMSLOT_AVAIL;
|
if (dram1_id[2:0] == n[2:0]) dram1 <= `DRAMSLOT_AVAIL;
|
if (dram1_id[2:0] == n[2:0]) dram1 <= `DRAMSLOT_AVAIL;
|
if (dram2_id[2:0] == n[2:0]) dram2 <= `DRAMSLOT_AVAIL;
|
if (dram2_id[2:0] == n[2:0]) dram2 <= `DRAMSLOT_AVAIL;
|
end
|
end
|
else if (iqentry_issue[n]) begin
|
else if (iqentry_issue[n]) begin
|
case (iqentry_islot[n])
|
case (iqentry_islot[n])
|
2'd0: if (alu0_available) begin
|
2'd0: if (alu0_available) begin
|
alu0_ld <= 1'b1;
|
alu0_ld <= 1'b1;
|
alu0_sourceid <= n[3:0];
|
alu0_sourceid <= n[3:0];
|
alu0_insnsz <= iqentry_insnsz[n];
|
alu0_insnsz <= iqentry_insnsz[n];
|
alu0_op <= iqentry_op[n];
|
alu0_op <= iqentry_op[n];
|
alu0_fn <= iqentry_fn[n];
|
alu0_fn <= iqentry_fn[n];
|
alu0_cond <= iqentry_cond[n];
|
alu0_cond <= iqentry_cond[n];
|
alu0_bt <= iqentry_bt[n];
|
alu0_bt <= iqentry_bt[n];
|
alu0_pc <= iqentry_pc[n];
|
alu0_pc <= iqentry_pc[n];
|
alu0_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
alu0_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
alu0_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
alu0_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu0_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
alu0_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu0_argC <=
|
alu0_argC <=
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
|
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
|
`endif
|
`endif
|
iqentry_a3_v[n] ? iqentry_a3[n]
|
iqentry_a3_v[n] ? iqentry_a3[n]
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu0_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
alu0_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu0_argI <= iqentry_a0[n];
|
alu0_argI <= iqentry_a0[n];
|
alu0_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
|
alu0_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
|
iqentry_out[n] <= `TRUE;
|
iqentry_out[n] <= `TRUE;
|
end
|
end
|
2'd1: if (alu1_available) begin
|
2'd1: if (alu1_available) begin
|
alu1_ld <= 1'b1;
|
alu1_ld <= 1'b1;
|
alu1_sourceid <= n[3:0];
|
alu1_sourceid <= n[3:0];
|
alu1_insnsz <= iqentry_insnsz[n];
|
alu1_insnsz <= iqentry_insnsz[n];
|
alu1_op <= iqentry_op[n];
|
alu1_op <= iqentry_op[n];
|
alu1_fn <= iqentry_fn[n];
|
alu1_fn <= iqentry_fn[n];
|
alu1_cond <= iqentry_cond[n];
|
alu1_cond <= iqentry_cond[n];
|
alu1_bt <= iqentry_bt[n];
|
alu1_bt <= iqentry_bt[n];
|
alu1_pc <= iqentry_pc[n];
|
alu1_pc <= iqentry_pc[n];
|
alu1_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
alu1_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
alu1_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
alu1_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu1_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
alu1_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu1_argC <=
|
alu1_argC <=
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
|
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
|
`endif
|
`endif
|
iqentry_a3_v[n] ? iqentry_a3[n]
|
iqentry_a3_v[n] ? iqentry_a3[n]
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu1_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
alu1_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
alu1_argI <= iqentry_a0[n];
|
alu1_argI <= iqentry_a0[n];
|
alu1_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
|
alu1_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
|
iqentry_out[n] <= `TRUE;
|
iqentry_out[n] <= `TRUE;
|
end
|
end
|
default: panic <= `PANIC_INVALIDISLOT;
|
default: panic <= `PANIC_INVALIDISLOT;
|
endcase
|
endcase
|
// iqentry_out[n] <= `TRUE;
|
// iqentry_out[n] <= `TRUE;
|
// if it is a memory operation, this is the address-generation step ... collect result into arg1
|
// if it is a memory operation, this is the address-generation step ... collect result into arg1
|
if (iqentry_mem[n] && !iqentry_tlb[n]) begin
|
if (iqentry_mem[n] && !iqentry_tlb[n]) begin
|
iqentry_a1_v[n] <= `INV;
|
iqentry_a1_v[n] <= `INV;
|
iqentry_a1_s[n] <= n[3:0];
|
iqentry_a1_s[n] <= n[3:0];
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
begin
|
begin
|
if (iqentry_v[n] && iqentry_stomp[n])
|
if (iqentry_v[n] && iqentry_stomp[n])
|
;
|
;
|
else if (iqentry_fpissue[n]) begin
|
else if (iqentry_fpissue[n]) begin
|
case (iqentry_fpislot[n])
|
case (iqentry_fpislot[n])
|
2'd0: if (1'b1) begin
|
2'd0: if (1'b1) begin
|
fp0_ld <= 1'b1;
|
fp0_ld <= 1'b1;
|
fp0_sourceid <= n[3:0];
|
fp0_sourceid <= n[3:0];
|
fp0_op <= iqentry_op[n];
|
fp0_op <= iqentry_op[n];
|
fp0_fn <= iqentry_fn[n];
|
fp0_fn <= iqentry_fn[n];
|
fp0_cond <= iqentry_cond[n];
|
fp0_cond <= iqentry_cond[n];
|
fp0_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
fp0_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
|
fp0_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
fp0_argA <= iqentry_a1_v[n] ? iqentry_a1[n]
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
fp0_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
fp0_argB <= iqentry_a2_v[n] ? iqentry_a2[n]
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
fp0_argC <= iqentry_a3_v[n] ? iqentry_a3[n]
|
fp0_argC <= iqentry_a3_v[n] ? iqentry_a3[n]
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
fp0_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
fp0_argT <= iqentry_T_v[n] ? iqentry_T[n]
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
fp0_argI <= iqentry_a0[n];
|
fp0_argI <= iqentry_a0[n];
|
end
|
end
|
default: panic <= `PANIC_INVALIDISLOT;
|
default: panic <= `PANIC_INVALIDISLOT;
|
endcase
|
endcase
|
iqentry_out[n] <= `TRUE;
|
iqentry_out[n] <= `TRUE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
|
|
// MEMORY
|
// MEMORY
|
//
|
//
|
// update the memory queues and put data out on bus if appropriate
|
// update the memory queues and put data out on bus if appropriate
|
// Always puts data on the bus even for stores. In the case of
|
// Always puts data on the bus even for stores. In the case of
|
// stores, the data is ignored.
|
// stores, the data is ignored.
|
//
|
//
|
//
|
//
|
// dram0, dram1, dram2 are the "state machines" that keep track
|
// dram0, dram1, dram2 are the "state machines" that keep track
|
// of three pipelined DRAM requests. if any has the value "00",
|
// of three pipelined DRAM requests. if any has the value "00",
|
// then it can accept a request (which bumps it up to the value "01"
|
// then it can accept a request (which bumps it up to the value "01"
|
// at the end of the cycle). once it hits the value "10" the request
|
// at the end of the cycle). once it hits the value "10" the request
|
// and the bus is acknowledged the dram request
|
// and the bus is acknowledged the dram request
|
// is finished and the dram_bus takes the value. if it is a store, the
|
// is finished and the dram_bus takes the value. if it is a store, the
|
// dram_bus value is not used, but the dram_v value along with the
|
// dram_bus value is not used, but the dram_v value along with the
|
// dram_id value signals the waiting memq entry that the store is
|
// dram_id value signals the waiting memq entry that the store is
|
// completed and the instruction can commit.
|
// completed and the instruction can commit.
|
//
|
//
|
if (tlb_state != 3'd0 && tlb_state < 3'd3)
|
if (tlb_state != 3'd0 && tlb_state < 3'd3)
|
tlb_state <= tlb_state + 3'd1;
|
tlb_state <= tlb_state + 3'd1;
|
if (tlb_state==3'd3) begin
|
if (tlb_state==3'd3) begin
|
dram_v <= `TRUE;
|
dram_v <= `TRUE;
|
dram_id <= tlb_id;
|
dram_id <= tlb_id;
|
dram_tgt <= tlb_tgt;
|
dram_tgt <= tlb_tgt;
|
dram_exc <= `EXC_NONE;
|
dram_exc <= `EXC_NONE;
|
dram_bus <= tlb_dato;
|
dram_bus <= tlb_dato;
|
tlb_op <= 4'h0;
|
tlb_op <= 4'h0;
|
tlb_state <= 3'd0;
|
tlb_state <= 3'd0;
|
end
|
end
|
|
|
case(dram0)
|
case(dram0)
|
// The first state is to translate the virtual to physical address.
|
// The first state is to translate the virtual to physical address.
|
// Also a good spot to check for debug match and segment limit violation.
|
// Also a good spot to check for debug match and segment limit violation.
|
3'd1:
|
3'd1:
|
begin
|
begin
|
$display("0MEM %c:%h %h cycle started",fnIsStore(dram0_op)?"S" : "L", dram0_addr, dram0_data);
|
$display("0MEM %c:%h %h cycle started",fnIsStore(dram0_op)?"S" : "L", dram0_addr, dram0_data);
|
if (dbg_lmatch|dbg_smatch) begin
|
if (dbg_lmatch|dbg_smatch) begin
|
dram_v <= `TRUE;
|
dram_v <= `TRUE;
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= `EXC_DBG;
|
dram_exc <= `EXC_DBG;
|
dram_bus <= 64'h0;
|
dram_bus <= 64'h0;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
`ifdef SEGLIMITS
|
`ifdef SEGLIMITS
|
else if (dram0_addr[ABW-1:12] >= dram0_lmt) begin
|
else if (dram0_addr[ABW-1:12] >= dram0_lmt) begin
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= `EXC_SEGV; //dram0_exc;
|
dram_exc <= `EXC_SEGV; //dram0_exc;
|
dram_bus <= 64'h0;
|
dram_bus <= 64'h0;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
`endif
|
`endif
|
`endif
|
`endif
|
else if (!cyc_o) dram0 <= dram0 + 3'd1;
|
else if (!cyc_o) dram0 <= dram0 + 3'd1;
|
end
|
end
|
|
|
// State 2:
|
// State 2:
|
// Check for a TLB miss on the translated address, and
|
// Check for a TLB miss on the translated address, and
|
// Initiate a bus transfer
|
// Initiate a bus transfer
|
3'd2:
|
3'd2:
|
if (DTLBMiss) begin
|
if (DTLBMiss) begin
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= `EXC_TLBMISS; //dram0_exc;
|
dram_exc <= `EXC_TLBMISS; //dram0_exc;
|
dram_bus <= 64'h0;
|
dram_bus <= 64'h0;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
else if (dram0_exc!=`EXC_NONE) begin
|
else if (dram0_exc!=`EXC_NONE) begin
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_v <= `TRUE; // we are finished the memory cycle
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= dram0_exc;
|
dram_exc <= dram0_exc;
|
dram_bus <= 64'h0;
|
dram_bus <= 64'h0;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
else begin
|
else begin
|
if (dram0_op==`LCL) begin
|
if (dram0_op==`LCL) begin
|
if (dram0_tgt==7'd0) begin
|
if (dram0_tgt==7'd0) begin
|
ic_invalidate_line <= `TRUE;
|
ic_invalidate_line <= `TRUE;
|
ic_lineno <= dram0_addr;
|
ic_lineno <= dram0_addr;
|
end
|
end
|
dram0 <= 3'd6;
|
dram0 <= 3'd6;
|
end
|
end
|
else if (uncached || fnIsStore(dram0_op) || fnIsLoadV(dram0_op) || dram0_op==`CAS ||
|
else if (uncached || fnIsStore(dram0_op) || fnIsLoadV(dram0_op) || dram0_op==`CAS ||
|
((dram0_op==`STMV || dram0_op==`INC) && stmv_flag)) begin
|
((dram0_op==`STMV || dram0_op==`INC) && stmv_flag)) begin
|
if (cstate==IDLE) begin // make sure an instruction load isn't taking place
|
if (cstate==IDLE) begin // make sure an instruction load isn't taking place
|
dram0_owns_bus <= `TRUE;
|
dram0_owns_bus <= `TRUE;
|
resv_o <= dram0_op==`LVWAR;
|
resv_o <= dram0_op==`LVWAR;
|
cres_o <= dram0_op==`SWCR;
|
cres_o <= dram0_op==`SWCR;
|
lock_o <= dram0_op==`CAS;
|
lock_o <= dram0_op==`CAS;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= fnIsStore(dram0_op) || ((dram0_op==`STMV || dram0_op==`INC) && stmv_flag);
|
we_o <= fnIsStore(dram0_op) || ((dram0_op==`STMV || dram0_op==`INC) && stmv_flag);
|
sel_o <= fnSelect(dram0_op,dram0_fn,pea);
|
sel_o <= fnSelect(dram0_op,dram0_fn,pea);
|
rsel <= fnSelect(dram0_op,dram0_fn,pea);
|
rsel <= fnSelect(dram0_op,dram0_fn,pea);
|
adr_o <= pea;
|
adr_o <= pea;
|
if (dram0_op==`INC)
|
if (dram0_op==`INC)
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data) + index;
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data) + index;
|
else
|
else
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
|
dram0 <= dram0 + 3'd1;
|
dram0 <= dram0 + 3'd1;
|
end
|
end
|
end
|
end
|
else begin // cached read
|
else begin // cached read
|
dram0 <= 3'd6;
|
dram0 <= 3'd6;
|
rsel <= fnSelect(dram0_op,dram0_fn,pea);
|
rsel <= fnSelect(dram0_op,dram0_fn,pea);
|
end
|
end
|
end
|
end
|
|
|
// State 3:
|
// State 3:
|
// Wait for a memory ack
|
// Wait for a memory ack
|
3'd3:
|
3'd3:
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
$display("MEM ack");
|
$display("MEM ack");
|
dram_v <= dram0_op != `CAS && dram0_op != `INC && dram0_op != `STS && dram0_op != `STMV && dram0_op != `STCMP && dram0_op != `STFND;
|
dram_v <= dram0_op != `CAS && dram0_op != `INC && dram0_op != `STS && dram0_op != `STMV && dram0_op != `STCMP && dram0_op != `STFND;
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;//dram0_exc;
|
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;//dram0_exc;
|
if (dram0_op==`SWCR)
|
if (dram0_op==`SWCR)
|
dram_bus <= {63'd0,resv_i};
|
dram_bus <= {63'd0,resv_i};
|
else
|
else
|
dram_bus <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
dram_bus <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
dram0_owns_bus <= `FALSE;
|
dram0_owns_bus <= `FALSE;
|
wb_nack();
|
wb_nack();
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
case(dram0_op)
|
case(dram0_op)
|
`ifdef STRINGOPS
|
`ifdef STRINGOPS
|
`STS:
|
`STS:
|
if (lc != 0 && !int_pending) begin
|
if (lc != 0 && !int_pending) begin
|
dram0_addr <= dram0_addr + fnIndexAmt(dram0_fn);
|
dram0_addr <= dram0_addr + fnIndexAmt(dram0_fn);
|
lc <= lc - 64'd1;
|
lc <= lc - 64'd1;
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
// dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
|
// dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
|
end
|
end
|
else begin
|
else begin
|
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
|
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
end
|
end
|
`STMV,`STCMP:
|
`STMV,`STCMP:
|
begin
|
begin
|
dram_bus <= index;
|
dram_bus <= index;
|
if (lc != 0 && !(int_pending && stmv_flag)) begin
|
if (lc != 0 && !(int_pending && stmv_flag)) begin
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
dram0_owns_bus <= `TRUE;
|
dram0_owns_bus <= `TRUE;
|
if (stmv_flag) begin
|
if (stmv_flag) begin
|
dram0_addr <= src_addr + index;
|
dram0_addr <= src_addr + index;
|
if (dram0_op==`STCMP) begin
|
if (dram0_op==`STCMP) begin
|
if (dram0_data != fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin
|
if (dram0_data != fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin
|
lc <= 64'd0;
|
lc <= 64'd0;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
end
|
end
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
dram0_addr <= dst_addr + index;
|
dram0_addr <= dst_addr + index;
|
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
end
|
end
|
if (!stmv_flag)
|
if (!stmv_flag)
|
inc_index(dram0_fn);
|
inc_index(dram0_fn);
|
stmv_flag <= ~stmv_flag;
|
stmv_flag <= ~stmv_flag;
|
end
|
end
|
else begin
|
else begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
end
|
end
|
end
|
end
|
`STFND:
|
`STFND:
|
if (lc != 0 && !int_pending) begin
|
if (lc != 0 && !int_pending) begin
|
dram0_addr <= src_addr + index;
|
dram0_addr <= src_addr + index;
|
inc_index(dram0_fn);
|
inc_index(dram0_fn);
|
if (dram0_data == fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin
|
if (dram0_data == fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin
|
lc <= 64'd0;
|
lc <= 64'd0;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram_bus <= index;
|
dram_bus <= index;
|
end
|
end
|
else
|
else
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
end
|
end
|
else begin
|
else begin
|
dram_bus <= index;
|
dram_bus <= index;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
end
|
end
|
`endif
|
`endif
|
`CAS:
|
`CAS:
|
if (dram0_datacmp == dat_i) begin
|
if (dram0_datacmp == dat_i) begin
|
$display("CAS match");
|
$display("CAS match");
|
dram0_owns_bus <= `TRUE;
|
dram0_owns_bus <= `TRUE;
|
cyc_o <= 1'b1; // hold onto cyc_o
|
cyc_o <= 1'b1; // hold onto cyc_o
|
dram0 <= dram0 + 3'd1;
|
dram0 <= dram0 + 3'd1;
|
end
|
end
|
else begin
|
else begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
`INC:
|
`INC:
|
begin
|
begin
|
if (stmv_flag) begin
|
if (stmv_flag) begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
else begin
|
else begin
|
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel);
|
stmv_flag <= ~stmv_flag;
|
stmv_flag <= ~stmv_flag;
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
end
|
end
|
end
|
end
|
`NOP:
|
`NOP:
|
begin
|
begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
|
|
// State 4:
|
// State 4:
|
// Start a second bus transaction for the CAS instruction
|
// Start a second bus transaction for the CAS instruction
|
3'd4:
|
3'd4:
|
begin
|
begin
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= fnSelect(dram0_op,dram0_fn,pea);
|
sel_o <= fnSelect(dram0_op,dram0_fn,pea);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
|
dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
|
dram0 <= dram0 + 3'd1;
|
dram0 <= dram0 + 3'd1;
|
end
|
end
|
|
|
// State 5:
|
// State 5:
|
// Wait for a memory ack for the second bus transaction of a CAS
|
// Wait for a memory ack for the second bus transaction of a CAS
|
//
|
//
|
3'd5:
|
3'd5:
|
begin
|
begin
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
$display("MEM ack2");
|
$display("MEM ack2");
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;
|
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;
|
dram0_owns_bus <= `FALSE;
|
dram0_owns_bus <= `FALSE;
|
wb_nack();
|
wb_nack();
|
lock_o <= 1'b0;
|
lock_o <= 1'b0;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
end
|
end
|
end
|
end
|
|
|
// State 6:
|
// State 6:
|
// Wait for a data cache read hit
|
// Wait for a data cache read hit
|
3'd6:
|
3'd6:
|
if (rhit && dram0_op!=`LCL) begin
|
if (rhit && dram0_op!=`LCL) begin
|
case(dram0_op)
|
case(dram0_op)
|
`ifdef STRINGOPS
|
`ifdef STRINGOPS
|
// The read portion of the STMV was just done, go back and do
|
// The read portion of the STMV was just done, go back and do
|
// the write portion.
|
// the write portion.
|
`STMV:
|
`STMV:
|
begin
|
begin
|
stmv_flag <= `TRUE;
|
stmv_flag <= `TRUE;
|
dram0_addr <= dst_addr + index;
|
dram0_addr <= dst_addr + index;
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
end
|
end
|
`STCMP:
|
`STCMP:
|
begin
|
begin
|
dram_bus <= index;
|
dram_bus <= index;
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
if (lc != 0 && !int_pending && stmv_flag) begin
|
if (lc != 0 && !int_pending && stmv_flag) begin
|
dram0_addr <= src_addr + index;
|
dram0_addr <= src_addr + index;
|
stmv_flag <= ~stmv_flag;
|
stmv_flag <= ~stmv_flag;
|
$display("*****************************");
|
$display("*****************************");
|
$display("STCMP READ2:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
|
$display("STCMP READ2:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
|
$display("*****************************");
|
$display("*****************************");
|
if (dram0_data != fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
|
if (dram0_data != fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
|
lc <= 64'd0;
|
lc <= 64'd0;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
end
|
end
|
end
|
end
|
else if (!stmv_flag) begin
|
else if (!stmv_flag) begin
|
stmv_flag <= ~stmv_flag;
|
stmv_flag <= ~stmv_flag;
|
dram0_addr <= dst_addr + index;
|
dram0_addr <= dst_addr + index;
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
$display("*****************************");
|
$display("*****************************");
|
$display("STCMP READ1:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
|
$display("STCMP READ1:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
|
$display("*****************************");
|
$display("*****************************");
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
inc_index(dram0_fn);
|
inc_index(dram0_fn);
|
end
|
end
|
else begin
|
else begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
end
|
end
|
end
|
end
|
`STFND:
|
`STFND:
|
begin
|
begin
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_bus <= index;
|
dram_bus <= index;
|
if (lc != 0 && !int_pending) begin
|
if (lc != 0 && !int_pending) begin
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
dram0_addr <= src_addr + index;
|
dram0_addr <= src_addr + index;
|
inc_index(dram0_fn);
|
inc_index(dram0_fn);
|
if (dram0_data == fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
|
if (dram0_data == fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
|
lc <= 64'd0;
|
lc <= 64'd0;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd7;
|
dram0 <= 3'd7;
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
`INC:
|
`INC:
|
begin
|
begin
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
stmv_flag <= `TRUE;
|
stmv_flag <= `TRUE;
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
end
|
end
|
// Set to NOP on a string miss
|
// Set to NOP on a string miss
|
`NOP: begin
|
`NOP: begin
|
dram_v <= `VAL;
|
dram_v <= `VAL;
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
default: begin
|
default: begin
|
$display("Read hit [%h]",dram0_addr);
|
$display("Read hit [%h]",dram0_addr);
|
dram_v <= `TRUE;
|
dram_v <= `TRUE;
|
dram_id <= dram0_id;
|
dram_id <= dram0_id;
|
dram_tgt <= dram0_tgt;
|
dram_tgt <= dram0_tgt;
|
dram_exc <= `EXC_NONE;
|
dram_exc <= `EXC_NONE;
|
dram_bus <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram_bus <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
3'd7:
|
3'd7:
|
begin
|
begin
|
dram0 <= 3'd0;
|
dram0 <= 3'd0;
|
end
|
end
|
default: dram0 <= 3'd0;
|
default: dram0 <= 3'd0;
|
endcase
|
endcase
|
|
|
//
|
//
|
// determine if the instructions ready to issue can, in fact, issue.
|
// determine if the instructions ready to issue can, in fact, issue.
|
// "ready" means that the instruction has valid operands but has not gone yet
|
// "ready" means that the instruction has valid operands but has not gone yet
|
//
|
//
|
// Stores can only issue if there is no possibility of a change of program flow.
|
// Stores can only issue if there is no possibility of a change of program flow.
|
// That means no flow control operations or instructions that can cause an
|
// That means no flow control operations or instructions that can cause an
|
// exception can be before the store.
|
// exception can be before the store.
|
iqentry_memissue[ head0 ] <= iqentry_memissue_head0;
|
iqentry_memissue[ head0 ] <= iqentry_memissue_head0;
|
iqentry_memissue[ head1 ] <= iqentry_memissue_head1;
|
iqentry_memissue[ head1 ] <= iqentry_memissue_head1;
|
iqentry_memissue[ head2 ] <= iqentry_memissue_head2;
|
iqentry_memissue[ head2 ] <= iqentry_memissue_head2;
|
iqentry_memissue[ head3 ] <= iqentry_memissue_head3;
|
iqentry_memissue[ head3 ] <= iqentry_memissue_head3;
|
iqentry_memissue[ head4 ] <= iqentry_memissue_head4;
|
iqentry_memissue[ head4 ] <= iqentry_memissue_head4;
|
iqentry_memissue[ head5 ] <= iqentry_memissue_head5;
|
iqentry_memissue[ head5 ] <= iqentry_memissue_head5;
|
iqentry_memissue[ head6 ] <= iqentry_memissue_head6;
|
iqentry_memissue[ head6 ] <= iqentry_memissue_head6;
|
iqentry_memissue[ head7 ] <= iqentry_memissue_head7;
|
iqentry_memissue[ head7 ] <= iqentry_memissue_head7;
|
|
|
/* ||
|
/* ||
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
( !fnIsFlowCtrl(iqentry_op[head0])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head1])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head2])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head3])
|
&& !fnIsFlowCtrl(iqentry_op[head4])
|
&& !fnIsFlowCtrl(iqentry_op[head4])
|
&& !fnIsFlowCtrl(iqentry_op[head5])
|
&& !fnIsFlowCtrl(iqentry_op[head5])
|
&& !fnIsFlowCtrl(iqentry_op[head6])));
|
&& !fnIsFlowCtrl(iqentry_op[head6])));
|
*/
|
*/
|
//
|
//
|
// take requests that are ready and put them into DRAM slots
|
// take requests that are ready and put them into DRAM slots
|
|
|
if (dram0 == `DRAMSLOT_AVAIL) dram0_exc <= `EXC_NONE;
|
if (dram0 == `DRAMSLOT_AVAIL) dram0_exc <= `EXC_NONE;
|
|
|
// Memory should also wait until segment registers are valid. The segment
|
// Memory should also wait until segment registers are valid. The segment
|
// registers are essentially static registers while a program runs. They are
|
// registers are essentially static registers while a program runs. They are
|
// setup by only the operating system. The system software must ensure the
|
// setup by only the operating system. The system software must ensure the
|
// segment registers are stable before they get used. We don't bother checking
|
// segment registers are stable before they get used. We don't bother checking
|
// for rf_v[].
|
// for rf_v[].
|
//
|
//
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && iqentry_tlb[n] && !iqentry_out[n]) begin
|
if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && iqentry_tlb[n] && !iqentry_out[n]) begin
|
$display("TLB issue");
|
$display("TLB issue");
|
if (!iqentry_cmt[n]) begin
|
if (!iqentry_cmt[n]) begin
|
iqentry_done[n] <= `TRUE;
|
iqentry_done[n] <= `TRUE;
|
iqentry_out[n] <= `FALSE;
|
iqentry_out[n] <= `FALSE;
|
iqentry_agen[n] <= `FALSE;
|
iqentry_agen[n] <= `FALSE;
|
iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
|
iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
end
|
end
|
else if (tlb_state==3'd0) begin
|
else if (tlb_state==3'd0) begin
|
tlb_state <= 3'd1;
|
tlb_state <= 3'd1;
|
tlb_id <= {1'b1, n[2:0]};
|
tlb_id <= {1'b1, n[2:0]};
|
tlb_op <= iqentry_a0[n][3:0];
|
tlb_op <= iqentry_a0[n][3:0];
|
tlb_regno <= iqentry_a0[n][7:4];
|
tlb_regno <= iqentry_a0[n][7:4];
|
tlb_tgt <= iqentry_tgt[n];
|
tlb_tgt <= iqentry_tgt[n];
|
tlb_data <= iqentry_a1[n];
|
tlb_data <= iqentry_a1[n];
|
iqentry_out[n] <= `TRUE;
|
iqentry_out[n] <= `TRUE;
|
end
|
end
|
end
|
end
|
else if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && !iqentry_out[n]) begin
|
else if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && !iqentry_out[n]) begin
|
if (!iqentry_cmt[n]) begin
|
if (!iqentry_cmt[n]) begin
|
iqentry_done[n] <= `TRUE;
|
iqentry_done[n] <= `TRUE;
|
iqentry_out[n] <= `FALSE;
|
iqentry_out[n] <= `FALSE;
|
iqentry_agen[n] <= `FALSE;
|
iqentry_agen[n] <= `FALSE;
|
iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
|
iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu0_id) ? alu0_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: (iqentry_T_s[n] == alu1_id) ? alu1_bus
|
: 64'hDEADDEADDEADDEAD;
|
: 64'hDEADDEADDEADDEAD;
|
end
|
end
|
else begin
|
else begin
|
if (fnIsStoreString(iqentry_op[n]))
|
if (fnIsStoreString(iqentry_op[n]))
|
string_pc <= iqentry_pc[n];
|
string_pc <= iqentry_pc[n];
|
$display("issued memory cycle");
|
$display("issued memory cycle");
|
if (dram0 == `DRAMSLOT_AVAIL) begin
|
if (dram0 == `DRAMSLOT_AVAIL) begin
|
dram0 <= 3'd1;
|
dram0 <= 3'd1;
|
dram0_id <= { 1'b1, n[2:0] };
|
dram0_id <= { 1'b1, n[2:0] };
|
dram0_misspc <= iqentry_pc[n];
|
dram0_misspc <= iqentry_pc[n];
|
dram0_op <= iqentry_op[n];
|
dram0_op <= iqentry_op[n];
|
dram0_fn <= iqentry_fn[n];
|
dram0_fn <= iqentry_fn[n];
|
dram0_tgt <= iqentry_tgt[n];
|
dram0_tgt <= iqentry_tgt[n];
|
dram0_data <= (iqentry_ndx[n] || iqentry_cas[n]) ? iqentry_a3[n] :
|
dram0_data <= (iqentry_ndx[n] || iqentry_cas[n]) ? iqentry_a3[n] :
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
iqentry_pea[n] ? iqentry_a2[n] + iqentry_a0[n] :
|
iqentry_pea[n] ? iqentry_a2[n] + iqentry_a0[n] :
|
`endif
|
`endif
|
iqentry_a2[n];
|
iqentry_a2[n];
|
dram0_datacmp <= iqentry_a2[n];
|
dram0_datacmp <= iqentry_a2[n];
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
if (iqentry_cmpmv[n])
|
if (iqentry_cmpmv[n])
|
dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
else
|
else
|
dram0_addr <= iqentry_a1[n];
|
dram0_addr <= iqentry_a1[n];
|
dram0_seg <= {sregs[iqentry_fn[n][5:3]],12'h000};
|
dram0_seg <= {sregs[iqentry_fn[n][5:3]],12'h000};
|
dram0_lmt <= sregs[iqentry_fn[n][5:3]] + sregs_lmt[iqentry_fn[n][5:3]];
|
dram0_lmt <= sregs[iqentry_fn[n][5:3]] + sregs_lmt[iqentry_fn[n][5:3]];
|
// dram0_exc <= (iqentry_a1[n][ABW-1:12] >= sregs_lmt[iqentry_fn[n][5:3]]) ? `EXC_SEGV : `EXC_NONE;
|
// dram0_exc <= (iqentry_a1[n][ABW-1:12] >= sregs_lmt[iqentry_fn[n][5:3]]) ? `EXC_SEGV : `EXC_NONE;
|
`ifdef STRINGOPS
|
`ifdef STRINGOPS
|
src_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
src_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
dst_addr <= iqentry_a2[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
dst_addr <= iqentry_a2[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
|
`endif
|
`endif
|
`else
|
`else
|
dram0_addr <= iqentry_a1[n];
|
dram0_addr <= iqentry_a1[n];
|
`ifdef STRINGOPS
|
`ifdef STRINGOPS
|
src_addr <= iqentry_a1[n];
|
src_addr <= iqentry_a1[n];
|
dst_addr <= iqentry_a2[n];
|
dst_addr <= iqentry_a2[n];
|
`endif
|
`endif
|
`endif
|
`endif
|
stmv_flag <= `FALSE;
|
stmv_flag <= `FALSE;
|
index <= iqentry_op[n]==`STS ? fnIndexAmt(iqentry_fn[n]) : iqentry_op[n]==`INC ? iqentry_a2[n] : iqentry_a3[n];
|
index <= iqentry_op[n]==`STS ? fnIndexAmt(iqentry_fn[n]) : iqentry_op[n]==`INC ? iqentry_a2[n] : iqentry_a3[n];
|
iqentry_out[n] <= `TRUE;
|
iqentry_out[n] <= `TRUE;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
for (n = 0; n < QENTRIES; n = n + 1)
|
for (n = 0; n < QENTRIES; n = n + 1)
|
begin
|
begin
|
if (iqentry_op[n]==`IMM && iqentry_v[(n+1)&7] &&
|
if (iqentry_op[n]==`IMM && iqentry_v[(n+1)&7] &&
|
((iqentry_pc[(n+1)&7]==iqentry_pc[n]+iqentry_insnsz[n]) ||
|
((iqentry_pc[(n+1)&7]==iqentry_pc[n]+iqentry_insnsz[n]) ||
|
(iqentry_pc[(n+1)&7]==iqentry_pc[n]))) // address inherited due to interrupt
|
(iqentry_pc[(n+1)&7]==iqentry_pc[n]))) // address inherited due to interrupt
|
iqentry_done[n] <= `TRUE;
|
iqentry_done[n] <= `TRUE;
|
if (!iqentry_v[n])
|
if (!iqentry_v[n])
|
iqentry_done[n] <= `FALSE;
|
iqentry_done[n] <= `FALSE;
|
end
|
end
|
|
|
|
|
// $display("TLB: en=%b imatch=%b pgsz=%d pcs=%h phys=%h", utlb1.TLBenabled,utlb1.IMatch,utlb1.PageSize,utlb1.pcs,utlb1.IPFN);
|
// $display("TLB: en=%b imatch=%b pgsz=%d pcs=%h phys=%h", utlb1.TLBenabled,utlb1.IMatch,utlb1.PageSize,utlb1.pcs,utlb1.IPFN);
|
// for (i = 0; i < 64; i = i + 1)
|
// for (i = 0; i < 64; i = i + 1)
|
// $display("vp=%h G=%b",utlb1.TLBVirtPage[i],utlb1.TLBG[i]);
|
// $display("vp=%h G=%b",utlb1.TLBVirtPage[i],utlb1.TLBG[i]);
|
//`include "Thor_commit.v"
|
//`include "Thor_commit.v"
|
// It didn't work in simulation when the following was declared under an
|
// It didn't work in simulation when the following was declared under an
|
// independant always clk block
|
// independant always clk block
|
//
|
//
|
commit_spr(commit0_v,commit0_tgt,commit0_bus,0);
|
commit_spr(commit0_v,commit0_tgt,commit0_bus,0);
|
commit_spr(commit1_v,commit1_tgt,commit1_bus,1);
|
commit_spr(commit1_v,commit1_tgt,commit1_bus,1);
|
|
|
// When the INT instruction commits set the hardware interrupt status to disable further interrupts.
|
// When the INT instruction commits set the hardware interrupt status to disable further interrupts.
|
if (int_commit)
|
if (int_commit)
|
begin
|
begin
|
$display("*********************");
|
$display("*********************");
|
$display("*********************");
|
$display("*********************");
|
$display("Interrupt committing");
|
$display("Interrupt committing");
|
$display("*********************");
|
$display("*********************");
|
$display("*********************");
|
$display("*********************");
|
StatusHWI <= `TRUE;
|
StatusHWI <= `TRUE;
|
imb <= im;
|
imb <= im;
|
im <= 1'b0;
|
im <= 1'b0;
|
// Reset the nmi edge sense circuit but only for an NMI
|
// Reset the nmi edge sense circuit but only for an NMI
|
if ((iqentry_a0[head0][7:0]==8'hFE && commit0_v && iqentry_op[head0]==`INT) ||
|
if ((iqentry_a0[head0][7:0]==8'hFE && commit0_v && iqentry_op[head0]==`INT) ||
|
(iqentry_a0[head1][7:0]==8'hFE && commit1_v && iqentry_op[head1]==`INT))
|
(iqentry_a0[head1][7:0]==8'hFE && commit1_v && iqentry_op[head1]==`INT))
|
nmi_edge <= 1'b0;
|
nmi_edge <= 1'b0;
|
string_pc <= 64'd0;
|
string_pc <= 64'd0;
|
`ifdef PCHIST
|
`ifdef PCHIST
|
pc_cap <= `FALSE;
|
pc_cap <= `FALSE;
|
`endif
|
`endif
|
end
|
end
|
|
|
if (sys_commit)
|
if (sys_commit)
|
begin
|
begin
|
if (StatusEXL!=8'hFF)
|
if (StatusEXL!=8'hFF)
|
StatusEXL <= StatusEXL + 8'd1;
|
StatusEXL <= StatusEXL + 8'd1;
|
end
|
end
|
|
|
// On a debug commit set status StatusDBG to prevent further single stepping.
|
// On a debug commit set status StatusDBG to prevent further single stepping.
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
if (dbg_commit)
|
if (dbg_commit)
|
begin
|
begin
|
StatusDBG <= `TRUE;
|
StatusDBG <= `TRUE;
|
end
|
end
|
`endif
|
`endif
|
|
|
oddball_commit(commit0_v,head0);
|
oddball_commit(commit0_v,head0);
|
oddball_commit(commit1_v,head1);
|
oddball_commit(commit1_v,head1);
|
|
|
//
|
//
|
// COMMIT PHASE (dequeue only ... not register-file update)
|
// COMMIT PHASE (dequeue only ... not register-file update)
|
//
|
//
|
// If the third instruction is invalidated or if it doesn't update the register
|
// If the third instruction is invalidated or if it doesn't update the register
|
// file then it is allowed to commit too.
|
// file then it is allowed to commit too.
|
// The head pointer might advance by three.
|
// The head pointer might advance by three.
|
//
|
//
|
if (~|panic)
|
if (~|panic)
|
casex ({ iqentry_v[head0],
|
casex ({ iqentry_v[head0],
|
iqentry_done[head0],
|
iqentry_done[head0],
|
iqentry_v[head1],
|
iqentry_v[head1],
|
iqentry_done[head1],
|
iqentry_done[head1],
|
iqentry_v[head2],
|
iqentry_v[head2],
|
iqentry_done[head2]})
|
iqentry_done[head2]})
|
|
|
// retire 3
|
// retire 3
|
6'b0x_0x_0x:
|
6'b0x_0x_0x:
|
if (head0 != tail0 && head1 != tail0 && head2 != tail0) begin
|
if (head0 != tail0 && head1 != tail0 && head2 != tail0) begin
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else if (head0 != tail0 && head1 != tail0) begin
|
else if (head0 != tail0 && head1 != tail0) begin
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
else if (head0 != tail0) begin
|
else if (head0 != tail0) begin
|
head_inc(1);
|
head_inc(1);
|
end
|
end
|
|
|
// retire 2 (wait for regfile for head2)
|
// retire 2 (wait for regfile for head2)
|
6'b0x_0x_10:
|
6'b0x_0x_10:
|
begin
|
begin
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
|
|
// retire 2 or 3 (wait for regfile for head2)
|
// retire 2 or 3 (wait for regfile for head2)
|
6'b0x_0x_11:
|
6'b0x_0x_11:
|
begin
|
begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
iqentry_v[head2] <= `INV;
|
iqentry_v[head2] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
end
|
end
|
|
|
// retire 3
|
// retire 3
|
6'b0x_11_0x:
|
6'b0x_11_0x:
|
if (head1 != tail0 && head2 != tail0) begin
|
if (head1 != tail0 && head2 != tail0) begin
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
|
|
// retire 2 (wait on head2 or wait on register file for head2)
|
// retire 2 (wait on head2 or wait on register file for head2)
|
6'b0x_11_10:
|
6'b0x_11_10:
|
begin
|
begin
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
6'b0x_11_11:
|
6'b0x_11_11:
|
begin
|
begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head2] <= `INV;
|
iqentry_v[head2] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
end
|
end
|
|
|
// 4'b00_00 - neither valid; skip both
|
// 4'b00_00 - neither valid; skip both
|
// 4'b00_01 - neither valid; skip both
|
// 4'b00_01 - neither valid; skip both
|
// 4'b00_10 - skip head0, wait on head1
|
// 4'b00_10 - skip head0, wait on head1
|
// 4'b00_11 - skip head0, commit head1
|
// 4'b00_11 - skip head0, commit head1
|
// 4'b01_00 - neither valid; skip both
|
// 4'b01_00 - neither valid; skip both
|
// 4'b01_01 - neither valid; skip both
|
// 4'b01_01 - neither valid; skip both
|
// 4'b01_10 - skip head0, wait on head1
|
// 4'b01_10 - skip head0, wait on head1
|
// 4'b01_11 - skip head0, commit head1
|
// 4'b01_11 - skip head0, commit head1
|
// 4'b10_00 - wait on head0
|
// 4'b10_00 - wait on head0
|
// 4'b10_01 - wait on head0
|
// 4'b10_01 - wait on head0
|
// 4'b10_10 - wait on head0
|
// 4'b10_10 - wait on head0
|
// 4'b10_11 - wait on head0
|
// 4'b10_11 - wait on head0
|
// 4'b11_00 - commit head0, skip head1
|
// 4'b11_00 - commit head0, skip head1
|
// 4'b11_01 - commit head0, skip head1
|
// 4'b11_01 - commit head0, skip head1
|
// 4'b11_10 - commit head0, wait on head1
|
// 4'b11_10 - commit head0, wait on head1
|
// 4'b11_11 - commit head0, commit head1
|
// 4'b11_11 - commit head0, commit head1
|
|
|
//
|
//
|
// retire 0 (stuck on head0)
|
// retire 0 (stuck on head0)
|
6'b10_xx_xx: ;
|
6'b10_xx_xx: ;
|
|
|
// retire 3
|
// retire 3
|
6'b11_0x_0x:
|
6'b11_0x_0x:
|
if (head1 != tail0 && head2 != tail0) begin
|
if (head1 != tail0 && head2 != tail0) begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else if (head1 != tail0) begin
|
else if (head1 != tail0) begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(1);
|
head_inc(1);
|
end
|
end
|
|
|
// retire 2 (wait for regfile for head2)
|
// retire 2 (wait for regfile for head2)
|
6'b11_0x_10:
|
6'b11_0x_10:
|
begin
|
begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
|
|
// retire 2 or 3 (wait for regfile for head2)
|
// retire 2 or 3 (wait for regfile for head2)
|
6'b11_0x_11:
|
6'b11_0x_11:
|
if (iqentry_tgt[head2]==7'd0) begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head2] <= `INV;
|
iqentry_v[head2] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
|
|
//
|
//
|
// retire 1 (stuck on head1)
|
// retire 1 (stuck on head1)
|
6'b00_10_xx,
|
6'b00_10_xx,
|
6'b01_10_xx,
|
6'b01_10_xx,
|
6'b11_10_xx:
|
6'b11_10_xx:
|
if (iqentry_v[head0] || head0 != tail0) begin
|
if (iqentry_v[head0] || head0 != tail0) begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
head_inc(1);
|
head_inc(1);
|
end
|
end
|
|
|
// retire 2 or 3
|
// retire 2 or 3
|
6'b11_11_0x:
|
6'b11_11_0x:
|
if (head2 != tail0) begin
|
if (head2 != tail0) begin
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head0] <= `INV;
|
iqentry_v[head1] <= `INV;
|
iqentry_v[head1] <= `INV;
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
|
|
// retire 2 (wait on regfile for head2)
|
// retire 2 (wait on regfile for head2)
|
6'b11_11_10:
|
6'b11_11_10:
|
begin
|
begin
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
6'b11_11_11:
|
6'b11_11_11:
|
if (iqentry_tgt[head2]==7'd0) begin
|
if (iqentry_tgt[head2]==7'd0) begin
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head2] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head2] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
head_inc(3);
|
head_inc(3);
|
end
|
end
|
else begin
|
else begin
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head0] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
iqentry_v[head1] <= `INV; // may conflict with STOMP, but since both are setting to 0, it is okay
|
head_inc(2);
|
head_inc(2);
|
end
|
end
|
endcase
|
endcase
|
|
|
if (branchmiss)
|
if (branchmiss)
|
rrmapno <= iqentry_renmapno[missid];
|
rrmapno <= iqentry_renmapno[missid];
|
|
|
case(cstate)
|
case(cstate)
|
RESET1:
|
RESET1:
|
begin
|
begin
|
ic_ld <= `TRUE;
|
ic_ld <= `TRUE;
|
ic_ld_cntr <= 32'd0;
|
ic_ld_cntr <= 32'd0;
|
cstate <= RESET2;
|
cstate <= RESET2;
|
end
|
end
|
RESET2:
|
RESET2:
|
begin
|
begin
|
ic_ld_cntr <= ic_ld_cntr + 32'd32;
|
ic_ld_cntr <= ic_ld_cntr + 32'd32;
|
if (ic_ld_cntr >= 32'd32768) begin
|
if (ic_ld_cntr >= 32'd32768) begin
|
ic_ld <= `FALSE;
|
ic_ld <= `FALSE;
|
ic_ld_cntr <= 32'd0;
|
ic_ld_cntr <= 32'd0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end;
|
end;
|
end
|
end
|
IDLE:
|
IDLE:
|
if (dcache_access_pending) begin
|
if (dcache_access_pending) begin
|
$display("********************");
|
$display("********************");
|
$display("DCache access to: %h",{pea[DBW-1:5],5'b00000});
|
$display("DCache access to: %h",{pea[DBW-1:5],5'b00000});
|
$display("********************");
|
$display("********************");
|
derr <= 1'b0;
|
derr <= 1'b0;
|
bte_o <= 2'b00;
|
bte_o <= 2'b00;
|
cti_o <= 3'b001;
|
cti_o <= 3'b001;
|
bl_o <= DBW==32 ? 5'd7 : 5'd3;
|
bl_o <= DBW==32 ? 5'd7 : 5'd3;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= {DBW/8{1'b1}};
|
sel_o <= {DBW/8{1'b1}};
|
adr_o <= {pea[DBW-1:5],5'b00000};
|
adr_o <= {pea[DBW-1:5],5'b00000};
|
dat_o <= {DBW{1'b0}};
|
dat_o <= {DBW{1'b0}};
|
cstate <= DCACHE1;
|
cstate <= DCACHE1;
|
end
|
end
|
else if ((!ihit && !mem_issue && dram0==3'd0)||(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0))) begin
|
else if ((!ihit && !mem_issue && dram0==3'd0)||(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0))) begin
|
if ((dram0!=2'd0 || dram1!=2'd0 || dram2!=2'd0) && !(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)))
|
if ((dram0!=2'd0 || dram1!=2'd0 || dram2!=2'd0) && !(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)))
|
$display("drams non-zero");
|
$display("drams non-zero");
|
else begin
|
else begin
|
$display("********************");
|
$display("********************");
|
$display("ICache access to: %h",
|
$display("ICache access to: %h",
|
(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)) ? {dram0_addr[ABW-1:5],5'h00} :
|
(dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)) ? {dram0_addr[ABW-1:5],5'h00} :
|
!hit0 ? {ppc[DBW-1:5],5'b00000} : {ppcp16[DBW-1:5],5'b00000});
|
!hit0 ? {ppc[DBW-1:5],5'b00000} : {ppcp16[DBW-1:5],5'b00000});
|
$display("********************");
|
$display("********************");
|
ierr <= 1'b0;
|
ierr <= 1'b0;
|
bte_o <= 2'b00;
|
bte_o <= 2'b00;
|
cti_o <= 3'b001;
|
cti_o <= 3'b001;
|
bl_o <= DBW==32 ? 5'd7 : 5'd3;
|
bl_o <= DBW==32 ? 5'd7 : 5'd3;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= {DBW/8{1'b1}};
|
sel_o <= {DBW/8{1'b1}};
|
adr_o <= (dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)) ? {dram0_addr[ABW-1:5],5'h00} : !hit0 ? {ppc[DBW-1:5],5'b00000} : {ppcp16[DBW-1:5],5'b00000};
|
adr_o <= (dram0==3'd6 && (dram0_op==`LCL && dram0_tgt==7'd0)) ? {dram0_addr[ABW-1:5],5'h00} : !hit0 ? {ppc[DBW-1:5],5'b00000} : {ppcp16[DBW-1:5],5'b00000};
|
dat_o <= {DBW{1'b0}};
|
dat_o <= {DBW{1'b0}};
|
cstate <= ICACHE1;
|
cstate <= ICACHE1;
|
end
|
end
|
end
|
end
|
ICACHE1:
|
ICACHE1:
|
begin
|
begin
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
ierr <= ierr | err_i; // cumulate an error status
|
ierr <= ierr | err_i; // cumulate an error status
|
if (DBW==32) begin
|
if (DBW==32) begin
|
adr_o[4:2] <= adr_o[4:2] + 3'd1;
|
adr_o[4:2] <= adr_o[4:2] + 3'd1;
|
if (adr_o[4:2]==3'b110)
|
if (adr_o[4:2]==3'b110)
|
cti_o <= 3'b111;
|
cti_o <= 3'b111;
|
if (adr_o[4:2]==3'b111) begin
|
if (adr_o[4:2]==3'b111) begin
|
wb_nack();
|
wb_nack();
|
cstate <= IDLE;
|
cstate <= IDLE;
|
if (dram0==3'd6 && dram0_op==`LCL) begin
|
if (dram0==3'd6 && dram0_op==`LCL) begin
|
dram0_op<=`NOP;
|
dram0_op<=`NOP;
|
end
|
end
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
adr_o[4:3] <= adr_o[4:3] + 2'd1;
|
adr_o[4:3] <= adr_o[4:3] + 2'd1;
|
if (adr_o[4:3]==2'b10)
|
if (adr_o[4:3]==2'b10)
|
cti_o <= 3'b111;
|
cti_o <= 3'b111;
|
if (adr_o[4:3]==2'b11) begin
|
if (adr_o[4:3]==2'b11) begin
|
wb_nack();
|
wb_nack();
|
cstate <= IDLE;
|
cstate <= IDLE;
|
if (dram0==3'd6 && dram0_op==`LCL) begin
|
if (dram0==3'd6 && dram0_op==`LCL) begin
|
dram0_op<=`NOP;
|
dram0_op<=`NOP;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
DCACHE1:
|
DCACHE1:
|
begin
|
begin
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
derr <= derr | err_i; // cumulate an error status
|
derr <= derr | err_i; // cumulate an error status
|
if (DBW==32) begin
|
if (DBW==32) begin
|
adr_o[4:2] <= adr_o[4:2] + 3'd1;
|
adr_o[4:2] <= adr_o[4:2] + 3'd1;
|
if (adr_o[4:2]==3'b110)
|
if (adr_o[4:2]==3'b110)
|
cti_o <= 3'b111;
|
cti_o <= 3'b111;
|
if (adr_o[4:2]==3'b111) begin
|
if (adr_o[4:2]==3'b111) begin
|
wb_nack();
|
wb_nack();
|
cstate <= IDLE;
|
cstate <= IDLE;
|
if (dram0_op==`LCL) begin
|
if (dram0_op==`LCL) begin
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
dram0_tgt <= 7'd0;
|
dram0_tgt <= 7'd0;
|
end
|
end
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
adr_o[4:3] <= adr_o[4:3] + 2'd1;
|
adr_o[4:3] <= adr_o[4:3] + 2'd1;
|
if (adr_o[4:3]==2'b10)
|
if (adr_o[4:3]==2'b10)
|
cti_o <= 3'b111;
|
cti_o <= 3'b111;
|
if (adr_o[4:3]==2'b11) begin
|
if (adr_o[4:3]==2'b11) begin
|
wb_nack();
|
wb_nack();
|
cstate <= IDLE;
|
cstate <= IDLE;
|
if (dram0_op==`LCL) begin
|
if (dram0_op==`LCL) begin
|
dram0_op <= `NOP;
|
dram0_op <= `NOP;
|
dram0_tgt <= 7'd0;
|
dram0_tgt <= 7'd0;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
default: cstate <= IDLE;
|
default: cstate <= IDLE;
|
endcase
|
endcase
|
|
|
// for (i=0; i<8; i=i+1)
|
// for (i=0; i<8; i=i+1)
|
// $display("%d: %h %d %o #", i, urf1.regs0[i], rf_v[i], rf_source[i]);
|
// $display("%d: %h %d %o #", i, urf1.regs0[i], rf_v[i], rf_source[i]);
|
|
|
if (ihit) begin
|
if (ihit) begin
|
$display("dr=%d I=%h A=%h B=%h op=%c%d bt=%d src=%o pc=%h #",
|
$display("dr=%d I=%h A=%h B=%h op=%c%d bt=%d src=%o pc=%h #",
|
alu0_dataready, alu0_argI, alu0_argA, alu0_argB,
|
alu0_dataready, alu0_argI, alu0_argA, alu0_argB,
|
(fnIsFlowCtrl(alu0_op) ? 98 : (fnIsMem(alu0_op)) ? 109 : 97),
|
(fnIsFlowCtrl(alu0_op) ? 98 : (fnIsMem(alu0_op)) ? 109 : 97),
|
alu0_op, alu0_bt, alu0_sourceid, alu0_pc);
|
alu0_op, alu0_bt, alu0_sourceid, alu0_pc);
|
$display("dr=%d I=%h A=%h B=%h op=%c%d bt=%d src=%o pc=%h #",
|
$display("dr=%d I=%h A=%h B=%h op=%c%d bt=%d src=%o pc=%h #",
|
alu1_dataready, alu1_argI, alu1_argA, alu1_argB,
|
alu1_dataready, alu1_argI, alu1_argA, alu1_argB,
|
(fnIsFlowCtrl(alu1_op) ? 98 : (fnIsMem(alu1_op)) ? 109 : 97),
|
(fnIsFlowCtrl(alu1_op) ? 98 : (fnIsMem(alu1_op)) ? 109 : 97),
|
alu1_op, alu1_bt, alu1_sourceid, alu1_pc);
|
alu1_op, alu1_bt, alu1_sourceid, alu1_pc);
|
$display("v=%d bus=%h id=%o 0 #", alu0_v, alu0_bus, alu0_id);
|
$display("v=%d bus=%h id=%o 0 #", alu0_v, alu0_bus, alu0_id);
|
$display("bmiss0=%b src=%o mpc=%h #", alu0_branchmiss, alu0_sourceid, alu0_misspc);
|
$display("bmiss0=%b src=%o mpc=%h #", alu0_branchmiss, alu0_sourceid, alu0_misspc);
|
$display("cmt=%b cnd=%d prd=%d", alu0_cmt, alu0_cond, alu0_pred);
|
$display("cmt=%b cnd=%d prd=%d", alu0_cmt, alu0_cond, alu0_pred);
|
$display("bmiss1=%b src=%o mpc=%h #", alu1_branchmiss, alu1_sourceid, alu1_misspc);
|
$display("bmiss1=%b src=%o mpc=%h #", alu1_branchmiss, alu1_sourceid, alu1_misspc);
|
$display("cmt=%b cnd=%d prd=%d", alu1_cmt, alu1_cond, alu1_pred);
|
$display("cmt=%b cnd=%d prd=%d", alu1_cmt, alu1_cond, alu1_pred);
|
$display("bmiss=%b mpc=%h", branchmiss, misspc);
|
$display("bmiss=%b mpc=%h", branchmiss, misspc);
|
|
|
$display("0: %d %h %o 0%d #", commit0_v, commit0_bus, commit0_id, commit0_tgt);
|
$display("0: %d %h %o 0%d #", commit0_v, commit0_bus, commit0_id, commit0_tgt);
|
$display("1: %d %h %o 0%d #", commit1_v, commit1_bus, commit1_id, commit1_tgt);
|
$display("1: %d %h %o 0%d #", commit1_v, commit1_bus, commit1_id, commit1_tgt);
|
end
|
end
|
if (|panic) begin
|
if (|panic) begin
|
$display("");
|
$display("");
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("--------------- PANIC:%s -----------------", message[panic]);
|
$display("--------------- PANIC:%s -----------------", message[panic]);
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("-----------------------------------------------------------------");
|
$display("");
|
$display("");
|
$display("instructions committed: %d", I);
|
$display("instructions committed: %d", I);
|
$display("total execution cycles: %d", $time / 10);
|
$display("total execution cycles: %d", $time / 10);
|
$display("");
|
$display("");
|
end
|
end
|
if (|panic && ~outstanding_stores) begin
|
if (|panic && ~outstanding_stores) begin
|
$finish;
|
$finish;
|
end
|
end
|
end
|
end
|
|
|
task wb_nack;
|
task wb_nack;
|
begin
|
begin
|
resv_o <= 1'b0;
|
resv_o <= 1'b0;
|
cres_o <= 1'b0;
|
cres_o <= 1'b0;
|
bte_o <= 2'b00;
|
bte_o <= 2'b00;
|
cti_o <= 3'b000;
|
cti_o <= 3'b000;
|
bl_o <= 5'd0;
|
bl_o <= 5'd0;
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
adr_o <= {DBW{1'b0}};
|
adr_o <= {DBW{1'b0}};
|
dat_o <= {DBW{1'b0}};
|
dat_o <= {DBW{1'b0}};
|
end
|
end
|
endtask
|
endtask
|
|
|
task commit_spr;
|
task commit_spr;
|
input commit_v;
|
input commit_v;
|
input [6:0] commit_tgt;
|
input [6:0] commit_tgt;
|
input [DBW-1:0] commit_bus;
|
input [DBW-1:0] commit_bus;
|
input which;
|
input which;
|
begin
|
begin
|
if (commit_v && commit_tgt[6]) begin
|
if (commit_v && commit_tgt[6]) begin
|
casex(commit_tgt[5:0])
|
casex(commit_tgt[5:0])
|
6'b00xxxx: begin
|
6'b00xxxx: begin
|
pregs[commit_tgt[3:0]] <= which ? cmt1nyb[commit_tgt[3:0]] : cmt0nyb[commit_tgt[3:0]];//commit_bus[3:0];
|
pregs[commit_tgt[3:0]] <= which ? cmt1nyb[commit_tgt[3:0]] : cmt0nyb[commit_tgt[3:0]];//commit_bus[3:0];
|
$display("pregs[%d]<=%h", commit_tgt[3:0], commit_bus[3:0]);
|
$display("pregs[%d]<=%h", commit_tgt[3:0], commit_bus[3:0]);
|
// $stop;
|
// $stop;
|
end
|
end
|
6'b01xxxx: begin
|
6'b01xxxx: begin
|
cregs[commit_tgt[3:0]] <= commit_bus;
|
cregs[commit_tgt[3:0]] <= commit_bus;
|
$display("cregs[%d]<=%h", commit_tgt[3:0], commit_bus);
|
$display("cregs[%d]<=%h", commit_tgt[3:0], commit_bus);
|
end
|
end
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
6'b100xxx: begin
|
6'b100xxx: begin
|
sregs[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
|
sregs[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
|
$display("sregs[%d]<=%h", commit_tgt[2:0], commit_bus);
|
$display("sregs[%d]<=%h", commit_tgt[2:0], commit_bus);
|
end
|
end
|
6'b101xxx: sregs_lmt[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
|
6'b101xxx: sregs_lmt[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
|
`endif
|
`endif
|
6'b110000:
|
6'b110000:
|
begin
|
begin
|
pregs[0] <= commit_bus[3:0];
|
pregs[0] <= commit_bus[3:0];
|
pregs[1] <= commit_bus[7:4];
|
pregs[1] <= commit_bus[7:4];
|
pregs[2] <= commit_bus[11:8];
|
pregs[2] <= commit_bus[11:8];
|
pregs[3] <= commit_bus[15:12];
|
pregs[3] <= commit_bus[15:12];
|
pregs[4] <= commit_bus[19:16];
|
pregs[4] <= commit_bus[19:16];
|
pregs[5] <= commit_bus[23:20];
|
pregs[5] <= commit_bus[23:20];
|
pregs[6] <= commit_bus[27:24];
|
pregs[6] <= commit_bus[27:24];
|
pregs[7] <= commit_bus[31:28];
|
pregs[7] <= commit_bus[31:28];
|
if (DBW==64) begin
|
if (DBW==64) begin
|
pregs[8] <= commit_bus[35:32];
|
pregs[8] <= commit_bus[35:32];
|
pregs[9] <= commit_bus[39:36];
|
pregs[9] <= commit_bus[39:36];
|
pregs[10] <= commit_bus[43:40];
|
pregs[10] <= commit_bus[43:40];
|
pregs[11] <= commit_bus[47:44];
|
pregs[11] <= commit_bus[47:44];
|
pregs[12] <= commit_bus[51:48];
|
pregs[12] <= commit_bus[51:48];
|
pregs[13] <= commit_bus[55:52];
|
pregs[13] <= commit_bus[55:52];
|
pregs[14] <= commit_bus[59:56];
|
pregs[14] <= commit_bus[59:56];
|
pregs[15] <= commit_bus[63:60];
|
pregs[15] <= commit_bus[63:60];
|
end
|
end
|
end
|
end
|
`LCTR: begin lc <= commit_bus; $display("LC <= %h", commit_bus); end
|
`LCTR: begin lc <= commit_bus; $display("LC <= %h", commit_bus); end
|
`ASID: asid <= commit_bus;
|
`ASID: asid <= commit_bus;
|
`SR: begin
|
`SR: begin
|
GM <= commit_bus[7:0];
|
GM <= commit_bus[7:0];
|
GMB <= commit_bus[23:16];
|
GMB <= commit_bus[23:16];
|
imb <= commit_bus[31];
|
imb <= commit_bus[31];
|
im <= commit_bus[15];
|
im <= commit_bus[15];
|
fxe <= commit_bus[12];
|
fxe <= commit_bus[12];
|
end
|
end
|
6'd60: spr_bir <= commit_bus[11:0];
|
6'd60: spr_bir <= commit_bus[11:0];
|
6'd61:
|
6'd61:
|
case(spr_bir[5:0])
|
case(spr_bir[5:0])
|
6'd0: dbg_adr0 <= commit_bus;
|
6'd0: dbg_adr0 <= commit_bus;
|
6'd1: dbg_adr1 <= commit_bus;
|
6'd1: dbg_adr1 <= commit_bus;
|
6'd2: dbg_adr2 <= commit_bus;
|
6'd2: dbg_adr2 <= commit_bus;
|
6'd3: dbg_adr3 <= commit_bus;
|
6'd3: dbg_adr3 <= commit_bus;
|
6'd4: dbg_ctrl <= commit_bus;
|
6'd4: dbg_ctrl <= commit_bus;
|
6'd5: dbg_stat <= commit_bus;
|
6'd5: dbg_stat <= commit_bus;
|
`ifdef PCHIST
|
`ifdef PCHIST
|
6'd18: pc_ndx <= commit_bus[5:0];
|
6'd18: pc_ndx <= commit_bus[5:0];
|
`endif
|
`endif
|
default: ;
|
default: ;
|
endcase
|
endcase
|
6'b111111:
|
6'b111111:
|
begin
|
begin
|
ld_clk_throttle <= `TRUE;
|
ld_clk_throttle <= `TRUE;
|
clk_throttle_new <= commit_bus[15:0];
|
clk_throttle_new <= commit_bus[15:0];
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
// For string memory operations.
|
// For string memory operations.
|
// Indexing amount, should synth to a ROM.
|
// Indexing amount, should synth to a ROM.
|
//
|
//
|
function [63:0] fnIndexAmt;
|
function [63:0] fnIndexAmt;
|
input [5:0] fn;
|
input [5:0] fn;
|
begin
|
begin
|
case(fn[2:0])
|
case(fn[2:0])
|
3'd0: fnIndexAmt = 64'd1;
|
3'd0: fnIndexAmt = 64'd1;
|
3'd1: fnIndexAmt = 64'd2;
|
3'd1: fnIndexAmt = 64'd2;
|
3'd2: fnIndexAmt = 64'd4;
|
3'd2: fnIndexAmt = 64'd4;
|
3'd3: fnIndexAmt = 64'd8;
|
3'd3: fnIndexAmt = 64'd8;
|
3'd4: fnIndexAmt = 64'd1;
|
3'd4: fnIndexAmt = 64'd1;
|
3'd5: fnIndexAmt = 64'd2;
|
3'd5: fnIndexAmt = 64'd2;
|
3'd6: fnIndexAmt = 64'd4;
|
3'd6: fnIndexAmt = 64'd4;
|
3'd7: fnIndexAmt = 64'd8;
|
3'd7: fnIndexAmt = 64'd8;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
// For string memory operations.
|
// For string memory operations.
|
//
|
//
|
task inc_index;
|
task inc_index;
|
input [5:0] fn;
|
input [5:0] fn;
|
begin
|
begin
|
index <= index + fnIndexAmt(fn);
|
index <= index + fnIndexAmt(fn);
|
lc <= lc - 64'd1;
|
lc <= lc - 64'd1;
|
end
|
end
|
endtask
|
endtask
|
|
|
function [DBW-1:0] fnSpr;
|
function [DBW-1:0] fnSpr;
|
input [5:0] regno;
|
input [5:0] regno;
|
input [63:0] epc;
|
input [63:0] epc;
|
begin
|
begin
|
// Read from the special registers unless overridden by the
|
// Read from the special registers unless overridden by the
|
// value on the commit bus.
|
// value on the commit bus.
|
casex(regno)
|
casex(regno)
|
6'b00xxxx: fnSpr = {DBW/4{pregs[regno[3:0]]}};
|
6'b00xxxx: fnSpr = {DBW/4{pregs[regno[3:0]]}};
|
6'b01xxxx: fnSpr = cregs[regno[3:0]];
|
6'b01xxxx: fnSpr = cregs[regno[3:0]];
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
6'b100xxx: fnSpr = {sregs[regno[2:0]],12'h000};
|
6'b100xxx: fnSpr = {sregs[regno[2:0]],12'h000};
|
6'b101xxx: fnSpr = {sregs_lmt[regno[2:0]],12'h000};
|
6'b101xxx: fnSpr = {sregs_lmt[regno[2:0]],12'h000};
|
`endif
|
`endif
|
6'b110000: if (DBW==64)
|
6'b110000: if (DBW==64)
|
fnSpr = {pregs[15],pregs[14],pregs[13],pregs[12],
|
fnSpr = {pregs[15],pregs[14],pregs[13],pregs[12],
|
pregs[11],pregs[10],pregs[9],pregs[8],
|
pregs[11],pregs[10],pregs[9],pregs[8],
|
pregs[7],pregs[6],pregs[5],pregs[4],
|
pregs[7],pregs[6],pregs[5],pregs[4],
|
pregs[3],pregs[2],pregs[1],pregs[0]};
|
pregs[3],pregs[2],pregs[1],pregs[0]};
|
else
|
else
|
fnSpr = {pregs[7],pregs[6],pregs[5],pregs[4],
|
fnSpr = {pregs[7],pregs[6],pregs[5],pregs[4],
|
pregs[3],pregs[2],pregs[1],pregs[0]};
|
pregs[3],pregs[2],pregs[1],pregs[0]};
|
`TICK: fnSpr = tick;
|
`TICK: fnSpr = tick;
|
`LCTR: fnSpr = lc;
|
`LCTR: fnSpr = lc;
|
`ASID: fnSpr = asid;
|
`ASID: fnSpr = asid;
|
`SR: begin
|
`SR: begin
|
fnSpr[7:0] = GM;
|
fnSpr[7:0] = GM;
|
fnSpr[23:16] = GMB;
|
fnSpr[23:16] = GMB;
|
fnSpr[31] = imb;
|
fnSpr[31] = imb;
|
fnSpr[15] = im;
|
fnSpr[15] = im;
|
fnSpr[12] = fxe;
|
fnSpr[12] = fxe;
|
end
|
end
|
6'd60: fnSpr = spr_bir;
|
6'd60: fnSpr = spr_bir;
|
6'd61:
|
6'd61:
|
casex(spr_bir[5:0])
|
casex(spr_bir[5:0])
|
6'd0: fnSpr = dbg_adr0;
|
6'd0: fnSpr = dbg_adr0;
|
6'd1: fnSpr = dbg_adr1;
|
6'd1: fnSpr = dbg_adr1;
|
6'd2: fnSpr = dbg_adr2;
|
6'd2: fnSpr = dbg_adr2;
|
6'd3: fnSpr = dbg_adr3;
|
6'd3: fnSpr = dbg_adr3;
|
6'd4: fnSpr = dbg_ctrl;
|
6'd4: fnSpr = dbg_ctrl;
|
6'd5: fnSpr = dbg_stat;
|
6'd5: fnSpr = dbg_stat;
|
`ifdef PCHIST
|
`ifdef PCHIST
|
6'd16: fnSpr = pc_histo[31:0];
|
6'd16: fnSpr = pc_histo[31:0];
|
6'd17: fnSpr = pc_histo[63:31];
|
6'd17: fnSpr = pc_histo[63:31];
|
`endif
|
`endif
|
default: fnSpr = 64'd0;
|
default: fnSpr = 64'd0;
|
endcase
|
endcase
|
default: fnSpr = 64'd0;
|
default: fnSpr = 64'd0;
|
endcase
|
endcase
|
// Not sure why bother read the commit bus here ? Why not the alu bus as well ?
|
// Not sure why bother read the commit bus here ? Why not the alu bus as well ?
|
// Need bypassing for write-through register file, reg read at same time as write
|
// Need bypassing for write-through register file, reg read at same time as write
|
// Shaves a clock cycle off register updates. rf_v is being set valid on the
|
// Shaves a clock cycle off register updates. rf_v is being set valid on the
|
// clock cycle of the commit.
|
// clock cycle of the commit.
|
// If an spr is committing...
|
// If an spr is committing...
|
if (commit0_v && commit0_tgt=={1'b1,regno}) begin
|
if (commit0_v && commit0_tgt=={1'b1,regno}) begin
|
if (regno[5:4]==2'b00) begin
|
if (regno[5:4]==2'b00) begin
|
if (DBW==32)
|
if (DBW==32)
|
fnSpr = {8{cmt0nyb[regno[2:0]]}};
|
fnSpr = {8{cmt0nyb[regno[2:0]]}};
|
else
|
else
|
fnSpr = {16{cmt0nyb[regno[3:0]]}};
|
fnSpr = {16{cmt0nyb[regno[3:0]]}};
|
end
|
end
|
else
|
else
|
fnSpr = commit0_bus;
|
fnSpr = commit0_bus;
|
end
|
end
|
if (commit1_v && commit1_tgt=={1'b1,regno}) begin
|
if (commit1_v && commit1_tgt=={1'b1,regno}) begin
|
if (regno[5:4]==2'b00) begin
|
if (regno[5:4]==2'b00) begin
|
if (DBW==32)
|
if (DBW==32)
|
fnSpr = {8{cmt1nyb[regno[2:0]]}};
|
fnSpr = {8{cmt1nyb[regno[2:0]]}};
|
else
|
else
|
fnSpr = {16{cmt1nyb[regno[3:0]]}};
|
fnSpr = {16{cmt1nyb[regno[3:0]]}};
|
end
|
end
|
else
|
else
|
fnSpr = commit1_bus;
|
fnSpr = commit1_bus;
|
end
|
end
|
|
|
// Special cases where the register would not be read from the commit bus
|
// Special cases where the register would not be read from the commit bus
|
case(regno)
|
case(regno)
|
`TICK: fnSpr = tick;
|
`TICK: fnSpr = tick;
|
6'b010000: fnSpr = 64'd0; // code address zero
|
6'b010000: fnSpr = 64'd0; // code address zero
|
6'b011111: fnSpr = epc; // current program counter from fetchbufx_pc
|
6'b011111: fnSpr = epc; // current program counter from fetchbufx_pc
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
// "oddball" instruction commit cases.
|
// "oddball" instruction commit cases.
|
//
|
//
|
task oddball_commit;
|
task oddball_commit;
|
input commit_v;
|
input commit_v;
|
input [2:0] head;
|
input [2:0] head;
|
begin
|
begin
|
if (commit_v)
|
if (commit_v)
|
case(iqentry_op[head])
|
case(iqentry_op[head])
|
`CLI: begin imcd <= IMCD; imb <= 1'b0; end
|
`CLI: begin imcd <= IMCD; imb <= 1'b0; end
|
`SEI: begin im <= 1'b1; imb <= 1'b1; end
|
`SEI: begin im <= 1'b1; imb <= 1'b1; end
|
// When the RTI instruction commits clear the hardware interrupt status to enable interrupts.
|
// When the RTI instruction commits clear the hardware interrupt status to enable interrupts.
|
`RTI: begin
|
`RTI: begin
|
StatusHWI <= `FALSE;
|
StatusHWI <= `FALSE;
|
if (imb)
|
if (imb)
|
im <= 1'b1;
|
im <= 1'b1;
|
else
|
else
|
imcd <= IMCD;
|
imcd <= IMCD;
|
end
|
end
|
`RTD:
|
`RTD:
|
begin
|
begin
|
StatusDBG <= `FALSE;
|
StatusDBG <= `FALSE;
|
if (StatusEXL!=8'h00)
|
if (StatusEXL!=8'h00)
|
StatusEXL <= StatusEXL - 8'd1;
|
StatusEXL <= StatusEXL - 8'd1;
|
end
|
end
|
`RTE:
|
`RTE:
|
begin
|
begin
|
if (StatusEXL!=8'h00)
|
if (StatusEXL!=8'h00)
|
StatusEXL <= StatusEXL - 8'd1;
|
StatusEXL <= StatusEXL - 8'd1;
|
end
|
end
|
`CACHE:
|
`CACHE:
|
begin
|
begin
|
case(iqentry_fn[head])
|
case(iqentry_fn[head])
|
6'd0: ic_invalidate <= `TRUE;
|
6'd0: ic_invalidate <= `TRUE;
|
6'd1: begin
|
6'd1: begin
|
ic_invalidate_line <= `TRUE;
|
ic_invalidate_line <= `TRUE;
|
ic_lineno <= iqentry_a1[head] + {sregs[3'd7],12'h000};
|
ic_lineno <= iqentry_a1[head] + {sregs[3'd7],12'h000};
|
end
|
end
|
6'd32: dc_invalidate <= `TRUE;
|
6'd32: dc_invalidate <= `TRUE;
|
6'd33: begin
|
6'd33: begin
|
dc_invalidate_line <= `TRUE;
|
dc_invalidate_line <= `TRUE;
|
dc_lineno <= iqentry_a1[head] + {sregs[iqentry_fn[head][5:3]],12'h000};
|
dc_lineno <= iqentry_a1[head] + {sregs[iqentry_fn[head][5:3]],12'h000};
|
end
|
end
|
default: ; // do nothing
|
default: ; // do nothing
|
endcase
|
endcase
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
endtask
|
endtask
|
|
|
// The exception_set var is used to reduce the number of logic levels. Rather
|
// The exception_set var is used to reduce the number of logic levels. Rather
|
// than having an if/elseif tree for all the exceptional conditions that are
|
// than having an if/elseif tree for all the exceptional conditions that are
|
// trapped. The exception_set var tracks these excaptions and reduces the
|
// trapped. The exception_set var tracks these excaptions and reduces the
|
// tree to a single if.
|
// tree to a single if.
|
task enque0a;
|
task enque0a;
|
input [2:0] tail;
|
input [2:0] tail;
|
input [2:0] inc;
|
input [2:0] inc;
|
input unlink;
|
input unlink;
|
begin
|
begin
|
if (fetchbuf0_pc==32'h0)
|
if (fetchbuf0_pc==32'h0)
|
$stop;
|
$stop;
|
if (fetchbuf0_pc==32'hF44)
|
if (fetchbuf0_pc==32'hF44)
|
$stop;
|
$stop;
|
if (fetchbuf0_pc==32'hFFFFD09B)
|
if (fetchbuf0_pc==32'hFFFC2F71)
|
$stop;
|
$stop;
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
`ifdef SEGLIMITS
|
`ifdef SEGLIMITS
|
// If segment limit exceeded and not in the non-segmented area.
|
// If segment limit exceeded and not in the non-segmented area.
|
if (fetchbuf0_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf0_pc[ABW-1:ABW-4]!=4'hF)
|
if (fetchbuf0_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf0_pc[ABW-1:ABW-4]!=4'hF)
|
set_exception(tail,8'd244);
|
set_exception(tail,8'd244);
|
`endif
|
`endif
|
`endif
|
`endif
|
// If targeting a kernel mode register and not in kernel mode.
|
// If targeting a kernel mode register and not in kernel mode.
|
// But okay if it is an SYS or INT instruction.
|
// But okay if it is an SYS or INT instruction.
|
if (fnIsKMOnlyReg(Rt0) && !km && !(opcode0==`SYS || opcode0==`INT))
|
if (fnIsKMOnlyReg(Rt0) && !km && !(opcode0==`SYS || opcode0==`INT))
|
set_exception(tail,8'd245);
|
set_exception(tail,8'd245);
|
// If attempting to use an undefined instruction
|
// If attempting to use an undefined instruction
|
`ifdef TRAP_ILLEGALOPS
|
`ifdef TRAP_ILLEGALOPS
|
if (fnIsIllegal(opcode0,opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr)))
|
if (fnIsIllegal(opcode0,opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr)))
|
set_exception(tail,8'd250);
|
set_exception(tail,8'd250);
|
`endif
|
`endif
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf0_pc==dbg_adr0)
|
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf0_pc==dbg_adr0)
|
dbg_imatchA0 = `TRUE;
|
dbg_imatchA0 = `TRUE;
|
if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf0_pc==dbg_adr1)
|
if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf0_pc==dbg_adr1)
|
dbg_imatchA1 = `TRUE;
|
dbg_imatchA1 = `TRUE;
|
if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf0_pc==dbg_adr2)
|
if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf0_pc==dbg_adr2)
|
dbg_imatchA2 = `TRUE;
|
dbg_imatchA2 = `TRUE;
|
if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf0_pc==dbg_adr3)
|
if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf0_pc==dbg_adr3)
|
dbg_imatchA3 = `TRUE;
|
dbg_imatchA3 = `TRUE;
|
if (dbg_imatchA0|dbg_imatchA1|dbg_imatchA2|dbg_imatchA3)
|
if (dbg_imatchA0|dbg_imatchA1|dbg_imatchA2|dbg_imatchA3)
|
dbg_imatchA = `TRUE;
|
dbg_imatchA = `TRUE;
|
if (dbg_imatchA)
|
if (dbg_imatchA)
|
set_exception(tail,8'd243); // Debug exception
|
set_exception(tail,8'd243); // Debug exception
|
`endif
|
`endif
|
if (!exception_set) begin
|
if (!exception_set) begin
|
interrupt_pc =
|
interrupt_pc =
|
// If the previous instruction was an interrupt, then inherit the address
|
// If the previous instruction was an interrupt, then inherit the address
|
(iqentry_op[(tail-3'd1)&7]==`INT && iqentry_v[(tail-3'd1)&7]==`VAL && iqentry_tgt[(tail-3'd1)&7][3:0]==4'hE) ?
|
(iqentry_op[(tail-3'd1)&7]==`INT && iqentry_v[(tail-3'd1)&7]==`VAL && iqentry_tgt[(tail-3'd1)&7][3:0]==4'hE) ?
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
// Otherwise inherit the address of any preceding immediate prefix.
|
// Otherwise inherit the address of any preceding immediate prefix.
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[(tail-3'd1)&7]==`VAL) ?
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[(tail-3'd1)&7]==`VAL) ?
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
// Otherwise use the address of the interrupted instruction
|
// Otherwise use the address of the interrupted instruction
|
(string_pc != 0 ? string_pc : fetchbuf0_pc);
|
(string_pc != 0 ? string_pc : fetchbuf0_pc);
|
iqentry_v [tail] <= `VAL;
|
iqentry_v [tail] <= `VAL;
|
iqentry_done [tail] <= `INV;
|
iqentry_done [tail] <= `INV;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_out [tail] <= `INV;
|
iqentry_out [tail] <= `INV;
|
iqentry_res [tail] <= `ZERO;
|
iqentry_res [tail] <= `ZERO;
|
iqentry_insnsz[tail] <= fnInsnLength(fetchbuf0_instr);
|
iqentry_insnsz[tail] <= fnInsnLength(fetchbuf0_instr);
|
iqentry_op [tail] <= opcode0;
|
iqentry_op [tail] <= opcode0;
|
iqentry_fn [tail] <= opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr);
|
iqentry_fn [tail] <= opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr);
|
iqentry_cond [tail] <= cond0;
|
iqentry_cond [tail] <= cond0;
|
iqentry_bt [tail] <= fnIsFlowCtrl(opcode0) && predict_taken0;
|
iqentry_bt [tail] <= fnIsFlowCtrl(opcode0) && predict_taken0;
|
iqentry_br [tail] <= opcode0[7:4]==`BR;
|
iqentry_br [tail] <= opcode0[7:4]==`BR;
|
iqentry_agen [tail] <= `INV;
|
iqentry_agen [tail] <= `INV;
|
iqentry_pc [tail] <= (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc;
|
iqentry_pc [tail] <= (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc;
|
iqentry_mem [tail] <= fetchbuf0_mem;
|
iqentry_mem [tail] <= fetchbuf0_mem;
|
iqentry_ndx [tail] <= fnIsIndexed(opcode0);
|
iqentry_ndx [tail] <= fnIsIndexed(opcode0);
|
iqentry_cas [tail] <= opcode0==`CAS;
|
iqentry_cas [tail] <= opcode0==`CAS;
|
iqentry_pushpop[tail] <= opcode0==`PUSH || opcode0==`POP;
|
iqentry_pushpop[tail] <= opcode0==`PUSH || opcode0==`POP;
|
iqentry_pea [tail] <= opcode0==`PEA;
|
iqentry_pea [tail] <= opcode0==`PEA;
|
iqentry_cmpmv[tail] <= opcode0==`STCMP || opcode0==`STMV;
|
iqentry_cmpmv[tail] <= opcode0==`STCMP || opcode0==`STMV;
|
iqentry_lla [tail] <= opcode0==`LLA || opcode0==`LLAX;
|
iqentry_lla [tail] <= opcode0==`LLA || opcode0==`LLAX;
|
iqentry_tlb [tail] <= opcode0==`TLB;
|
iqentry_tlb [tail] <= opcode0==`TLB;
|
iqentry_jmp [tail] <= fetchbuf0_jmp;
|
iqentry_jmp [tail] <= fetchbuf0_jmp;
|
iqentry_jmpi [tail] <= opcode0==`JMPI || opcode0==`JMPIX;
|
iqentry_jmpi [tail] <= opcode0==`JMPI || opcode0==`JMPIX;
|
iqentry_sync [tail] <= opcode0==`SYNC;
|
iqentry_sync [tail] <= opcode0==`SYNC;
|
iqentry_memsb[tail] <= opcode0==`MEMSB;
|
iqentry_memsb[tail] <= opcode0==`MEMSB;
|
iqentry_memdb[tail] <= opcode0==`MEMDB;
|
iqentry_memdb[tail] <= opcode0==`MEMDB;
|
iqentry_fp [tail] <= fetchbuf0_fp;
|
iqentry_fp [tail] <= fetchbuf0_fp;
|
iqentry_rfw [tail] <= fetchbuf0_rfw;
|
iqentry_rfw [tail] <= fetchbuf0_rfw;
|
iqentry_tgt [tail] <= Rt0;
|
iqentry_tgt [tail] <= Rt0;
|
iqentry_preg [tail] <= Pn0;
|
iqentry_preg [tail] <= Pn0;
|
// Need the bypassing on the preg file for write-through register effect.
|
// Need the bypassing on the preg file for write-through register effect.
|
iqentry_pred [tail] <= fnSpr({2'h0,Pn0},fetchbuf0_pc);//pregs[Pn0];
|
iqentry_pred [tail] <= fnSpr({2'h0,Pn0},fetchbuf0_pc);//pregs[Pn0];
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
iqentry_a0[tail] <= (opcode0==`INT || opcode0==`SYS) ? fnImm(fetchbuf0_instr) :
|
iqentry_a0[tail] <= (opcode0==`INT || opcode0==`SYS) ? fnImm(fetchbuf0_instr) :
|
fnIsBranch(opcode0) ? {{DBW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} :
|
fnIsBranch(opcode0) ? {{DBW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} :
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[tail-3'd1]) ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf0_instr)}:
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[tail-3'd1]) ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf0_instr)}:
|
opcode0==`IMM ? fnImmImm(fetchbuf0_instr) :
|
opcode0==`IMM ? fnImmImm(fetchbuf0_instr) :
|
fnImm(fetchbuf0_instr);
|
fnImm(fetchbuf0_instr);
|
// These register recordings for simulation debug. They should be stripped
|
// These register recordings for simulation debug. They should be stripped
|
// out of synthesis because they don't drive any signals.
|
// out of synthesis because they don't drive any signals.
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
iqentry_r1 [tail] <= Ra0;
|
iqentry_r1 [tail] <= Ra0;
|
iqentry_r2 [tail] <= Rb0;
|
iqentry_r2 [tail] <= Rb0;
|
iqentry_r3 [tail] <= Rc0;
|
iqentry_r3 [tail] <= Rc0;
|
iqentry_rt [tail] <= Rt0;
|
iqentry_rt [tail] <= Rt0;
|
`endif
|
`endif
|
iqentry_a1 [tail] <= fnOpa(opcode0,Ra0,fetchbuf0_instr,rfoa0,fetchbuf0_pc);
|
iqentry_a1 [tail] <= fnOpa(opcode0,Ra0,fetchbuf0_instr,rfoa0,fetchbuf0_pc);
|
iqentry_a2 [tail] <= fnOpb(opcode0,Rb0,fetchbuf0_instr,rfob0,fetchbuf0_pc);
|
iqentry_a2 [tail] <= fnOpb(opcode0,Rb0,fetchbuf0_instr,rfob0,fetchbuf0_pc);
|
iqentry_a3 [tail] <= rfoc0;
|
iqentry_a3 [tail] <= rfoc0;
|
iqentry_T [tail] <= fnOpt(Rt0,rfot0,fetchbuf0_pc);
|
iqentry_T [tail] <= fnOpt(Rt0,rfot0,fetchbuf0_pc);
|
// The source is set even though the arg might be automatically valid (less logic).
|
// The source is set even though the arg might be automatically valid (less logic).
|
// This is harmless to do. Note there is no source for the 'I' argument.
|
// This is harmless to do. Note there is no source for the 'I' argument.
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn0}];
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn0}];
|
iqentry_a1_s [tail] <= //unlink ? {1'b0, (tail-1)&7} :
|
iqentry_a1_s [tail] <= //unlink ? {1'b0, (tail-1)&7} :
|
rf_source[Ra0];
|
rf_source[Ra0];
|
iqentry_a2_s [tail] <= rf_source[Rb0];
|
iqentry_a2_s [tail] <= rf_source[Rb0];
|
iqentry_a3_s [tail] <= rf_source[Rc0];
|
iqentry_a3_s [tail] <= rf_source[Rc0];
|
iqentry_T_s [tail] <= rf_source[Rt0];
|
iqentry_T_s [tail] <= rf_source[Rt0];
|
// Always do this because it's the first queue slot.
|
// Always do this because it's the first queue slot.
|
validate_args10(tail);
|
validate_args10(tail);
|
end
|
end
|
tail0 <= tail0 + inc;
|
tail0 <= tail0 + inc;
|
tail1 <= tail1 + inc;
|
tail1 <= tail1 + inc;
|
tail2 <= tail2 + inc;
|
tail2 <= tail2 + inc;
|
queued1 = `TRUE;
|
queued1 = `TRUE;
|
rrmapno <= rrmapno + 3'd1;
|
rrmapno <= rrmapno + 3'd1;
|
end
|
end
|
endtask
|
endtask
|
|
|
task enquePushpopAdd;
|
task enquePushpopAdd;
|
input [2:0] tail;
|
input [2:0] tail;
|
input pushpop;
|
input pushpop;
|
input link;
|
input link;
|
input unlink;
|
input unlink;
|
input which;
|
input which;
|
begin
|
begin
|
$display("Pushpop add");
|
$display("Pushpop add");
|
iqentry_v [tail] <= `VAL;
|
iqentry_v [tail] <= `VAL;
|
iqentry_done [tail] <= `INV;
|
iqentry_done [tail] <= `INV;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_out [tail] <= `INV;
|
iqentry_out [tail] <= `INV;
|
iqentry_res [tail] <= 64'd0;
|
iqentry_res [tail] <= 64'd0;
|
iqentry_insnsz[tail] <= 4'd0;
|
iqentry_insnsz[tail] <= 4'd0;
|
iqentry_op [tail] <= `ADDUI;
|
iqentry_op [tail] <= `ADDUI;
|
iqentry_fn [tail] <= 6'b0;
|
iqentry_fn [tail] <= 6'b0;
|
iqentry_cond [tail] <= which ? cond1 :cond0;
|
iqentry_cond [tail] <= which ? cond1 :cond0;
|
iqentry_bt [tail] <= 1'b0;
|
iqentry_bt [tail] <= 1'b0;
|
iqentry_agen [tail] <= `INV;
|
iqentry_agen [tail] <= `INV;
|
iqentry_pc [tail] <= which ? fetchbuf1_pc : fetchbuf0_pc;
|
iqentry_pc [tail] <= which ? fetchbuf1_pc : fetchbuf0_pc;
|
iqentry_mem [tail] <= 1'b0;
|
iqentry_mem [tail] <= 1'b0;
|
iqentry_ndx [tail] <= 1'b0;
|
iqentry_ndx [tail] <= 1'b0;
|
iqentry_cas [tail] <= 1'b0;
|
iqentry_cas [tail] <= 1'b0;
|
iqentry_pushpop[tail] <= 1'b0;
|
iqentry_pushpop[tail] <= 1'b0;
|
iqentry_pea [tail] <= 1'b0;
|
iqentry_pea [tail] <= 1'b0;
|
iqentry_cmpmv[tail] <= 1'b0;
|
iqentry_cmpmv[tail] <= 1'b0;
|
iqentry_lla [tail] <= 1'b0;
|
iqentry_lla [tail] <= 1'b0;
|
iqentry_tlb [tail] <= 1'b0;
|
iqentry_tlb [tail] <= 1'b0;
|
iqentry_jmp [tail] <= 1'b0;
|
iqentry_jmp [tail] <= 1'b0;
|
iqentry_jmpi [tail] <= 1'b0;
|
iqentry_jmpi [tail] <= 1'b0;
|
iqentry_sync [tail] <= 1'b0;
|
iqentry_sync [tail] <= 1'b0;
|
iqentry_memsb[tail] <= 1'b0;
|
iqentry_memsb[tail] <= 1'b0;
|
iqentry_memdb[tail] <= 1'b0;
|
iqentry_memdb[tail] <= 1'b0;
|
iqentry_fp [tail] <= 1'b0;
|
iqentry_fp [tail] <= 1'b0;
|
iqentry_rfw [tail] <= 1'b1;
|
iqentry_rfw [tail] <= 1'b1;
|
iqentry_tgt [tail] <= 7'd27;
|
iqentry_tgt [tail] <= 7'd27;
|
iqentry_pred [tail] <= pregs[which ? Pn1 : Pn0];
|
iqentry_pred [tail] <= pregs[which ? Pn1 : Pn0];
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
iqentry_a0 [tail] <= link ? (which ? {{46{fetchbuf1_instr[39]}},fetchbuf1_instr[21:16],fetchbuf1_instr[39:28],3'b000} :
|
iqentry_a0 [tail] <= link ? (which ? {{46{fetchbuf1_instr[39]}},fetchbuf1_instr[21:16],fetchbuf1_instr[39:28],3'b000} :
|
{{46{fetchbuf0_instr[39]}},fetchbuf0_instr[21:16],fetchbuf0_instr[39:28],3'b000}) :
|
{{46{fetchbuf0_instr[39]}},fetchbuf0_instr[21:16],fetchbuf0_instr[39:28],3'b000}) :
|
(pushpop|unlink) ? 64'd8 : -64'd8;
|
(pushpop|unlink) ? 64'd8 : -64'd8;
|
iqentry_a1 [tail] <= which ? rfoa1 : rfoa0;
|
iqentry_a1 [tail] <= which ? rfoa1 : rfoa0;
|
iqentry_a2 [tail] <= 64'd0;
|
iqentry_a2 [tail] <= 64'd0;
|
iqentry_a3 [tail] <= 64'd0;
|
iqentry_a3 [tail] <= 64'd0;
|
iqentry_T [tail] <= //unlink ? (which ? rfot1 : rfot0) :
|
iqentry_T [tail] <= //unlink ? (which ? rfot1 : rfot0) :
|
(which ? rfoa1 : rfoa0);
|
(which ? rfoa1 : rfoa0);
|
// The source is set even though the arg might be automatically valid (less logic).
|
// The source is set even though the arg might be automatically valid (less logic).
|
// This is harmless to do. Note there is no source for the 'I' argument.
|
// This is harmless to do. Note there is no source for the 'I' argument.
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,which ? Pn1 : Pn0}];
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,which ? Pn1 : Pn0}];
|
iqentry_a1_s [tail] <= rf_source[Ra0];
|
iqentry_a1_s [tail] <= rf_source[Ra0];
|
iqentry_a2_s [tail] <= rf_source[Rb0];
|
iqentry_a2_s [tail] <= rf_source[Rb0];
|
iqentry_a3_s [tail] <= rf_source[Rc0];
|
iqentry_a3_s [tail] <= rf_source[Rc0];
|
iqentry_T_s [tail] <= rf_source[Ra0];
|
iqentry_T_s [tail] <= rf_source[Ra0];
|
// Always do this because it's the first queue slot.
|
// Always do this because it's the first queue slot.
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,which ? Pn1:Pn0}] || ((which ? cond1 : cond0) < 4'h2);
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,which ? Pn1:Pn0}] || ((which ? cond1 : cond0) < 4'h2);
|
iqentry_a1_v [tail] <= rf_v[ which ? Ra1 : Ra0 ];
|
iqentry_a1_v [tail] <= rf_v[ which ? Ra1 : Ra0 ];
|
iqentry_a2_v [tail] <= 1'b1;
|
iqentry_a2_v [tail] <= 1'b1;
|
iqentry_a3_v [tail] <= 1'b1;
|
iqentry_a3_v [tail] <= 1'b1;
|
iqentry_T_v [tail] <= //unlink ? rf_v[which ? Rt1 : Rt0] :
|
iqentry_T_v [tail] <= //unlink ? rf_v[which ? Rt1 : Rt0] :
|
rf_v[ which ? Ra1 : Ra0 ];
|
rf_v[ which ? Ra1 : Ra0 ];
|
rf_v[ 7'd27 ] = `INV;
|
rf_v[ 7'd27 ] = `INV;
|
rf_source[ 7'd27 ] <= { 1'b0, tail }; // top bit indicates ALU/MEM bus
|
rf_source[ 7'd27 ] <= { 1'b0, tail }; // top bit indicates ALU/MEM bus
|
end
|
end
|
endtask
|
endtask
|
|
|
// enque 0 on tail0 or tail1
|
// enque 0 on tail0 or tail1
|
task enque0;
|
task enque0;
|
input [2:0] tail;
|
input [2:0] tail;
|
input [2:0] inc;
|
input [2:0] inc;
|
input test_stomp;
|
input test_stomp;
|
input validate_args;
|
input validate_args;
|
begin
|
begin
|
if (`FALSE)
|
if (opcode0==`NOP)
|
;
|
queued1 = `TRUE; // to update fetch buffers
|
// if (opcode0==`NOP)
|
|
// queued1 = `TRUE; // to update fetch buffers
|
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
else
|
else
|
if (dbg_ctrl[7] && !StatusDBG) begin
|
if (dbg_ctrl[7] && !StatusDBG) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
enque0a(tail,3'd2,1'b0);
|
enque0a(tail,3'd2,1'b0);
|
set_exception((tail+1)&7,8'd243);
|
set_exception((tail+1)&7,8'd243);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
// A pop instruction takes 2 queue entries.
|
// A pop instruction takes 2 queue entries.
|
else if (fnIsPop(fetchbuf0_instr)|fnIsPush(fetchbuf0_instr)|opcode0==`LINK) begin
|
else if (fnIsPop(fetchbuf0_instr)|fnIsPush(fetchbuf0_instr)|opcode0==`LINK) begin
|
$display("0 found push/pop");
|
$display("0 found push/pop");
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
$display("enqueing2");
|
$display("enqueing2");
|
enque0a(tail,3'd2,1'b0);
|
enque0a(tail,3'd2,1'b0);
|
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf0_instr),opcode0==`LINK,0,0);
|
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf0_instr),opcode0==`LINK,0,0);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`ifdef UNLINKOP
|
`ifdef UNLINKOP
|
else if (opcode0==`UNLINK) begin
|
else if (opcode0==`UNLINK) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
enquePushpopAdd(tail,1'b0,1'b0,1'b1,0);
|
enquePushpopAdd(tail,1'b0,1'b0,1'b1,0);
|
enque0a((tail+1)&7,3'd2,1'b1);
|
enque0a((tail+1)&7,3'd2,1'b1);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
`endif
|
`endif
|
else if (iqentry_v[tail] == `INV) begin
|
else if (iqentry_v[tail] == `INV) begin
|
if ((({fnIsBranch(opcode0), predict_taken0} == {`TRUE, `TRUE})||(opcode0==`LOOP)) && test_stomp)
|
if ((({fnIsBranch(opcode0), predict_taken0} == {`TRUE, `TRUE})||(opcode0==`LOOP)) && test_stomp)
|
qstomp = `TRUE;
|
qstomp = `TRUE;
|
enque0a(tail,inc,0);
|
enque0a(tail,inc,0);
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
task enque1a;
|
task enque1a;
|
input [2:0] tail;
|
input [2:0] tail;
|
input [2:0] inc;
|
input [2:0] inc;
|
input validate_args;
|
input validate_args;
|
input unlink;
|
input unlink;
|
begin
|
begin
|
if (fetchbuf1_pc==32'h0)
|
if (fetchbuf1_pc==32'h0)
|
$stop;
|
$stop;
|
if (fetchbuf1_pc==32'hF44)
|
if (fetchbuf1_pc==32'hF44)
|
$stop;
|
$stop;
|
if (fetchbuf1_pc==32'hFFFFD09B)
|
if (fetchbuf1_pc==32'hFFFC2F71)
|
$stop;
|
$stop;
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
`ifdef SEGLIMITS
|
`ifdef SEGLIMITS
|
if (fetchbuf1_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF)
|
if (fetchbuf1_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF)
|
set_exception(tail,8'd244);
|
set_exception(tail,8'd244);
|
`endif
|
`endif
|
`endif
|
`endif
|
if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT))
|
if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT))
|
set_exception(tail,8'd245);
|
set_exception(tail,8'd245);
|
`ifdef TRAP_ILLEGALOPS
|
`ifdef TRAP_ILLEGALOPS
|
if (fnIsIllegal(opcode1,opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr)))
|
if (fnIsIllegal(opcode1,opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr)))
|
set_exception(tail,8'd250);
|
set_exception(tail,8'd250);
|
`endif
|
`endif
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf1_pc==dbg_adr0)
|
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf1_pc==dbg_adr0)
|
dbg_imatchB0 = `TRUE;
|
dbg_imatchB0 = `TRUE;
|
if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf1_pc==dbg_adr1)
|
if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf1_pc==dbg_adr1)
|
dbg_imatchB1 = `TRUE;
|
dbg_imatchB1 = `TRUE;
|
if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf1_pc==dbg_adr2)
|
if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf1_pc==dbg_adr2)
|
dbg_imatchB2 = `TRUE;
|
dbg_imatchB2 = `TRUE;
|
if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf1_pc==dbg_adr3)
|
if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf1_pc==dbg_adr3)
|
dbg_imatchB3 = `TRUE;
|
dbg_imatchB3 = `TRUE;
|
if (dbg_imatchB0|dbg_imatchB1|dbg_imatchB2|dbg_imatchB3)
|
if (dbg_imatchB0|dbg_imatchB1|dbg_imatchB2|dbg_imatchB3)
|
dbg_imatchB = `TRUE;
|
dbg_imatchB = `TRUE;
|
if (dbg_imatchB)
|
if (dbg_imatchB)
|
set_exception(tail,8'd243); // debug excpetion
|
set_exception(tail,8'd243); // debug excpetion
|
`endif
|
`endif
|
if (!exception_set) begin
|
if (!exception_set) begin
|
// If an instruction wasn't enqueued or it wasn't an interrupt instruction then
|
// If an instruction wasn't enqueued or it wasn't an interrupt instruction then
|
// the interrupt pc will need to be set. Othersise this enqueue will inherit
|
// the interrupt pc will need to be set. Othersise this enqueue will inherit
|
// from the previous one.
|
// from the previous one.
|
if (!queued1 || !(opcode0==`INT && Rt0[3:0]==4'hE))
|
if (!queued1 || !(opcode0==`INT && Rt0[3:0]==4'hE))
|
interrupt_pc = (iqentry_op[(tail-3'd1)&7]==`INT && iqentry_v[(tail-3'd1)&7]==`VAL && iqentry_tgt[(tail-3'd1)&7][3:0]==4'hE) ?
|
interrupt_pc = (iqentry_op[(tail-3'd1)&7]==`INT && iqentry_v[(tail-3'd1)&7]==`VAL && iqentry_tgt[(tail-3'd1)&7][3:0]==4'hE) ?
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[(tail-3'd1)&7]==`VAL) ? (string_pc != 0 ? string_pc :
|
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[(tail-3'd1)&7]==`VAL) ? (string_pc != 0 ? string_pc :
|
iqentry_pc[(tail-3'd1)&7]) : (string_pc != 0 ? string_pc : fetchbuf1_pc);
|
iqentry_pc[(tail-3'd1)&7]) : (string_pc != 0 ? string_pc : fetchbuf1_pc);
|
iqentry_v [tail] <= `VAL;
|
iqentry_v [tail] <= `VAL;
|
iqentry_done [tail] <= `INV;
|
iqentry_done [tail] <= `INV;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_cmt [tail] <= `TRUE;
|
iqentry_out [tail] <= `INV;
|
iqentry_out [tail] <= `INV;
|
iqentry_res [tail] <= `ZERO;
|
iqentry_res [tail] <= `ZERO;
|
iqentry_insnsz[tail] <= fnInsnLength(fetchbuf1_instr);
|
iqentry_insnsz[tail] <= fnInsnLength(fetchbuf1_instr);
|
iqentry_op [tail] <= opcode1;
|
iqentry_op [tail] <= opcode1;
|
iqentry_fn [tail] <= opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr);
|
iqentry_fn [tail] <= opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr);
|
iqentry_cond [tail] <= cond1;
|
iqentry_cond [tail] <= cond1;
|
iqentry_bt [tail] <= fnIsFlowCtrl(opcode1) && predict_taken1;
|
iqentry_bt [tail] <= fnIsFlowCtrl(opcode1) && predict_taken1;
|
iqentry_br [tail] <= opcode1[7:4]==`BR;
|
iqentry_br [tail] <= opcode1[7:4]==`BR;
|
iqentry_agen [tail] <= `INV;
|
iqentry_agen [tail] <= `INV;
|
// If an interrupt is being enqueued and the previous instruction was an immediate prefix, then
|
// If an interrupt is being enqueued and the previous instruction was an immediate prefix, then
|
// inherit the address of the previous instruction, so that the prefix will be executed on return
|
// inherit the address of the previous instruction, so that the prefix will be executed on return
|
// from interrupt.
|
// from interrupt.
|
// If a string operation was in progress then inherit the address of the string operation so that
|
// If a string operation was in progress then inherit the address of the string operation so that
|
// it can be continued.
|
// it can be continued.
|
|
|
iqentry_pc [tail] <= (opcode1==`INT && Rt1[3:0]==4'hE) ? interrupt_pc : fetchbuf1_pc;
|
iqentry_pc [tail] <= (opcode1==`INT && Rt1[3:0]==4'hE) ? interrupt_pc : fetchbuf1_pc;
|
iqentry_mem [tail] <= fetchbuf1_mem;
|
iqentry_mem [tail] <= fetchbuf1_mem;
|
iqentry_ndx [tail] <= fnIsIndexed(opcode1);
|
iqentry_ndx [tail] <= fnIsIndexed(opcode1);
|
iqentry_cas [tail] <= opcode1==`CAS;
|
iqentry_cas [tail] <= opcode1==`CAS;
|
iqentry_pushpop[tail] <= opcode1==`PUSH || opcode1==`POP;
|
iqentry_pushpop[tail] <= opcode1==`PUSH || opcode1==`POP;
|
iqentry_pea [tail] <= opcode1==`PEA;
|
iqentry_pea [tail] <= opcode1==`PEA;
|
iqentry_cmpmv[tail] <= opcode1==`STCMP || opcode1==`STMV;
|
iqentry_cmpmv[tail] <= opcode1==`STCMP || opcode1==`STMV;
|
iqentry_lla [tail] <= opcode1==`LLA || opcode1==`LLAX;
|
iqentry_lla [tail] <= opcode1==`LLA || opcode1==`LLAX;
|
iqentry_tlb [tail] <= opcode1==`TLB;
|
iqentry_tlb [tail] <= opcode1==`TLB;
|
iqentry_jmp [tail] <= fetchbuf1_jmp;
|
iqentry_jmp [tail] <= fetchbuf1_jmp;
|
iqentry_jmpi [tail] <= opcode1==`JMPI || opcode1==`JMPIX;
|
iqentry_jmpi [tail] <= opcode1==`JMPI || opcode1==`JMPIX;
|
iqentry_sync [tail] <= opcode1==`SYNC;
|
iqentry_sync [tail] <= opcode1==`SYNC;
|
iqentry_memsb[tail] <= opcode1==`MEMSB;
|
iqentry_memsb[tail] <= opcode1==`MEMSB;
|
iqentry_memdb[tail] <= opcode1==`MEMDB;
|
iqentry_memdb[tail] <= opcode1==`MEMDB;
|
iqentry_fp [tail] <= fetchbuf1_fp;
|
iqentry_fp [tail] <= fetchbuf1_fp;
|
iqentry_rfw [tail] <= fetchbuf1_rfw;
|
iqentry_rfw [tail] <= fetchbuf1_rfw;
|
iqentry_tgt [tail] <= Rt1;
|
iqentry_tgt [tail] <= Rt1;
|
iqentry_preg [tail] <= Pn1;
|
iqentry_preg [tail] <= Pn1;
|
iqentry_pred [tail] <= fnSpr({2'h0,Pn1},fetchbuf1_pc);//pregs[Pn1];
|
iqentry_pred [tail] <= fnSpr({2'h0,Pn1},fetchbuf1_pc);//pregs[Pn1];
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
// Look at the previous queue slot to see if an immediate prefix is enqueued
|
// But don't allow it for a branch
|
// But don't allow it for a branch
|
iqentry_a0[tail] <= (opcode1==`INT || opcode1==`SYS) ? fnImm(fetchbuf1_instr) :
|
iqentry_a0[tail] <= (opcode1==`INT || opcode1==`SYS) ? fnImm(fetchbuf1_instr) :
|
fnIsBranch(opcode1) ? {{DBW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} :
|
fnIsBranch(opcode1) ? {{DBW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} :
|
(queued1 && opcode0==`IMM) ? {fnImmImm(fetchbuf0_instr)|fnImm8(fetchbuf1_instr)} :
|
(queued1 && opcode0==`IMM) ? {fnImmImm(fetchbuf0_instr)|fnImm8(fetchbuf1_instr)} :
|
(!queued1 && iqentry_op[(tail-3'd1)&7]==`IMM) && iqentry_v[(tail-3'd1)&7] ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf1_instr)} :
|
(!queued1 && iqentry_op[(tail-3'd1)&7]==`IMM) && iqentry_v[(tail-3'd1)&7] ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf1_instr)} :
|
opcode1==`IMM ? fnImmImm(fetchbuf1_instr) :
|
opcode1==`IMM ? fnImmImm(fetchbuf1_instr) :
|
fnImm(fetchbuf1_instr);
|
fnImm(fetchbuf1_instr);
|
iqentry_a1 [tail] <= fnOpa(opcode1,Ra1,fetchbuf1_instr,rfoa1,fetchbuf1_pc);
|
iqentry_a1 [tail] <= fnOpa(opcode1,Ra1,fetchbuf1_instr,rfoa1,fetchbuf1_pc);
|
iqentry_a2 [tail] <= fnOpb(opcode1,Rb1,fetchbuf1_instr,rfob1,fetchbuf1_pc);
|
iqentry_a2 [tail] <= fnOpb(opcode1,Rb1,fetchbuf1_instr,rfob1,fetchbuf1_pc);
|
iqentry_a3 [tail] <= rfoc1;
|
iqentry_a3 [tail] <= rfoc1;
|
iqentry_T [tail] <= fnOpt(Rt1,rfot1,fetchbuf1_pc);
|
iqentry_T [tail] <= fnOpt(Rt1,rfot1,fetchbuf1_pc);
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
iqentry_r1 [tail] <= Ra1;
|
iqentry_r1 [tail] <= Ra1;
|
iqentry_r2 [tail] <= Rb1;
|
iqentry_r2 [tail] <= Rb1;
|
iqentry_r3 [tail] <= Rc1;
|
iqentry_r3 [tail] <= Rc1;
|
iqentry_rt [tail] <= Rt1;
|
iqentry_rt [tail] <= Rt1;
|
`endif
|
`endif
|
// The source is set even though the arg might be automatically valid (less logic). If
|
// The source is set even though the arg might be automatically valid (less logic). If
|
// queueing two entries the source settings may be overridden in the argument valudation.
|
// queueing two entries the source settings may be overridden in the argument valudation.
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn1}];
|
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn1}];
|
iqentry_a1_s [tail] <= //unlink ? {1'b0, (tail-3'd1)&7} :
|
iqentry_a1_s [tail] <= //unlink ? {1'b0, (tail-3'd1)&7} :
|
rf_source[Ra1];
|
rf_source[Ra1];
|
iqentry_a2_s [tail] <= rf_source[Rb1];
|
iqentry_a2_s [tail] <= rf_source[Rb1];
|
iqentry_a3_s [tail] <= rf_source[Rc1];
|
iqentry_a3_s [tail] <= rf_source[Rc1];
|
iqentry_T_s [tail] <= rf_source[Rt1];
|
iqentry_T_s [tail] <= rf_source[Rt1];
|
if (validate_args)
|
if (validate_args)
|
validate_args11(tail);
|
validate_args11(tail);
|
end
|
end
|
tail0 <= tail0 + inc;
|
tail0 <= tail0 + inc;
|
tail1 <= tail1 + inc;
|
tail1 <= tail1 + inc;
|
tail2 <= tail2 + inc;
|
tail2 <= tail2 + inc;
|
end
|
end
|
endtask
|
endtask
|
|
|
// enque 1 on tail0 or tail1
|
// enque 1 on tail0 or tail1
|
task enque1;
|
task enque1;
|
input [2:0] tail;
|
input [2:0] tail;
|
input [2:0] inc;
|
input [2:0] inc;
|
input test_stomp;
|
input test_stomp;
|
input validate_args;
|
input validate_args;
|
begin
|
begin
|
if (`FALSE)
|
if (opcode1==`NOP) begin
|
;
|
if (queued1==`TRUE) queued2 = `TRUE;
|
// if (opcode1==`NOP) begin
|
queued1 = `TRUE;
|
// if (queued1==`TRUE) queued2 = `TRUE;
|
end
|
// queued1 = `TRUE;
|
|
// end
|
|
`ifdef DEBUG_LOGIC
|
`ifdef DEBUG_LOGIC
|
else
|
else
|
if (dbg_ctrl[7] && !StatusDBG) begin
|
if (dbg_ctrl[7] && !StatusDBG) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
enque1a(tail,3'd2,1,0);
|
enque1a(tail,3'd2,1,0);
|
set_exception((tail+1)&7,8'd243);
|
set_exception((tail+1)&7,8'd243);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
else if (fnIsPop(fetchbuf1_instr)|fnIsPush(fetchbuf1_instr)|opcode1==`LINK) begin
|
else if (fnIsPop(fetchbuf1_instr)|fnIsPush(fetchbuf1_instr)|opcode1==`LINK) begin
|
$display("1 found push/pop");
|
$display("1 found push/pop");
|
$display("iqv[%d]:%d", tail,iqentry_v[tail]);
|
$display("iqv[%d]:%d", tail,iqentry_v[tail]);
|
$display("iqv[%d+1]:%d", tail, iqentry_v[tail+1]);
|
$display("iqv[%d+1]:%d", tail, iqentry_v[tail+1]);
|
$display("valargs:%d", validate_args);
|
$display("valargs:%d", validate_args);
|
$display("qd1:%d", queued1);
|
$display("qd1:%d", queued1);
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV && validate_args && !queued1) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV && validate_args && !queued1) begin
|
$display("1 enq 2 ");
|
$display("1 enq 2 ");
|
enque1a(tail,3'd2,1,0);
|
enque1a(tail,3'd2,1,0);
|
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf1_instr),opcode1==`LINK,0,1);
|
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf1_instr),opcode1==`LINK,0,1);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`ifdef UNLINKOP
|
`ifdef UNLINKOP
|
else if (opcode1==`UNLINK) begin
|
else if (opcode1==`UNLINK) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
|
enquePushpopAdd(tail,1'b0,1'b0,1'b1,1);
|
enquePushpopAdd(tail,1'b0,1'b0,1'b1,1);
|
enque1a((tail+1)&7,3'd2,1,1);
|
enque1a((tail+1)&7,3'd2,1,1);
|
allowq = `FALSE;
|
allowq = `FALSE;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
`endif
|
`endif
|
else if (iqentry_v[tail] == `INV && !qstomp) begin
|
else if (iqentry_v[tail] == `INV && !qstomp) begin
|
if ((({fnIsBranch(opcode1), predict_taken1} == {`TRUE, `TRUE})||(opcode1==`LOOP)) && test_stomp)
|
if ((({fnIsBranch(opcode1), predict_taken1} == {`TRUE, `TRUE})||(opcode1==`LOOP)) && test_stomp)
|
qstomp = `TRUE;
|
qstomp = `TRUE;
|
enque1a(tail,inc,validate_args,0);
|
enque1a(tail,inc,validate_args,0);
|
if (queued1==`TRUE) queued2 = `TRUE;
|
if (queued1==`TRUE) queued2 = `TRUE;
|
else queued1 = `TRUE;
|
else queued1 = `TRUE;
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
task validate_args10;
|
task validate_args10;
|
input [2:0] tail;
|
input [2:0] tail;
|
begin
|
begin
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn0}] || cond0 < 4'h2;
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn0}] || cond0 < 4'h2;
|
iqentry_a1_v [tail] <= fnSource1_v( opcode0 ) | rf_v[ Ra0 ];
|
iqentry_a1_v [tail] <= fnSource1_v( opcode0 ) | rf_v[ Ra0 ];
|
iqentry_a2_v [tail] <= fnSource2_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[Rb0];
|
iqentry_a2_v [tail] <= fnSource2_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[Rb0];
|
iqentry_a3_v [tail] <= fnSource3_v( opcode0 ) | rf_v[ Rc0 ];
|
iqentry_a3_v [tail] <= fnSource3_v( opcode0 ) | rf_v[ Rc0 ];
|
iqentry_T_v [tail] <= fnSourceT_v( opcode0 ) | rf_v[ Rt0 ];
|
iqentry_T_v [tail] <= fnSourceT_v( opcode0 ) | rf_v[ Rt0 ];
|
if (fetchbuf0_rfw|fetchbuf0_pfw) begin
|
if (fetchbuf0_rfw|fetchbuf0_pfw) begin
|
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
|
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
|
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
|
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
|
$display("reg[%d] <= INV",Rt0);
|
$display("reg[%d] <= INV",Rt0);
|
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail }; // top bit indicates ALU/MEM bus
|
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail }; // top bit indicates ALU/MEM bus
|
$display("10:rf_src[%d] <= %d, insn=%h", Rt0, tail,fetchbuf0_instr);
|
$display("10:rf_src[%d] <= %d, insn=%h", Rt0, tail,fetchbuf0_instr);
|
invalidate_pregs(tail, Rt0, fetchbuf0_mem);
|
invalidate_pregs(tail, Rt0, fetchbuf0_mem);
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
task validate_args11;
|
task validate_args11;
|
input [2:0] tail;
|
input [2:0] tail;
|
begin
|
begin
|
// The predicate is automatically valid for condiitions 0 and 1 (always false or always true).
|
// The predicate is automatically valid for condiitions 0 and 1 (always false or always true).
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_a1_v [tail] <= fnSource1_v( opcode1 ) | rf_v[ Ra1 ];
|
iqentry_a1_v [tail] <= fnSource1_v( opcode1 ) | rf_v[ Ra1 ];
|
iqentry_a2_v [tail] <= fnSource2_v( opcode1, fnFunc(fetchbuf1_instr) ) | rf_v[ Rb1 ];
|
iqentry_a2_v [tail] <= fnSource2_v( opcode1, fnFunc(fetchbuf1_instr) ) | rf_v[ Rb1 ];
|
iqentry_a3_v [tail] <= fnSource3_v( opcode1 ) | rf_v[ Rc1 ];
|
iqentry_a3_v [tail] <= fnSource3_v( opcode1 ) | rf_v[ Rc1 ];
|
iqentry_T_v [tail] <= fnSourceT_v( opcode1 ) | rf_v[ Rt1 ];
|
iqentry_T_v [tail] <= fnSourceT_v( opcode1 ) | rf_v[ Rt1 ];
|
if (fetchbuf1_rfw|fetchbuf1_pfw) begin
|
if (fetchbuf1_rfw|fetchbuf1_pfw) begin
|
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
|
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
|
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
|
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
|
$display("reg[%d] <= INV",Rt1);
|
$display("reg[%d] <= INV",Rt1);
|
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail }; // top bit indicates ALU/MEM bus
|
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail }; // top bit indicates ALU/MEM bus
|
invalidate_pregs(tail, Rt1, fetchbuf1_mem);
|
invalidate_pregs(tail, Rt1, fetchbuf1_mem);
|
$display("11:rf_src[%d] <= %d, insn=%h", Rt1, tail,fetchbuf0_instr);
|
$display("11:rf_src[%d] <= %d, insn=%h", Rt1, tail,fetchbuf0_instr);
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
// If two entries were queued then validate the arguments for the second entry.
|
// If two entries were queued then validate the arguments for the second entry.
|
//
|
//
|
task validate_args;
|
task validate_args;
|
begin
|
begin
|
if (queued2) begin
|
if (queued2) begin
|
// SOURCE 1 ... this is relatively straightforward, because all instructions
|
// SOURCE 1 ... this is relatively straightforward, because all instructions
|
// that have a source (i.e. every instruction but LUI) read from RB
|
// that have a source (i.e. every instruction but LUI) read from RB
|
//
|
//
|
// if the argument is an immediate or not needed, we're done
|
// if the argument is an immediate or not needed, we're done
|
if (fnSource1_v( opcode1 ) == `VAL) begin
|
if (fnSource1_v( opcode1 ) == `VAL) begin
|
$display("fnSource1_v=1 iq[%d]", tail1);
|
$display("fnSource1_v=1 iq[%d]", tail1);
|
iqentry_a1_v [tail1] <= `VAL;
|
iqentry_a1_v [tail1] <= `VAL;
|
iqentry_a1_s [tail1] <= 4'hF;
|
iqentry_a1_s [tail1] <= 4'hF;
|
// iqentry_a1_s [tail1] <= 4'd0;
|
// iqentry_a1_s [tail1] <= 4'd0;
|
end
|
end
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
else if (!fetchbuf0_rfw) begin
|
else if (!fetchbuf0_rfw) begin
|
iqentry_a1_v [tail1] <= rf_v [Ra1];
|
iqentry_a1_v [tail1] <= rf_v [Ra1];
|
iqentry_a1_s [tail1] <= rf_source [Ra1];
|
iqentry_a1_s [tail1] <= rf_source [Ra1];
|
end
|
end
|
// otherwise, previous instruction does write to RF ... see if overlap
|
// otherwise, previous instruction does write to RF ... see if overlap
|
else if (Rt0 != 7'd0 && Ra1 == Rt0) begin
|
else if (Rt0 != 7'd0 && Ra1 == Rt0) begin
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
$display("invalidating iqentry_a1_v[%d]", tail1);
|
$display("invalidating iqentry_a1_v[%d]", tail1);
|
iqentry_a1_v [tail1] <= `INV;
|
iqentry_a1_v [tail1] <= `INV;
|
iqentry_a1_s [tail1] <= {fetchbuf0_mem, tail0};
|
iqentry_a1_s [tail1] <= {fetchbuf0_mem, tail0};
|
end
|
end
|
// if no overlap, get info from rf_v and rf_source
|
// if no overlap, get info from rf_v and rf_source
|
else begin
|
else begin
|
iqentry_a1_v [tail1] <= rf_v [Ra1];
|
iqentry_a1_v [tail1] <= rf_v [Ra1];
|
iqentry_a1_s [tail1] <= rf_source [Ra1];
|
iqentry_a1_s [tail1] <= rf_source [Ra1];
|
$display("2:iqentry_a1_s[%d] <= %d", tail1, rf_source [Ra1]);
|
$display("2:iqentry_a1_s[%d] <= %d", tail1, rf_source [Ra1]);
|
end
|
end
|
|
|
if (!fetchbuf0_pfw) begin
|
if (!fetchbuf0_pfw) begin
|
iqentry_p_v [tail1] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_p_v [tail1] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_p_s [tail1] <= rf_source [{1'b1,2'h0,Pn1}];
|
iqentry_p_s [tail1] <= rf_source [{1'b1,2'h0,Pn1}];
|
end
|
end
|
else if ((Rt0 != 7'd0 && (Pn1==Rt0[3:0] || Rt0==7'h70)) && ((Rt0 & 7'h70)==7'h40)||Rt0==7'h70) begin
|
else if ((Rt0 != 7'd0 && (Pn1==Rt0[3:0] || Rt0==7'h70)) && ((Rt0 & 7'h70)==7'h40)||Rt0==7'h70) begin
|
iqentry_p_v [tail1] <= cond1 < 4'h2;
|
iqentry_p_v [tail1] <= cond1 < 4'h2;
|
iqentry_p_s [tail1] <= {fetchbuf0_mem, tail0};
|
iqentry_p_s [tail1] <= {fetchbuf0_mem, tail0};
|
end
|
end
|
else begin
|
else begin
|
iqentry_p_v [tail1] <= rf_v[{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_p_v [tail1] <= rf_v[{1'b1,2'h0,Pn1}] || cond1 < 4'h2;
|
iqentry_p_s [tail1] <= rf_source[{1'b1,2'h0,Pn1}];
|
iqentry_p_s [tail1] <= rf_source[{1'b1,2'h0,Pn1}];
|
end
|
end
|
|
|
//
|
//
|
// SOURCE 2 ... this is more contorted than the logic for SOURCE 1 because
|
// SOURCE 2 ... this is more contorted than the logic for SOURCE 1 because
|
// some instructions (NAND and ADD) read from RC and others (SW, BEQ) read from RA
|
// some instructions (NAND and ADD) read from RC and others (SW, BEQ) read from RA
|
//
|
//
|
// if the argument is an immediate or not needed, we're done
|
// if the argument is an immediate or not needed, we're done
|
if (fnSource2_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin
|
if (fnSource2_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin
|
iqentry_a2_v [tail1] <= `VAL;
|
iqentry_a2_v [tail1] <= `VAL;
|
iqentry_a2_s [tail1] <= 4'hF;
|
iqentry_a2_s [tail1] <= 4'hF;
|
end
|
end
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
else if (!fetchbuf0_rfw) begin
|
else if (!fetchbuf0_rfw) begin
|
iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
|
iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
|
iqentry_a2_s [tail1] <= rf_source[Rb1];
|
iqentry_a2_s [tail1] <= rf_source[Rb1];
|
end
|
end
|
// otherwise, previous instruction does write to RF ... see if overlap
|
// otherwise, previous instruction does write to RF ... see if overlap
|
else if (Rt0 != 7'd0 && Rb1 == Rt0) begin
|
else if (Rt0 != 7'd0 && Rb1 == Rt0) begin
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
iqentry_a2_v [tail1] <= `INV;
|
iqentry_a2_v [tail1] <= `INV;
|
iqentry_a2_s [tail1] <= {fetchbuf0_mem,tail0};
|
iqentry_a2_s [tail1] <= {fetchbuf0_mem,tail0};
|
end
|
end
|
// if no overlap, get info from rf_v and rf_source
|
// if no overlap, get info from rf_v and rf_source
|
else begin
|
else begin
|
iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
|
iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
|
iqentry_a2_s [tail1] <= rf_source[Rb1];
|
iqentry_a2_s [tail1] <= rf_source[Rb1];
|
end
|
end
|
|
|
//
|
//
|
// SOURCE 3 ... this is relatively straightforward, because all instructions
|
// SOURCE 3 ... this is relatively straightforward, because all instructions
|
// that have a source (i.e. every instruction but LUI) read from RC
|
// that have a source (i.e. every instruction but LUI) read from RC
|
//
|
//
|
// if the argument is an immediate or not needed, we're done
|
// if the argument is an immediate or not needed, we're done
|
if (fnSource3_v( opcode1 ) == `VAL) begin
|
if (fnSource3_v( opcode1 ) == `VAL) begin
|
iqentry_a3_v [tail1] <= `VAL;
|
iqentry_a3_v [tail1] <= `VAL;
|
iqentry_a3_v [tail1] <= 4'hF;
|
iqentry_a3_v [tail1] <= 4'hF;
|
// iqentry_a1_s [tail1] <= 4'd0;
|
// iqentry_a1_s [tail1] <= 4'd0;
|
end
|
end
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
else if (!fetchbuf0_rfw) begin
|
else if (!fetchbuf0_rfw) begin
|
iqentry_a3_v [tail1] <= rf_v [Rc1];
|
iqentry_a3_v [tail1] <= rf_v [Rc1];
|
iqentry_a3_s [tail1] <= rf_source [Rc1];
|
iqentry_a3_s [tail1] <= rf_source [Rc1];
|
end
|
end
|
// otherwise, previous instruction does write to RF ... see if overlap
|
// otherwise, previous instruction does write to RF ... see if overlap
|
else if (Rt0 != 7'd0 && Rc1 == Rt0) begin
|
else if (Rt0 != 7'd0 && Rc1 == Rt0) begin
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
iqentry_a3_v [tail1] <= `INV;
|
iqentry_a3_v [tail1] <= `INV;
|
iqentry_a3_s [tail1] <= {fetchbuf0_mem,tail0};
|
iqentry_a3_s [tail1] <= {fetchbuf0_mem,tail0};
|
end
|
end
|
// if no overlap, get info from rf_v and rf_source
|
// if no overlap, get info from rf_v and rf_source
|
else begin
|
else begin
|
iqentry_a3_v [tail1] <= rf_v [Rc1];
|
iqentry_a3_v [tail1] <= rf_v [Rc1];
|
iqentry_a3_s [tail1] <= rf_source [Rc1];
|
iqentry_a3_s [tail1] <= rf_source [Rc1];
|
end
|
end
|
|
|
|
|
//
|
//
|
// Target 3 ... this is relatively straightforward, because all instructions
|
// Target 3 ... this is relatively straightforward, because all instructions
|
// that have a source (i.e. every instruction but LUI) read from RC
|
// that have a source (i.e. every instruction but LUI) read from RC
|
//
|
//
|
// if the argument is an immediate or not needed, we're done
|
// if the argument is an immediate or not needed, we're done
|
if (fnSourceT_v( opcode1 ) == `VAL) begin
|
if (fnSourceT_v( opcode1 ) == `VAL) begin
|
iqentry_T_v [tail1] <= `VAL;
|
iqentry_T_v [tail1] <= `VAL;
|
iqentry_T_v [tail1] <= 4'hF;
|
iqentry_T_v [tail1] <= 4'hF;
|
end
|
end
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source
|
else if (!fetchbuf0_rfw) begin
|
else if (!fetchbuf0_rfw) begin
|
iqentry_T_v [tail1] <= rf_v [Rt1];
|
iqentry_T_v [tail1] <= rf_v [Rt1];
|
iqentry_T_s [tail1] <= rf_source [Rt1];
|
iqentry_T_s [tail1] <= rf_source [Rt1];
|
end
|
end
|
// otherwise, previous instruction does write to RF ... see if overlap
|
// otherwise, previous instruction does write to RF ... see if overlap
|
else if (Rt0 != 7'd0 && Rt1 == Rt0) begin
|
else if (Rt0 != 7'd0 && Rt1 == Rt0) begin
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
// if the previous instruction is a LW, then grab result from memq, not the iq
|
iqentry_T_v [tail1] <= `INV;
|
iqentry_T_v [tail1] <= `INV;
|
iqentry_T_s [tail1] <= {fetchbuf0_mem,tail0};
|
iqentry_T_s [tail1] <= {fetchbuf0_mem,tail0};
|
end
|
end
|
// if no overlap, get info from rf_v and rf_source
|
// if no overlap, get info from rf_v and rf_source
|
else begin
|
else begin
|
iqentry_T_v [tail1] <= rf_v [Rt1];
|
iqentry_T_v [tail1] <= rf_v [Rt1];
|
iqentry_T_s [tail1] <= rf_source [Rt1];
|
iqentry_T_s [tail1] <= rf_source [Rt1];
|
end
|
end
|
end
|
end
|
if (queued1|queued2) begin
|
if (queued1|queued2) begin
|
if (fetchbuf0_rfw|fetchbuf0_pfw) begin
|
if (fetchbuf0_rfw|fetchbuf0_pfw) begin
|
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
|
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
|
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
|
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
|
$display("reg[%d] <= INV",Rt0);
|
$display("reg[%d] <= INV",Rt0);
|
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail0 }; // top bit indicates ALU/MEM bus
|
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail0 }; // top bit indicates ALU/MEM bus
|
$display("12:rf_src[%d] <= %d, insn=%h", Rt0, tail0,fetchbuf0_instr);
|
$display("12:rf_src[%d] <= %d, insn=%h", Rt0, tail0,fetchbuf0_instr);
|
invalidate_pregs(tail0, Rt0, fetchbuf0_mem);
|
invalidate_pregs(tail0, Rt0, fetchbuf0_mem);
|
end
|
end
|
end
|
end
|
if (queued2) begin
|
if (queued2) begin
|
if (fetchbuf1_rfw|fetchbuf1_pfw) begin
|
if (fetchbuf1_rfw|fetchbuf1_pfw) begin
|
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
|
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
|
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
|
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
|
$display("reg[%d] <= INV",Rt1);
|
$display("reg[%d] <= INV",Rt1);
|
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail1 }; // top bit indicates ALU/MEM bus
|
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail1 }; // top bit indicates ALU/MEM bus
|
invalidate_pregs(tail1, Rt1, fetchbuf1_mem);
|
invalidate_pregs(tail1, Rt1, fetchbuf1_mem);
|
end
|
end
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
task fetchAB;
|
task fetchAB;
|
begin
|
begin
|
fetchbufA_instr <= insn0;
|
fetchbufA_instr <= insn0;
|
fetchbufA_pc <= pc;
|
fetchbufA_pc <= pc;
|
fetchbufA_v <= ld_fetchbuf;
|
fetchbufA_v <= ld_fetchbuf;
|
fetchbufB_instr <= insn1;
|
fetchbufB_instr <= insn1;
|
fetchbufB_pc <= pc + fnInsnLength(insn);
|
fetchbufB_pc <= pc + fnInsnLength(insn);
|
fetchbufB_v <= ld_fetchbuf;
|
fetchbufB_v <= ld_fetchbuf;
|
end
|
end
|
endtask
|
endtask
|
|
|
task fetchCD;
|
task fetchCD;
|
begin
|
begin
|
fetchbufC_instr <= insn0;
|
fetchbufC_instr <= insn0;
|
fetchbufC_pc <= pc;
|
fetchbufC_pc <= pc;
|
fetchbufC_v <= ld_fetchbuf;
|
fetchbufC_v <= ld_fetchbuf;
|
fetchbufD_instr <= insn1;
|
fetchbufD_instr <= insn1;
|
fetchbufD_pc <= pc + fnInsnLength(insn);
|
fetchbufD_pc <= pc + fnInsnLength(insn);
|
fetchbufD_v <= ld_fetchbuf;
|
fetchbufD_v <= ld_fetchbuf;
|
end
|
end
|
endtask
|
endtask
|
|
|
// Reset the tail pointers.
|
// Reset the tail pointers.
|
// Used by the enqueue logic
|
// Used by the enqueue logic
|
//
|
//
|
task reset_tail_pointers;
|
task reset_tail_pointers;
|
input first;
|
input first;
|
begin
|
begin
|
if ((iqentry_stomp[0] & ~iqentry_stomp[7]) | first) begin
|
if ((iqentry_stomp[0] & ~iqentry_stomp[7]) | first) begin
|
tail0 <= 0;
|
tail0 <= 0;
|
tail1 <= 1;
|
tail1 <= 1;
|
end
|
end
|
else if (iqentry_stomp[1] & ~iqentry_stomp[0]) begin
|
else if (iqentry_stomp[1] & ~iqentry_stomp[0]) begin
|
tail0 <= 1;
|
tail0 <= 1;
|
tail1 <= 2;
|
tail1 <= 2;
|
end
|
end
|
else if (iqentry_stomp[2] & ~iqentry_stomp[1]) begin
|
else if (iqentry_stomp[2] & ~iqentry_stomp[1]) begin
|
tail0 <= 2;
|
tail0 <= 2;
|
tail1 <= 3;
|
tail1 <= 3;
|
end
|
end
|
else if (iqentry_stomp[3] & ~iqentry_stomp[2]) begin
|
else if (iqentry_stomp[3] & ~iqentry_stomp[2]) begin
|
tail0 <= 3;
|
tail0 <= 3;
|
tail1 <= 4;
|
tail1 <= 4;
|
end
|
end
|
else if (iqentry_stomp[4] & ~iqentry_stomp[3]) begin
|
else if (iqentry_stomp[4] & ~iqentry_stomp[3]) begin
|
tail0 <= 4;
|
tail0 <= 4;
|
tail1 <= 5;
|
tail1 <= 5;
|
end
|
end
|
else if (iqentry_stomp[5] & ~iqentry_stomp[4]) begin
|
else if (iqentry_stomp[5] & ~iqentry_stomp[4]) begin
|
tail0 <= 5;
|
tail0 <= 5;
|
tail1 <= 6;
|
tail1 <= 6;
|
end
|
end
|
else if (iqentry_stomp[6] & ~iqentry_stomp[5]) begin
|
else if (iqentry_stomp[6] & ~iqentry_stomp[5]) begin
|
tail0 <= 6;
|
tail0 <= 6;
|
tail1 <= 7;
|
tail1 <= 7;
|
end
|
end
|
else if (iqentry_stomp[7] & ~iqentry_stomp[6]) begin
|
else if (iqentry_stomp[7] & ~iqentry_stomp[6]) begin
|
tail0 <= 7;
|
tail0 <= 7;
|
tail1 <= 0;
|
tail1 <= 0;
|
end
|
end
|
// otherwise, it is the last instruction in the queue that has been mispredicted ... do nothing
|
// otherwise, it is the last instruction in the queue that has been mispredicted ... do nothing
|
end
|
end
|
endtask
|
endtask
|
|
|
// Increment the head pointers
|
// Increment the head pointers
|
// Also increments the instruction counter
|
// Also increments the instruction counter
|
// Used when instructions are committed.
|
// Used when instructions are committed.
|
// Also clear any outstanding state bits that foul things up.
|
// Also clear any outstanding state bits that foul things up.
|
//
|
//
|
task head_inc;
|
task head_inc;
|
input [2:0] amt;
|
input [2:0] amt;
|
begin
|
begin
|
head0 <= head0 + amt;
|
head0 <= head0 + amt;
|
head1 <= head1 + amt;
|
head1 <= head1 + amt;
|
head2 <= head2 + amt;
|
head2 <= head2 + amt;
|
head3 <= head3 + amt;
|
head3 <= head3 + amt;
|
head4 <= head4 + amt;
|
head4 <= head4 + amt;
|
head5 <= head5 + amt;
|
head5 <= head5 + amt;
|
head6 <= head6 + amt;
|
head6 <= head6 + amt;
|
head7 <= head7 + amt;
|
head7 <= head7 + amt;
|
I <= I + amt;
|
I <= I + amt;
|
if (amt==3'd3) begin
|
if (amt==3'd3) begin
|
iqentry_agen[head0] <= `INV;
|
iqentry_agen[head0] <= `INV;
|
iqentry_agen[head1] <= `INV;
|
iqentry_agen[head1] <= `INV;
|
iqentry_agen[head2] <= `INV;
|
iqentry_agen[head2] <= `INV;
|
end else if (amt==3'd2) begin
|
end else if (amt==3'd2) begin
|
iqentry_agen[head0] <= `INV;
|
iqentry_agen[head0] <= `INV;
|
iqentry_agen[head1] <= `INV;
|
iqentry_agen[head1] <= `INV;
|
end else if (amt==3'd1)
|
end else if (amt==3'd1)
|
iqentry_agen[head0] <= `INV;
|
iqentry_agen[head0] <= `INV;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// set_exception:
|
// set_exception:
|
// Used to requeue the instruction as an exception if an exception occurs.
|
// Used to requeue the instruction as an exception if an exception occurs.
|
|
|
task set_exception;
|
task set_exception;
|
input [2:0] id; // instruction queue id
|
input [2:0] id; // instruction queue id
|
input [7:0] exc; // exception number
|
input [7:0] exc; // exception number
|
begin
|
begin
|
iqentry_op [id[2:0] ] <= `INT;
|
iqentry_op [id[2:0] ] <= `INT;
|
iqentry_cond [id[2:0]] <= 4'd1; // always execute
|
iqentry_cond [id[2:0]] <= 4'd1; // always execute
|
iqentry_mem[id[2:0]] <= `FALSE;
|
iqentry_mem[id[2:0]] <= `FALSE;
|
iqentry_rfw[id[2:0]] <= `TRUE; // writes to IPC
|
iqentry_rfw[id[2:0]] <= `TRUE; // writes to IPC
|
iqentry_a0 [id[2:0]] <= exc;
|
iqentry_a0 [id[2:0]] <= exc;
|
iqentry_p_v [id[2:0]] <= `TRUE;
|
iqentry_p_v [id[2:0]] <= `TRUE;
|
iqentry_a1 [id[2:0]] <= cregs[4'hC]; // *** assumes BR12 is static
|
iqentry_a1 [id[2:0]] <= cregs[4'hC]; // *** assumes BR12 is static
|
iqentry_a1_v [id[2:0]] <= `TRUE; // Flag arguments as valid
|
iqentry_a1_v [id[2:0]] <= `TRUE; // Flag arguments as valid
|
iqentry_a2_v [id[2:0]] <= `TRUE;
|
iqentry_a2_v [id[2:0]] <= `TRUE;
|
iqentry_a3_v [id[2:0]] <= `TRUE;
|
iqentry_a3_v [id[2:0]] <= `TRUE;
|
iqentry_T_v [id[2:0]] <= `TRUE;
|
iqentry_T_v [id[2:0]] <= `TRUE;
|
iqentry_out [id[2:0]] <= `FALSE;
|
iqentry_out [id[2:0]] <= `FALSE;
|
iqentry_agen [id[2:0]] <= `FALSE;
|
iqentry_agen [id[2:0]] <= `FALSE;
|
iqentry_tgt[id[2:0]] <= {1'b1,2'h1,(exc==8'd243)?4'hB:4'hD}; // Target EPC
|
iqentry_tgt[id[2:0]] <= {1'b1,2'h1,(exc==8'd243)?4'hB:4'hD}; // Target EPC
|
exception_set = `TRUE;
|
exception_set = `TRUE;
|
end
|
end
|
endtask
|
endtask
|
|
|
// The core should really invalidate all the predicate registers when the
|
// The core should really invalidate all the predicate registers when the
|
// sideways slice of all the pregs is manipulated. But then the problem is
|
// sideways slice of all the pregs is manipulated. But then the problem is
|
// reading the result register into all the predicate registers at once.
|
// reading the result register into all the predicate registers at once.
|
// The source for each register would be a bit field of the result register
|
// The source for each register would be a bit field of the result register
|
// and the core does not support this sort of thing.
|
// and the core does not support this sort of thing.
|
// So. After manipulating the sideways slice of predicate registers the
|
// So. After manipulating the sideways slice of predicate registers the
|
// instruction should be followed with a SYNC instruction to ensure that
|
// instruction should be followed with a SYNC instruction to ensure that
|
// the results are picked up.
|
// the results are picked up.
|
// To be fixed one day.
|
// To be fixed one day.
|
task invalidate_pregs;
|
task invalidate_pregs;
|
input [2:0] tail;
|
input [2:0] tail;
|
input [6:0] Rt;
|
input [6:0] Rt;
|
input mem;
|
input mem;
|
begin
|
begin
|
if (Rt==7'h70) begin
|
if (Rt==7'h70) begin
|
rf_v[7'h40] <= `INV;
|
rf_v[7'h40] <= `INV;
|
rf_v[7'h41] <= `INV;
|
rf_v[7'h41] <= `INV;
|
rf_v[7'h42] <= `INV;
|
rf_v[7'h42] <= `INV;
|
rf_v[7'h43] <= `INV;
|
rf_v[7'h43] <= `INV;
|
rf_v[7'h44] <= `INV;
|
rf_v[7'h44] <= `INV;
|
rf_v[7'h45] <= `INV;
|
rf_v[7'h45] <= `INV;
|
rf_v[7'h46] <= `INV;
|
rf_v[7'h46] <= `INV;
|
rf_v[7'h47] <= `INV;
|
rf_v[7'h47] <= `INV;
|
rf_v[7'h48] <= `INV;
|
rf_v[7'h48] <= `INV;
|
rf_v[7'h49] <= `INV;
|
rf_v[7'h49] <= `INV;
|
rf_v[7'h4A] <= `INV;
|
rf_v[7'h4A] <= `INV;
|
rf_v[7'h4B] <= `INV;
|
rf_v[7'h4B] <= `INV;
|
rf_v[7'h4C] <= `INV;
|
rf_v[7'h4C] <= `INV;
|
rf_v[7'h4D] <= `INV;
|
rf_v[7'h4D] <= `INV;
|
rf_v[7'h4E] <= `INV;
|
rf_v[7'h4E] <= `INV;
|
rf_v[7'h4F] <= `INV;
|
rf_v[7'h4F] <= `INV;
|
rf_source[7'h40] <= { mem, tail };
|
rf_source[7'h40] <= { mem, tail };
|
rf_source[7'h41] <= { mem, tail };
|
rf_source[7'h41] <= { mem, tail };
|
rf_source[7'h42] <= { mem, tail };
|
rf_source[7'h42] <= { mem, tail };
|
rf_source[7'h43] <= { mem, tail };
|
rf_source[7'h43] <= { mem, tail };
|
rf_source[7'h44] <= { mem, tail };
|
rf_source[7'h44] <= { mem, tail };
|
rf_source[7'h45] <= { mem, tail };
|
rf_source[7'h45] <= { mem, tail };
|
rf_source[7'h46] <= { mem, tail };
|
rf_source[7'h46] <= { mem, tail };
|
rf_source[7'h47] <= { mem, tail };
|
rf_source[7'h47] <= { mem, tail };
|
rf_source[7'h48] <= { mem, tail };
|
rf_source[7'h48] <= { mem, tail };
|
rf_source[7'h49] <= { mem, tail };
|
rf_source[7'h49] <= { mem, tail };
|
rf_source[7'h4A] <= { mem, tail };
|
rf_source[7'h4A] <= { mem, tail };
|
rf_source[7'h4B] <= { mem, tail };
|
rf_source[7'h4B] <= { mem, tail };
|
rf_source[7'h4C] <= { mem, tail };
|
rf_source[7'h4C] <= { mem, tail };
|
rf_source[7'h4D] <= { mem, tail };
|
rf_source[7'h4D] <= { mem, tail };
|
rf_source[7'h4E] <= { mem, tail };
|
rf_source[7'h4E] <= { mem, tail };
|
rf_source[7'h4F] <= { mem, tail };
|
rf_source[7'h4F] <= { mem, tail };
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
endmodule
|
endmodule
|
|
|