OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [rtl/] [verilog/] [Thor.v] - Rev 37

Go to most recent revision | Compare with Previous | Blame | View Log

//
//	COPYRIGHT 2000 by Bruce L. Jacob
//	(contact info: http://www.ece.umd.edu/~blj/)
//
//	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;
//	  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 
//	     notice or following comments (i.e. the first 3-4 dozen lines of this file).
//
//	RiSC-16
//
//	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
//	of the Little Computer (LC-896) developed by Peter Chen at the University of Michigan.
//	The primary differences include the following:
//	  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
//	     now simply special instances of other instructions: NOP is a do-nothing ADD, and
//	     HALT is a subset of JALR.
//
//	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
//	undergraduates who do not yet know how computers work.  This implementation was targetted
//	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,
//	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 
//	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
//	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
//	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
//	output ... also, you will see statements like
//
//	    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.
//
//	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:
//
//	    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
//	for more/different/modified documents.  Same goes for bug fixes.
//
//
//	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
//	  will get confused.  This can be fixed by having a separate did_branchback status register
//	  for each of the fetch buffers.
//
// ============================================================================
//        __
//   \\__/ o\    (C) 2013-2016  Robert Finch, Stratford
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
// 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 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
//                                                                          
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//
//
// Thor Superscaler
//
// 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
// (FPGA) as opposed to just simulation. To the RiSC-16 are added:
//
//	64/32 bit datapath rather than 16 bit
//   64 general purpose registers
//   16 code address registers
//   16 predicate registers / predicated instruction execution
//    8 segment registers
//      A branch history table, and a (2,2) correlating branch predictor added
//      variable length instruction encodings (code density)
//      support for interrupts
//      The instruction set is changed completely with many new instructions.
//      An instruction and data cache were added.
//      A WISHBONE bus interface was added,
//
// 53,950 (86,500 LC's)
// with segmentation
// no bitfield, stack or FP ops
//
// ============================================================================
//
`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,
    cyc_o, stb_o, ack_i, err_i, we_o, sel_o, adr_o, dat_i, dat_o);
parameter DBW = 32;         // databus width
parameter ABW = 32;         // address bus width
parameter RSTCSEG = 52'h0;
parameter RSTPC = 64'hFFFFFFFFFFFC0000;
parameter STARTUP_POWER = 16'hFFFF;
parameter IMCD = 6'h30;
localparam AMSB = ABW-1;
parameter QENTRIES = 8;
parameter ALU1BIG = 0;
parameter RESET1 = 4'd0;
parameter RESET2 = 4'd1;
parameter IDLE = 4'd2;
parameter ICACHE1 = 4'd3;
parameter DCACHE1 = 4'd4;
parameter IBUF1 = 4'd5;
parameter IBUF2 = 4'd6;
parameter IBUF3 = 4'd7;
parameter IBUF4 = 4'd8;
parameter IBUF5 = 4'd9;
parameter NREGS = 127;
parameter PF = 4'd0;
parameter PT = 4'd1;
parameter PEQ = 4'd2;
parameter PNE = 4'd3;
parameter PLE = 4'd4;
parameter PGT = 4'd5;
parameter PGE = 4'd6;
parameter PLT = 4'd7;
parameter PLEU = 4'd8;
parameter PGTU = 4'd9;
parameter PGEU = 4'd10;
parameter PLTU = 4'd11;
input [63:0] corenum;
input rst_i;
input clk_i;
output clk_o;
output km;
input nmi_i;
input irq_i;
input [7:0] vec_i;
output reg [1:0] bte_o;
output reg [2:0] cti_o;
output reg [4:0] bl_o;
output reg lock_o;
output reg resv_o;
input resv_i;
output reg cres_o;
output reg cyc_o;
output reg stb_o;
input ack_i;
input err_i;
output reg we_o;
output reg [DBW/8-1:0] sel_o;
output reg [ABW-1:0] adr_o;
input [DBW-1:0] dat_i;
output reg [DBW-1:0] dat_o;
 
integer n,i;
reg [1:0] mode;
reg [DBW/8-1:0] rsel;
reg [3:0] cstate;
reg [ABW:0] pc;				     // program counter (virtual)
wire [ABW-1:0] ppc;				// physical pc address
reg [ABW-1:0] interrupt_pc;     // working register for interrupt pc
reg [DBW-1:0] vadr;				// data virtual address
reg [3:0] panic;		// indexes the message structure
reg [128:0] message [0:15];	// indexed by panic
reg [DBW-1:0] cregs [0:15];		// code address registers
reg [ 3:0] pregs [0:15];		// predicate registers
`ifdef SEGMENTATION
reg [DBW-1:12] sregs [0:7];	// segment registers
reg [DBW-1:12] sregs_lmt [0:7];
`endif
reg [2:0] rrmapno;				// register rename map number
wire ITLBMiss;
wire DTLBMiss;
wire uncached;
wire [DBW-1:0] cdat;
reg pwe;
wire [DBW-1:0] pea;
reg [DBW-1:0] tick;
reg [DBW-1:0] lc;				// loop counter
reg [DBW-1:0] rfoa0,rfoa1;
reg [DBW-1:0] rfob0,rfob1;
reg [DBW-1:0] rfoc0,rfoc1;
reg [DBW-1:0] rfot0,rfot1;
reg ic_invalidate,dc_invalidate;
reg ic_invalidate_line,dc_invalidate_line;
reg [ABW-1:0] ic_lineno,dc_lineno;
reg ierr,derr;					// err_i during icache load
wire insnerr;					// err_i during icache load
wire [127:0] insn;
wire iuncached;
reg [NREGS:0] rf_v;
//reg [15:0] pf_v;
reg im,imb;
reg [5:0] imcd;
reg fxe;
reg nmi1,nmi_edge;
reg StatusHWI;
reg StatusDBG;
reg [7:0] StatusEXL;
assign km = StatusHWI | |StatusEXL;
reg [7:0] GM;		// register group mask
reg [7:0] GMB;
wire [63:0] sr = {32'd0,imb,7'b0,GMB,im,1'b0,km,fxe,4'b0,GM};
wire int_commit;
wire int_pending;
wire sys_commit;
wire dbg_commit;
`ifdef SEGMENTATION
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];
`else
wire [DBW-1:0] spc = pc;
`endif
wire [DBW-1:0] ppcp16 = ppc + 64'd16;
reg [DBW-1:0] string_pc;
reg stmv_flag;
reg [7:0] asid;
 
wire clk;
 
// Operand registers
wire take_branch;
wire take_branch0;
wire take_branch1;
 
reg [3:0] rf_source [0:NREGS];
//reg [3:0] pf_source [15:0];
 
// instruction queue (ROB)
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_done	[0:7];	// instruction result valid
reg [7:0]  iqentry_cmt;  		// commit result to machine state
reg        iqentry_bt  	[0:7];	// branch-taken (used only for branches)
reg        iqentry_br   [0:7];  // branch instruction decode
reg        iqentry_agen [0:7];  // memory address is generated
reg        iqentry_mem	[0:7];	// touches memory: 1 if LW/SW
reg        iqentry_ndx  [0:7];  // TRUE if indexed memory op
reg        iqentry_cas  [0:7];
reg        iqentry_pushpop [0:7];
reg        iqentry_pea  [0:7];
reg        iqentry_cmpmv [0:7];
reg        iqentry_lla  [0:7];  // load linear address
reg        iqentry_tlb  [0:7];
reg        iqentry_jmp	[0:7];	// changes control flow: 1 if BEQ/JALR
reg        iqentry_jmpi [0:7];
reg        iqentry_sync [0:7];  // sync instruction
reg        iqentry_memsb[0:7];
reg        iqentry_memdb[0:7];
reg        iqentry_fp   [0:7];  // is an floating point operation
reg        iqentry_rfw	[0:7];	// writes to register file
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_cond [0:7];	// predicating condition
reg  [3:0] iqentry_preg [0:7];  // predicate regno
reg  [3:0] iqentry_pred [0:7];	// predicate value
reg        iqentry_p_v  [0:7];	// predicate is valid
reg  [3:0] iqentry_p_s  [0:7];	// predicate source
reg  [7:0] iqentry_op	[0:7];	// instruction opcode
reg  [5:0] iqentry_fn   [0:7];  // instruction function
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 [DBW-1:0] iqentry_a0	[0:7];	// argument 0 (immediate)
reg [DBW-1:0] iqentry_a1	[0:7];	// argument 1
reg [6:0]  iqentry_r1   [0:7];
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 [6:0]  iqentry_r2   [0:7];
reg [DBW-1:0] iqentry_a2	[0:7];	// argument 2
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 [6:0]  iqentry_r3   [0:7];
reg [DBW-1:0] iqentry_a3	[0:7];	// argument 3
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 [6:0]  iqentry_rt   [0:7];
reg [DBW-1:0] iqentry_T [0:7];
reg        iqentry_T_v [0:7];
reg  [3:0] iqentry_T_s [0:7];
reg [DBW-1:0] iqentry_pc	[0:7];	// program counter for this instruction
 
reg  [7:0] iqentry_source;
wire  iqentry_imm [0:7];
wire  iqentry_memready [0:7];
wire  iqentry_memopsvalid [0:7];
reg qstomp;
 
wire stomp_all;
reg  [7:0] iqentry_fpissue;
reg  [7:0] iqentry_memissue;
wire iqentry_memissue_head0;
wire iqentry_memissue_head1;
wire iqentry_memissue_head2;
wire iqentry_memissue_head3;
wire iqentry_memissue_head4;
wire iqentry_memissue_head5;
wire iqentry_memissue_head6;
wire iqentry_memissue_head7;
wire  [7:0] iqentry_stomp;
reg  [7:0] iqentry_issue;
wire  [1:0] iqentry_0_islot;
wire  [1:0] iqentry_1_islot;
wire  [1:0] iqentry_2_islot;
wire  [1:0] iqentry_3_islot;
wire  [1:0] iqentry_4_islot;
wire  [1:0] iqentry_5_islot;
wire  [1:0] iqentry_6_islot;
wire  [1:0] iqentry_7_islot;
reg  [1:0] iqentry_islot[0:7];
reg [1:0] iqentry_fpislot[0:7];
 
reg queued1,queued2;
reg queued3;    // for three-way config
reg allowq;
 
wire  [NREGS:1] livetarget;
wire  [NREGS:1] iqentry_0_livetarget;
wire  [NREGS:1] iqentry_1_livetarget;
wire  [NREGS:1] iqentry_2_livetarget;
wire  [NREGS:1] iqentry_3_livetarget;
wire  [NREGS:1] iqentry_4_livetarget;
wire  [NREGS:1] iqentry_5_livetarget;
wire  [NREGS:1] iqentry_6_livetarget;
wire  [NREGS:1] iqentry_7_livetarget;
wire  [NREGS:1] iqentry_0_latestID;
wire  [NREGS:1] iqentry_1_latestID;
wire  [NREGS:1] iqentry_2_latestID;
wire  [NREGS:1] iqentry_3_latestID;
wire  [NREGS:1] iqentry_4_latestID;
wire  [NREGS:1] iqentry_5_latestID;
wire  [NREGS:1] iqentry_6_latestID;
wire  [NREGS:1] iqentry_7_latestID;
wire  [NREGS:1] iqentry_0_cumulative;
wire  [NREGS:1] iqentry_1_cumulative;
wire  [NREGS:1] iqentry_2_cumulative;
wire  [NREGS:1] iqentry_3_cumulative;
wire  [NREGS:1] iqentry_4_cumulative;
wire  [NREGS:1] iqentry_5_cumulative;
wire  [NREGS:1] iqentry_6_cumulative;
wire  [NREGS:1] iqentry_7_cumulative;
 
 
reg  [2:0] tail0;
reg  [2:0] tail1;
reg  [2:0] tail2;   // used only for three-way config
reg  [2:0] head0;
reg  [2:0] head1;
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] head4;	// 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] head7;	// used only to determine memory-access ordering
reg  [2:0] headinc;
 
wire  [2:0] missid;
reg   fetchbuf;		// determines which pair to read from & write to
 
reg  [63:0] fetchbuf0_instr;
reg  [DBW-1:0] fetchbuf0_pc;
reg         fetchbuf0_v;
wire        fetchbuf0_mem;
wire        fetchbuf0_jmp;
wire 		fetchbuf0_fp;
wire        fetchbuf0_rfw;
wire        fetchbuf0_pfw;
reg  [63:0] fetchbuf1_instr;
reg  [DBW-1:0] fetchbuf1_pc;
reg        fetchbuf1_v;
wire        fetchbuf1_mem;
wire        fetchbuf1_jmp;
wire 		fetchbuf1_fp;
wire        fetchbuf1_rfw;
wire        fetchbuf1_pfw;
wire        fetchbuf1_bfw;
reg  [63:0] fetchbuf2_instr;
reg  [DBW-1:0] fetchbuf2_pc;
reg        fetchbuf2_v;
wire        fetchbuf2_mem;
wire        fetchbuf2_jmp;
wire 		fetchbuf2_fp;
wire        fetchbuf2_rfw;
wire        fetchbuf2_pfw;
wire        fetchbuf2_bfw;
 
reg [63:0] fetchbufA_instr;	
reg [DBW-1:0] fetchbufA_pc;
reg        fetchbufA_v;
reg [63:0] fetchbufB_instr;
reg [DBW-1:0] fetchbufB_pc;
reg        fetchbufB_v;
reg [63:0] fetchbufC_instr;
reg [DBW-1:0] fetchbufC_pc;
reg        fetchbufC_v;
reg [63:0] fetchbufD_instr;
reg [DBW-1:0] fetchbufD_pc;
reg        fetchbufD_v;
 
reg        did_branchback;
reg 		did_branchback0;
reg			did_branchback1;
 
reg        alu0_ld;
reg        alu0_available;
reg        alu0_dataready;
reg  [3:0] alu0_sourceid;
reg  [3:0] alu0_insnsz;
reg  [7:0] alu0_op;
reg  [5:0] alu0_fn;
reg  [3:0] alu0_cond;
reg        alu0_bt;
reg        alu0_cmt;
reg [DBW-1:0] alu0_argA;
reg [DBW-1:0] alu0_argB;
reg [DBW-1:0] alu0_argC;
reg [DBW-1:0] alu0_argT;
reg [DBW-1:0] alu0_argI;
reg  [3:0] alu0_pred;
reg [DBW-1:0] alu0_pc;
reg [DBW-1:0] alu0_bus;
reg  [3:0] alu0_id;
wire  [3:0] alu0_exc;
reg        alu0_v;
wire        alu0_branchmiss;
reg [ABW:0] alu0_misspc;
 
reg        alu1_ld;
reg        alu1_available;
reg        alu1_dataready;
reg  [3:0] alu1_sourceid;
reg  [3:0] alu1_insnsz;
reg  [7:0] alu1_op;
reg  [5:0] alu1_fn;
reg  [3:0] alu1_cond;
reg        alu1_bt;
reg        alu1_cmt;
reg [DBW-1:0] alu1_argA;
reg [DBW-1:0] alu1_argB;
reg [DBW-1:0] alu1_argC;
reg [DBW-1:0] alu1_argT;
reg [DBW-1:0] alu1_argI;
reg  [3:0] alu1_pred;
reg [DBW-1:0] alu1_pc;
reg [DBW-1:0] alu1_bus;
reg  [3:0] alu1_id;
wire  [3:0] alu1_exc;
reg        alu1_v;
wire        alu1_branchmiss;
reg [ABW:0] alu1_misspc;
 
wire jmpi_miss;
reg [ABW-1:0] jmpi_misspc;
wire mem_stringmissx;
reg mem_stringmiss;
wire        branchmiss;
wire [ABW:0] misspc;
 
`ifdef FLOATING_POINT
reg        fp0_ld;
reg        fp0_available;
reg        fp0_dataready;
reg  [3:0] fp0_sourceid;
reg  [7:0] fp0_op;
reg  [5:0] fp0_fn;
reg  [3:0] fp0_cond;
wire        fp0_cmt;
reg 		fp0_done;
reg [DBW-1:0] fp0_argA;
reg [DBW-1:0] fp0_argB;
reg [DBW-1:0] fp0_argC;
reg [DBW-1:0] fp0_argI;
reg  [3:0] fp0_pred;
reg [DBW-1:0] fp0_pc;
wire [DBW-1:0] fp0_bus;
wire  [3:0] fp0_id;
wire  [7:0] fp0_exc;
wire        fp0_v;
`endif
 
wire        dram_avail;
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] dram2;	// state of the DRAM request (latency = 4; can have three in pipeline)
reg  [2:0] tlb_state;
reg [3:0] tlb_id;
reg [3:0] tlb_op;
reg [3:0] tlb_regno;
reg [8:0] tlb_tgt;
reg [DBW-1:0] tlb_data;
 
wire [DBW-1:0] tlb_dato;
reg dram0_owns_bus;
reg [DBW-1:0] dram0_data;
reg [DBW-1:0] dram0_datacmp;
reg [DBW-1:0] dram0_addr;
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  [7:0] dram0_op;
reg  [5:0] dram0_fn;
reg  [8:0] dram0_tgt;
reg  [3:0] dram0_id;
reg  [3:0] dram0_exc;
reg [ABW-1:0] dram0_misspc;
reg dram1_owns_bus;
reg [DBW-1:0] dram1_data;
reg [DBW-1:0] dram1_datacmp;
reg [DBW-1:0] dram1_addr;
reg  [7:0] dram1_op;
reg  [5:0] dram1_fn;
reg  [6:0] dram1_tgt;
reg  [3:0] dram1_id;
reg  [3:0] dram1_exc;
reg [DBW-1:0] dram2_data;
reg [DBW-1:0] dram2_datacmp;
reg [DBW-1:0] dram2_addr;
reg  [7:0] dram2_op;
reg  [5:0] dram2_fn;
reg  [6:0] dram2_tgt;
reg  [3:0] dram2_id;
reg  [3:0] dram2_exc;
 
reg [DBW-1:0] dram_bus;
reg  [6:0] dram_tgt;
reg  [3:0] dram_id;
reg  [3:0] dram_exc;
reg        dram_v;
 
reg [DBW-1:0] index;
reg [DBW-1:0] src_addr,dst_addr;
wire mem_issue;
 
wire        outstanding_stores;
reg [DBW-1:0] I;	// instruction count
 
wire        commit0_v;
wire  [3:0] commit0_id;
wire  [6:0] commit0_tgt;
wire [DBW-1:0] commit0_bus;
wire        commit1_v;
wire  [3:0] commit1_id;
wire  [6:0] commit1_tgt;
wire [DBW-1:0] commit1_bus;
wire limit_cmt;
wire committing2;
 
wire [63:0] alu0_divq;
wire [63:0] alu0_rem;
wire alu0_div_done;
 
wire [63:0] alu1_divq;
wire [63:0] alu1_rem;
wire alu1_div_done;
 
wire [127:0] alu0_prod;
wire alu0_mult_done;
wire [127:0] alu1_prod;
wire alu1_mult_done;
 
reg exception_set;
 
//-----------------------------------------------------------------------------
// Debug
//-----------------------------------------------------------------------------
 
wire [DBW-1:0] dbg_stat1x;
reg [DBW-1:0] dbg_stat;
reg [DBW-1:0] dbg_ctrl;
reg [ABW-1:0] dbg_adr0;
reg [ABW-1:0] dbg_adr1;
reg [ABW-1:0] dbg_adr2;
reg [ABW-1:0] dbg_adr3;
reg dbg_imatchA0,dbg_imatchA1,dbg_imatchA2,dbg_imatchA3,dbg_imatchA;
reg dbg_imatchB0,dbg_imatchB1,dbg_imatchB2,dbg_imatchB3,dbg_imatchB;
 
wire dbg_lmatch0 =
			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'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'b11)
				 ;
wire dbg_lmatch1 =
             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'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'b11)
                  ;
wire dbg_lmatch2 =
               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'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'b11)
                    ;
wire dbg_lmatch3 =
                 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'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'b11)
                      ;
wire dbg_lmatch = dbg_lmatch0|dbg_lmatch1|dbg_lmatch2|dbg_lmatch3;
 
wire dbg_smatch0 =
			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'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'b11)
				 ;
wire dbg_smatch1 =
             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'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'b11)
                  ;
wire dbg_smatch2 =
               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'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'b11)
                    ;
wire dbg_smatch3 =
                 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'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'b11)
                      ;
wire dbg_smatch = dbg_smatch0|dbg_smatch1|dbg_smatch2|dbg_smatch3;
 
wire dbg_stat0 = dbg_imatchA0 | dbg_imatchB0 | dbg_lmatch0 | dbg_smatch0;
wire dbg_stat1 = dbg_imatchA1 | dbg_imatchB1 | dbg_lmatch1 | dbg_smatch1;
wire dbg_stat2 = dbg_imatchA2 | dbg_imatchB2 | dbg_lmatch2 | dbg_smatch2;
wire dbg_stat3 = dbg_imatchA3 | dbg_imatchB3 | dbg_lmatch3 | dbg_smatch3;
assign dbg_stat1x = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0};
wire debug_on = |dbg_ctrl[3:0]|dbg_ctrl[7];
 
reg [11:0] spr_bir;
 
always @(StatusHWI or StatusDBG or StatusEXL)
if (StatusHWI)
    mode = 2'd1;
else if (StatusDBG)
    mode = 2'd3;
else if (StatusEXL)
    mode = 2'd2;
else
    mode = 2'd0;
 
//
// BRANCH-MISS LOGIC: livetarget
//
// 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
// 
/*
Thor_livetarget #(NREGS) ultgt1 
(
	iqentry_v,
	iqentry_stomp,
	iqentry_cmt,
	iqentry_tgt[0],
	iqentry_tgt[1],
	iqentry_tgt[2],
	iqentry_tgt[3],
	iqentry_tgt[4],
	iqentry_tgt[5],
	iqentry_tgt[6],
	iqentry_tgt[7],
	livetarget,
	iqentry_0_livetarget,
	iqentry_1_livetarget,
	iqentry_2_livetarget,
	iqentry_3_livetarget,
	iqentry_4_livetarget,
	iqentry_5_livetarget,
	iqentry_6_livetarget,
	iqentry_7_livetarget
);
 
//
// BRANCH-MISS LOGIC: latestID
//
// 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.
// 
 
assign iqentry_0_latestID = ((missid == 3'd0)|| ((iqentry_0_livetarget & iqentry_1_cumulative) == {NREGS{1'b0}}))
				? iqentry_0_livetarget
				: {NREGS{1'b0}};
assign iqentry_0_cumulative = (missid == 3'd0)
				? iqentry_0_livetarget
				: iqentry_0_livetarget | iqentry_1_cumulative;
 
assign iqentry_1_latestID = ((missid == 3'd1)|| ((iqentry_1_livetarget & iqentry_2_cumulative) == {NREGS{1'b0}}))
				? iqentry_1_livetarget
				: {NREGS{1'b0}};
assign iqentry_1_cumulative = (missid == 3'd1)
				? iqentry_1_livetarget
				: iqentry_1_livetarget | iqentry_2_cumulative;
 
assign iqentry_2_latestID = ((missid == 3'd2) || ((iqentry_2_livetarget & iqentry_3_cumulative) == {NREGS{1'b0}}))
				? iqentry_2_livetarget
				: {NREGS{1'b0}};
assign iqentry_2_cumulative = (missid == 3'd2)
				? iqentry_2_livetarget
				: iqentry_2_livetarget | iqentry_3_cumulative;
 
assign iqentry_3_latestID = ((missid == 3'd3)|| ((iqentry_3_livetarget & iqentry_4_cumulative) == {NREGS{1'b0}}))
				? iqentry_3_livetarget
				: {NREGS{1'b0}};
assign iqentry_3_cumulative = (missid == 3'd3)
				? iqentry_3_livetarget
				: iqentry_3_livetarget | iqentry_4_cumulative;
 
assign iqentry_4_latestID = ((missid == 3'd4) || ((iqentry_4_livetarget & iqentry_5_cumulative) == {NREGS{1'b0}}))
				? iqentry_4_livetarget
				: {NREGS{1'b0}};
assign iqentry_4_cumulative = (missid == 3'd4)
				? iqentry_4_livetarget
				: iqentry_4_livetarget | iqentry_5_cumulative;
 
assign iqentry_5_latestID = ((missid == 3'd5)|| ((iqentry_5_livetarget & iqentry_6_cumulative) == {NREGS{1'b0}}))
				? iqentry_5_livetarget
				: 287'd0;
assign iqentry_5_cumulative = (missid == 3'd5)
				? iqentry_5_livetarget
				: iqentry_5_livetarget | iqentry_6_cumulative;
 
assign iqentry_6_latestID = ((missid == 3'd6) || ((iqentry_6_livetarget & iqentry_7_cumulative) == {NREGS{1'b0}}))
				? iqentry_6_livetarget
				: {NREGS{1'b0}};
assign iqentry_6_cumulative = (missid == 3'd6)
				? iqentry_6_livetarget
				: iqentry_6_livetarget | iqentry_7_cumulative;
 
assign iqentry_7_latestID = ((missid == 3'd7) || ((iqentry_7_livetarget & iqentry_0_cumulative) == {NREGS{1'b0}}))
				? iqentry_7_livetarget
				: {NREGS{1'b0}};
assign iqentry_7_cumulative = (missid==3'd7)
				? iqentry_7_livetarget
				: iqentry_7_livetarget | iqentry_0_cumulative;
 
assign
	iqentry_source[0] = | iqentry_0_latestID,
	iqentry_source[1] = | iqentry_1_latestID,
	iqentry_source[2] = | iqentry_2_latestID,
	iqentry_source[3] = | iqentry_3_latestID,
	iqentry_source[4] = | iqentry_4_latestID,
	iqentry_source[5] = | iqentry_5_latestID,
	iqentry_source[6] = | iqentry_6_latestID,
	iqentry_source[7] = | iqentry_7_latestID;
*/
always @*
begin
iqentry_source = 8'h00;
if (missid==head0) begin
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
end
else if (missid==head1) begin
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
end
else if (missid==head2) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
end
else if (missid==head3) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
    if (iqentry_v[head3] && !iqentry_stomp[head3])
        iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
end
else if (missid==head4) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
    if (iqentry_v[head3] && !iqentry_stomp[head3])
        iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
    if (iqentry_v[head4] && !iqentry_stomp[head4])
        iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
end
else if (missid==head5) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
    if (iqentry_v[head3] && !iqentry_stomp[head3])
        iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
    if (iqentry_v[head4] && !iqentry_stomp[head4])
        iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
    if (iqentry_v[head5] && !iqentry_stomp[head5])
        iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
end
else if (missid==head6) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
    if (iqentry_v[head3] && !iqentry_stomp[head3])
        iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
    if (iqentry_v[head4] && !iqentry_stomp[head4])
        iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
    if (iqentry_v[head5] && !iqentry_stomp[head5])
        iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
    if (iqentry_v[head6] && !iqentry_stomp[head6])
        iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
end
else if (missid==head7) begin 
    if (iqentry_v[head0] && !iqentry_stomp[head0])
        iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]);
    if (iqentry_v[head1] && !iqentry_stomp[head1])
        iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]);
    if (iqentry_v[head2] && !iqentry_stomp[head2])
        iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]);
    if (iqentry_v[head3] && !iqentry_stomp[head3])
        iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]);
    if (iqentry_v[head4] && !iqentry_stomp[head4])
        iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]);
    if (iqentry_v[head5] && !iqentry_stomp[head5])
        iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]);
    if (iqentry_v[head6] && !iqentry_stomp[head6])
        iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]);
    if (iqentry_v[head7] && !iqentry_stomp[head7])
        iqentry_source[head7] = !fnRegIsAutoValid(iqentry_tgt[head7]);
end
end
 
//assign iqentry_0_islot = iqentry_islot[0];
//assign iqentry_1_islot = iqentry_islot[1];
//assign iqentry_2_islot = iqentry_islot[2];
//assign iqentry_3_islot = iqentry_islot[3];
//assign iqentry_4_islot = iqentry_islot[4];
//assign iqentry_5_islot = iqentry_islot[5];
//assign iqentry_6_islot = iqentry_islot[6];
//assign iqentry_7_islot = iqentry_islot[7];
 
// 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.
// If there aren't enough read ports available then the second instruction
// isn't enqueued (it'll be enqueued in the next cycle).
reg [1:0] ports_avail;  // available read ports for instruction #3.
reg [6:0] pRa0,pRb0,pRa1,pRb1,pRt0,pRt1;
wire [DBW-1:0] prfoa0,prfob0,prfoa1,prfob1;
wire [DBW-1:0] prfot0,prfot1;
 
wire [6:0] Ra0 = fnRa(fetchbuf0_instr);
wire [6:0] Rb0 = fnRb(fetchbuf0_instr);
wire [6:0] Rc0 = fnRc(fetchbuf0_instr);
wire [6:0] Ra1 = fnRa(fetchbuf1_instr);
wire [6:0] Rb1 = fnRb(fetchbuf1_instr);
wire [6:0] Rc1 = fnRc(fetchbuf1_instr);
wire [6:0] Rt0 = fnTargetReg(fetchbuf0_instr);
wire [6:0] Rt1 = fnTargetReg(fetchbuf1_instr);
always @*
begin
    pRt0 = Rt0;
    pRt1 = Rt1;
    rfot0 = prfot0;
    rfot1 = prfot1; 
    case(fetchbuf0_v ? fnNumReadPorts(fetchbuf0_instr) : 2'd0)
    2'd0:   begin
            pRa0 = 7'd0;
            pRb0 = Rc1;
            pRa1 = Ra1;
            pRb1 = Rb1;
            rfoa0 = 64'd0;
            rfob0 = 64'd0;
            rfoc0 = 64'd0;
            rfoa1 = prfoa1;
            rfob1 = prfob1;
            rfoc1 = prfob0;
            ports_avail = 2'd3;
            end
    2'd1:   begin
            pRa0 = Ra0;
            pRb0 = Rc1;
            pRa1 = Ra1;
            pRb1 = Rb1;
            rfoa0 = prfoa0;
            rfob0 = 64'd0;
            rfoc0 = 64'd0;
            rfoa1 = prfoa1;
            rfob1 = prfob1;
            rfoc1 = prfob0;
            ports_avail = 2'd3;
            end
    2'd2:   begin
            pRa0 = Ra0;
            pRb0 = Rb0;
            pRa1 = Ra1;
            pRb1 = Rb1;
            rfoa0 = prfoa0;
            rfob0 = prfob0;
            rfoc0 = 64'd0;
            rfoa1 = prfoa1;
            rfob1 = prfob1;
            rfoc1 = 64'd0; 
            ports_avail = 2'd2;
            end   
    2'd3:   begin
            pRa0 = Ra0;
            pRb0 = Rb0;
            pRa1 = Rc0;
            pRb1 = Ra1;
            rfoa0 = prfoa0;
            rfob0 = prfob0;
            rfoc0 = prfoa1;
            rfoa1 = prfob1;
            rfob1 = 64'd0;
            rfoc1 = 64'd0;
            ports_avail = 2'd1;
            end
    endcase
end
 
/*
wire [8:0] Rb0 = ((fnNumReadPorts(fetchbuf0_instr) < 3'd2) || !fetchbuf0_v) ? {1'b0,fetchbuf1_instr[`INSTRUCTION_RC]} :
				fnRb(fetchbuf0_instr);
wire [8:0] Ra1 = (!fetchbuf0_v || fnNumReadPorts(fetchbuf0_instr) < 3'd3) ? fnRa(fetchbuf1_instr) :
					fetchbuf0_instr[`INSTRUCTION_RC];
wire [8:0] Rb1 = (fnNumReadPorts(fetchbuf1_instr) < 3'd2 && fetchbuf0_v) ? fnRa(fetchbuf1_instr):fnRb(fetchbuf1_instr);
*/
function [7:0] fnOpcode;
input [63:0] ins;
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];
endfunction
 
wire [7:0] opcode0 = fnOpcode(fetchbuf0_instr);
wire [7:0] opcode1 = fnOpcode(fetchbuf1_instr);
wire [3:0] cond0 = fetchbuf0_instr[3:0];
wire [3:0] cond1 = fetchbuf1_instr[3:0];
wire [3:0] Pn0 = fetchbuf0_instr[7:4];
wire [3:0] Pt0 = fetchbuf0_instr[11:8];
wire [3:0] Pn1 = fetchbuf1_instr[7:4];
wire [3:0] Pt1 = fetchbuf1_instr[11:8];
 
wire [6:0] r27 = 7'd27 + mode;
 
function [6:0] fnRa;
input [63:0] isn;
	case(isn[15:8])
	`RTS2:  fnRa = 7'h51;
	`RTI:	fnRa = 7'h5E;
	`RTD:   fnRa = 7'h5B;
	`RTE:	fnRa = 7'h5D;
	`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
		fnRa = {3'h5,isn[23:20]};
	`TLB:  fnRa = {1'b0,isn[29:24]};
	`P:    fnRa = 7'h70;
	`LOOP:  fnRa = 7'h73;
	`PUSH:   fnRa = r27;
`ifdef STACKOPS
	`PEA,`POP,`LINK:   fnRa = r27;
`endif
    `MFSPR,`MOVS:   
        if (isn[`INSTRUCTION_RA]==`USP)
            fnRa = 7'd27;
        else
            fnRa = {1'b1,isn[`INSTRUCTION_RA]};
	default:
	       if (isn[`INSTRUCTION_RA]==6'd27)
	           fnRa = r27;
	       else	
	           fnRa = {1'b0,isn[`INSTRUCTION_RA]};
	endcase
endfunction
 
function [6:0] fnRb;
input [63:0] isn;
	case(isn[15:8])
//	`LOOP:  fnRb = 7'h73;
//	`RTS,`STP,`TLB,`POP:   fnRb = 7'd0;
	`JSR,`JSRS,`JSRZ,`SYS,`INT:
		fnRb = {3'h5,isn[23:20]};
	`SWS:  if (isn[27:22]==`USP)
	           fnRb = {1'b0,6'd27};
	       else 
	           fnRb = {1'b1,isn[27:22]};
	`PUSH:  fnRb = isn[22:16];
`ifdef STACKOPS
	`LINK:  fnRb = {1'b0,isn[27:22]};
	`PEA:   fnRb = {1'b0,isn[21:16]};
`endif
	default:
	   if (isn[`INSTRUCTION_RB]==6'd27)
	       fnRb = r27;
	   else	
	       fnRb = {1'b0,isn[`INSTRUCTION_RB]};
	endcase
endfunction
 
function [6:0] fnRc;
input [63:0] isn;
if (isn[`INSTRUCTION_RC]==6'd27)
    fnRc = r27;
else
    fnRc = {1'b0,isn[`INSTRUCTION_RC]};
endfunction
 
function [3:0] fnCar;
input [63:0] isn;
	case(isn[15:8])
	`RTS2:  fnCar = 4'h1;
	`RTI:	fnCar = 4'hE;
	`RTD:   fnCar = 4'hB;
	`RTE:	fnCar = 4'hD;
	`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS:
		fnCar = {isn[23:20]};
	default:	fnCar = 4'h0;
	endcase
endfunction
 
function [5:0] fnFunc;
input [63:0] isn;
case(isn[15:8])
`BITFIELD:	fnFunc = isn[43:40];
`R:     fnFunc = isn[31:28];
`R2:    fnFunc = isn[31:28];
`DOUBLE_R:  fnFunc = isn[31:28];
`SINGLE_R:  fnFunc = isn[31:28];
8'h10:	fnFunc = isn[31:28];
8'h11:	fnFunc = isn[31:28];
8'h12:	fnFunc = isn[31:28];
8'h13:	fnFunc = isn[31:28];
8'h14:	fnFunc = isn[31:28];
8'h15:	fnFunc = isn[31:28];
8'h16:	fnFunc = isn[31:28];
8'h17:	fnFunc = isn[31:28];
8'h18:	fnFunc = isn[31:28];
8'h19:	fnFunc = isn[31:28];
8'h1A:	fnFunc = isn[31:28];
8'h1B:	fnFunc = isn[31:28];
8'h1C:	fnFunc = isn[31:28];
8'h1D:	fnFunc = isn[31:28];
8'h1E:	fnFunc = isn[31:28];
8'h1F:	fnFunc = isn[31:28];
8'h00:	fnFunc = isn[23:22];
8'h01:	fnFunc = isn[23:22];
8'h02:	fnFunc = isn[23:22];
8'h03:	fnFunc = isn[23:22];
8'h04:	fnFunc = isn[23:22];
8'h05:	fnFunc = isn[23:22];
8'h06:	fnFunc = isn[23:22];
8'h07:	fnFunc = isn[23:22];
8'h08:	fnFunc = isn[23:22];
8'h09:	fnFunc = isn[23:22];
8'h0A:	fnFunc = isn[23:22];
8'h0B:	fnFunc = isn[23:22];
8'h0C:	fnFunc = isn[23:22];
8'h0D:	fnFunc = isn[23:22];
8'h0E:	fnFunc = isn[23:22];
8'h0F:	fnFunc = isn[23:22];
`INC:   fnFunc = {isn[39:37],isn[24:22]};
`TLB:   fnFunc = isn[19:16];
`RTS:   fnFunc = isn[19:16];   // used to pass a small immediate
`CACHE: fnFunc = isn[31:26];
`PUSH,`PEA: fnFunc = km ? 6'b0 : 6'b110000; // select segment register #6
`JMPI:  fnFunc = {isn[39:37],1'b0,isn[27:26]};
`JMPIX: fnFunc = {isn[39:37],1'b0,isn[33:32]};
default:
	fnFunc = isn[39:34];
endcase
endfunction
 
// Returns true if the operation is limited to ALU #0
function fnIsAlu0Op;
input [7:0] opcode;
input [5:0] func;
case(opcode)
`R:
    case(func)
    `CNTLZ,`CNTLO,`CNTPOP:  fnIsAlu0Op = `TRUE;
    `ABS,`SGN,`ZXB,`ZXC,`ZXH,`SXB,`SXC,`SXH:  fnIsAlu0Op = `TRUE;
    default:    fnIsAlu0Op = `FALSE;
    endcase
`R2:    fnIsAlu0Op = `TRUE;
`RR:
    case(func)
    `DIV,`DIVU: fnIsAlu0Op = `TRUE;
    `MOD,`MODU: fnIsAlu0Op = `TRUE;
    `MIN,`MAX:  fnIsAlu0Op = `TRUE;
    default:    fnIsAlu0Op = `FALSE;
    endcase
`BCD:       fnIsAlu0Op = `TRUE;
`DIVI,`DIVUI:   fnIsAlu0Op = `TRUE;
`MODI,`MODUI:   fnIsAlu0Op = `TRUE;
//`DOUBLE:    fnIsAlu0Op = `TRUE;
`SHIFT:     fnIsAlu0Op = `TRUE;
`BITFIELD:  fnIsAlu0Op = `TRUE;
default:    fnIsAlu0Op = `FALSE;
endcase
endfunction
 
// Returns TRUE if the alu will be valid immediately
//
function fnAluValid;
input [7:0] opcode;
input [5:0] func;
case(opcode)
`R: fnAluValid = `TRUE;
`RR:
    case(func)
    `MUL,`MULU,`DIV,`DIVU,`MOD,`MODU: fnAluValid = `FALSE;
    default:    fnAluValid = `TRUE;
    endcase
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:   fnAluValid = `FALSE;
default:    fnAluValid = `TRUE;
endcase
endfunction
 
Thor_regfile2w6r #(DBW) urf1
(
	.clk(clk),
	.rclk(~clk),
	.wr0(commit0_v && ~commit0_tgt[6]),
	.wr1(commit1_v && ~commit1_tgt[6]),
	.wa0(commit0_tgt[5:0]),
	.wa1(commit1_tgt[5:0]),
	.ra0(pRa0[5:0]),
	.ra1(pRb0[5:0]),
	.ra2(pRa1[5:0]),
	.ra3(pRb1[5:0]),
	.ra4(pRt0[5:0]),
	.ra5(pRt1[5:0]),
	.i0(commit0_bus),
	.i1(commit1_bus),
	.o0(prfoa0),
	.o1(prfob0),
	.o2(prfoa1),
	.o3(prfob1),
	.o4(prfot0),
	.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] 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, 
// 0 if we need a RF value
function fnSource1_v;
input [7:0] opcode;
	case(opcode)
	`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP:
					fnSource1_v = 1'b1;
	`LDI,`LDIS,`IMM:	fnSource1_v = 1'b1;
	default:
	   case(opcode[7:4])
       `BR:		fnSource1_v = 1'b1;
	   default:    fnSource1_v = 1'b0;
	   endcase
	endcase
endfunction
 
//
// 1 if the the operand is automatically valid, 
// 0 if we need a RF value
function fnSource2_v;
input [7:0] opcode;
input [5:0] func;
	case(opcode)
	`R,`P:		fnSource2_v = 1'b1;
	`LDI,`LDIS,`IMM,`NOP,`STP:		fnSource2_v = 1'b1;
	`SEI,`CLI,`MEMSB,`MEMDB,`SYNC:
					fnSource2_v = 1'b1;
	`RTI,`RTD,`RTE,`JMPI:	fnSource2_v = 1'b1;
	// TST
	8'h00:			fnSource2_v = 1'b1;
	8'h01:			fnSource2_v = 1'b1;
	8'h02:			fnSource2_v = 1'b1;
	8'h03:			fnSource2_v = 1'b1;
	8'h04:			fnSource2_v = 1'b1;
	8'h05:			fnSource2_v = 1'b1;
	8'h06:			fnSource2_v = 1'b1;
	8'h07:			fnSource2_v = 1'b1;
	8'h08:			fnSource2_v = 1'b1;
	8'h09:			fnSource2_v = 1'b1;
	8'h0A:			fnSource2_v = 1'b1;
	8'h0B:			fnSource2_v = 1'b1;
	8'h0C:			fnSource2_v = 1'b1;
	8'h0D:			fnSource2_v = 1'b1;
	8'h0E:			fnSource2_v = 1'b1;
	8'h0F:			fnSource2_v = 1'b1;
	`ADDI,`ADDUI,`ADDUIS:
	                fnSource2_v = 1'b1;
	`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
					fnSource2_v = 1'b1;
	`SUBI,`SUBUI:	fnSource2_v = 1'b1;
	// CMPI
	8'h20:			fnSource2_v = 1'b1;
	8'h21:			fnSource2_v = 1'b1;
	8'h22:			fnSource2_v = 1'b1;
	8'h23:			fnSource2_v = 1'b1;
	8'h24:			fnSource2_v = 1'b1;
	8'h25:			fnSource2_v = 1'b1;
	8'h26:			fnSource2_v = 1'b1;
	8'h27:			fnSource2_v = 1'b1;
	8'h28:			fnSource2_v = 1'b1;
	8'h29:			fnSource2_v = 1'b1;
	8'h2A:			fnSource2_v = 1'b1;
	8'h2B:			fnSource2_v = 1'b1;
	8'h2C:			fnSource2_v = 1'b1;
	8'h2D:			fnSource2_v = 1'b1;
	8'h2E:			fnSource2_v = 1'b1;
	8'h2F:			fnSource2_v = 1'b1;
	// BR
    8'h30:            fnSource2_v = 1'b1;
    8'h31:            fnSource2_v = 1'b1;
    8'h32:            fnSource2_v = 1'b1;
    8'h33:            fnSource2_v = 1'b1;
    8'h34:            fnSource2_v = 1'b1;
    8'h35:            fnSource2_v = 1'b1;
    8'h36:            fnSource2_v = 1'b1;
    8'h37:            fnSource2_v = 1'b1;
    8'h38:            fnSource2_v = 1'b1;
    8'h39:            fnSource2_v = 1'b1;
    8'h3A:            fnSource2_v = 1'b1;
    8'h3B:            fnSource2_v = 1'b1;
    8'h3C:            fnSource2_v = 1'b1;
    8'h3D:            fnSource2_v = 1'b1;
    8'h3E:            fnSource2_v = 1'b1;
    8'h3F:            fnSource2_v = 1'b1;
	`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
					fnSource2_v = 1'b1;
	`ANDI,`BITI:	fnSource2_v = 1'b1;
	`ORI:			fnSource2_v = 1'b1;
	`EORI:			fnSource2_v = 1'b1;
	`SHIFT:
	           if (func>=6'h10)
	               fnSource2_v = `TRUE;
	           else
	               fnSource2_v = `FALSE;
	`CACHE,`LCL,`TLB,`LLA,
	`LVB,`LVC,`LVH,`LVW,`LVWAR,
	`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`STI,`INC:
			fnSource2_v = 1'b1;
	`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2:
			fnSource2_v = 1'b1;
	`MTSPR,`MFSPR,`POP,`UNLINK:
				fnSource2_v = 1'b1;
	`BITFIELD:
	       if (func==`BFINS)
	           fnSource2_v = 1'b0;
	       else
	           fnSource2_v = 1'b1;
	`LOOP:      fnSource2_v = 1'b1;
	default:    fnSource2_v = 1'b0;
	endcase
endfunction
 
 
// Source #3 valid
// Since most instructions don't use a third source the default it to return 
// a valid status.
// 1 if the the operand is automatically valid, 
// 0 if we need a RF value
function fnSource3_v;
input [7:0] opcode;
input [5:0] func;
	case(opcode)
	`RR:
	   case(func)
	   `CHK:   fnSource3_v = 1'b0;
	   default:    fnSource3_v = 1'b1;
	   endcase
	`SBX,`SCX,`SHX,`SWX,`CAS,`STMV,`STCMP,`STFND:	fnSource3_v = 1'b0;
	`MUX:	fnSource3_v = 1'b0;
	default:	fnSource3_v = 1'b1;
	endcase
endfunction
 
function fnSourceT_v;
input [7:0] opcode;
input [5:0] func;
    case(opcode)
    `RR:
        case(func)
        `CHK:   fnSourceT_v = 1'b1;
        default:    fnSourceT_v = 1'b0;
        endcase
    // BR
    8'h30,8'h31,8'h32,8'h33,
    8'h34,8'h35,8'h36,8'h37,
    8'h38,8'h39,8'h3A,8'h3B,
    8'h3C,8'h3D,8'h3E,8'h3F,
    `SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS,
    `CACHE,`CHKI,
    `SEI,`CLI,`NOP,`STP,`RTI,`RTD,`RTE,
    `MEMSB,`MEMDB,`SYNC:
            fnSourceT_v = 1'b1;
    default:    fnSourceT_v = 1'b0;
    endcase
endfunction
 
// Return the number of register read ports required for an instruction.
function [2:0] fnNumReadPorts;
input [63:0] ins;
case(fnOpcode(ins))
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`MOVS,`STP:
					fnNumReadPorts = 3'd0;
`LDI,`LDIS,`IMM:		fnNumReadPorts = 3'd0;
`R,`P,`STI,`LOOP,`JMPI:   fnNumReadPorts = 3'd1;
`RTI,`RTD,`RTE:		fnNumReadPorts = 3'd1;
`ADDI,`ADDUI,`ADDUIS:
                    fnNumReadPorts = 3'd1;
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI:
					fnNumReadPorts = 3'd1;
`SUBI,`SUBUI:		fnNumReadPorts = 3'd1;
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI:
					fnNumReadPorts = 3'd1;
`BITI,
`ANDI,`ORI,`EORI:	fnNumReadPorts = 3'd1;
`SHIFT:
                    if (ins[39:38]==2'h1)   // shift immediate
					   fnNumReadPorts = 3'd1;
					else
					   fnNumReadPorts = 3'd2;
`CACHE,`LCL,`TLB,`LLA,					 
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`INC:
					fnNumReadPorts = 3'd1;
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2,`BR:
					fnNumReadPorts = 3'd1;
`SBX,`SCX,`SHX,`SWX,
`MUX,`CAS,`STMV,`STCMP:
					fnNumReadPorts = 3'd3;
`MTSPR,`MFSPR,`POP,`UNLINK:	fnNumReadPorts = 3'd1;
`STFND:	   fnNumReadPorts = 3'd2;	// *** TLB reads on Rb we say 2 for simplicity
`RR:
    case(ins[39:34])
    `CHK:   fnNumReadPorts = 3'd3;
    default:    fnNumReadPorts = 3'd2;
    endcase
`BITFIELD:
    case(ins[43:40])
    `BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU,`BFINSI:
					fnNumReadPorts = 3'd1;
    `BFINS:         fnNumReadPorts = 3'd2;
    default:        fnNumReadPorts = 3'd0;
    endcase
default:
    case(ins[15:12])
    `TST:			fnNumReadPorts = 3'd1;
    `CMPI:			fnNumReadPorts = 3'd1;
    `CMP:			fnNumReadPorts = 3'd2;
    `BR:            fnNumReadPorts = 3'd0;
    default:        fnNumReadPorts = 3'd2;
    endcase
endcase
endfunction
 
function fnIsBranch;
input [7:0] opcode;
case(opcode[7:4])
`BR:	fnIsBranch = `TRUE;
default:	fnIsBranch = `FALSE;
endcase
endfunction
 
function fnIsPush;
input [63:0] isn;
fnIsPush = isn[15:8]==`PUSH || isn[15:8]==`PEA;
endfunction
 
function fnIsPop;
input [63:0] isn;
fnIsPop = isn[15:8]==`POP;
endfunction
 
function fnIsStoreString;
input [7:0] opcode;
fnIsStoreString =
	opcode==`STS;
endfunction
 
reg [DBW-1:0] branch_pc;
wire xbr = iqentry_br[head0] | iqentry_br[head1];
wire takb = iqentry_br[head0] ? commit0_v : commit1_v;
wire [DBW-1:0] xbrpc = iqentry_br[head0] ? iqentry_pc[head0] : iqentry_pc[head1];
 
wire predict_taken0;
wire predict_taken1;
 
// This is really just a single history table with three read ports.
// One for fetchbuf0, one for fetchbuf1 and one for the branch_pc.
// Ideally, there really needs to be two write ports as well (for
// head0 and head1).
// There is only a single write port for branches committing at
// head0 or head1. If there are two branches one after the other
// in code, then the prediction will be off because the taken/
// not taken status for the second branch won't be updated. It
// doesn't happen that often that branches are piled together and
// executing during the same clock cycle.
// There's usually at least an intervening compare operation.
// Needs more work yet.
//
// ToDo: add return address stack predictor.
//
Thor_BranchHistory #(DBW) ubhtA
(
	.rst(rst_i),
	.clk(clk),
	.advanceX(xbr),
	.xisBranch(xbr),
	.pc(branch_pc),
	.xpc(xbrpc),
	.takb(takb),
	.predict_taken(predict_takenBr)
);
 
Thor_BranchHistory #(DBW) ubhtB
(
	.rst(rst_i),
	.clk(clk),
	.advanceX(xbr),
	.xisBranch(xbr),
	.pc(fetchbuf0_pc),
	.xpc(xbrpc),
	.takb(takb),
	.predict_taken(predict_taken0)
);
 
Thor_BranchHistory #(DBW) ubhtC
(
	.rst(rst_i),
	.clk(clk),
	.advanceX(xbr),
	.xisBranch(xbr),
	.pc(fetchbuf1_pc),
	.xpc(xbrpc),
	.takb(takb),
	.predict_taken(predict_taken1)
);
 
/*
Thor_BranchHistory #(DBW) ubhtC
(
	.rst(rst_i),
	.clk(clk),
	.advanceX(xbr),
	.xisBranch(xbr),
	.pc(pc),
	.xpc(xbrpc),
	.takb(takb),
	.predict_taken(predict_takenC)
);
 
Thor_BranchHistory #(DBW) ubhtD
(
	.rst(rst_i),
	.clk(clk),
	.advanceX(xbr),
	.xisBranch(xbr),
	.pc(pc+fnInsnLength(insn)),
	.xpc(xbrpc),
	.takb(takb),
	.predict_taken(predict_takenD)
);
*/
`ifdef PCHIST
wire [63:0] pc_histo;
reg pc_cap;
reg [5:0] pc_ndx;
vtdl #(.WID(64),.DEP(64)) uvtl1
(
    .clk(clk),
    .ce(pc_cap),
    .a(pc_ndx),
    .d({fetchbuf1_pc,fetcbuf0_pc}),
    .q(pc_histo)
);
`endif
 
Thor_icachemem #(.DBW(DBW),.ABW(ABW),.ECC(1'b0)) uicm1
(
	.wclk(clk),
	.wce(cstate==ICACHE1),
	.wr(ack_i|err_i),
	.wa(adr_o),
	.wd(dat_i),
	.rclk(~clk),
	.pc(ppc),
	.insn(insn)
);
 
wire hit0,hit1;
reg ic_ld;
reg [31:0] ic_ld_cntr;
Thor_itagmem #(DBW-1) uitm1
(
	.wclk(clk),
	.wce((cstate==ICACHE1 && cti_o==3'b111)|ic_ld),
	.wr(ack_i|err_i|ic_ld),
	.wa(adr_o|ic_ld_cntr),
	.err_i(err_i|ierr),
	.invalidate(ic_invalidate),
	.invalidate_line(ic_invalidate_line),
	.invalidate_lineno(ic_lineno),
	.rclk(~clk),
	.rce(1'b1),
	.pc(ppc),
	.hit0(hit0),
	.hit1(hit1),
	.err_o(insnerr)
);
 
wire ihit = hit0 & hit1;
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 whit;
 
Thor_dcachemem_1w1r #(DBW) udcm1
(
	.wclk(clk),
	.wce(whit || cstate==DCACHE1),
	.wr(ack_i|err_i),
	.sel(whit ? sel_o : 8'hFF),
	.wa(adr_o),
	.wd(whit ? dat_o : dat_i[DBW-1:0]),
	.rclk(~clk),
	.rce(1'b1),
	.ra(pea),
	.o(cdat)
);
 
Thor_dtagmem #(DBW-1) udtm1
(
	.wclk(clk),
	.wce(cstate==DCACHE1 && cti_o==3'b111),
	.wr(ack_i|err_i),
	.wa(adr_o),
	.err_i(err_i|derr),
	.invalidate(dc_invalidate),
	.invalidate_line(dc_invalidate_line),
    .invalidate_lineno(dc_lineno),
	.rclk(~clk),
	.rce(1'b1),
	.ra(pea),
	.whit(whit),
	.rhit(rhit),
	.err_o()
);
 
wire [DBW-1:0] shfto0,shfto1;
 
function fnIsShiftiop;
input [63:0] isn;
fnIsShiftiop =  isn[15:8]==`SHIFT && (
                isn[39:34]==`SHLI || isn[39:34]==`SHLUI ||
				isn[39:34]==`SHRI || isn[39:34]==`SHRUI ||
				isn[39:34]==`ROLI || isn[39:34]==`RORI
				)
				;
endfunction
 
function fnIsShiftop;
input [7:0] opcode;
fnIsShiftop = opcode==`SHL || opcode==`SHLI || opcode==`SHLU || opcode==`SHLUI ||
				opcode==`SHR || opcode==`SHRI || opcode==`SHRU || opcode==`SHRUI ||
				opcode==`ROL || opcode==`ROLI || opcode==`ROR || opcode==`RORI
				;
endfunction
 
function fnIsFP;
input [7:0] opcode;
fnIsFP = 	opcode==`DOUBLE_R||opcode==`FLOAT||opcode==`SINGLE_R;
//            opcode==`ITOF || opcode==`FTOI || opcode==`FNEG || opcode==`FSIGN || /*opcode==`FCMP || */ opcode==`FABS ||
//			opcode==`FADD || opcode==`FSUB || opcode==`FMUL || opcode==`FDIV
//			;
endfunction
 
function fnIsFPCtrl;
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)) ||
             (isn[15:8]==`DOUBLE_R && (isn[31:28]==`FRM))
             ;
endfunction
 
function fnIsBitfield;
input [7:0] opcode;
fnIsBitfield = opcode==`BITFIELD;
endfunction
 
//wire [3:0] Pn = ir[7:4];
 
// Set the target register
// 00-3F = general register file
// 40-4F = predicate register
// 50-5F = code address register
// 60-67 = segment base register
// 68-6F = segment limit register
// 70 = predicate register horizontal
// 73 = loop counter
// 7C = breakout index register
// 7D = broken out register
// 7F = power shift register
function [6:0] fnTargetReg;
input [63:0] ir;
begin
    // Process special predicates (NOP, IMM)
    // Note that BRK (00) is already translated to a SYS instruction
	if (ir[3:0]==4'h0)
		fnTargetReg = 7'h000;
	else
		case(fnOpcode(ir))
		`POP: fnTargetReg = ir[22:16];
		`LDI,`ADDUIS,`STS,`LINK,`UNLINK:
		    if (ir[21:16]==6'd27)
		        fnTargetReg = r27;
		    else
			    fnTargetReg = {1'b0,ir[21:16]};
		`LDIS:
			fnTargetReg = {1'b1,ir[21:16]};
		`RR,
		`SHIFT,
		`BCD,
        `LOGIC,`FLOAT,
        `LWX,`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`STMV,`STCMP,`STFND:
		    if (ir[33:28]==6'd27)
		        fnTargetReg = r27;
		    else
			    fnTargetReg = {1'b0,ir[33:28]};
		`R,`R2,`DOUBLE_R,`SINGLE_R,
		`ADDI,`ADDUI,`SUBI,`SUBUI,
		`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
		`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,
		`ANDI,`ORI,`EORI,`LLA,
		`LVB,`LVC,`LVH,`LVW,`LVWAR,
		`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LINK,
		`BITFIELD,`MFSPR:
		    if (ir[27:22]==6'd27)
		        fnTargetReg = r27;
		    else
			    fnTargetReg = {1'b0,ir[27:22]};
		`CAS:
			fnTargetReg = {1'b0,ir[39:34]};
		`TLB:
			if (ir[19:16]==`TLB_RDREG)
				fnTargetReg = {1'b0,ir[29:24]};
			else
				fnTargetReg = 7'h00;
		`BITI:
		      fnTargetReg = {3'h4,ir[25:22]};
		// TST
		8'h00,8'h01,8'h02,8'h03,
		8'h04,8'h05,8'h06,8'h07,
		8'h08,8'h09,8'h0A,8'h0B,
		8'h0C,8'h0D,8'h0E,8'h0F,
		// CMP
		8'h10,8'h11,8'h12,8'h13,
        8'h14,8'h15,8'h16,8'h17,
        8'h18,8'h19,8'h1A,8'h1B,
        8'h1C,8'h1D,8'h1E,8'h1F,
		// CMPI
        8'h20,8'h21,8'h22,8'h23,
        8'h24,8'h25,8'h26,8'h27,
        8'h28,8'h29,8'h2A,8'h2B,
        8'h2C,8'h2D,8'h2E,8'h2F:
		    begin
			fnTargetReg = {3'h4,ir[11:8]};
			end
		`SWCR:    fnTargetReg = {3'h4,4'h0};
		`JSR,`JSRZ,`JSRS,`SYS,`INT:
			fnTargetReg = {3'h5,ir[19:16]};
		`JMPI:
		    fnTargetReg = {3'h5,ir[25:22]};
		`JMPIX:
		    fnTargetReg = {3'h5,ir[31:28]};
		`MTSPR,`MOVS,`LWS:
		    if (ir[27:22]==`USP)
		        fnTargetReg = {1'b0,6'd27};
		    else
		        fnTargetReg = {1'b1,ir[27:22]};
/*
			if (ir[27:26]==2'h1)		// Move to code address register
				fnTargetReg = {3'h5,ir[25:22]};
			else if (ir[27:26]==2'h2)	// Move to seg. reg.
				fnTargetReg = {3'h6,ir[25:22]};
			else if (ir[27:22]==6'h04)
				fnTargetReg = 7'h70;
			else
				fnTargetReg = 7'h00;
*/      
        `PUSH:      fnTargetReg = r27;
        `LOOP:      fnTargetReg = 7'h73;
        `STP:       fnTargetReg = 7'h7F;
        `P:         fnTargetReg = 7'h70;
		default:	fnTargetReg = 7'h00;
		endcase
end
endfunction
/*
function fnAllowedReg;
input [8:0] regno;
fnAllowedReg = allowedRegs[regno] ? regno : 9'h000;
endfunction
*/
function fnTargetsCa;
input [63:0] ir;
begin
if (ir[3:0]==4'h0)
	fnTargetsCa = `FALSE;
else begin
	case(fnOpcode(ir))
	`JSR,`JSRZ,`JSRS,`SYS,`INT:
	       fnTargetsCa = `TRUE;
	`JMPI,`JMPIX:
	       fnTargetsCa = `TRUE;
	`LWS:
		if (ir[27:26]==2'h1)
			fnTargetsCa = `TRUE;
		else
			fnTargetsCa = `FALSE;
	`LDIS:
		if (ir[21:20]==2'h1)
			fnTargetsCa = `TRUE;
		else
			fnTargetsCa = `FALSE;
	`MTSPR,`MOVS:
		begin
			if (ir[27:26]==2'h1)
				fnTargetsCa = `TRUE;
			else
				fnTargetsCa = `FALSE;
		end
	default:	fnTargetsCa = `FALSE;
	endcase
end
end
endfunction
 
function fnTargetsSegreg;
input [63:0] ir;
if (ir[3:0]==4'h0)
	fnTargetsSegreg = `FALSE;
else
	case(fnOpcode(ir))
	`LWS:
		if (ir[27:26]==2'h2)
			fnTargetsSegreg = `TRUE;
		else
			fnTargetsSegreg = `FALSE;
	`LDIS:
		if (ir[21:20]==2'h2)
			fnTargetsSegreg = `TRUE;
		else
			fnTargetsSegreg = `FALSE;
	`MTSPR,`MOVS:
		if (ir[27:26]==2'h2)
			fnTargetsSegreg = `TRUE;
		else
			fnTargetsSegreg = `FALSE;
	default:	fnTargetsSegreg = `FALSE;
	endcase
endfunction
 
function fnHasConst;
input [7:0] opcode;
	case(opcode)
	`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS,
	`LDI,`LDIS,`ADDUIS,
	`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI,
	`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,`CHKI,
	// CMPI
	8'h20,8'h21,8'h22,8'h23,
	8'h24,8'h25,8'h26,8'h27,
	8'h28,8'h29,8'h2A,8'h2B,
	8'h2C,8'h2D,8'h2E,8'h2F,
	// BR
    8'h30,8'h31,8'h32,8'h33,
    8'h34,8'h35,8'h36,8'h37,
    8'h38,8'h39,8'h3A,8'h3B,
    8'h3C,8'h3D,8'h3E,8'h3F,
	`ANDI,`ORI,`EORI,`BITI,
//	`SHLI,`SHLUI,`SHRI,`SHRUI,`ROLI,`RORI,
	`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`INC,
	`LVB,`LVC,`LVH,`LVW,`LVWAR,`STI,`JMPI,
	`SB,`SC,`SH,`SW,`SWCR,`CAS,`SWS,
	`RTI,`RTD,`RTE,`LLA,
	`JSR,`JSRS,`SYS,`INT,`LOOP,`PEA,`LINK,`UNLINK:
		fnHasConst = 1'b1;
	default:
		fnHasConst = 1'b0;
	endcase
endfunction
 
// Used by memory issue logic.
function fnIsFlowCtrl;
input [7:0] opcode;
begin
case(opcode)
`JMPI,`JMPIX,
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE:
	fnIsFlowCtrl = 1'b1;
default:
    if (opcode[7:4]==`BR)
        fnIsFlowCtrl = 1'b1;
    else
        fnIsFlowCtrl = 1'b0;
endcase
end
endfunction
 
// fnCanException
//
// Used by memory issue logic.
// Returns TRUE if the instruction can cause an exception.
// In debug mode any instruction could potentially cause a breakpoint exception.
// 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
// 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.
//
function fnCanException;
input [7:0] op;
input [5:0] func;
if (debug_on)
    fnCanException = `TRUE;
else
case(op)
`FLOAT:
    case(func)
    `FDIVS,`FMULS,`FADDS,`FSUBS,
    `FDIV,`FMUL,`FADD,`FSUB:
        fnCanException = `TRUE;
    default:    fnCanException = `FALSE;
    endcase
`SINGLE_R:
    if (func==`FTX) fnCanException = `TRUE;
    else fnCanException = `FALSE;
`ADDI,`SUBI,`DIVI,`MODI,`MULI,`CHKI:
    fnCanException = `TRUE;
`RR:
    if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD || func==`CHK)
        fnCanException = `TRUE;
    else
        fnCanException = `FALSE;
`TLB,`RTI,`RTD,`RTE,`CLI,`SEI:
    fnCanException = `TRUE;
default:
    fnCanException = fnIsMem(op);
endcase
endfunction
 
// fnInsnLength
// Used by fetch logic.
// Return the length of an instruction.
//
function [3:0] fnInsnLength;
input [127:0] isn;
case(isn[7:0])
8'b00000000:	fnInsnLength = 4'd1;	// BRK
8'b00010000:	fnInsnLength = 4'd1;	// NOP
8'b00100000:	fnInsnLength = 4'd2;
8'b00110000:	fnInsnLength = 4'd3;
8'b01000000:	fnInsnLength = 4'd4;
8'b01010000:	fnInsnLength = 4'd5;
8'b01100000:	fnInsnLength = 4'd6;
8'b01110000:	fnInsnLength = 4'd7;
8'b10000000:	fnInsnLength = 4'd8;
default:
	case(isn[15:8])
	`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`MEMSB,`MEMDB,`SYNC:
		fnInsnLength = 4'd2;
	`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK:
		fnInsnLength = 4'd3;
	`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`STP:
		fnInsnLength = 4'd4;
	`BITFIELD,`JSR,`MUX,`BCD,`INC:
		fnInsnLength = 4'd6;
	`CAS:
		fnInsnLength = 4'd6;
	default:
	   begin
	    case(isn[15:12])
	    `TST:     fnInsnLength = 4'd3;
	    `BR:      fnInsnLength = 4'd3;
	    `CMP,`CMPI:    fnInsnLength = 4'd4;
	    default:       fnInsnLength = 4'd5;
	    endcase
	    end
	endcase
endcase
endfunction
 
function [3:0] fnInsnLength1;
input [127:0] isn;
case(fnInsnLength(isn))
4'd1:	fnInsnLength1 = fnInsnLength(isn[127: 8]);
4'd2:	fnInsnLength1 = fnInsnLength(isn[127:16]);
4'd3:	fnInsnLength1 = fnInsnLength(isn[127:24]);
4'd4:	fnInsnLength1 = fnInsnLength(isn[127:32]);
4'd5:	fnInsnLength1 = fnInsnLength(isn[127:40]);
4'd6:	fnInsnLength1 = fnInsnLength(isn[127:48]);
4'd7:	fnInsnLength1 = fnInsnLength(isn[127:56]);
4'd8:	fnInsnLength1 = fnInsnLength(isn[127:64]);
default:	fnInsnLength1 = 4'd0;
endcase
endfunction
 
function [3:0] fnInsnLength2;
input [127:0] isn;
case(fnInsnLength(isn)+fnInsnLength1(isn))
4'd2:	fnInsnLength2 = fnInsnLength(isn[127:16]);
4'd3:	fnInsnLength2 = fnInsnLength(isn[127:24]);
4'd4:	fnInsnLength2 = fnInsnLength(isn[127:32]);
4'd5:	fnInsnLength2 = fnInsnLength(isn[127:40]);
4'd6:	fnInsnLength2 = fnInsnLength(isn[127:48]);
4'd7:	fnInsnLength2 = fnInsnLength(isn[127:56]);
4'd8:	fnInsnLength2 = fnInsnLength(isn[127:64]);
4'd9:	fnInsnLength2 = fnInsnLength(isn[127:72]);
4'd10:	fnInsnLength2 = fnInsnLength(isn[127:80]);
4'd11:	fnInsnLength2 = fnInsnLength(isn[127:88]);
4'd12:	fnInsnLength2 = fnInsnLength(isn[127:96]);
4'd13:	fnInsnLength2 = fnInsnLength(isn[127:104]);
4'd14:	fnInsnLength2 = fnInsnLength(isn[127:112]);
4'd15:	fnInsnLength2 = fnInsnLength(isn[127:120]);
default:	fnInsnLength2 = 4'd0;
endcase
endfunction
 
wire [5:0] total_insn_length = fnInsnLength(insn) + fnInsnLength1(insn) + fnInsnLength2(insn);
wire [5:0] insn_length12 = fnInsnLength(insn) + fnInsnLength1(insn);
wire insn3_will_fit = total_insn_length < 6'd16;
 
always @(fetchbuf or fetchbufA_instr or fetchbufA_v or fetchbufA_pc
 or fetchbufB_instr or fetchbufB_v or fetchbufB_pc
 or fetchbufC_instr or fetchbufC_v or fetchbufC_pc
 or fetchbufD_instr or fetchbufD_v or fetchbufD_pc
)
begin
	fetchbuf0_instr <= (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr;
	fetchbuf0_v     <= (fetchbuf == 1'b0) ? fetchbufA_v     : fetchbufC_v    ;
 
	if (int_pending && string_pc!=64'd0)
		fetchbuf0_pc <= string_pc;
	else
	fetchbuf0_pc    <= (fetchbuf == 1'b0) ? fetchbufA_pc    : fetchbufC_pc   ;
 
	fetchbuf1_instr <= (fetchbuf == 1'b0) ? fetchbufB_instr : fetchbufD_instr;
	fetchbuf1_v     <= (fetchbuf == 1'b0) ? fetchbufB_v     : fetchbufD_v    ;
 
	if (int_pending && string_pc != 64'd0)
		fetchbuf1_pc <= string_pc;
	else
	fetchbuf1_pc    <= (fetchbuf == 1'b0) ? fetchbufB_pc    : fetchbufD_pc   ;
end
 
wire [7:0] opcodeA = fnOpcode(fetchbufA_instr);
wire [7:0] opcodeB = fnOpcode(fetchbufB_instr);
wire [7:0] opcodeC = fnOpcode(fetchbufC_instr);
wire [7:0] opcodeD = fnOpcode(fetchbufD_instr);
 
function fnIsMem;
input [7:0] opcode;
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==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
			opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
			opcode==`STS || opcode==`LCL ||
			opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
			opcode==`TLB || opcode==`CAS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
			opcode==`LWS || opcode==`SWS || opcode==`STI ||
			opcode==`INC ||
			opcode==`JMPI || opcode==`JMPIX ||
			opcode==`PUSH || opcode==`POP || opcode==`PEA || opcode==`LINK || opcode==`UNLINK
			;
endfunction
 
// Determines which instruction write to the register file
function fnIsRFW;
input [7:0] opcode;
input [63:0] ir;
begin
fnIsRFW =	// General registers
			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==`LVB || opcode==`LVH || opcode==`LVC || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR ||
			opcode==`STP || opcode==`LLA || opcode==`LLAX || 
			opcode==`CAS || opcode==`LWS || opcode==`STMV || opcode==`STCMP || opcode==`STFND ||
			opcode==`STS || opcode==`PUSH || opcode==`POP || opcode==`LINK || opcode==`UNLINK ||
			opcode==`JMPI || opcode==`JMPIX ||
			opcode==`ADDI || opcode==`SUBI || opcode==`ADDUI || opcode==`SUBUI ||
			opcode==`MULI || opcode==`MULUI || opcode==`DIVI || opcode==`DIVUI || opcode==`MODI || opcode==`MODUI ||
			opcode==`_2ADDUI || opcode==`_4ADDUI || opcode==`_8ADDUI || opcode==`_16ADDUI ||
			opcode==`ANDI || opcode==`ORI || opcode==`EORI ||
			opcode==`SHIFT || opcode==`LOGIC ||
			opcode==`R || opcode==`R2 || opcode==`RR || opcode==`P || opcode==`LOOP ||
			opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST ||
			opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR ||
`ifdef FLOATING_POINT
			opcode==`DOUBLE_R || opcode==`FLOAT_RR || opcode==`SINGLE_R ||
`endif
			// Branch registers / Segment registers
			((opcode==`MTSPR || opcode==`MOVS) /*&& (fnTargetsCa(ir) || fnTargetsSegreg(ir))*/) ||
			opcode==`JSR || opcode==`JSRS || opcode==`JSRZ || opcode==`SYS || opcode==`INT ||
			// predicate registers
			(opcode[7:4] < 4'h3) ||
			(opcode==`TLB && ir[19:16]==`TLB_RDREG) ||
			opcode==`BCD 
			;
end
endfunction
 
function fnIsStore;
input [7:0] opcode;
fnIsStore = 	opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW ||
				opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX ||
				opcode==`STS || opcode==`SWCR ||
				opcode==`SWS || opcode==`STI ||
				opcode==`PUSH || opcode==`PEA || opcode==`LINK; 
endfunction
 
function fnIsLoad;
input [7:0] opcode;
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==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL ||
			opcode==`LWS || opcode==`UNLINK || opcode==`JMPI || opcode==`JMPIX ||
			opcode==`POP;
endfunction
 
function fnIsLoadV;
input [7:0] opcode;
fnIsLoadV = opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL;
endfunction
 
function fnIsIndexed;
input [7:0] opcode;
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;
endfunction
 
// 
function fnIsPFW;
input [7:0] opcode;
fnIsPFW =	opcode[7:4]<4'h3 || opcode==`BITI || opcode==`P;//opcode==`CMP || opcode==`CMPI || opcode==`TST;
endfunction
 
// Decoding for illegal opcodes
function fnIsIllegal;
input [7:0] op;
input [5:0] fn;
casex(op)
8'h40:
    if (fn > 6'h17)
        fnIsIllegal = `TRUE;
    else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h15 || fn==6'h16)
        fnIsIllegal = `TRUE; 
    else fnIsIllegal = `FALSE;
8'h41:
    if (fn > 6'd3)  fnIsIllegal = `TRUE;
    else fnIsIllegal = `FALSE;
8'h42:
    if (fn > 6'd7)  fnIsIllegal = `TRUE;
    else fnIsIllegal = `FALSE;
8'h50:
    if (fn > 6'd7)  fnIsIllegal = `TRUE;
    else fnIsIllegal = `FALSE;
8'h58:
    if (fn > 6'h15 || (fn > 6'h5 && fn < 6'h10))
        fnIsIllegal = `TRUE; 
    else
        fnIsIllegal = `FALSE;
8'h77:
    if (fn==8'h99 || fn==8'h9A || fn==8'h9B || fn==8'h9E || fn==8'h9F)
        fnIsIllegal = `TRUE; 
    else 
        fnIsIllegal = `FALSE;
8'h78:
    if ((fn >= 8'h07 && fn <= 8'h0B) || (fn >= 8'h17 && fn <= 8'h1B))
        fnIsIllegal = `FALSE; 
    else
        fnIsIllegal = `TRUE;
8'h79:
    if (fn==8'h99 || fn==8'h9A || fn==8'h9B)
        fnIsIllegal = `TRUE; 
    else 
        fnIsIllegal = `FALSE;
8'hAA:
    if (fn > 4'd6)
        fnIsIllegal = `TRUE; 
    else 
        fnIsIllegal = `FALSE;
8'hF5:
    if (fn > 4'd2)
        fnIsIllegal = `TRUE; 
    else 
        fnIsIllegal = `FALSE;
8'h43,8'h44,8'h45:  fnIsIllegal = `TRUE;
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5C,8'h5E:
    fnIsIllegal = `TRUE;
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69:
    fnIsIllegal = `TRUE;
8'h73,8'h74,8'h75,8'h76,8'h7A,8'h7B,8'h7C,8'h7D,8'h7E,8'h7F:
    fnIsIllegal = `TRUE;
8'h87,8'h88,8'h89,8'h8A:
    fnIsIllegal = `TRUE;
8'h94,8'h95,8'h9C:
    fnIsIllegal = `TRUE;
8'hB9,8'hBA,8'hBB,8'hBC,8'hBD,8'hBE,8'hBF:
    fnIsIllegal = `TRUE;
8'hC4,8'hC5,8'b11001xxx:
    fnIsIllegal = `TRUE;
8'hDx:  fnIsIllegal = `TRUE;
8'hEx:  fnIsIllegal = `TRUE;
8'hFD,8'hFE:    fnIsIllegal = `TRUE;
default:    fnIsIllegal = `FALSE;
endcase
endfunction
 
function [7:0] fnSelect;
input [7:0] opcode;
input [5:0] fn;
input [DBW-1:0] adr;
begin
if (DBW==32)
	case(opcode)
	`STS,`STMV,`STCMP,`STFND,`INC:
	   case(fn[2:0])
	   3'd0:
           case(adr[1:0])
           3'd0:    fnSelect = 8'h11;
           3'd1:    fnSelect = 8'h22;
           3'd2:    fnSelect = 8'h44;
           3'd3:    fnSelect = 8'h88;
           endcase
       3'd1:
		   case(adr[1])
           1'd0:    fnSelect = 8'h33;
           1'd1:    fnSelect = 8'hCC;
           endcase
       3'd2:
    		fnSelect = 8'hFF;
       default: fnSelect = 8'h00;
       endcase
    `JMPI,`JMPIX:
        case(fn[1:0])
        2'd1:
            case(adr[1]) 
            1'b0:   fnSelect = 8'h33;
            1'b1:   fnSelect = 8'hCC;
            endcase
        2'd2:   fnSelect = 8'hFF;
        2'd3:   fnSelect = 8'hFF;
        default:    fnSelect = 8'h00;
        endcase
	`LB,`LBU,`LBX,`LBUX,`SB,`SBX,`LVB:
		case(adr[1:0])
		3'd0:	fnSelect = 8'h11;
		3'd1:	fnSelect = 8'h22;
		3'd2:	fnSelect = 8'h44;
		3'd3:	fnSelect = 8'h88;
		endcase
	`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
		case(adr[1])
		1'd0:	fnSelect = 8'h33;
		1'd1:	fnSelect = 8'hCC;
		endcase
	`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
		fnSelect = 8'hFF;
	`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
	`PUSH,`PEA,`POP,`LINK,`UNLINK:
		fnSelect = 8'hFF;
	default:	fnSelect = 8'h00;
	endcase
else
	case(opcode)
	`STS,`STMV,`STCMP,`STFND,`INC:
       case(fn[2:0])
       3'd0:
           case(adr[2:0])
           3'd0:    fnSelect = 8'h01;
           3'd1:    fnSelect = 8'h02;
           3'd2:    fnSelect = 8'h04;
           3'd3:    fnSelect = 8'h08;
           3'd4:    fnSelect = 8'h10;
           3'd5:    fnSelect = 8'h20;
           3'd6:    fnSelect = 8'h40;
           3'd7:    fnSelect = 8'h80;
           endcase
       3'd1:
           case(adr[2:1])
           2'd0:    fnSelect = 8'h03;
           2'd1:    fnSelect = 8'h0C;
           2'd2:    fnSelect = 8'h30;
           2'd3:    fnSelect = 8'hC0;
           endcase
       3'd2:
           case(adr[2])
           1'b0:    fnSelect = 8'h0F;
           1'b1:    fnSelect = 8'hF0;
           endcase
       3'd3:
           fnSelect = 8'hFF;
       default: fnSelect = 8'h00;
       endcase
    `JMPI,`JMPIX:
       case(fn[1:0])
       2'd1:
           case(adr[2:1]) 
           2'd0:   fnSelect = 8'h03;
           2'd1:   fnSelect = 8'h0C;
           2'd2:   fnSelect = 8'h30;
           2'd3:   fnSelect = 8'hC0;
           endcase
       2'd2:
            case(adr[2])
            1'b0:   fnSelect = 8'h0F;
            1'b1:   fnSelect = 8'hF0;
            endcase
       2'd3:   fnSelect = 8'hFF;
       default:    fnSelect = 8'h00;
       endcase
    `LB,`LBU,`LBX,`SB,`LVB,`LBUX,`SBX:
		case(adr[2:0])
		3'd0:	fnSelect = 8'h01;
		3'd1:	fnSelect = 8'h02;
		3'd2:	fnSelect = 8'h04;
		3'd3:	fnSelect = 8'h08;
		3'd4:	fnSelect = 8'h10;
		3'd5:	fnSelect = 8'h20;
		3'd6:	fnSelect = 8'h40;
		3'd7:	fnSelect = 8'h80;
		endcase
	`LC,`LCU,`SC,`LVC,`LCX,`LCUX,`SCX:
		case(adr[2:1])
		2'd0:	fnSelect = 8'h03;
		2'd1:	fnSelect = 8'h0C;
		2'd2:	fnSelect = 8'h30;
		2'd3:	fnSelect = 8'hC0;
		endcase
	`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX:
		case(adr[2])
		1'b0:	fnSelect = 8'h0F;
		1'b1:	fnSelect = 8'hF0;
		endcase
	`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL,
	`PUSH,`PEA,`POP,`LINK,`UNLINK:
		fnSelect = 8'hFF;
	default:	fnSelect = 8'h00;
	endcase
end
endfunction
 
function [DBW-1:0] fnDatai;
input [7:0] opcode;
input [5:0] func;
input [DBW-1:0] dat;
input [7:0] sel;
begin
if (DBW==32)
	case(opcode)
	`STMV,`STCMP,`STFND,`INC:
	   case(func[2:0])
	   3'd0,3'd4:
		case(sel[3:0])
        4'h1:    fnDatai = dat[7:0];
        4'h2:    fnDatai = dat[15:8];
        4'h4:    fnDatai = dat[23:16];
        4'h8:    fnDatai = dat[31:24];
        default:    fnDatai = {DBW{1'b1}};
        endcase
       3'd1,3'd5:
		case(sel[3:0])
        4'h3:    fnDatai = dat[15:0];
        4'hC:    fnDatai = dat[31:16];
        default:    fnDatai = {DBW{1'b1}};
        endcase
       default:    
		fnDatai = dat[31:0];
	   endcase
	`JMPI,`JMPIX:
	   case(func[1:0])
	   2'd1:
	       case(sel[3:0])
	       4'h3:   fnDatai = dat[15:0];
	       4'hC:   fnDatai = dat[31:16];
	       default:    fnDatai = {DBW{1'b1}};
	       endcase
	   2'd2:   fnDatai = dat[31:0];
	   default:    fnDatai = dat[31:0];
	   endcase
	`LB,`LBX,`LVB:
		case(sel[3:0])
		8'h1:	fnDatai = {{24{dat[7]}},dat[7:0]};
		8'h2:	fnDatai = {{24{dat[15]}},dat[15:8]};
		8'h4:	fnDatai = {{24{dat[23]}},dat[23:16]};
		8'h8:	fnDatai = {{24{dat[31]}},dat[31:24]};
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LBU,`LBUX:
		case(sel[3:0])
		4'h1:	fnDatai = dat[7:0];
		4'h2:	fnDatai = dat[15:8];
		4'h4:	fnDatai = dat[23:16];
		4'h8:	fnDatai = dat[31:24];
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LC,`LVC,`LCX:
		case(sel[3:0])
		4'h3:	fnDatai = {{16{dat[15]}},dat[15:0]};
		4'hC:	fnDatai = {{16{dat[31]}},dat[31:16]};
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LCU,`LCUX:
		case(sel[3:0])
		4'h3:	fnDatai = dat[15:0];
		4'hC:	fnDatai = dat[31:16];
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LCL,`LWS,`POP,`UNLINK:
		fnDatai = dat[31:0];
	default:	fnDatai = {DBW{1'b1}};
	endcase
else
	case(opcode)
	`STMV,`STCMP,`STFND,`INC:
	   case(func[2:0])
	   3'd0,3'd4:
		case(sel)
        8'h01:    fnDatai = dat[DBW*1/8-1:0];
        8'h02:    fnDatai = dat[DBW*2/8-1:DBW*1/8];
        8'h04:    fnDatai = dat[DBW*3/8-1:DBW*2/8];
        8'h08:    fnDatai = dat[DBW*4/8-1:DBW*3/8];
        8'h10:    fnDatai = dat[DBW*5/8-1:DBW*4/8];
        8'h20:    fnDatai = dat[DBW*6/8-1:DBW*5/8];
        8'h40:    fnDatai = dat[DBW*7/8-1:DBW*6/8];
        8'h80:    fnDatai = dat[DBW-1:DBW*7/8];
        default:    fnDatai = {DBW{1'b1}};
        endcase
       3'd1,3'd5:
		case(sel)
        8'h03:    fnDatai = dat[DBW/4-1:0];
        8'h0C:    fnDatai = dat[DBW/2-1:DBW/4];
        8'h30:    fnDatai = dat[DBW*3/4-1:DBW/2];
        8'hC0:    fnDatai = dat[DBW-1:DBW*3/4];
        default:    fnDatai = {DBW{1'b1}};
        endcase
       3'd2,3'd6:
		case(sel)
        8'h0F:    fnDatai = dat[DBW/2-1:0];
        8'hF0:    fnDatai = dat[DBW-1:DBW/2];
        default:    fnDatai = {DBW{1'b1}};
        endcase
       3'd3,3'd7:   fnDatai = dat;
	   endcase
	`JMPI,`JMPIX:
	   case(func[1:0])
	   2'd1:
	       case(sel[7:0])
	       8'h03:  fnDatai = dat[15:0];
	       8'h0C:  fnDatai = dat[31:16];
	       8'h30:  fnDatai = dat[47:32];
	       8'hC0:  fnDatai = dat[63:48];
	       default:    fnDatai = dat[15:0];
	       endcase
	   2'd2:
	       case(sel[7:0])
           8'h0F:  fnDatai = dat[31:0];
           8'hF0:  fnDatai = dat[63:32];
           default: fnDatai = dat[31:0];
           endcase
       2'd3:    fnDatai = dat;
       default: fnDatai = dat;
	   endcase
	`LB,`LBX,`LVB:
		case(sel)
		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'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'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'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]};
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LBU,`LBUX:
		case(sel)
		8'h01:	fnDatai = dat[DBW*1/8-1:0];
		8'h02:	fnDatai = dat[DBW*2/8-1:DBW*1/8];
		8'h04:	fnDatai = dat[DBW*3/8-1:DBW*2/8];
		8'h08:	fnDatai = dat[DBW*4/8-1:DBW*3/8];
		8'h10:	fnDatai = dat[DBW*5/8-1:DBW*4/8];
		8'h20:	fnDatai = dat[DBW*6/8-1:DBW*5/8];
		8'h40:	fnDatai = dat[DBW*7/8-1:DBW*6/8];
		8'h80:	fnDatai = dat[DBW-1:DBW*7/8];
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LC,`LVC,`LCX:
		case(sel)
		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'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]};
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LCU,`LCUX:
		case(sel)
		8'h03:	fnDatai = dat[DBW/4-1:0];
		8'h0C:	fnDatai = dat[DBW/2-1:DBW/4];
		8'h30:	fnDatai = dat[DBW*3/4-1:DBW/2];
		8'hC0:	fnDatai = dat[DBW-1:DBW*3/4];
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LH,`LVH,`LHX:
		case(sel)
		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]};
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LHU,`LHUX:
		case(sel)
		8'h0F:	fnDatai = dat[DBW/2-1:0];
		8'hF0:	fnDatai = dat[DBW-1:DBW/2];
		default:	fnDatai = {DBW{1'b1}};
		endcase
	`LW,`LWX,`LVW,`LVWAR,`CAS,`LCL,`LWS,`POP,`UNLINK:
		case(sel)
		8'hFF:	fnDatai = dat;
		default:	fnDatai = {DBW{1'b1}};
		endcase
	default:	fnDatai = {DBW{1'b1}};
	endcase
end
endfunction
 
function [DBW-1:0] fnDatao;
input [7:0] opcode;
input [5:0] func;
input [DBW-1:0] dat;
if (DBW==32)
	case(opcode)
	`STMV,`INC:
	   case(func[2:0])
	   3'd0,3'd4:  fnDatao = {4{dat[7:0]}};
	   3'd1,3'd5:  fnDatao = {2{dat[15:8]}};
	   default:    fnDatao = dat;
	   endcase
	`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
	`PUSH,`PEA,`LINK:	fnDatao = dat;
	`SH,`SHX:	fnDatao = dat;
	`SC,`SCX:	fnDatao = {2{dat[15:0]}};
	`SB,`SBX:	fnDatao = {4{dat[7:0]}};
	default:	fnDatao = dat;
	endcase
else
	case(opcode)
	`STMV,`INC:
	   case(func[2:0])
	   3'd0,3'd4:  fnDatao = {8{dat[DBW/8-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'd3,3'd7:  fnDatao = dat;
	   endcase
	`SW,`SWCR,`SWX,`CAS,`SWS,`STI,
	`PUSH,`PEA,`LINK:	fnDatao = dat;
	`SH,`SHX:	fnDatao = {2{dat[DBW/2-1:0]}};
	`SC,`SCX:	fnDatao = {4{dat[DBW/4-1:0]}};
	`SB,`SBX:	fnDatao = {8{dat[DBW/8-1:0]}};
	default:	fnDatao = dat;
	endcase
endfunction
 
assign fetchbuf0_mem	= fnIsMem(opcode0);
assign fetchbuf0_jmp   = fnIsFlowCtrl(opcode0);
assign fetchbuf0_fp		= fnIsFP(opcode0);
assign fetchbuf0_rfw	= fnIsRFW(opcode0,fetchbuf0_instr);
assign fetchbuf0_pfw	= fnIsPFW(opcode0);
assign fetchbuf1_mem	= fnIsMem(opcode1);
assign fetchbuf1_jmp   = fnIsFlowCtrl(opcode1);
assign fetchbuf1_fp		= fnIsFP(opcode1);
assign fetchbuf1_rfw	= fnIsRFW(opcode1,fetchbuf1_instr);
assign fetchbuf1_pfw    = fnIsPFW(opcode1);
 
//
// 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}) ||
                      ({fetchbuf0_v, opcode0==`LOOP}  == {`VAL, `TRUE})
                        ;
assign take_branch1 = ({fetchbuf1_v, fnIsBranch(opcode1), predict_taken1}  == {`VAL, `TRUE, `TRUE}) ||
                      ({fetchbuf1_v, opcode1==`LOOP}  == {`VAL, `TRUE})
                        ;
assign take_branch = take_branch0 || take_branch1
        ;
 
always @*
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;
end
else if (opcode0==`LOOP && fetchbuf0_v) begin
    branch_pc <= fetchbuf0_pc + {{ABW-8{fetchbuf0_instr[23]}},fetchbuf0_instr[23:16]} + 64'd3;
end
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;
end
else if (opcode1==`LOOP && fetchbuf1_v) begin
    branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3;
end
else begin
    branch_pc <= RSTPC;  // set to something to prevent a latch
end
 
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) ||
                        ((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);
 
// "Stream" interrupt instructions into the instruction stream until an INT
// instruction commits. This avoids the problem of an INT instruction being
// stomped on by a previous branch instruction.
// Populate the instruction buffers with INT instructions for a hardware interrupt
// Also populate the instruction buffers with a call to the instruction error vector
// if an error occurred during instruction load time.
// Translate the BRK opcode to a syscall.
 
// 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
// signal.
 
// On a cache miss the instruction buffers are loaded with NOPs this prevents
// the PC from being trashed by invalid branch instructions.
reg [63:0] insn1a,insn2a;
reg [63:0] insn0,insn1,insn2;
always @*
//if (int_commit)
//	insn0 <= {8{8'h10}};	// load with NOPs
//else
if (nmi_edge & ~StatusHWI & ~int_commit)
	insn0 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
else if (ITLBMiss)
	insn0 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
else if (insnerr)
	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)
	insn0 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
else if (ihit) begin
	if (insn[7:0]==8'h00)
		insn0 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
	else
        insn0 <= insn[63:0];
end
else
	insn0 <= {8{8'h10}};	// load with NOPs
 
 
always @*
//if (int_commit)
//	insn1 <= {8{8'h10}};	// load with NOPs
//else
if (nmi_edge & ~StatusHWI & ~int_commit)
	insn1 <= {8'hFE,8'hCE,8'hA6,8'h01,8'hFE,8'hCE,8'hA6,8'h01};
else if (ITLBMiss)
	insn1 <= {8'hF9,8'hCE,8'hA6,8'h01,8'hF9,8'hCE,8'hA6,8'h01};
else if (insnerr)
	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)
	insn1 <= {vec_i,8'hCE,8'hA6,8'h01,vec_i,8'hCE,8'hA6,8'h01};
else if (ihit) begin
	if (insn1a[7:0]==8'h00)
		insn1 <= {8'h00,8'hCD,8'hA5,8'h01,8'h00,8'hCD,8'hA5,8'h01};
	else
		insn1 <= insn1a;
end
else
	insn1 <= {8{8'h10}};	// load with NOPs
 
 
// Find the second instruction in the instruction line.
always @(insn)
	case(fnInsnLength(insn))
	4'd1:	insn1a <= insn[71: 8];
	4'd2:	insn1a <= insn[79:16];
	4'd3:	insn1a <= insn[87:24];
	4'd4:	insn1a <= insn[95:32];
	4'd5:	insn1a <= insn[103:40];
	4'd6:	insn1a <= insn[111:48];
	4'd7:	insn1a <= insn[119:56];
	4'd8:	insn1a <= insn[127:64];
	default:	insn1a <= {8{8'h10}};	// NOPs
	endcase
 
// Return the immediate field of an instruction
function [63:0] fnImm;
input [127:0] insn;
case(insn[15:8])
`P:     fnImm = insn[33:16];
`CAS:	fnImm = {{56{insn[47]}},insn[47:40]};
`BCD:	fnImm = insn[47:40];
`TLB:	fnImm = insn[23:16];
`LOOP:	fnImm = {{56{insn[23]}},insn[23:16]};
`STP:   fnImm = insn[31:16];
`JSR:	fnImm = {{40{insn[47]}},insn[47:24]};
`JSRS:  fnImm = {{48{insn[39]}},insn[39:24]};
`BITFIELD:	fnImm = insn[47:32];
`SYS,`INT:	fnImm = {insn[31:24],4'h0};
//`CMPI,
8'h20,8'h21,8'h22,8'h23,
8'h24,8'h25,8'h26,8'h27,
8'h28,8'h29,8'h2A,8'h2B,
8'h2C,8'h2D,8'h2E,8'h2F,
`LDI,`LDIS,`ADDUIS:
	fnImm = {{54{insn[31]}},insn[31:22]};
`RTS:	fnImm = insn[19:16];
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS:	fnImm = 64'h0;
`STI:	fnImm = {{58{insn[33]}},insn[33:28]};
`PUSH:  fnImm = 64'hFFFFFFFFFFFFFFF8;   //-8
//`LINK:  fnImm = {insn[39:28],3'b000};
`JMPI,`LLA,
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
	fnImm = {{55{insn[36]}},insn[36:28]};
default:
	fnImm = {{52{insn[39]}},insn[39:28]};
endcase
 
endfunction
 
function [7:0] fnImm8;
input [127:0] insn;
case(insn[15:8])
`CAS:	fnImm8 = insn[47:40];
`BCD:	fnImm8 = insn[47:40];
`TLB:	fnImm8 = insn[23:16];
`LOOP:	fnImm8 = insn[23:16];
`STP:   fnImm8 = insn[23:16];
`JSR,`JSRS:	fnImm8 = insn[31:24];
`BITFIELD:	fnImm8 = insn[39:32];
`SYS,`INT:	fnImm8 = {insn[27:24],4'h0};
//`CMPI,
8'h20,8'h21,8'h22,8'h23,
8'h24,8'h25,8'h26,8'h27,
8'h28,8'h29,8'h2A,8'h2B,
8'h2C,8'h2D,8'h2E,8'h2F,
`LDI,`LDIS,`ADDUIS:	fnImm8 = insn[29:22];
`RTS:	fnImm8 = insn[19:16];
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS:	fnImm8 = 8'h00;
`STI:	fnImm8 = insn[35:28];
`PUSH:  fnImm8 = 8'hF8;
`ifdef STACKOPS
`LINK:  fnImm8 = {insn[32:28],3'b000};
`endif
`JMPI,`LLA,
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA:
	fnImm8 = insn[35:28];
default:	fnImm8 = insn[35:28];
endcase
endfunction
 
// Return MSB of immediate value for instruction
function fnImmMSB;
input [127:0] insn;
case(insn[15:8])
`CAS:	fnImmMSB = insn[47];
`TLB,`BCD,`STP:
	fnImmMSB = 1'b0;		// TLB regno is unsigned
`LOOP:
	fnImmMSB = insn[23];
`JSR:
	fnImmMSB = insn[47];
`JSRS:
    fnImmMSB = insn[39];
//`CMPI,
8'h20,8'h21,8'h22,8'h23,
8'h24,8'h25,8'h26,8'h27,
8'h28,8'h29,8'h2A,8'h2B,
8'h2C,8'h2D,8'h2E,8'h2F,
`LDI,`LDIS,`ADDUIS:
	fnImmMSB = insn[31];
`SYS,`INT,`CACHE,`LINK:
	fnImmMSB = 1'b0;		// SYS,INT are unsigned
`RTS,`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`RTS2,`STS:
	fnImmMSB = 1'b0;		// RTS is unsigned
`PUSH:  fnImmMSB = 1'b1;
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX,
`SBX,`SCX,`SHX,`SWX:
	fnImmMSB = insn[47];
`JMPI,`LLA,
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,
`SB,`SC,`SH,`SW,`SWCR,`STI,`LWS,`SWS,`INC,`LCL,`PEA:
	fnImmMSB = insn[36];
default:
	fnImmMSB = insn[39];
endcase
 
endfunction
 
function [63:0] fnImmImm;
input [63:0] insn;
case(insn[7:4])
4'd2:	fnImmImm = {{48{insn[15]}},insn[15: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'd5:	fnImmImm = {{24{insn[39]}},insn[39: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'd8:	fnImmImm = {insn[63:8],8'h00};
default:	fnImmImm = 64'd0;
endcase
endfunction
 
 
// Used during enque
// Operand A is a little more work than B or C as it may read from special
// purpose registers.
function [63:0] fnOpa;
input [7:0] opcode;
input [6:0] Ra;
input [63:0] ins;
input [63:0] rfo;
input [63:0] epc;
begin
`ifdef BITFIELDOPS
    if (opcode==`BITFIELD && ins[43:40]==`BFINSI)
        fnOpa = ins[21:16];
    else
`endif
	if (Ra[6])
		fnOpa = fnSpr(Ra[5:0],epc);
	else
		fnOpa = rfo;
end
endfunction
 
function [DBW-1:0] fnOpb;
input [7:0] opcode;
input [6:0] Rb;
input [63:0] ins;
input [63:0] rfo;
input [63:0] epc;
begin
    fnOpb = fnIsShiftiop(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==`STI ? ins[27:22] :
            Rb[6] ? fnSpr(Rb[5:0],epc) :
            rfo;
end                                
endfunction
 
// Used during enque
function [63:0] fnOpt;
input [6:0] tgt;
input [63:0] rfo;
input [63:0] epc;
begin
    if (tgt[6])
        fnOpt = fnSpr(tgt[5:0],epc);
    else
        fnOpt = rfo;
end
endfunction
 
// Returns TRUE if instruction is only allowed in kernel mode.
function fnIsKMOnly;
input [7:0] op;
`ifdef PRIVCHKS
    fnIsKMOnly = op==`RTI || op==`RTE || op==`RTD || op==`TLB || op==`CLI || op==`SEI ||
                 op==`STP
                ;
`else
    fnIsKMOnly = `FALSE;
`endif
endfunction
 
function fnIsKMOnlyReg;
input [6:0] regx;
`ifdef PRIVCHKS
    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
                    ;
`else
    fnIsKMOnlyReg = `FALSE;
`endif
endfunction
 
// Returns TRUE if the register is automatically valid.
function fnRegIsAutoValid;
input [6:0] regno;  // r0, c0, c15, tick
fnRegIsAutoValid = regno==7'h00 || regno==7'h50 || regno==7'h5F || regno==7'h72;
endfunction
 
function [15:0] fnRegstrGrp;
input [6:0] Rn;
if (!Rn[6]) begin
	fnRegstrGrp="GP";
end
else
	case(Rn[5:4])
	2'h0:	fnRegstrGrp="PR";
	2'h1:	fnRegstrGrp="CA";
	2'h2:	fnRegstrGrp="SG";
	2'h3:
	       case(Rn[3:0])
	       3'h0:   fnRegstrGrp="PA";
	       3'h3:   fnRegstrGrp="LC";
	       endcase
	endcase
 
endfunction
 
function [7:0] fnRegstr;
input [6:0] Rn;
begin
if (!Rn[6]) begin
	fnRegstr = Rn[5:0];
end
else
	fnRegstr = Rn[3:0];
end
endfunction
 
initial begin
	//
	// set up panic messages
	message[ `PANIC_NONE ]			= "NONE            ";
	message[ `PANIC_FETCHBUFBEQ ]		= "FETCHBUFBEQ     ";
	message[ `PANIC_INVALIDISLOT ]		= "INVALIDISLOT    ";
	message[ `PANIC_IDENTICALDRAMS ]	= "IDENTICALDRAMS  ";
	message[ `PANIC_OVERRUN ]		= "OVERRUN         ";
	message[ `PANIC_HALTINSTRUCTION ]	= "HALTINSTRUCTION ";
	message[ `PANIC_INVALIDMEMOP ]		= "INVALIDMEMOP    ";
	message[ `PANIC_INVALIDFBSTATE ]	= "INVALIDFBSTATE  ";
	message[ `PANIC_INVALIDIQSTATE ]	= "INVALIDIQSTATE  ";
	message[ `PANIC_BRANCHBACK ]		= "BRANCHBACK      ";
	message[ `PANIC_MEMORYRACE ]		= "MEMORYRACE      ";
end
 
//`include "Thor_issue_combo.v"
/*
assign  iqentry_imm[0] = fnHasConst(iqentry_op[0]),
	iqentry_imm[1] = fnHasConst(iqentry_op[1]),
	iqentry_imm[2] = fnHasConst(iqentry_op[2]),
	iqentry_imm[3] = fnHasConst(iqentry_op[3]),
	iqentry_imm[4] = fnHasConst(iqentry_op[4]),
	iqentry_imm[5] = fnHasConst(iqentry_op[5]),
	iqentry_imm[6] = fnHasConst(iqentry_op[6]),
	iqentry_imm[7] = fnHasConst(iqentry_op[7]);
*/
//
// additional logic for ISSUE
//
// 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 
// 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
//
/*
always @*
for (n = 0; n < QENTRIES; n = n + 1)
    iq_cmt[n] <= fnPredicate(iqentry_pred[n], iqentry_cond[n]) ||
        (iqentry_cond[n] < 4'h2 && ({iqentry_pred[n],iqentry_cond[n]}!=8'h90));
*/
wire [QENTRIES-1:0] args_valid;
wire [QENTRIES-1:0] could_issue;
 
genvar g;
generate
begin : argsv
 
for (g = 0; g < QENTRIES; g = g + 1)
begin
assign  iqentry_imm[g] = fnHasConst(iqentry_op[g]);
 
assign args_valid[g] =
			(iqentry_p_v[g]
				|| (iqentry_p_s[g]==alu0_sourceid && alu0_v)
				|| (iqentry_p_s[g]==alu1_sourceid && alu1_v))
			&& (iqentry_a1_v[g] 
//				|| (iqentry_mem[g] && !iqentry_agen[g] && iqentry_op[g]!=`TLB)
				|| (iqentry_a1_s[g] == alu0_sourceid && alu0_v)
				|| (iqentry_a1_s[g] == alu1_sourceid && alu1_v))
			&& (iqentry_a2_v[g] 
				|| (iqentry_a2_s[g] == alu0_sourceid && alu0_v)
				|| (iqentry_a2_s[g] == alu1_sourceid && alu1_v))
			&& (iqentry_a3_v[g] 
				|| (iqentry_a3_s[g] == alu0_sourceid && alu0_v)
				|| (iqentry_a3_s[g] == alu1_sourceid && alu1_v))
			&& (iqentry_T_v[g]
				|| (iqentry_T_s[g] == alu0_sourceid && alu0_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] &&
                         (iqentry_mem[g] ? !iqentry_agen[g] : 1'b1);
 
end
end
endgenerate
 
// 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
// 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 
// divide.
always @*//(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
begin
	iqentry_issue = 8'h00;
	iqentry_islot[0] = 2'b00;
	iqentry_islot[1] = 2'b00;
	iqentry_islot[2] = 2'b00;
	iqentry_islot[3] = 2'b00;
	iqentry_islot[4] = 2'b00;
	iqentry_islot[5] = 2'b00;
	iqentry_islot[6] = 2'b00;
	iqentry_islot[7] = 2'b00;
	if (could_issue[head0] & !iqentry_fp[head0] & alu0_idle) begin
		iqentry_issue[head0] = `TRUE;
		iqentry_islot[head0] = 2'b00;
	end
	else if (could_issue[head1] & !iqentry_fp[head1]  & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0]))
	begin
		iqentry_issue[head1] = `TRUE;
		iqentry_islot[head1] = 2'b00;
	end
	else if (could_issue[head2] & !iqentry_fp[head2] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	)
	begin
		iqentry_issue[head2] = `TRUE;
		iqentry_islot[head2] = 2'b00;
	end
	else if (could_issue[head3] & !iqentry_fp[head3] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	) begin
		iqentry_issue[head3] = `TRUE;
		iqentry_islot[head3] = 2'b00;
	end
	else if (could_issue[head4] & !iqentry_fp[head4] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	) begin
		iqentry_issue[head4] = `TRUE;
		iqentry_islot[head4] = 2'b00;
	end
	else if (could_issue[head5] & !iqentry_fp[head5] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	) begin
		iqentry_issue[head5] = `TRUE;
		iqentry_islot[head5] = 2'b00;
	end
	else if (could_issue[head6] & !iqentry_fp[head6] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	) begin
		iqentry_issue[head6] = `TRUE;
		iqentry_islot[head6] = 2'b00;
	end
	else if (could_issue[head7] & !iqentry_fp[head7] & alu0_idle
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	&& !(iqentry_v[head6] && iqentry_sync[head6])
	) begin
		iqentry_issue[head7] = `TRUE;
		iqentry_islot[head7] = 2'b00;
	end
 
    // Don't bother checking head0, it should have issued to the first
    // instruction.
	if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1])
	&& !(iqentry_v[head0] && iqentry_sync[head0]))
	begin
		iqentry_issue[head1] = `TRUE;
		iqentry_islot[head1] = 2'b01;
	end
	else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	)
	begin
		iqentry_issue[head2] = `TRUE;
		iqentry_islot[head2] = 2'b01;
	end
	else if (could_issue[head3] & !iqentry_fp[head3] && !iqentry_issue[head3] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	) begin
		iqentry_issue[head3] = `TRUE;
		iqentry_islot[head3] = 2'b01;
	end
	else if (could_issue[head4] & !iqentry_fp[head4] && !iqentry_issue[head4] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	) begin
		iqentry_issue[head4] = `TRUE;
		iqentry_islot[head4] = 2'b01;
	end
	else if (could_issue[head5] & !iqentry_fp[head5] && !iqentry_issue[head5] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	) begin
		iqentry_issue[head5] = `TRUE;
		iqentry_islot[head5] = 2'b01;
	end
	else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	) begin
		iqentry_issue[head6] = `TRUE;
		iqentry_islot[head6] = 2'b01;
	end
	else if (could_issue[head7] & !iqentry_fp[head7] && !iqentry_issue[head7] & alu1_idle
	&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7])
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	&& !(iqentry_v[head6] && iqentry_sync[head6])
	) begin
		iqentry_issue[head7] = `TRUE;
		iqentry_islot[head7] = 2'b01;
	end
end
 
 
`ifdef FLOATING_POINT
reg [3:0] fpispot;
always @(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7)
begin
	iqentry_fpissue = 8'h00;
	iqentry_fpislot[0] = 2'b00;
	iqentry_fpislot[1] = 2'b00;
	iqentry_fpislot[2] = 2'b00;
	iqentry_fpislot[3] = 2'b00;
	iqentry_fpislot[4] = 2'b00;
	iqentry_fpislot[5] = 2'b00;
	iqentry_fpislot[6] = 2'b00;
	iqentry_fpislot[7] = 2'b00;
	fpispot = head0;
	if (could_issue[head0] & iqentry_fp[head0]) begin
		iqentry_fpissue[head0] = `TRUE;
		iqentry_fpislot[head0] = 2'b00;
		fpispot = head0;
	end
	else if (could_issue[head1] & iqentry_fp[head1]
	&& !(iqentry_v[head0] && iqentry_sync[head0]))
	begin
		iqentry_fpissue[head1] = `TRUE;
		iqentry_fpislot[head1] = 2'b00;
		fpispot = head1;
	end
	else if (could_issue[head2] & iqentry_fp[head2]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	)
	begin
		iqentry_fpissue[head2] = `TRUE;
		iqentry_fpislot[head2] = 2'b00;
		fpispot = head2;
	end
	else if (could_issue[head3] & iqentry_fp[head3]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	) begin
		iqentry_fpissue[head3] = `TRUE;
		iqentry_fpislot[head3] = 2'b00;
		fpispot = head3;
	end
	else if (could_issue[head4] & iqentry_fp[head4]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	) begin
		iqentry_fpissue[head4] = `TRUE;
		iqentry_fpislot[head4] = 2'b00;
		fpispot = head4;
	end
	else if (could_issue[head5] & iqentry_fp[head5]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	) begin
		iqentry_fpissue[head5] = `TRUE;
		iqentry_fpislot[head5] = 2'b00;
		fpispot = head5;
	end
	else if (could_issue[head6] & iqentry_fp[head6]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	) begin
		iqentry_fpissue[head6] = `TRUE;
		iqentry_fpislot[head6] = 2'b00;
		fpispot = head6;
	end
	else if (could_issue[head7] & iqentry_fp[head7]
	&& !(iqentry_v[head0] && iqentry_sync[head0])
	&& !(iqentry_v[head1] && iqentry_sync[head1])
	&& !(iqentry_v[head2] && iqentry_sync[head2])
	&& !(iqentry_v[head3] && iqentry_sync[head3])
	&& !(iqentry_v[head4] && iqentry_sync[head4])
	&& !(iqentry_v[head5] && iqentry_sync[head5])
	&& !(iqentry_v[head6] && iqentry_sync[head6])
	) begin
		iqentry_fpissue[head7] = `TRUE;
		iqentry_fpislot[head7] = 2'b00;
		fpispot = head7;
	end
	else
		fpispot = 4'd8;
 
end
`endif
 
// 
// additional logic for handling a branch miss (STOMP logic)
//
wire [QENTRIES-1:0] alu0_issue_;
wire [QENTRIES-1:0] alu1_issue_;
wire [QENTRIES-1:0] fp0_issue_;
generate
begin : stomp_logic
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)
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)
begin
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 fp0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_fpissue[g] && iqentry_islot[g]==2'd0);
end
end
endgenerate
 
assign alu0_issue = |alu0_issue_;
assign alu1_issue = |alu1_issue_;
`ifdef FLOATING_POINT
assign fp0_issue = |fp0_issue_;
`endif
 
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.
// "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.
// That means no flow control operations or instructions that can cause an
// exception can be before the store.
 
// 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
// 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
// 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_head1 =	~iqentry_stomp[head1] && iqentry_memready[ head1 ] 		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				// ... and there is no address-overlap with any preceding instruction
				&& (!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]))
				// ... and, if it is a SW, there is no chance of it being undone
				&& (fnIsStore(iqentry_op[head1]) ? !fnIsFlowCtrl(iqentry_op[head0])
				&& !fnCanException(iqentry_op[head0],iqentry_fn[head0]) : `TRUE)
				&& (!iqentry_cas[head1])
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) 
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
 
assign iqentry_memissue_head2 =	~iqentry_stomp[head2] && iqentry_memready[ head2 ]		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_mem[head1] || (iqentry_agen[head1] & iqentry_out[head1]) 
					|| (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
				&& (fnIsStore(iqentry_op[head2]) ?
				    !fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) && 
				    !fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) 
				    : `TRUE)
				&& (!iqentry_cas[head2])
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
				&& !(iqentry_v[head1] && iqentry_memsb[head1])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
//					(   !fnIsFlowCtrl(iqentry_op[head0])
//					 && !fnIsFlowCtrl(iqentry_op[head1])));
 
assign iqentry_memissue_head3 =	~iqentry_stomp[head3] && iqentry_memready[ head3 ] 	// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				&& ~iqentry_memready[head2] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_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_mem[head2] || (iqentry_agen[head2] & iqentry_out[head2]) 
					|| (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
				&& (fnIsStore(iqentry_op[head3]) ?
                    !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[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) 
                    : `TRUE)
				&& (!iqentry_cas[head3])
				// ... and there is no memory barrier
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
                && !(iqentry_v[head1] && iqentry_memsb[head1]) 
                && !(iqentry_v[head2] && iqentry_memsb[head2])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
/*					(   !fnIsFlowCtrl(iqentry_op[head0])
					 && !fnIsFlowCtrl(iqentry_op[head1])
					 && !fnIsFlowCtrl(iqentry_op[head2])));
*/
assign iqentry_memissue_head4 =	~iqentry_stomp[head4] && iqentry_memready[ head4 ] 		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				&& ~iqentry_memready[head2] 
				&& ~iqentry_memready[head3] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_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_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_mem[head3] || (iqentry_agen[head3] & iqentry_out[head3]) 
					|| (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
				&& (fnIsStore(iqentry_op[head4]) ?
                    !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[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) && 
                    !fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) 
                    : `TRUE)
				&& (!iqentry_cas[head4])
				// ... and there is no memory barrier
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
				&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
                && !(iqentry_v[head1] && iqentry_memsb[head1]) 
                && !(iqentry_v[head2] && iqentry_memsb[head2]) 
                && !(iqentry_v[head3] && iqentry_memsb[head3])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
/* ||
					(   !fnIsFlowCtrl(iqentry_op[head0])
					 && !fnIsFlowCtrl(iqentry_op[head1])
					 && !fnIsFlowCtrl(iqentry_op[head2])
					 && !fnIsFlowCtrl(iqentry_op[head3])));
*/
assign iqentry_memissue_head5 =	~iqentry_stomp[head5] && iqentry_memready[ head5 ] 		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				&& ~iqentry_memready[head2] 
				&& ~iqentry_memready[head3] 
				&& ~iqentry_memready[head4] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_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_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_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_mem[head4] || (iqentry_agen[head4] & iqentry_out[head4]) 
					|| (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
				&& (fnIsStore(iqentry_op[head5]) ?
                    !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[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) && 
                    !fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) && 
                    !fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) 
                    : `TRUE)
				&& (!iqentry_cas[head5])
				// ... and there is no memory barrier
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
				&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
				&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
                && !(iqentry_v[head1] && iqentry_memsb[head1]) 
                && !(iqentry_v[head2] && iqentry_memsb[head2]) 
                && !(iqentry_v[head3] && iqentry_memsb[head3]) 
                && !(iqentry_v[head4] && iqentry_memsb[head4])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
/*||
					(   !fnIsFlowCtrl(iqentry_op[head0])
					 && !fnIsFlowCtrl(iqentry_op[head1])
					 && !fnIsFlowCtrl(iqentry_op[head2])
					 && !fnIsFlowCtrl(iqentry_op[head3])
					 && !fnIsFlowCtrl(iqentry_op[head4])));
*/
assign iqentry_memissue_head6 =	~iqentry_stomp[head6] && iqentry_memready[ head6 ] 		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				&& ~iqentry_memready[head2] 
				&& ~iqentry_memready[head3] 
				&& ~iqentry_memready[head4] 
				&& ~iqentry_memready[head5] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_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_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_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_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_mem[head5] || (iqentry_agen[head5] & iqentry_out[head5]) 
					|| (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
				&& (fnIsStore(iqentry_op[head6]) ?
                    !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[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) && 
                    !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[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) 
                    : `TRUE)
				&& (!iqentry_cas[head6])
				// ... and there is no memory barrier
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
				&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
				&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
				&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
                && !(iqentry_v[head1] && iqentry_memsb[head1]) 
                && !(iqentry_v[head2] && iqentry_memsb[head2]) 
                && !(iqentry_v[head3] && iqentry_memsb[head3]) 
                && !(iqentry_v[head4] && iqentry_memsb[head4]) 
                && !(iqentry_v[head5] && iqentry_memsb[head5])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
				/*||
					(   !fnIsFlowCtrl(iqentry_op[head0])
					 && !fnIsFlowCtrl(iqentry_op[head1])
					 && !fnIsFlowCtrl(iqentry_op[head2])
					 && !fnIsFlowCtrl(iqentry_op[head3])
					 && !fnIsFlowCtrl(iqentry_op[head4])
					 && !fnIsFlowCtrl(iqentry_op[head5])));
*/
assign iqentry_memissue_head7 =	~iqentry_stomp[head7] && iqentry_memready[ head7 ] 		// addr and data are valid
				// ... and no preceding instruction is ready to go
				&& ~iqentry_memready[head0]
				&& ~iqentry_memready[head1] 
				&& ~iqentry_memready[head2] 
				&& ~iqentry_memready[head3] 
				&& ~iqentry_memready[head4] 
				&& ~iqentry_memready[head5] 
				&& ~iqentry_memready[head6] 
				// ... and there is no address-overlap with any preceding instruction
				&& (!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_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_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_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_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_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_mem[head6] || (iqentry_agen[head6] & iqentry_out[head6]) 
					|| (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
				&& (fnIsStore(iqentry_op[head7]) ?
                    !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[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) && 
                    !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[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) && 
                    !fnIsFlowCtrl(iqentry_op[head6]) && !fnCanException(iqentry_op[head6],iqentry_fn[head6]) 
                    : `TRUE)
				&& (!iqentry_cas[head7])
				// ... and there is no memory barrier
				&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0])
				&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1])
				&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2])
				&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3])
				&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4])
				&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5])
				&& !(iqentry_v[head6] && fnIsMem(iqentry_op[head6]) && iqentry_memdb[head6])
				// ... and there is no instruction barrier
				&& !(iqentry_v[head0] && iqentry_memsb[head0]) 
                && !(iqentry_v[head1] && iqentry_memsb[head1]) 
                && !(iqentry_v[head2] && iqentry_memsb[head2]) 
                && !(iqentry_v[head3] && iqentry_memsb[head3]) 
                && !(iqentry_v[head4] && iqentry_memsb[head4]) 
                && !(iqentry_v[head5] && iqentry_memsb[head5]) 
                && !(iqentry_v[head6] && iqentry_memsb[head6])
				&& cstate==IDLE && !dcache_access_pending && dram0==0
				;
 
`include "Thor_execute_combo.v"
//`include "Thor_memory_combo.v"
// additional DRAM-enqueue logic
 
Thor_TLB #(DBW) utlb1
(
	.rst(rst_i),
	.clk(clk),
	.km(km),
	.pc(spc),
	.ea(dram0_addr),
	.ppc(ppc),
	.pea(pea),
	.iuncached(iuncached),
	.uncached(uncached),
	.m1IsStore(we_o),
	.ASID(asid),
	.op(tlb_op),
	.state(tlb_state),
	.regno(tlb_regno),
	.dati(tlb_data),
	.dato(tlb_dato),
	.ITLBMiss(ITLBMiss),
	.DTLBMiss(DTLBMiss),
	.HTLBVirtPageo()
);
 
assign dram_avail = (dram0 == `DRAMSLOT_AVAIL || dram1 == `DRAMSLOT_AVAIL || dram2 == `DRAMSLOT_AVAIL);
 
generate
begin : memr
    for (g = 0; g < QENTRIES; g = g + 1)
    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_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
endgenerate
 
/*
assign
    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));
 
// This signal needed to stave off an instruction cache access.
assign mem_issue =
    iqentry_memissue_head0 |
    iqentry_memissue_head1 |
    iqentry_memissue_head2 |
    iqentry_memissue_head3 |
    iqentry_memissue_head4 |
    iqentry_memissue_head5 |
    iqentry_memissue_head6 |
    iqentry_memissue_head7
    ;
 
// Nybble slices for predicate register forwarding
wire [3:0] alu0nyb[0:15];
wire [3:0] alu1nyb[0:15];
wire [3:0] cmt0nyb[0:15];
wire [3:0] cmt1nyb[0:15];
 
generate
begin : nybs
    for (g = 0; g < DBW/4; g = g + 1)
    begin
assign alu0nyb[g] = alu0_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 cmt1nyb[g] = commit1_bus[g*4+3:g*4];
    end
end
endgenerate
 
//`include "Thor_commit_combo.v"
 
assign commit0_v = ({iqentry_v[head0], iqentry_done[head0]} == 2'b11 && ~|panic);
assign commit1_v = ({iqentry_v[head0], iqentry_done[head0]} != 2'b10 
		&& {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 commit1_id = {iqentry_mem[head1], head1};	// if a memory op, it has a DRAM-bus id
 
assign commit0_tgt = iqentry_tgt[head0];
assign commit1_tgt = iqentry_tgt[head1];
 
assign commit0_bus = iqentry_res[head0];
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.
// 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
// 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) ||
                    (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 &&
                        (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 &&
                        (iqentry_tgt[head1][3:0]==4'hD || iqentry_tgt[head1][3:0]==4'hB))) && commit1_v);
`ifdef DEBUG_LOGIC                       
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) ||
       (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);
`endif
 
always @(posedge clk)
	if (rst_i)
		tick <= 64'd0;
	else
		tick <= tick + 64'd1;
 
always @(posedge clk)
	if (rst_i)
		nmi1 <= 1'b0;
	else
		nmi1 <= nmi_i;
 
//-----------------------------------------------------------------------------
// Clock control
// - reset or NMI reenables the clock
// - this circuit must be under the clk_i domain
//-----------------------------------------------------------------------------
//
reg cpu_clk_en;
reg [15:0] clk_throttle;
reg [15:0] clk_throttle_new;
reg ld_clk_throttle;
 
//BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
 
reg lct1;
always @(posedge clk_i)
if (rst_i) begin
	cpu_clk_en <= 1'b1;
	lct1 <= 1'b0;
	clk_throttle <= STARTUP_POWER;	// 50% power
end
else begin
	lct1 <= ld_clk_throttle;
	clk_throttle <= {clk_throttle[14:0],clk_throttle[15]};
	if (ld_clk_throttle && !lct1) begin
		clk_throttle <= clk_throttle_new;
    end
	if (nmi_i)
		clk_throttle <= STARTUP_POWER;
	cpu_clk_en <= clk_throttle[15];
end
 
// Clock throttling bypassed for now
assign clk_o = clk;
assign clk = clk_i;
 
//-----------------------------------------------------------------------------
// 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
// logic isn't placed in the same always block.
//-----------------------------------------------------------------------------
 
always @(posedge clk) begin
 
	if (nmi_i & !nmi1)
		nmi_edge <= 1'b1;
 
	ld_clk_throttle <= `FALSE;
	dram_v <= `INV;
	alu0_ld <= 1'b0;
	alu1_ld <= 1'b0;
`ifdef FLOATING_POINT
	fp0_ld <= 1'b0;
`endif
 
    // Interrupt enable countdown delay.    
    if (imcd!=6'h3f)
        imcd <= {imcd[4:0],1'b0};
    if (imcd==6'd0) begin
        im <= 1'b0;
        imcd <= 6'h3f;
    end
 
    mem_stringmiss <= `FALSE;
    if (mem_stringmissx) begin
        mem_stringmiss <= `TRUE;
//        dram0_op <= `NOP;   // clears string miss
    end
	ic_invalidate <= `FALSE;
	dc_invalidate <= `FALSE;
	ic_invalidate_line <= `FALSE;
    dc_invalidate_line <= `FALSE;
    alu0_dataready <= `FALSE;
    alu1_dataready <= `FALSE;
 
    // Reset segmentation flag once operating in non-segmented area.
    if (pc[ABW-1:ABW-4]==4'hF)
        pc[ABW] <= 1'b0;
 
    if (rst_i)
        cstate <= RESET1;
	if (rst_i||cstate==RESET1||cstate==RESET2) begin
	    imcd <= 6'h3F;
	    wb_nack();
`ifdef PCHIST
	    pc_cap <= `TRUE;
`endif
	    ierr <= 1'b0;
		GM <= 8'hFF;
		nmi_edge <= 1'b0;
		pc <= RSTPC[ABW-1:0];
		StatusHWI <= `TRUE;		// disables interrupts at startup until an RTI instruction is executed.
		im <= 1'b1;
		imb <= 1'b1;
		ic_invalidate <= `TRUE;
		dc_invalidate <= `TRUE;
		fetchbuf <= 1'b0;
		fetchbufA_v <= `INV;
		fetchbufB_v <= `INV;
		fetchbufC_v <= `INV;
		fetchbufD_v <= `INV;
		fetchbufA_instr <= {8{8'h10}};
		fetchbufB_instr <= {8{8'h10}};
		fetchbufC_instr <= {8{8'h10}};
		fetchbufD_instr <= {8{8'h10}};
		fetchbufA_pc <= {{DBW-4{1'b1}},4'h0};
		fetchbufB_pc <= {{DBW-4{1'b1}},4'h0};
		fetchbufC_pc <= {{DBW-4{1'b1}},4'h0};
		fetchbufD_pc <= {{DBW-4{1'b1}},4'h0};
		for (i=0; i< QENTRIES; i=i+1) begin
			iqentry_v[i] <= `INV;
			iqentry_agen[i] <= `FALSE;
			iqentry_op[i] <= `NOP;
			iqentry_memissue[i] <= `FALSE;
			iqentry_a1[i] <= 64'd0;
			iqentry_a2[i] <= 64'd0;
			iqentry_a3[i] <= 64'd0;
			iqentry_T[i] <= 64'd0;
			iqentry_a1_v[i] <= `INV;
			iqentry_a2_v[i] <= `INV;
			iqentry_a3_v[i] <= `INV;
			iqentry_T_v[i] <= `INV;
			iqentry_a1_s[i] <= 4'd0;
			iqentry_a2_s[i] <= 4'd0;
			iqentry_a3_s[i] <= 4'd0;
			iqentry_T_s[i] <= 4'd0;
		end
		// All the register are flagged as valid on startup even though they
		// may not contain valid data. Otherwise the processor will stall
		// waiting for the registers to become valid. Ideally the registers
		// 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
		// to stall.
		for (n = 1; n < NREGS; n = n + 1) begin
			rf_v[n] = `VAL;
`ifdef SIMULATION
			rf_source[n] <= 4'd0;
`endif
        dbg_ctrl <= {DBW{1'b0}};
`ifdef SIMULATION
        dbg_adr0 <= 0;
        dbg_adr1 <= 0;
        dbg_adr2 <= 0;
        dbg_adr3 <= 0;
`endif
		end
		if (ABW==32)
		  sregs_lmt[7] = 20'hFFFFF;
		else
		  sregs_lmt[7] = 52'hFFFFFFFFFFFFF;
		rf_source[0] <= 4'd0;
//		rf_v[0] = `VAL;
//		rf_v[7'h50] = `VAL;
//		rf_v[7'h5F] = `VAL;
		alu0_available <= `TRUE;
		alu1_available <= `TRUE;
        reset_tail_pointers(1);
		head0 <= 3'd0;
		head1 <= 3'd1;
		head2 <= 3'd2;
		head3 <= 3'd3;
		head4 <= 3'd4;
		head5 <= 3'd5;
		head6 <= 3'd6;
		head7 <= 3'd7;
		dram0 <= 3'b00;
		dram1 <= 3'b00;
		dram2 <= 3'b00;
		tlb_state <= 3'd0;
		panic <= `PANIC_NONE;
		string_pc <= 64'd0;
		// The pc wraps around to address zero while fetching the reset vector.
		// This causes the processor to use the code segement register so the
		// CS has to be defined for reset.
		sregs[7] <= RSTCSEG;
		for (i=0; i < 16; i=i+1)
			pregs[i] <= 4'd0;
		asid <= 8'h00;
		rrmapno <= 3'd0;
		dram0_id <= 0;
		alu1_sourceid <= 0;
	end
 
	// The following registers are always valid
	rf_v[7'h00] = `VAL;
	rf_v[7'h50] = `VAL;	// C0
	rf_v[7'h5F] = `VAL;	// C15 (PC)
	rf_v[7'h72] = `VAL; // tick
    queued1 = `FALSE;
    queued2 = `FALSE;
    allowq = `TRUE;
    dbg_stat <= dbg_stat | dbg_stat1x;
 
	did_branchback <= take_branch;
	did_branchback0 <= take_branch0;
	did_branchback1 <= take_branch1;
 
`include "Thor_Retarget.v"
/*
	if (branchmiss) begin
		for (n = 1; n < NREGS; n = n + 1)
			if (rf_v[n] == `INV && ~livetarget[n]) begin
			  $display("brmiss: rf_v[%d] <= VAL",n);
			  rf_v[n] = `VAL;
			end
 
	    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_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_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_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 };
 
	end
*/
	if (ihit) begin
		$display("\r\n");
		$display("TIME %0d", $time);
	end
 
// 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
//
// why is it happening here and not in another phase?
// 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.
// requires BLOCKING assignments, so that we can read from rf[i] later.
//
if (commit0_v) begin
        if (!rf_v[ commit0_tgt ]) begin 
            rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || ((branchmiss) && iqentry_source[ commit0_id[2:0] ]);
        end
        if (commit0_tgt != 7'd0) $display("r%d <- %h", commit0_tgt, commit0_bus);
end
if (commit1_v) begin
        if (!rf_v[ commit1_tgt ]) begin 
            rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| ((branchmiss) && iqentry_source[ commit1_id[2:0] ]);
        end
        if (commit1_tgt != 7'd0) $display("r%d <- %h", commit1_tgt, commit1_bus);
end
 
// This chunk of code has to be before the enqueue stage so that the agen bit
// can be reset to zero by enqueue.
// 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_done) begin
        alu0_dataready <= `TRUE;
    end
end
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
    if (alu0_done) begin
        alu0_dataready <= `TRUE;
    end
end
 
if (alu0_v) begin
	if (|alu0_exc)
	    set_exception(alu0_id,
	       alu0_exc==`EXC_PRIV ? 8'd245 :
	       alu0_exc==`EXC_DBZ ? 8'd241 :
	       alu0_exc==`EXC_CHK ? 8'd239 : 8'h00);
	else begin
        if (iqentry_op[alu0_id[2:0]]!=`IMM)
            iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ 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;
        else
            iqentry_res	[ alu0_id[2:0] ] <= alu0_bus;
        iqentry_out	[ alu0_id[2:0] ] <= `FALSE;
		iqentry_cmt [ alu0_id[2:0] ] <= alu0_cmt;
        iqentry_agen[ alu0_id[2:0] ] <= `TRUE;
	end
end
 
 
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI) && ALU1BIG) begin
    if (alu1_done) begin
        alu1_dataready <= `TRUE;
    end
end
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
    if (alu1_done) begin
        alu1_dataready <= `TRUE;
    end
end
 
if (alu1_v) begin
	if (|alu1_exc)
	    set_exception(alu1_id,
	       alu1_exc==`EXC_PRIV ? 8'd245 :
	       alu1_exc==`EXC_DBZ ? 8'd241 :
	       alu1_exc==`EXC_CHK ? 8'd239 : 8'h00);
	else begin
        if (iqentry_op[alu1_id[2:0]]!=`IMM)
             iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ 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;
         else
             iqentry_res [ alu1_id[2:0] ] <= alu1_bus;
        iqentry_out	[ alu1_id[2:0] ] <= `FALSE;
		iqentry_cmt [ alu1_id[2:0] ] <= alu1_cmt;
        iqentry_agen[ alu1_id[2:0] ] <= `TRUE;
	end
end
 
`ifdef FLOATING_POINT
if (fp0_v) begin
	$display("0results to iq[%d]=%h", fp0_id[2:0],fp0_bus);
	if (|fp0_exc)
	    set_exception(fp0_id, fp0_exc);
	else begin
		iqentry_res	[ fp0_id[2:0] ] <= fp0_bus;
		iqentry_done[ fp0_id[2:0] ] <= fp0_done || !fp0_cmt;
		iqentry_out	[ fp0_id[2:0] ] <= `FALSE;
		iqentry_cmt [ fp0_id[2:0] ] <= fp0_cmt;
		iqentry_agen[ fp0_id[2:0] ] <= `TRUE;
	end
end
`endif
 
//-------------------------------------------------------------------------------
// ENQUEUE
//
// 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
// 0, 1, or 2 of the fetch buffers may have valid data
// 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
// branch, (set branchback/backpc and delete any instructions after it in
// fetchbuf)
//
// 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
// tracked in the queue stage by variables queued1,queued2,queued3. Blocking
// assignments are used for these vars.
//-------------------------------------------------------------------------------
//
    exception_set = `FALSE;
    queued1 = `FALSE;
    queued2 = `FALSE;
    allowq = `TRUE;
    qstomp = `FALSE;
    if (branchmiss) // don't bother doing anything if there's been a branch miss
        reset_tail_pointers(0);
    else begin
        case ({fetchbuf0_v, fetchbuf1_v && fnNumReadPorts(fetchbuf1_instr) <=  ports_avail})
        2'b00: ; // do nothing
        2'b01:  enque1(tail0,1,0,1);
        2'b10:  enque0(tail0,1,0,1);
        2'b11:  begin
                enque0(tail0,1,1,1);
                if (allowq)
                    enque1(tail1,2,0,0);
                validate_args();
                end
        endcase
    end
 
//------------------------------------------------------------------------------
// FETCH
//
// 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
// like alpha approach)
//------------------------------------------------------------------------------
//
if (branchmiss) begin
    $display("pc <= %h", misspc);
    pc <= misspc;
    fetchbuf <= 1'b0;
    fetchbufA_v <= 1'b0;
    fetchbufB_v <= 1'b0;
    fetchbufC_v <= 1'b0;
    fetchbufD_v <= 1'b0;
end
else if (take_branch) begin
	if (fetchbuf == 1'b0) begin
		case ({fetchbufA_v,fetchbufB_v,fetchbufC_v,fetchbufD_v})
		4'b0000:
			begin
			    fetchCD();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbuf <= 1'b1;
			end
		4'b0100:
			begin
			    fetchCD();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbufB_v <= !queued1;
				if (queued1) begin
				    fetchbufB_instr <= 64'd0;
					fetchbuf <= 1'b1;
				end
				if (queued2|queued3)
				    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b0111:
			begin
				fetchbufB_v <= !queued1;
				if (queued1) begin
					fetchbuf <= 1'b1;
				    fetchbufB_instr <= 64'd0;
				end
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1000:
			begin
			    fetchCD();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbufA_v <= !queued1;
				if (queued1) begin
					fetchbuf <= 1'b1;
				    fetchbufA_instr <= 64'd0;
				end
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1011:
			begin
				fetchbufA_v <= !queued1;
				if (queued1) begin
					fetchbuf <= 1'b1;
				    fetchbufB_instr <= 64'd0;
			    end
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1100: 
			// Note that there is no point to loading C,D here because
			// there is a predicted taken branch that would stomp on the
			// instructions anyways.
			if ((fnIsBranch(opcodeA) && predict_takenBr)||opcodeA==`LOOP) begin
				pc <= branch_pc;
				fetchbufA_v <= !(queued1|queued2);
				fetchbufB_v <= `INV;		// stomp on it
				// may as well stick with same fetchbuf
			end
			else begin
				if (did_branchback0) begin
				    fetchCD();
					if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
					fetchbufA_v <= !(queued1|queued2);
					fetchbufB_v <= !queued2;
					if (queued2)
						fetchbuf <= 1'b1;
				end
				else begin
					pc[ABW-1:0] <= branch_pc;
					fetchbufA_v <= !(queued1|queued2);
					fetchbufB_v <= !queued2;
					// may as well keep the same fetchbuffer
				end
			end
		4'b1111:
			begin
				fetchbufA_v <= !(queued1|queued2);
				fetchbufB_v <= !queued2;
				if (queued2) begin
					fetchbuf <= 1'b1;
				    fetchbufA_instr <= 64'd0;
				    fetchbufB_instr <= 64'd0;
			    end
			end
		default: panic <= `PANIC_INVALIDFBSTATE;
		endcase
	end
	else begin	// fetchbuf==1'b1
		case ({fetchbufC_v,fetchbufD_v,fetchbufA_v,fetchbufB_v})
		4'b0000:
			begin
			    fetchAB();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbuf <= 1'b0;
			end
		4'b0100:
			begin
			    fetchAB();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbufD_v <= !queued1;
				if (queued1)
					fetchbuf <= 1'b0;
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b0111:
			begin
				fetchbufD_v <= !queued1;
				if (queued1)
					fetchbuf <= 1'b0;
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1000:
			begin
			    fetchAB();
				if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
				fetchbufC_v <= !queued1;
				if (queued1)
					fetchbuf <= 1'b0;
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1011:
			begin
				fetchbufC_v <= !queued1;
				if (queued1)
					fetchbuf <= 1'b0;
				if (queued2|queued3)
                    panic <= `PANIC_INVALIDIQSTATE;
			end
		4'b1100:
			if ((fnIsBranch(opcodeC) && predict_takenBr)||opcodeC==`LOOP) begin
				pc <= branch_pc;
				fetchbufC_v <= !(queued1|queued2);
				fetchbufD_v <= `INV;		// stomp on it
				// may as well stick with same fetchbuf
			end
			else begin
				if (did_branchback1) begin
				    fetchAB();
					if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
					fetchbufC_v <= !(queued1|queued2);
					fetchbufD_v <= !queued2;
					if (queued2)
						fetchbuf <= 1'b0;
				end
				else begin
					pc[ABW-1:0] <= branch_pc;
					fetchbufC_v <= !(queued1|queued2);
					fetchbufD_v <= !queued2;
					// may as well keep the same fetchbuffer
				end
			end
		4'b1111:
			begin
				fetchbufC_v <= !(queued1|queued2);
				fetchbufD_v <= !queued2;
				if (queued2)
					fetchbuf <= 1'b0;
			end
		default: panic <= `PANIC_INVALIDFBSTATE;
		endcase
	end
end
else begin
	if (fetchbuf == 1'b0)
		case ({fetchbufA_v, fetchbufB_v})
		2'b00: ;
		2'b01: begin
			fetchbufB_v <= !(queued2|queued1);
			fetchbuf <= queued2|queued1;
			end
		2'b10: begin
			fetchbufA_v <= !(queued2|queued1);
			fetchbuf <= queued2|queued1;
			end
		2'b11: begin
			fetchbufA_v <= !(queued1|queued2);
			fetchbufB_v <= !queued2;
			fetchbuf <= queued2;
			end
		endcase
	else
		case ({fetchbufC_v, fetchbufD_v})
		2'b00:    ;
		2'b01: begin
			fetchbufD_v <= !(queued2|queued1);
			fetchbuf <= !(queued2|queued1);
			end
		2'b10: begin
			fetchbufC_v <= !(queued2|queued1);
			fetchbuf <= !(queued2|queued1);
			end
		2'b11: begin
			fetchbufC_v <= !(queued2|queued1);
			fetchbufD_v <= !queued2;
			fetchbuf <= !queued2;
			end
		endcase
	if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
	    fetchAB();
		if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
		// fetchbuf steering logic correction
		if (fetchbufC_v==`INV && fetchbufD_v==`INV && do_pcinc)
			fetchbuf <= 1'b0;
		$display("hit %b 1pc <= %h", do_pcinc, pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
	end
	else if (fetchbufC_v == `INV && fetchbufD_v == `INV) begin
	    fetchCD();
		if (do_pcinc) pc[31:0] <= pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn);
		$display("2pc <= %h", pc[31:0] + fnInsnLength(insn) + fnInsnLength1(insn));
	end
end
 
	if (ihit) begin
	$display("%h %h hit0=%b hit1=%b#", spc, pc, hit0, hit1);
	$display("insn=%h", insn);
	$display("%c insn0=%h insn1=%h", nmi_edge ? "*" : " ",insn0, insn1);
	$display("takb=%d br_pc=%h #", take_branch, branch_pc);
	$display("%c%c A: %d %h %h # %d",
	    45, fetchbuf?45:62, fetchbufA_v, fetchbufA_instr, fetchbufA_pc, fnInsnLength(fetchbufA_instr));
	$display("%c%c B: %d %h %h # %d",
	    45, fetchbuf?45:62, fetchbufB_v, fetchbufB_instr, fetchbufB_pc, fnInsnLength(fetchbufB_instr));
	$display("%c%c C: %d %h %h # %d",
	    45, fetchbuf?62:45, fetchbufC_v, fetchbufC_instr, fetchbufC_pc, fnInsnLength(fetchbufC_instr));
	$display("%c%c D: %d %h %h # %d",
	    45, fetchbuf?62:45, fetchbufD_v, fetchbufD_instr, fetchbufD_pc, fnInsnLength(fetchbufD_instr));
	$display("fetchbuf=%d",fetchbuf);
	end
 
//	if (ihit) begin
	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 #",
		(i[2:0]==head0)?72:46, (i[2:0]==tail0)?84:46, i,
		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_agen[i]?"a":"-", iqentry_issue[i]?"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==4) ? iqentry_4_islot : (i==5) ? iqentry_5_islot : (i==6) ? iqentry_6_islot : iqentry_7_islot),
		 iqentry_stomp[i] ? "s" : "-",
		(fnIsFlowCtrl(iqentry_op[i]) ? 98 : fnIsMem(iqentry_op[i]) ? 109 : 97), 
		iqentry_op[i],
		fnRegstr(iqentry_tgt[i]),fnRegstrGrp(iqentry_tgt[i]),
		iqentry_res[i], iqentry_a0[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_a3[i], iqentry_a3_v[i]?"v":"-", iqentry_a3_s[i],
		iqentry_pred[i], iqentry_p_v[i]?"v":"-", iqentry_p_s[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("com1:%c%c %d r%d %h", commit1_v?"v":"-", iqentry_cmt[head1]?"c":"-", commit1_id, commit1_tgt, commit1_bus);
 
//	end
//`include "Thor_dataincoming.v"
// DATAINCOMING
//
// wait for operand/s to appear on alu busses and puts them into 
// the iqentry_a1 and iqentry_a2 slots (if appropriate)
// 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
	$display("dram results to iq[%d]=%h", dram_id[2:0],dram_bus);
	if (!iqentry_jmpi[dram_id[2:0]]) 
	   iqentry_res	[ dram_id[2:0] ] <= dram_bus;
	// If an exception occurred, stuff an interrupt instruction into the queue
	// slot. The instruction will re-issue as an ALU operation. We can change
	// the queued instruction because it isn't finished yet.
	if (|dram_exc) begin
	    set_exception(dram_id,
	       dram_exc==`EXC_DBE ? 8'hFB :
	       dram_exc==`EXC_DBG ? 8'd243 : 
	       dram_exc==`EXC_SEGV ? 8'd244 : 
	       8'hF8);    // F8 = TLBMiss exception 243 = debug
	       $stop;
	end
	else begin
	    // Note that the predicate was already evaluated to TRUE before the
	    // dram operation started.
	    iqentry_cmt[dram_id[2:0]] <= `TRUE;
		iqentry_done[ dram_id[2:0] ] <= `TRUE;
		if ((iqentry_op[dram_id[2:0]]==`STS ||
		     iqentry_op[dram_id[2:0]]==`STCMP ||
		     iqentry_op[dram_id[2:0]]==`STMV ||
		     iqentry_op[dram_id[2:0]]==`STFND
		     ) && lc==64'd0) begin
			string_pc <= 64'd0;
		end
	end
end
 
// 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
//
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;
	iqentry_done[ dram0_id[2:0] ] <= `TRUE;
	iqentry_cmt [ dram0_id[2:0]] <= `TRUE;
	iqentry_out[ dram0_id[2:0] ] <= `FALSE;
end
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;
	iqentry_done[ dram1_id[2:0] ] <= `TRUE;
	iqentry_cmt [ dram1_id[2:0]] <= `TRUE;
	iqentry_out[ dram1_id[2:0] ] <= `FALSE;
end
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;
	iqentry_done[ dram2_id[2:0] ] <= `TRUE;
	iqentry_cmt [ dram2_id[2:0]] <= `TRUE;
	iqentry_out[ dram2_id[2:0] ] <= `FALSE;
end
 
//
// see if anybody else wants the results ... look at lots of buses:
//  - alu0_bus
//  - alu1_bus
//  - fp0_bus
//  - mem_bus
//  - commit0_bus
//  - commit1_bus
//
 
for (n = 0; n < QENTRIES; n = n + 1)
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_p_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
	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_p_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
`ifdef FLOATING_POINT
/*
	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_p_v[n] <= `VAL;
	end
*/
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
`endif
    // For SWCR
	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_p_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
	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_p_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
	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_p_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
	end
	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_v[n] <= `VAL;
    end
end
 
//`include "Thor_issue.v"
// ISSUE 
//
// determines what instructions are ready to go, then places them
// in the various ALU queues.  
// also invalidates instructions following a branch-miss BEQ or any JALR (STOMP logic)
//
//alu0_dataready <= alu0_available && alu0_issue;
/*
			&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
			 || (iqentry_issue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
			 || (iqentry_issue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
			 || (iqentry_issue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
			 || (iqentry_issue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
			 || (iqentry_issue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
			 || (iqentry_issue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
			 || (iqentry_issue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
*/
//alu1_dataready <= alu1_available && alu1_issue;
/* 
			&& ((iqentry_issue[0] && iqentry_islot[0] == 4'd1 && !iqentry_stomp[0])
			 || (iqentry_issue[1] && iqentry_islot[1] == 4'd1 && !iqentry_stomp[1])
			 || (iqentry_issue[2] && iqentry_islot[2] == 4'd1 && !iqentry_stomp[2])
			 || (iqentry_issue[3] && iqentry_islot[3] == 4'd1 && !iqentry_stomp[3])
			 || (iqentry_issue[4] && iqentry_islot[4] == 4'd1 && !iqentry_stomp[4])
			 || (iqentry_issue[5] && iqentry_islot[5] == 4'd1 && !iqentry_stomp[5])
			 || (iqentry_issue[6] && iqentry_islot[6] == 4'd1 && !iqentry_stomp[6])
			 || (iqentry_issue[7] && iqentry_islot[7] == 4'd1 && !iqentry_stomp[7]));
*/
`ifdef FLOATING_POINT
fp0_dataready <= 1'b1
			&& ((iqentry_fpissue[0] && iqentry_islot[0] == 4'd0 && !iqentry_stomp[0])
			 || (iqentry_fpissue[1] && iqentry_islot[1] == 4'd0 && !iqentry_stomp[1])
			 || (iqentry_fpissue[2] && iqentry_islot[2] == 4'd0 && !iqentry_stomp[2])
			 || (iqentry_fpissue[3] && iqentry_islot[3] == 4'd0 && !iqentry_stomp[3])
			 || (iqentry_fpissue[4] && iqentry_islot[4] == 4'd0 && !iqentry_stomp[4])
			 || (iqentry_fpissue[5] && iqentry_islot[5] == 4'd0 && !iqentry_stomp[5])
			 || (iqentry_fpissue[6] && iqentry_islot[6] == 4'd0 && !iqentry_stomp[6])
			 || (iqentry_fpissue[7] && iqentry_islot[7] == 4'd0 && !iqentry_stomp[7]));
`endif
 
for (n = 0; n < QENTRIES; n = n + 1)
begin
	if (iqentry_v[n] && iqentry_stomp[n]) begin
		iqentry_v[n] <= `INV;
		if (dram0_id[2:0] == n[2:0])	dram0 <= `DRAMSLOT_AVAIL;
		if (dram1_id[2:0] == n[2:0])	dram1 <= `DRAMSLOT_AVAIL;
		if (dram2_id[2:0] == n[2:0])	dram2 <= `DRAMSLOT_AVAIL;
	end
	else if (iqentry_issue[n]) begin
		case (iqentry_islot[n]) 
		2'd0: if (alu0_available) begin
			alu0_ld <= 1'b1;
			alu0_sourceid	<= n[3:0];
			alu0_insnsz <= iqentry_insnsz[n];
			alu0_op		<= iqentry_op[n];
			alu0_fn     <= iqentry_fn[n];
			alu0_cond   <= iqentry_cond[n];
			alu0_bt		<= iqentry_bt[n];
			alu0_pc		<= iqentry_pc[n];
			alu0_pred   <= iqentry_p_v[n] ? iqentry_pred[n] :
							(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
							(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
			alu0_argA	<= iqentry_a1_v[n] ? iqentry_a1[n]
						: (iqentry_a1_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a1_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			alu0_argB	<= iqentry_a2_v[n] ? iqentry_a2[n]
						: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			alu0_argC	<=
`ifdef SEGMENTATION
			               ((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
`endif			               
			               iqentry_a3_v[n] ? iqentry_a3[n]
						: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			alu0_argT	<= iqentry_T_v[n] ? iqentry_T[n]
                        : (iqentry_T_s[n] == alu0_id) ? alu0_bus
                        : (iqentry_T_s[n] == alu1_id) ? alu1_bus
                        : 64'hDEADDEADDEADDEAD;
            alu0_argI	<= iqentry_a0[n];
            alu0_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
    		iqentry_out[n] <= `TRUE;
			end
		2'd1: if (alu1_available) begin
			alu1_ld <= 1'b1;
			alu1_sourceid	<= n[3:0];
			alu1_insnsz <= iqentry_insnsz[n];
			alu1_op		<= iqentry_op[n];
			alu1_fn     <= iqentry_fn[n];
			alu1_cond   <= iqentry_cond[n];
			alu1_bt		<= iqentry_bt[n];
			alu1_pc		<= iqentry_pc[n];
			alu1_pred   <= iqentry_p_v[n] ? iqentry_pred[n] :
							(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
							(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
			alu1_argA	<= iqentry_a1_v[n] ? iqentry_a1[n]
                            : (iqentry_a1_s[n] == alu0_id) ? alu0_bus
                            : (iqentry_a1_s[n] == alu1_id) ? alu1_bus
                            : 64'hDEADDEADDEADDEAD;
			alu1_argB	<= iqentry_a2_v[n] ? iqentry_a2[n]
						: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			alu1_argC	<=
`ifdef SEGMENTATION
			               ((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} :
`endif			                
			               iqentry_a3_v[n] ? iqentry_a3[n]
						: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			alu1_argT	<= iqentry_T_v[n] ? iqentry_T[n]
                        : (iqentry_T_s[n] == alu0_id) ? alu0_bus
                        : (iqentry_T_s[n] == alu1_id) ? alu1_bus
                        : 64'hDEADDEADDEADDEAD;
            alu1_argI	<= iqentry_a0[n];
            alu1_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]);
    		iqentry_out[n] <= `TRUE;
			end
		default: panic <= `PANIC_INVALIDISLOT;
		endcase
//		iqentry_out[n] <= `TRUE;
		// if it is a memory operation, this is the address-generation step ... collect result into arg1
		if (iqentry_mem[n] && !iqentry_tlb[n]) begin
			iqentry_a1_v[n] <= `INV;
			iqentry_a1_s[n] <= n[3:0];
		end
	end
end
 
 
`ifdef FLOATING_POINT
for (n = 0; n < QENTRIES; n = n + 1)
begin
	if (iqentry_v[n] && iqentry_stomp[n])
		;
	else if (iqentry_fpissue[n]) begin
		case (iqentry_fpislot[n]) 
		2'd0: if (1'b1) begin
			fp0_ld <= 1'b1;
			fp0_sourceid	<= n[3:0];
			fp0_op		<= iqentry_op[n];
			fp0_fn     <= iqentry_fn[n];
			fp0_cond   <= iqentry_cond[n];
			fp0_pred   <= iqentry_p_v[n] ? iqentry_pred[n] :
							(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
							(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0;
			fp0_argA	<= iqentry_a1_v[n] ? iqentry_a1[n]
                            : (iqentry_a1_s[n] == alu0_id) ? alu0_bus
                            : (iqentry_a1_s[n] == alu1_id) ? alu1_bus
                            : 64'hDEADDEADDEADDEAD;
            fp0_argB	<= iqentry_a2_v[n] ? iqentry_a2[n]
						: (iqentry_a2_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a2_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			fp0_argC	<= iqentry_a3_v[n] ? iqentry_a3[n]
						: (iqentry_a3_s[n] == alu0_id) ? alu0_bus
						: (iqentry_a3_s[n] == alu1_id) ? alu1_bus
						: 64'hDEADDEADDEADDEAD;
			fp0_argT	<= iqentry_T_v[n] ? iqentry_T[n]
                        : (iqentry_T_s[n] == alu0_id) ? alu0_bus
                        : (iqentry_T_s[n] == alu1_id) ? alu1_bus
                        : 64'hDEADDEADDEADDEAD;
			fp0_argI	<= iqentry_a0[n];
			end
		default: panic <= `PANIC_INVALIDISLOT;
		endcase
		iqentry_out[n] <= `TRUE;
	end
end
`endif
 
// MEMORY
//
// 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
// stores, the data is ignored.
//
//
// dram0, dram1, dram2 are the "state machines" that keep track
// 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"
// at the end of the cycle).  once it hits the value "10" the request
// and the bus is acknowledged the dram request
// 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_id value signals the waiting memq entry that the store is
// completed and the instruction can commit.
//
if (tlb_state != 3'd0 && tlb_state < 3'd3)
	tlb_state <= tlb_state + 3'd1;
if (tlb_state==3'd3) begin
	dram_v <= `TRUE;
	dram_id <= tlb_id;
	dram_tgt <= tlb_tgt;
	dram_exc <= `EXC_NONE;
	dram_bus <= tlb_dato;
	tlb_op <= 4'h0;
	tlb_state <= 3'd0;
end
 
case(dram0)
// The first state is to translate the virtual to physical address.
// Also a good spot to check for debug match and segment limit violation.
3'd1:
	begin
		$display("0MEM %c:%h %h cycle started",fnIsStore(dram0_op)?"S" : "L", dram0_addr, dram0_data);
		if (dbg_lmatch|dbg_smatch) begin
		    dram_v <= `TRUE;
		    dram_id <= dram0_id;
		    dram_tgt <= dram0_tgt;
            dram_exc <= `EXC_DBG;
            dram_bus <= 64'h0;
            dram0 <= 3'd0;
        end
`ifdef SEGMENTATION
`ifdef SEGLIMITS
        else if (dram0_addr[ABW-1:12] >= dram0_lmt) begin
            dram_v <= `TRUE;            // we are finished the memory cycle
            dram_id <= dram0_id;
            dram_tgt <= dram0_tgt;
            dram_exc <= `EXC_SEGV;    //dram0_exc;
            dram_bus <= 64'h0;
            dram0 <= 3'd0;
        end
`endif
`endif
        else if (!cyc_o) dram0 <= dram0 + 3'd1;
	end
 
// State 2:
// Check for a TLB miss on the translated address, and
// Initiate a bus transfer
3'd2:
	if (DTLBMiss) begin
		dram_v <= `TRUE;			// we are finished the memory cycle
		dram_id <= dram0_id;
		dram_tgt <= dram0_tgt;
		dram_exc <= `EXC_TLBMISS;	//dram0_exc;
		dram_bus <= 64'h0;
		dram0 <= 3'd0;
	end
	else if (dram0_exc!=`EXC_NONE) begin
		dram_v <= `TRUE;			// we are finished the memory cycle
        dram_id <= dram0_id;
        dram_tgt <= dram0_tgt;
        dram_exc <= dram0_exc;
		dram_bus <= 64'h0;
        dram0 <= 3'd0;
	end
	else begin
	    if (dram0_op==`LCL) begin
	       if (dram0_tgt==7'd0) begin
	           ic_invalidate_line <= `TRUE;
	           ic_lineno <= dram0_addr;
	       end
           dram0 <= 3'd6;
	    end
		else if (uncached || fnIsStore(dram0_op) || fnIsLoadV(dram0_op) || dram0_op==`CAS ||
		  ((dram0_op==`STMV || dram0_op==`INC) && stmv_flag)) begin
    		if (cstate==IDLE) begin // make sure an instruction load isn't taking place
                dram0_owns_bus <= `TRUE;
                resv_o <= dram0_op==`LVWAR;
                cres_o <= dram0_op==`SWCR;
                lock_o <= dram0_op==`CAS;
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                we_o <= fnIsStore(dram0_op) || ((dram0_op==`STMV || dram0_op==`INC) && stmv_flag);
                sel_o <= fnSelect(dram0_op,dram0_fn,pea);
                rsel <= fnSelect(dram0_op,dram0_fn,pea);
                adr_o <= pea;
                if (dram0_op==`INC)
                    dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data) + index;
                else
                    dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
                dram0 <= dram0 + 3'd1;
			end
		end
		else begin	// cached read
			dram0 <= 3'd6;
            rsel <= fnSelect(dram0_op,dram0_fn,pea);
	   end
	end
 
// State 3:
// Wait for a memory ack
3'd3:
	if (ack_i|err_i) begin
		$display("MEM ack");
		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_tgt <= dram0_tgt;
		dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;//dram0_exc;
		if (dram0_op==`SWCR)
		     dram_bus <= {63'd0,resv_i};
		else
		     dram_bus <= fnDatai(dram0_op,dram0_fn,dat_i[DBW-1:0],rsel);
		dram0_owns_bus <= `FALSE;
		wb_nack();
        dram0 <= 3'd7;
		case(dram0_op)
`ifdef STRINGOPS
		`STS:
			if (lc != 0 && !int_pending) begin
				dram0_addr <= dram0_addr + fnIndexAmt(dram0_fn);
				lc <= lc - 64'd1;
				dram0 <= 3'd1;
//				dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
            end
            else begin
                dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg;
                dram_v <= `VAL;
                dram0_op <= `NOP;
            end
        `STMV,`STCMP:
            begin
                dram_bus <= index;
                if (lc != 0 && !(int_pending && stmv_flag)) begin 
                    dram0 <= 3'd1;
                    dram0_owns_bus <= `TRUE;
                    if (stmv_flag) begin
                        dram0_addr <= src_addr + index;
                        if (dram0_op==`STCMP) begin
                            if (dram0_data != fnDatai(dram0_op,dram0_fn,dat_i[DBW-1:0],rsel)) begin
                                lc <= 64'd0;
                                dram0 <= 3'd7;
                                dram_v <= `VAL;
                            end
                        end
                    end               
                    else begin
                        dram0_addr <= dst_addr + index;
                        dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i[DBW-1:0],rsel);
                    end
                    if (!stmv_flag)
                        inc_index(dram0_fn);
                    stmv_flag <= ~stmv_flag;
                end
                else begin
                    dram_v <= `VAL;
                    dram0_op <= `NOP;
                end
            end
        `STFND:
            if (lc != 0 && !int_pending) begin 
                dram0_addr <= src_addr + index;
                inc_index(dram0_fn);
                if (dram0_data == fnDatai(dram0_op,dram0_fn,dat_i[DBW-1:0],rsel)) begin
                    lc <= 64'd0;
                    dram_v <= `VAL;
                    dram_bus <= index;
                end
                else
                    dram0 <= 3'd1;
            end
            else begin
                dram_bus <= index;
                dram_v <= `VAL;
                dram0_op <= `NOP;
            end
`endif
        `CAS:
			if (dram0_datacmp == dat_i[DBW-1:0]) begin
				$display("CAS match");
				dram0_owns_bus <= `TRUE;
				cyc_o <= 1'b1;	// hold onto cyc_o
				dram0 <= dram0 + 3'd1;
			end
			else begin
				dram_v <= `VAL;
				dram0 <= 3'd0;
		    end
		`INC:
		     begin
		         if (stmv_flag) begin
		             dram_v <= `VAL;
    				 dram0 <= 3'd0;
		         end
		         else begin
		             dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i[DBW-1:0],rsel);
                     stmv_flag <= ~stmv_flag;
                     dram0 <= 3'd1;
		         end
		     end
		`NOP:
		      begin
	              dram_v <= `VAL;
                  dram0 <= 3'd0;
		      end
		default:  ;
		endcase
	end
 
// State 4:
// Start a second bus transaction for the CAS instruction
3'd4:
	begin
		stb_o <= 1'b1;
		we_o <= 1'b1;
		sel_o <= fnSelect(dram0_op,dram0_fn,pea);
		adr_o <= pea;
		dat_o <= fnDatao(dram0_op,dram0_fn,dram0_data);
		dram0 <= dram0 + 3'd1;
	end
 
// State 5:
// Wait for a memory ack for the second bus transaction of a CAS
//
3'd5:
    begin
        dram_id <= dram0_id;
        dram_tgt <= dram0_tgt;
        if (ack_i|err_i) begin
            $display("MEM ack2");
            dram_v <= `VAL;
            dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;
            dram0_owns_bus <= `FALSE;
            wb_nack();
            lock_o <= 1'b0;
            dram0 <= 3'd7;
        end
    end
 
// State 6:
// Wait for a data cache read hit
3'd6:
	if (rhit && dram0_op!=`LCL) begin
	    case(dram0_op)
`ifdef STRINGOPS
	    // The read portion of the STMV was just done, go back and do
	    // the write portion.
        `STMV:
           begin
               stmv_flag <= `TRUE;
               dram0_addr <= dst_addr + index;
               dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
               dram0 <= 3'd1;
           end
        `STCMP:
            begin
                dram_bus <= index;
                dram_id <= dram0_id;
                dram_tgt <= dram0_tgt;
                if (lc != 0 && !int_pending && stmv_flag) begin
                    dram0_addr <= src_addr + index;
                    stmv_flag <= ~stmv_flag;
                    $display("*****************************");
                    $display("STCMP READ2:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
                    $display("*****************************");
                    if (dram0_data != fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
                        lc <= 64'd0;
                        dram0 <= 3'd7;
                        dram_v <= `VAL;
                    end
                end
                else if (!stmv_flag) begin
                    stmv_flag <= ~stmv_flag;
                    dram0_addr <= dst_addr + index;
                    dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
                    $display("*****************************");
                    $display("STCMP READ1:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel));
                    $display("*****************************");
                    dram0 <= 3'd1;
                    inc_index(dram0_fn);
                end
                else begin
                    dram_v <= `VAL;
                    dram0 <= 3'd7;
                    dram0_op <= `NOP;
                end
            end
        `STFND:
            begin
                dram_id <= dram0_id;
                dram_tgt <= dram0_tgt;
                dram_bus <= index;
                if (lc != 0 && !int_pending) begin 
                    dram0 <= 3'd1;
                    dram0_addr <= src_addr + index;
                    inc_index(dram0_fn);
                    if (dram0_data == fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin
                        lc <= 64'd0;
                        dram0 <= 3'd7;
                        dram_v <= `VAL;
                    end
                end
                else begin
                    dram_v <= `VAL;              
                    dram0 <= 3'd7;
                    dram0_op <= `NOP;
                end
            end
`endif
		`INC:
             begin
                 dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
                 stmv_flag <= `TRUE;
                 dram0 <= 3'd1;
            end
        // Set to NOP on a string miss
        `NOP:   begin
                dram_v <= `VAL;
                dram0 <= 3'd0;
                end
    default: begin
            $display("Read hit [%h]",dram0_addr);
            dram_v <= `TRUE;
            dram_id <= dram0_id;
            dram_tgt <= dram0_tgt;
            dram_exc <= `EXC_NONE;
            dram_bus <= fnDatai(dram0_op,dram0_fn,cdat,rsel);
            dram0 <= 3'd0;
            end
        endcase
	end
3'd7:
    begin
    dram0 <= 3'd0;
    end
default:    dram0 <= 3'd0;
endcase
 
//
// determine if the instructions ready to issue can, in fact, issue.
// "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.
// That means no flow control operations or instructions that can cause an
// exception can be before the store.
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;
 
				/* ||
					(   !fnIsFlowCtrl(iqentry_op[head0])
					 && !fnIsFlowCtrl(iqentry_op[head1])
					 && !fnIsFlowCtrl(iqentry_op[head2])
					 && !fnIsFlowCtrl(iqentry_op[head3])
					 && !fnIsFlowCtrl(iqentry_op[head4])
					 && !fnIsFlowCtrl(iqentry_op[head5])
					 && !fnIsFlowCtrl(iqentry_op[head6])));
*/
//
// take requests that are ready and put them into DRAM slots
 
if (dram0 == `DRAMSLOT_AVAIL)	dram0_exc <= `EXC_NONE;
 
// Memory should also wait until segment registers are valid. The segment
// registers are essentially static registers while a program runs. They are
// 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
// for rf_v[].
//
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
	    $display("TLB issue");
	    if (!iqentry_cmt[n]) begin
	        iqentry_done[n] <= `TRUE;
	        iqentry_out[n] <= `FALSE;
	        iqentry_agen[n] <= `FALSE;
	        iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
                        : (iqentry_T_s[n] == alu0_id) ? alu0_bus
                        : (iqentry_T_s[n] == alu1_id) ? alu1_bus
                        : 64'hDEADDEADDEADDEAD;
	    end
		else if (tlb_state==3'd0) begin
			tlb_state <= 3'd1;
			tlb_id <= {1'b1, n[2:0]};
			tlb_op <= iqentry_a0[n][3:0];
			tlb_regno <= iqentry_a0[n][7:4];
			tlb_tgt <= iqentry_tgt[n];
			tlb_data <= iqentry_a1[n];
			iqentry_out[n] <= `TRUE;
		end
	end
	else if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && !iqentry_out[n]) begin
	    if (!iqentry_cmt[n]) begin
            iqentry_done[n] <= `TRUE;
            iqentry_out[n] <= `FALSE;
            iqentry_agen[n] <= `FALSE;
	        iqentry_res[n] <= iqentry_T_v[n] ? iqentry_T[n]
                        : (iqentry_T_s[n] == alu0_id) ? alu0_bus
                        : (iqentry_T_s[n] == alu1_id) ? alu1_bus
                        : 64'hDEADDEADDEADDEAD;
        end
        else begin
            if (fnIsStoreString(iqentry_op[n]))
                string_pc <= iqentry_pc[n];
            $display("issued memory cycle");
            if (dram0 == `DRAMSLOT_AVAIL) begin
                dram0 		<= 3'd1;
                dram0_id 	<= { 1'b1, n[2:0] };
                dram0_misspc <= iqentry_pc[n];
                dram0_op 	<= iqentry_op[n];
                dram0_fn    <= iqentry_fn[n];
                dram0_tgt 	<= iqentry_tgt[n];
                dram0_data	<= (iqentry_ndx[n] || iqentry_cas[n]) ? iqentry_a3[n] :
`ifdef STACKOPS                
                                iqentry_pea[n] ? iqentry_a2[n] + iqentry_a0[n] :
`endif
                                iqentry_a2[n];
                dram0_datacmp <= iqentry_a2[n];
`ifdef SEGMENTATION
                if (iqentry_cmpmv[n])
                    dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000};
                else
                    dram0_addr <= iqentry_a1[n];
                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_exc <= (iqentry_a1[n][ABW-1:12] >= sregs_lmt[iqentry_fn[n][5:3]]) ? `EXC_SEGV : `EXC_NONE;
`ifdef STRINGOPS                
                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};
`endif
`else
                dram0_addr <= iqentry_a1[n];
`ifdef STRINGOPS
                src_addr <= iqentry_a1[n];
                dst_addr <= iqentry_a2[n];
`endif
`endif
                stmv_flag <= `FALSE;
                index <= iqentry_op[n]==`STS ? fnIndexAmt(iqentry_fn[n]) : iqentry_op[n]==`INC ? iqentry_a2[n] : iqentry_a3[n];
                iqentry_out[n]	<= `TRUE;
            end
		end
	end
 
for (n = 0; n < QENTRIES; n = n + 1)
begin
    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]))) // address inherited due to interrupt
        iqentry_done[n] <= `TRUE;
    if (!iqentry_v[n])
        iqentry_done[n] <= `FALSE;
end
 
 
//	$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)
//		$display("vp=%h G=%b",utlb1.TLBVirtPage[i],utlb1.TLBG[i]);
//`include "Thor_commit.v"
// It didn't work in simulation when the following was declared under an
// independant always clk block
//
commit_spr(commit0_v,commit0_tgt,commit0_bus,0);
commit_spr(commit1_v,commit1_tgt,commit1_bus,1);
 
// When the INT instruction commits set the hardware interrupt status to disable further interrupts.
if (int_commit)
begin
	$display("*********************");
	$display("*********************");
	$display("Interrupt committing");
	$display("*********************");
	$display("*********************");
	StatusHWI <= `TRUE;
	imb <= im;
	im <= 1'b0;
	// 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) ||
	    (iqentry_a0[head1][7:0]==8'hFE && commit1_v && iqentry_op[head1]==`INT))
		nmi_edge <= 1'b0;
	string_pc <= 64'd0;
`ifdef PCHIST
	pc_cap <= `FALSE;
`endif
end
 
if (sys_commit)
begin
	if (StatusEXL!=8'hFF)
		StatusEXL <= StatusEXL + 8'd1;
end
 
// On a debug commit set status StatusDBG to prevent further single stepping.
`ifdef DEBUG_LOGIC
if (dbg_commit)
begin
    StatusDBG <= `TRUE;
end
`endif
 
oddball_commit(commit0_v,head0);
oddball_commit(commit1_v,head1);
 
//
// COMMIT PHASE (dequeue only ... not register-file update)
//
// If the third instruction is invalidated or if it doesn't update the register
// file then it is allowed to commit too.
// The head pointer might advance by three.
//
if (~|panic)
casex ({ iqentry_v[head0],
	iqentry_done[head0],
	iqentry_v[head1],
	iqentry_done[head1],
	iqentry_v[head2],
	iqentry_done[head2]})
 
	// retire 3
	6'b0x_0x_0x:
		if (head0 != tail0 && head1 != tail0 && head2 != tail0) begin
		    head_inc(3);
		end
		else if (head0 != tail0 && head1 != tail0) begin
 		    head_inc(2);
		end
		else if (head0 != tail0) begin
		    head_inc(1);
		end
 
	// retire 2 (wait for regfile for head2)
	6'b0x_0x_10:
		begin
		    head_inc(2);
		end
 
	// retire 2 or 3 (wait for regfile for head2)
	6'b0x_0x_11:
	   begin
	        if (iqentry_tgt[head2]==7'd0) begin
	            iqentry_v[head2] <= `INV;
	            head_inc(3);
	        end
	        else begin
	            head_inc(2);
			end
		end
 
	// retire 3
	6'b0x_11_0x:
		if (head1 != tail0 && head2 != tail0) begin
			iqentry_v[head1] <= `INV;
			head_inc(3);
		end
		else begin
			iqentry_v[head1] <= `INV;
			head_inc(2);
		end
 
	// retire 2	(wait on head2 or wait on register file for head2)
	6'b0x_11_10:
		begin
			iqentry_v[head1] <= `INV;
			head_inc(2);
		end
	6'b0x_11_11:
        begin
            if (iqentry_tgt[head2]==7'd0) begin
                iqentry_v[head1] <= `INV;
                iqentry_v[head2] <= `INV;
                head_inc(3);
            end
            else begin
                iqentry_v[head1] <= `INV;
                head_inc(2);
            end
        end
 
	// 4'b00_00	- neither valid; skip both
	// 4'b00_01	- neither valid; skip both
	// 4'b00_10	- skip head0, wait on head1
	// 4'b00_11	- skip head0, commit head1
	// 4'b01_00	- neither valid; skip both
	// 4'b01_01	- neither valid; skip both
	// 4'b01_10	- skip head0, wait on head1
	// 4'b01_11	- skip head0, commit head1
	// 4'b10_00	- wait on head0
	// 4'b10_01	- wait on head0
	// 4'b10_10	- wait on head0
	// 4'b10_11	- wait on head0
	// 4'b11_00	- commit head0, skip head1
	// 4'b11_01	- commit head0, skip head1
	// 4'b11_10	- commit head0, wait on head1
	// 4'b11_11	- commit head0, commit head1
 
	//
	// retire 0 (stuck on head0)
	6'b10_xx_xx:	;
 
	// retire 3
	6'b11_0x_0x:
		if (head1 != tail0 && head2 != tail0) begin
			iqentry_v[head0] <= `INV;
			head_inc(3);
		end
		else if (head1 != tail0) begin
			iqentry_v[head0] <= `INV;
			head_inc(2);
		end
		else begin
			iqentry_v[head0] <= `INV;
			head_inc(1);
		end
 
	// retire 2 (wait for regfile for head2)
	6'b11_0x_10:
		begin
			iqentry_v[head0] <= `INV;
			head_inc(2);
		end
 
	// retire 2 or 3 (wait for regfile for head2)
	6'b11_0x_11:
	    if (iqentry_tgt[head2]==7'd0) begin
			iqentry_v[head0] <= `INV;
			iqentry_v[head2] <= `INV;
			head_inc(3);
	    end
	    else begin
			iqentry_v[head0] <= `INV;
			head_inc(2);
		end
 
	//
	// retire 1 (stuck on head1)
	6'b00_10_xx,
	6'b01_10_xx,
	6'b11_10_xx:
		if (iqentry_v[head0] || head0 != tail0) begin
    	    iqentry_v[head0] <= `INV;
    	    head_inc(1);
		end
 
	// retire 2 or 3
	6'b11_11_0x:
		if (head2 != tail0) begin
			iqentry_v[head0] <= `INV;	// may conflict with STOMP, but since both are setting to 0, it is okay
			iqentry_v[head1] <= `INV;
			head_inc(3);
		end
		else begin
			iqentry_v[head0] <= `INV;
			iqentry_v[head1] <= `INV;
			head_inc(2);
		end
 
	// retire 2 (wait on regfile for head2)
	6'b11_11_10:
		begin
			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
			head_inc(2);
		end
	6'b11_11_11:
	    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[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
            head_inc(3);
	    end
        else begin
            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
            head_inc(2);
        end
endcase
 
	if (branchmiss)
		rrmapno <= iqentry_renmapno[missid];
 
	case(cstate)
	RESET1:
	   begin
	       ic_ld <= `TRUE;
	       ic_ld_cntr <= 32'd0;
	       cstate <= RESET2;
	   end
	RESET2:
	   begin
	       ic_ld_cntr <= ic_ld_cntr + 32'd32;
	       if (ic_ld_cntr >= 32'd32768) begin
	           ic_ld <= `FALSE;
	           ic_ld_cntr <= 32'd0;
	           cstate <= IDLE;
	       end;
	   end
	IDLE:
		if (dcache_access_pending) begin
				$display("********************");
				$display("DCache access to: %h",{pea[DBW-1:5],5'b00000});
				$display("********************");
				derr <= 1'b0;
				bte_o <= 2'b00;
				cti_o <= 3'b001;
				bl_o <= DBW==32 ? 5'd7 : 5'd3;
				cyc_o <= 1'b1;
				stb_o <= 1'b1;
				we_o <= 1'b0;
				sel_o <= {DBW/8{1'b1}};
				adr_o <= {pea[DBW-1:5],5'b00000};
				dat_o <= {DBW{1'b0}};
				cstate <= DCACHE1;
		end
		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)))
				$display("drams non-zero");
			else begin
				$display("********************");
				$display("ICache access to: %h",
				    (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});
				$display("********************");
				ierr <= 1'b0;
				bte_o <= 2'b00;
				cti_o <= 3'b001;
				bl_o <= DBW==32 ? 5'd7 : 5'd3;
				cyc_o <= 1'b1;
				stb_o <= 1'b1;
				we_o <= 1'b0;
				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};
				dat_o <= {DBW{1'b0}};
				cstate <= ICACHE1;
			end
		end
	ICACHE1:
		begin
			if (ack_i|err_i) begin
				ierr <= ierr | err_i;	// cumulate an error status
				if (DBW==32) begin
					adr_o[4:2] <= adr_o[4:2] + 3'd1;
					if (adr_o[4:2]==3'b110)
						cti_o <= 3'b111;
					if (adr_o[4:2]==3'b111) begin
						wb_nack();
						cstate <= IDLE;
						if (dram0==3'd6 && dram0_op==`LCL) begin
						     dram0_op<=`NOP;
						end
					end
				end
				else begin
					adr_o[4:3] <= adr_o[4:3] + 2'd1;
					if (adr_o[4:3]==2'b10)
						cti_o <= 3'b111;
					if (adr_o[4:3]==2'b11) begin
						wb_nack();
						cstate <= IDLE;
						if (dram0==3'd6 && dram0_op==`LCL) begin
                             dram0_op<=`NOP;
                        end
					end
				end
			end
		end
	DCACHE1:
		begin
			if (ack_i|err_i) begin
				derr <= derr | err_i;	// cumulate an error status
				if (DBW==32) begin
					adr_o[4:2] <= adr_o[4:2] + 3'd1;
					if (adr_o[4:2]==3'b110)
						cti_o <= 3'b111;
					if (adr_o[4:2]==3'b111) begin
						wb_nack();
						cstate <= IDLE;
						if (dram0_op==`LCL) begin
						    dram0_op <= `NOP;
						    dram0_tgt <= 7'd0;
						end
					end
				end
				else begin
					adr_o[4:3] <= adr_o[4:3] + 2'd1;
					if (adr_o[4:3]==2'b10)
						cti_o <= 3'b111;
					if (adr_o[4:3]==2'b11) begin
						wb_nack();
						cstate <= IDLE;
						if (dram0_op==`LCL) begin
						    dram0_op <= `NOP;
						    dram0_tgt <= 7'd0;
					    end
					end
				end
			end
		end
    default:    cstate <= IDLE;
	endcase
 
//	for (i=0; i<8; i=i+1)
//	    $display("%d: %h %d %o #", i, urf1.regs0[i], rf_v[i], rf_source[i]);
 
	if (ihit) begin
	$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, 
		 (fnIsFlowCtrl(alu0_op) ? 98 : (fnIsMem(alu0_op)) ? 109 : 97),
		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 #",
		alu1_dataready, alu1_argI, alu1_argA, alu1_argB, 
		 (fnIsFlowCtrl(alu1_op) ? 98 : (fnIsMem(alu1_op)) ? 109 : 97),
		alu1_op, alu1_bt, alu1_sourceid, alu1_pc);
	$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("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("cmt=%b cnd=%d prd=%d", alu1_cmt, alu1_cond, alu1_pred);
	$display("bmiss=%b mpc=%h", branchmiss, misspc);
 
	$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);
	end
	if (|panic) begin
	    $display("");
	    $display("-----------------------------------------------------------------");
	    $display("-----------------------------------------------------------------");
	    $display("---------------     PANIC:%s     -----------------", message[panic]);
	    $display("-----------------------------------------------------------------");
	    $display("-----------------------------------------------------------------");
	    $display("");
	    $display("instructions committed: %d", I);
	    $display("total execution cycles: %d", $time / 10);
	    $display("");
	end
	if (|panic && ~outstanding_stores) begin
	    $finish;
	end
end
 
task wb_nack;
begin
    resv_o <= 1'b0;
    cres_o <= 1'b0;
	bte_o <= 2'b00;
	cti_o <= 3'b000;
	bl_o <= 5'd0;
	cyc_o <= 1'b0;
	stb_o <= 1'b0;
	we_o <= 1'b0;
	sel_o <= 8'h00;
	adr_o <= {DBW{1'b0}};
	dat_o <= {DBW{1'b0}};
end
endtask
 
task commit_spr;
input commit_v;
input [6:0] commit_tgt;
input [DBW-1:0] commit_bus;
input which;
begin
if (commit_v && commit_tgt[6]) begin
    casex(commit_tgt[5:0])
    6'b00xxxx:  begin
                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]);
//	            $stop;
                end
    6'b01xxxx:  begin
                cregs[commit_tgt[3:0]] <= commit_bus;
	            $display("cregs[%d]<=%h", commit_tgt[3:0], commit_bus);
	           end
`ifdef SEGMENTATION    
    6'b100xxx:  begin
                sregs[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
	            $display("sregs[%d]<=%h", commit_tgt[2:0], commit_bus);
	            end
	6'b101xxx:  sregs_lmt[commit_tgt[2:0]] <= commit_bus[DBW-1:12];
`endif
    6'b110000:
        begin
        pregs[0] <= commit_bus[3:0];
        pregs[1] <= commit_bus[7:4];
        pregs[2] <= commit_bus[11:8];
        pregs[3] <= commit_bus[15:12];
        pregs[4] <= commit_bus[19:16];
        pregs[5] <= commit_bus[23:20];
        pregs[6] <= commit_bus[27:24];
        pregs[7] <= commit_bus[31:28];
        if (DBW==64) begin
            pregs[8] <= commit_bus[35:32];
            pregs[9] <= commit_bus[39:36];
            pregs[10] <= commit_bus[43:40];
            pregs[11] <= commit_bus[47:44];
            pregs[12] <= commit_bus[51:48];
            pregs[13] <= commit_bus[55:52];
            pregs[14] <= commit_bus[59:56];
            pregs[15] <= commit_bus[63:60];
        end
        end
    `LCTR:  begin    lc <= commit_bus; $display("LC <= %h", commit_bus); end
	`ASID:	    asid <= commit_bus;
    `SR:    begin
            GM <= commit_bus[7:0];
            GMB <= commit_bus[23:16];
            imb <= commit_bus[31];
            im <= commit_bus[15];
            fxe <= commit_bus[12];
            end
    6'd60:  spr_bir <= commit_bus[11:0];
    6'd61:
            case(spr_bir[5:0])
            6'd0:   dbg_adr0 <= commit_bus;  
            6'd1:   dbg_adr1 <= commit_bus;  
            6'd2:   dbg_adr2 <= commit_bus;  
            6'd3:   dbg_adr3 <= commit_bus;  
            6'd4:   dbg_ctrl <= commit_bus;
            6'd5:   dbg_stat <= commit_bus;
`ifdef PCHIST
            6'd18:  pc_ndx <= commit_bus[5:0];
`endif
            default:    ;
            endcase
    6'b111111:
            begin
                ld_clk_throttle <= `TRUE;
                clk_throttle_new <= commit_bus[15:0];
            end
    default:    ;
    endcase
end
end
endtask
 
// For string memory operations.
// Indexing amount, should synth to a ROM.
//
function [63:0] fnIndexAmt;
input [5:0] fn;
begin
    case(fn[2:0])
    3'd0:   fnIndexAmt = 64'd1;
    3'd1:   fnIndexAmt = 64'd2;
    3'd2:   fnIndexAmt = 64'd4;
    3'd3:   fnIndexAmt = 64'd8;
    3'd4:   fnIndexAmt = 64'd1;
    3'd5:   fnIndexAmt = 64'd2;
    3'd6:   fnIndexAmt = 64'd4;
    3'd7:   fnIndexAmt = 64'd8;
    endcase
end
endfunction
 
 
// For string memory operations.
//
task inc_index;
input [5:0] fn;
begin
    index <= index + fnIndexAmt(fn);
    lc <= lc - 64'd1;    
end
endtask
 
function [DBW-1:0] fnSpr;
input [5:0] regno;
input [63:0] epc;
begin
    // Read from the special registers unless overridden by the
    // value on the commit bus.
    casex(regno)
    6'b00xxxx:  fnSpr = {DBW/4{pregs[regno[3:0]]}};
    6'b01xxxx:  fnSpr = cregs[regno[3:0]];
`ifdef SEGMENTATION
    6'b100xxx:  fnSpr = {sregs[regno[2:0]],12'h000};
    6'b101xxx:  fnSpr = {sregs_lmt[regno[2:0]],12'h000};
`endif
    6'b110000:  if (DBW==64)
                fnSpr = {pregs[15],pregs[14],pregs[13],pregs[12],
                         pregs[11],pregs[10],pregs[9],pregs[8],
                         pregs[7],pregs[6],pregs[5],pregs[4],
                         pregs[3],pregs[2],pregs[1],pregs[0]};
                else
                fnSpr = {pregs[7],pregs[6],pregs[5],pregs[4],
                         pregs[3],pregs[2],pregs[1],pregs[0]};
    `TICK:      fnSpr = tick;                    
    `LCTR:      fnSpr = lc;
    `ASID:      fnSpr = asid; 
    `SR:    begin
            fnSpr[7:0] = GM;
            fnSpr[23:16] = GMB;
            fnSpr[31] = imb;
            fnSpr[15] = im;
            fnSpr[12] = fxe;
            end
    6'd60:  fnSpr = spr_bir;
    6'd61:
            casex(spr_bir[5:0])
            6'd0:   fnSpr = dbg_adr0;  
            6'd1:   fnSpr = dbg_adr1;  
            6'd2:   fnSpr = dbg_adr2;  
            6'd3:   fnSpr = dbg_adr3;  
            6'd4:   fnSpr = dbg_ctrl;
            6'd5:   fnSpr = dbg_stat;
`ifdef PCHIST            
            6'd16:  fnSpr = pc_histo[31:0];
            6'd17:  fnSpr = pc_histo[63:31];
`endif            
            default:    fnSpr = 64'd0;
            endcase
    default:    fnSpr = 64'd0;
    endcase
// 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
// Shaves a clock cycle off register updates. rf_v is being set valid on the
// clock cycle of the commit.   
    // If an spr is committing...
    if (commit0_v && commit0_tgt=={1'b1,regno}) begin
        if (regno[5:4]==2'b00) begin
            if (DBW==32)
                fnSpr = {8{cmt0nyb[regno[2:0]]}};
            else
                fnSpr = {16{cmt0nyb[regno[3:0]]}};
        end
        else
            fnSpr = commit0_bus;
    end
    if (commit1_v && commit1_tgt=={1'b1,regno}) begin
        if (regno[5:4]==2'b00) begin
            if (DBW==32)
                fnSpr = {8{cmt1nyb[regno[2:0]]}};
            else
                fnSpr = {16{cmt1nyb[regno[3:0]]}};
        end
        else
            fnSpr = commit1_bus;
    end
 
    // Special cases where the register would not be read from the commit bus
    case(regno)
    `TICK:      fnSpr = tick;
    6'b010000:  fnSpr = 64'd0;  // code address zero
    6'b011111:  fnSpr = epc;    // current program counter from fetchbufx_pc
    default:    ;
    endcase
end
endfunction
 
// "oddball" instruction commit cases.
//
task oddball_commit;
input commit_v;
input [2:0] head;
begin
    if (commit_v)
        case(iqentry_op[head])
        `CLI:	begin imcd <= IMCD; imb <= 1'b0; end
        `SEI:	begin im <= 1'b1; imb <= 1'b1; end
        // When the RTI instruction commits clear the hardware interrupt status to enable interrupts.
        `RTI:	begin
                StatusHWI <= `FALSE;
                if (imb)
                    im <= 1'b1;
                else
                    imcd <= IMCD;
                end
        `RTD:
                begin
                    StatusDBG <= `FALSE;
                    if (StatusEXL!=8'h00)
                        StatusEXL <= StatusEXL - 8'd1;
                end
        `RTE:
                begin
                    if (StatusEXL!=8'h00)
                        StatusEXL <= StatusEXL - 8'd1;
                end
        `CACHE:
               begin
                   case(iqentry_fn[head])
                   6'd0:   ic_invalidate <= `TRUE;
                   6'd1:   begin
                           ic_invalidate_line <= `TRUE;
                           ic_lineno <= iqentry_a1[head]  + {sregs[3'd7],12'h000};
                           end
                   6'd32:  dc_invalidate <= `TRUE;
                   6'd33:  begin
                           dc_invalidate_line <= `TRUE;
                           dc_lineno <= iqentry_a1[head] + {sregs[iqentry_fn[head][5:3]],12'h000};
                           end
                   default: ;   // do nothing
                   endcase
               end
        default:	;
        endcase
end
endtask
 
// 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
// trapped. The exception_set var tracks these excaptions and reduces the
// tree to a single if.
task enque0a;
input [2:0] tail;
input [2:0] inc;
input unlink;
begin
    if (fetchbuf0_pc==32'h0)
        $stop;
    if (fetchbuf0_pc==32'hF44)
        $stop;
    if (fetchbuf0_pc==32'hFFFC275A)
        $stop;
`ifdef SEGMENTATION
`ifdef SEGLIMITS
    // 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)
        set_exception(tail,8'd244);
`endif
`endif
    // If targeting a kernel mode register and not in kernel mode.
    // But okay if it is an SYS or INT instruction.
    if (fnIsKMOnlyReg(Rt0) && !km && !(opcode0==`SYS || opcode0==`INT))
        set_exception(tail,8'd245);
    // If attempting to use an undefined instruction
`ifdef TRAP_ILLEGALOPS
    if (fnIsIllegal(opcode0,opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr)))
        set_exception(tail,8'd250);
`endif
`ifdef DEBUG_LOGIC
    if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf0_pc==dbg_adr0)
        dbg_imatchA0 = `TRUE;
    if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf0_pc==dbg_adr1)
        dbg_imatchA1 = `TRUE;
    if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf0_pc==dbg_adr2)
        dbg_imatchA2 = `TRUE;
    if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf0_pc==dbg_adr3)
        dbg_imatchA3 = `TRUE;
    if (dbg_imatchA0|dbg_imatchA1|dbg_imatchA2|dbg_imatchA3)
        dbg_imatchA = `TRUE;
    if (dbg_imatchA)
        set_exception(tail,8'd243); // Debug exception
`endif
    if (!exception_set) begin
        interrupt_pc =
            // 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) ?
            (string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) :
            // Otherwise inherit the address of any preceding immediate prefix.
            (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]) :
            // Otherwise use the address of the interrupted instruction
            (string_pc != 0 ? string_pc : fetchbuf0_pc);
    iqentry_v    [tail]    <=   `VAL;
    iqentry_done [tail]    <=   `INV;
    iqentry_cmt  [tail]    <=   `TRUE;
    iqentry_out  [tail]    <=   `INV;
    iqentry_res  [tail]    <=   `ZERO;
    iqentry_insnsz[tail]   <=  fnInsnLength(fetchbuf0_instr);
    iqentry_op   [tail]    <=   opcode0; 
    iqentry_fn   [tail]    <=   opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr);
    iqentry_cond [tail]    <=   cond0;
    iqentry_bt   [tail]    <=   fnIsFlowCtrl(opcode0) && predict_taken0;
    iqentry_br   [tail]    <=   opcode0[7:4]==`BR;
    iqentry_agen [tail]    <=   `INV;
    iqentry_pc   [tail]    <=   (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc;
    iqentry_mem  [tail]    <=   fetchbuf0_mem;
    iqentry_ndx  [tail]    <=   fnIsIndexed(opcode0);
    iqentry_cas  [tail]    <=   opcode0==`CAS;
    iqentry_pushpop[tail]  <=   opcode0==`PUSH || opcode0==`POP;
    iqentry_pea  [tail]    <=   opcode0==`PEA;
    iqentry_cmpmv[tail]    <=   opcode0==`STCMP || opcode0==`STMV;
    iqentry_lla  [tail]    <=   opcode0==`LLA || opcode0==`LLAX;
    iqentry_tlb  [tail]    <=   opcode0==`TLB;
    iqentry_jmp  [tail]    <=   fetchbuf0_jmp;
    iqentry_jmpi [tail]    <=   opcode0==`JMPI || opcode0==`JMPIX;
    iqentry_sync [tail]    <=   opcode0==`SYNC;
    iqentry_memsb[tail]    <=   opcode0==`MEMSB;
    iqentry_memdb[tail]    <=   opcode0==`MEMDB;
    iqentry_fp   [tail]    <=   fetchbuf0_fp;
    iqentry_rfw  [tail]    <=   fetchbuf0_rfw;
    iqentry_tgt  [tail]    <=   Rt0;
    iqentry_preg [tail]    <=   Pn0;
    // Need the bypassing on the preg file for write-through register effect.
    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
    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]} : 
                                (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) :
                                fnImm(fetchbuf0_instr);
    // These register recordings for simulation debug. They should be stripped
    // out of synthesis because they don't drive any signals.
`ifdef SIMULATION    
    iqentry_r1   [tail]    <=   Ra0;
    iqentry_r2   [tail]    <=   Rb0;
    iqentry_r3   [tail]    <=   Rc0;
    iqentry_rt   [tail]    <=   Rt0;
`endif
    iqentry_a1   [tail]    <=   fnOpa(opcode0,Ra0,fetchbuf0_instr,rfoa0,fetchbuf0_pc);
    iqentry_a2   [tail]    <=   fnOpb(opcode0,Rb0,fetchbuf0_instr,rfob0,fetchbuf0_pc);   
    iqentry_a3   [tail]    <=   rfoc0;
    iqentry_T    [tail]    <=   fnOpt(Rt0,rfot0,fetchbuf0_pc);
    // 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.
    iqentry_p_s  [tail]    <=   rf_source[{1'b1,2'h0,Pn0}];
    iqentry_a1_s [tail]    <=   //unlink ? {1'b0, (tail-1)&7} :
                                 rf_source[Ra0];
    iqentry_a2_s [tail]    <=   rf_source[Rb0];
    iqentry_a3_s [tail]    <=   rf_source[Rc0];
    iqentry_T_s  [tail]    <=   rf_source[Rt0];
    // Always do this because it's the first queue slot.
    validate_args10(tail);
    end
    tail0 <= tail0 + inc;
    tail1 <= tail1 + inc;
    tail2 <= tail2 + inc;
    queued1 = `TRUE;
    rrmapno <= rrmapno + 3'd1;
end
endtask
 
task enquePushpopAdd;
input [2:0] tail;
input pushpop;
input link;
input unlink;
input which;
begin
    $display("Pushpop add");
    iqentry_v    [tail]    <=   `VAL;
    iqentry_done [tail]    <=   `INV;
    iqentry_cmt  [tail]    <=   `TRUE;
    iqentry_out  [tail]    <=   `INV;
    iqentry_res  [tail]    <=   64'd0;
    iqentry_insnsz[tail]   <=   4'd0;
    iqentry_op   [tail]    <=   `ADDUI; 
    iqentry_fn   [tail]    <=   6'b0;
    iqentry_cond [tail]    <=   which ? cond1 :cond0;
    iqentry_bt   [tail]    <=   1'b0; 
    iqentry_agen [tail]    <=   `INV;
    iqentry_pc   [tail]    <=   which ? fetchbuf1_pc : fetchbuf0_pc;
    iqentry_mem  [tail]    <=   1'b0;
    iqentry_ndx  [tail]    <=   1'b0;
    iqentry_cas  [tail]    <=   1'b0;
    iqentry_pushpop[tail]  <=   1'b0;
    iqentry_pea  [tail]    <=   1'b0;
    iqentry_cmpmv[tail]    <=   1'b0;
    iqentry_lla  [tail]    <=   1'b0;
    iqentry_tlb  [tail]    <=   1'b0;
    iqentry_jmp  [tail]    <=   1'b0;
    iqentry_jmpi [tail]    <=   1'b0;
    iqentry_sync [tail]    <=   1'b0;
    iqentry_memsb[tail]    <=   1'b0;
    iqentry_memdb[tail]    <=   1'b0;
    iqentry_fp   [tail]    <=   1'b0;
    iqentry_rfw  [tail]    <=   1'b1;
    iqentry_tgt  [tail]    <=   7'd27;
    iqentry_pred [tail]    <=   pregs[which ? Pn1 : Pn0];
    // 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} :
                                                {{46{fetchbuf0_instr[39]}},fetchbuf0_instr[21:16],fetchbuf0_instr[39:28],3'b000}) :
                                (pushpop|unlink) ? 64'd8 : -64'd8;
    iqentry_a1   [tail]    <=   which ? rfoa1 : rfoa0;
    iqentry_a2   [tail]    <=   64'd0;
    iqentry_a3   [tail]    <=   64'd0;
    iqentry_T    [tail]    <=   //unlink ? (which ? rfot1 : rfot0) :
                                 (which ? rfoa1 : rfoa0);
    // 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.
    iqentry_p_s  [tail]    <=   rf_source[{1'b1,2'h0,which ? Pn1 : Pn0}];
    iqentry_a1_s [tail]    <=   rf_source[Ra0];
    iqentry_a2_s [tail]    <=   rf_source[Rb0];
    iqentry_a3_s [tail]    <=   rf_source[Rc0];
    iqentry_T_s  [tail]    <=   rf_source[Ra0];
    // 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_a1_v [tail]    <=   rf_v[ which ? Ra1 :  Ra0 ];
    iqentry_a2_v [tail]    <=   1'b1;
    iqentry_a3_v [tail]    <=   1'b1;
    iqentry_T_v  [tail]    <=   //unlink ? rf_v[which ? Rt1 : Rt0] :
                                rf_v[ which ? Ra1 :  Ra0 ];
    rf_v[ 7'd27 ] = `INV;
    rf_source[ 7'd27 ] <= { 1'b0, tail };    // top bit indicates ALU/MEM bus
end
endtask
 
// enque 0 on tail0 or tail1
task enque0;
input [2:0] tail;
input [2:0] inc;
input test_stomp;
input validate_args;
begin
    if (opcode0==`NOP)
        queued1 = `TRUE;    // to update fetch buffers
`ifdef DEBUG_LOGIC
    else
    if (dbg_ctrl[7] && !StatusDBG) begin
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
            enque0a(tail,3'd2,1'b0);
            set_exception((tail+1)&7,8'd243);
            allowq = `FALSE;
        end
    end
`endif
`ifdef STACKOPS
    // A pop instruction takes 2 queue entries.
    else if (fnIsPop(fetchbuf0_instr)|fnIsPush(fetchbuf0_instr)|opcode0==`LINK) begin
        $display("0 found push/pop");
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
            $display("enqueing2");
            enque0a(tail,3'd2,1'b0);
            enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf0_instr),opcode0==`LINK,0,0);
            allowq = `FALSE;
        end
    end
`ifdef UNLINKOP
    else if (opcode0==`UNLINK) begin
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
            enquePushpopAdd(tail,1'b0,1'b0,1'b1,0);
            enque0a((tail+1)&7,3'd2,1'b1);
            allowq = `FALSE;
        end
    end
`endif
`endif
    else if (iqentry_v[tail] == `INV) begin
        if ((({fnIsBranch(opcode0), predict_taken0} == {`TRUE, `TRUE})||(opcode0==`LOOP)) && test_stomp)
            qstomp = `TRUE;
        enque0a(tail,inc,0);
    end
end
endtask
 
task enque1a;
input [2:0] tail;
input [2:0] inc;
input validate_args;
input unlink;
begin
    if (fetchbuf1_pc==32'h0)
        $stop;
    if (fetchbuf1_pc==32'hF44)
        $stop;
    if (fetchbuf1_pc==32'hFFFC275A)
        $stop;
`ifdef SEGMENTATION
`ifdef SEGLIMITS
    if (fetchbuf1_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF)
        set_exception(tail,8'd244);
`endif
`endif
    if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT))
        set_exception(tail,8'd245);
`ifdef TRAP_ILLEGALOPS
    if (fnIsIllegal(opcode1,opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr)))
        set_exception(tail,8'd250);
`endif
`ifdef DEBUG_LOGIC
    if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf1_pc==dbg_adr0)
        dbg_imatchB0 = `TRUE;
    if (dbg_ctrl[1] && dbg_ctrl[21:20]==2'b00 && fetchbuf1_pc==dbg_adr1)
        dbg_imatchB1 = `TRUE;
    if (dbg_ctrl[2] && dbg_ctrl[25:24]==2'b00 && fetchbuf1_pc==dbg_adr2)
        dbg_imatchB2 = `TRUE;
    if (dbg_ctrl[3] && dbg_ctrl[29:28]==2'b00 && fetchbuf1_pc==dbg_adr3)
        dbg_imatchB3 = `TRUE;
    if (dbg_imatchB0|dbg_imatchB1|dbg_imatchB2|dbg_imatchB3)
        dbg_imatchB = `TRUE;
    if (dbg_imatchB)
        set_exception(tail,8'd243);     // debug excpetion
`endif
    if (!exception_set) begin
    // 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
    // from the previous one.
    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) ?
            (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_pc[(tail-3'd1)&7]) : (string_pc != 0 ? string_pc : fetchbuf1_pc);
    iqentry_v    [tail]    <=   `VAL;
    iqentry_done [tail]    <=   `INV;
    iqentry_cmt  [tail]    <=   `TRUE;
    iqentry_out  [tail]    <=   `INV;
    iqentry_res  [tail]    <=   `ZERO;
    iqentry_insnsz[tail]   <=  fnInsnLength(fetchbuf1_instr);
    iqentry_op   [tail]    <=   opcode1;
    iqentry_fn   [tail]    <=   opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr);
    iqentry_cond [tail]    <=   cond1;
    iqentry_bt   [tail]    <=   fnIsFlowCtrl(opcode1) && predict_taken1; 
    iqentry_br   [tail]    <=   opcode1[7:4]==`BR;
    iqentry_agen [tail]    <=   `INV;
    // 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
    // from interrupt.
    // If a string operation was in progress then inherit the address of the string operation so that
    // it can be continued.
 
    iqentry_pc   [tail]    <= (opcode1==`INT && Rt1[3:0]==4'hE) ? interrupt_pc : fetchbuf1_pc;
    iqentry_mem  [tail]    <=   fetchbuf1_mem;
    iqentry_ndx  [tail]    <=   fnIsIndexed(opcode1);
    iqentry_cas  [tail]    <=   opcode1==`CAS;
    iqentry_pushpop[tail]  <=   opcode1==`PUSH || opcode1==`POP;
    iqentry_pea  [tail]    <=   opcode1==`PEA;
    iqentry_cmpmv[tail]    <=   opcode1==`STCMP || opcode1==`STMV;
    iqentry_lla  [tail]    <=   opcode1==`LLA || opcode1==`LLAX;
    iqentry_tlb  [tail]    <=   opcode1==`TLB;
    iqentry_jmp  [tail]    <=   fetchbuf1_jmp;
    iqentry_jmpi [tail]    <=   opcode1==`JMPI || opcode1==`JMPIX;
    iqentry_sync [tail]    <=   opcode1==`SYNC;
    iqentry_memsb[tail]    <=   opcode1==`MEMSB;
    iqentry_memdb[tail]    <=   opcode1==`MEMDB;
    iqentry_fp   [tail]    <=   fetchbuf1_fp;
    iqentry_rfw  [tail]    <=   fetchbuf1_rfw;
    iqentry_tgt  [tail]    <=   Rt1;
    iqentry_preg [tail]    <=   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
    // But don't allow it for a branch
    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]} :
                                (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)} :
                                opcode1==`IMM ? fnImmImm(fetchbuf1_instr) :
                                fnImm(fetchbuf1_instr);
    iqentry_a1   [tail]    <=   fnOpa(opcode1,Ra1,fetchbuf1_instr,rfoa1,fetchbuf1_pc);
    iqentry_a2   [tail]    <=   fnOpb(opcode1,Rb1,fetchbuf1_instr,rfob1,fetchbuf1_pc);
    iqentry_a3   [tail]    <=   rfoc1;
    iqentry_T    [tail]    <=   fnOpt(Rt1,rfot1,fetchbuf1_pc);
`ifdef SIMULATION
    iqentry_r1   [tail]    <=   Ra1;
    iqentry_r2   [tail]    <=   Rb1;
    iqentry_r3   [tail]    <=   Rc1;
    iqentry_rt   [tail]    <=   Rt1;
`endif
    // 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.
    iqentry_p_s  [tail]    <=   rf_source[{1'b1,2'h0,Pn1}];
    iqentry_a1_s [tail]    <=   //unlink ? {1'b0, (tail-3'd1)&7} :
                                rf_source[Ra1];
    iqentry_a2_s [tail]    <=   rf_source[Rb1];
    iqentry_a3_s [tail]    <=   rf_source[Rc1];
    iqentry_T_s  [tail]    <=   rf_source[Rt1];
    if (validate_args)
        validate_args11(tail);
    end
    tail0 <= tail0 + inc;
    tail1 <= tail1 + inc;
    tail2 <= tail2 + inc;
end
endtask
 
// enque 1 on tail0 or tail1
task enque1;
input [2:0] tail;
input [2:0] inc;
input test_stomp;
input validate_args;
begin
    if (opcode1==`NOP) begin
        if (queued1==`TRUE) queued2 = `TRUE;
        queued1 = `TRUE;
    end
`ifdef DEBUG_LOGIC
    else
    if (dbg_ctrl[7] && !StatusDBG) begin
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
            enque1a(tail,3'd2,1,0);
            set_exception((tail+1)&7,8'd243);
            allowq = `FALSE;
        end
    end
`endif
`ifdef STACKOPS
    else if (fnIsPop(fetchbuf1_instr)|fnIsPush(fetchbuf1_instr)|opcode1==`LINK) begin
        $display("1 found push/pop");
        $display("iqv[%d]:%d", tail,iqentry_v[tail]);
        $display("iqv[%d+1]:%d", tail, iqentry_v[tail+1]);
        $display("valargs:%d", validate_args);
        $display("qd1:%d", queued1);
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV && validate_args && !queued1) begin
            $display("1 enq 2 ");
            enque1a(tail,3'd2,1,0);
            enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf1_instr),opcode1==`LINK,0,1);
            allowq = `FALSE;
        end
    end
`ifdef UNLINKOP
    else if (opcode1==`UNLINK) begin
        if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin
            enquePushpopAdd(tail,1'b0,1'b0,1'b1,1);
            enque1a((tail+1)&7,3'd2,1,1);
            allowq = `FALSE;
        end
    end
`endif
`endif
    else if (iqentry_v[tail] == `INV && !qstomp) begin
        if ((({fnIsBranch(opcode1), predict_taken1} == {`TRUE, `TRUE})||(opcode1==`LOOP)) && test_stomp)
            qstomp = `TRUE;
        enque1a(tail,inc,validate_args,0);
        if (queued1==`TRUE) queued2 = `TRUE;
        else queued1 = `TRUE;
    end
end
endtask
 
task validate_args10;
input [2:0] tail;
begin
    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_a2_v [tail]    <=   fnSource2_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[Rb0];
    iqentry_a3_v [tail]    <=   fnSource3_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[ Rc0 ];
    iqentry_T_v  [tail]    <=   fnSourceT_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[ Rt0 ];
    if (fetchbuf0_rfw|fetchbuf0_pfw) begin
        $display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
        rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
        $display("reg[%d] <= INV",Rt0);
        rf_source[ Rt0 ] <= { fetchbuf0_mem, tail };    // top bit indicates ALU/MEM bus
        $display("10:rf_src[%d] <= %d, insn=%h", Rt0, tail,fetchbuf0_instr);
        invalidate_pregs(tail, Rt0, fetchbuf0_mem);
    end
end
endtask
 
task validate_args11;
input [2:0] tail;
begin
    // 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_a1_v [tail]    <=   fnSource1_v( opcode1 ) | rf_v[ Ra1 ];
    iqentry_a2_v [tail]    <=   fnSource2_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rb1 ];
    iqentry_a3_v [tail]    <=   fnSource3_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rc1 ];
    iqentry_T_v  [tail]    <=   fnSourceT_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rt1 ];
    if (fetchbuf1_rfw|fetchbuf1_pfw) begin
        $display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
        rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
        $display("reg[%d] <= INV",Rt1);
        rf_source[ Rt1 ] <= { fetchbuf1_mem, tail };    // top bit indicates ALU/MEM bus
        invalidate_pregs(tail, Rt1, fetchbuf1_mem);
        $display("11:rf_src[%d] <= %d, insn=%h", Rt1, tail,fetchbuf0_instr);
    end
end
endtask
 
// If two entries were queued then validate the arguments for the second entry.
//
task validate_args;
begin
    if (queued2) begin
    // SOURCE 1 ... this is relatively straightforward, because all instructions
       // 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 (fnSource1_v( opcode1 ) == `VAL) begin
           $display("fnSource1_v=1 iq[%d]", tail1);
           iqentry_a1_v [tail1] <= `VAL;
           iqentry_a1_s [tail1] <= 4'hF;
//                    iqentry_a1_s [tail1] <= 4'd0;
       end
       // if previous instruction writes nothing to RF, then get info from rf_v and rf_source
       else if (!fetchbuf0_rfw) begin
           iqentry_a1_v [tail1]    <=   rf_v [Ra1];
           iqentry_a1_s [tail1]    <=   rf_source [Ra1];
       end
       // otherwise, previous instruction does write to RF ... see if overlap
       else if (Rt0 != 7'd0 && Ra1 == Rt0) begin
           // if the previous instruction is a LW, then grab result from memq, not the iq
           $display("invalidating iqentry_a1_v[%d]", tail1);
           iqentry_a1_v [tail1]    <=   `INV;
           iqentry_a1_s [tail1]    <=   {fetchbuf0_mem, tail0};
       end
       // if no overlap, get info from rf_v and rf_source
       else begin
           iqentry_a1_v [tail1]    <=   rf_v [Ra1];
           iqentry_a1_s [tail1]    <=   rf_source [Ra1];
           $display("2:iqentry_a1_s[%d] <= %d", tail1, rf_source [Ra1]);
       end
 
       if (!fetchbuf0_pfw) begin
           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}];
       end
       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_s [tail1] <= {fetchbuf0_mem, tail0};
       end
       else begin
           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}];
       end
 
       //
       // 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
       //
       // if the argument is an immediate or not needed, we're done
       if (fnSource2_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin
           iqentry_a2_v [tail1] <= `VAL;
           iqentry_a2_s [tail1] <= 4'hF;
       end
       // if previous instruction writes nothing to RF, then get info from rf_v and rf_source
       else if (!fetchbuf0_rfw) begin
           iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
           iqentry_a2_s [tail1] <= rf_source[Rb1];
       end
       // otherwise, previous instruction does write to RF ... see if overlap
       else if (Rt0 != 7'd0 && Rb1 == Rt0) begin
           // if the previous instruction is a LW, then grab result from memq, not the iq
           iqentry_a2_v [tail1]    <=   `INV;
           iqentry_a2_s [tail1]    <=   {fetchbuf0_mem,tail0};
       end
       // if no overlap, get info from rf_v and rf_source
       else begin
           iqentry_a2_v [tail1] <= rf_v[ Rb1 ];
           iqentry_a2_s [tail1] <= rf_source[Rb1];
       end
 
       //
       // SOURCE 3 ... this is relatively straightforward, because all instructions
       // 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 (fnSource3_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin
           iqentry_a3_v [tail1] <= `VAL;
           iqentry_a3_v [tail1] <= 4'hF;
//                    iqentry_a1_s [tail1] <= 4'd0;
       end
       // if previous instruction writes nothing to RF, then get info from rf_v and rf_source
       else if (!fetchbuf0_rfw) begin
           iqentry_a3_v [tail1]    <=   rf_v [Rc1];
           iqentry_a3_s [tail1]    <=   rf_source [Rc1];
       end
       // otherwise, previous instruction does write to RF ... see if overlap
       else if (Rt0 != 7'd0 && Rc1 == Rt0) begin
           // if the previous instruction is a LW, then grab result from memq, not the iq
           iqentry_a3_v [tail1]    <=   `INV;
           iqentry_a3_s [tail1]    <=   {fetchbuf0_mem,tail0};
       end
       // if no overlap, get info from rf_v and rf_source
       else begin
           iqentry_a3_v [tail1]    <=   rf_v [Rc1];
           iqentry_a3_s [tail1]    <=   rf_source [Rc1];
       end
 
 
       //
       // Target 3 ... this is relatively straightforward, because all instructions
       // 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 (fnSourceT_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin
           iqentry_T_v [tail1] <= `VAL;
           iqentry_T_v [tail1] <= 4'hF;
       end
       // if previous instruction writes nothing to RF, then get info from rf_v and rf_source
       else if (!fetchbuf0_rfw) begin
           iqentry_T_v [tail1]    <=   rf_v [Rt1];
           iqentry_T_s [tail1]    <=   rf_source [Rt1];
       end
       // otherwise, previous instruction does write to RF ... see if overlap
       else if (Rt0 != 7'd0 && Rt1 == Rt0) begin
           // if the previous instruction is a LW, then grab result from memq, not the iq
           iqentry_T_v [tail1]    <=   `INV;
           iqentry_T_s [tail1]    <=   {fetchbuf0_mem,tail0};
       end
       // if no overlap, get info from rf_v and rf_source
       else begin
           iqentry_T_v [tail1]    <=   rf_v [Rt1];
           iqentry_T_s [tail1]    <=   rf_source [Rt1];
       end
    end
    if (queued1|queued2) begin
        if (fetchbuf0_rfw|fetchbuf0_pfw) begin
            $display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]);
            rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0);
            $display("reg[%d] <= INV",Rt0);
            rf_source[ Rt0 ] <= { fetchbuf0_mem, tail0 };    // top bit indicates ALU/MEM bus
            $display("12:rf_src[%d] <= %d, insn=%h", Rt0, tail0,fetchbuf0_instr);
            invalidate_pregs(tail0, Rt0, fetchbuf0_mem);
        end
    end
    if (queued2) begin
        if (fetchbuf1_rfw|fetchbuf1_pfw) begin
            $display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]);
            rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1);
            $display("reg[%d] <= INV",Rt1);
            rf_source[ Rt1 ] <= { fetchbuf1_mem, tail1 };    // top bit indicates ALU/MEM bus
            invalidate_pregs(tail1, Rt1, fetchbuf1_mem);
        end
    end
end
endtask
 
task fetchAB;
begin
    fetchbufA_instr <= insn0;
    fetchbufA_pc <= pc;
    fetchbufA_v <= ld_fetchbuf;
    fetchbufB_instr <= insn1;
    fetchbufB_pc <= pc + fnInsnLength(insn);
    fetchbufB_v <= ld_fetchbuf;
end
endtask
 
task fetchCD;
begin
    fetchbufC_instr <= insn0;
    fetchbufC_pc <= pc;
    fetchbufC_v <= ld_fetchbuf;
    fetchbufD_instr <= insn1;
    fetchbufD_pc <= pc + fnInsnLength(insn);
    fetchbufD_v <= ld_fetchbuf;
end
endtask
 
// Reset the tail pointers.
// Used by the enqueue logic
//
task reset_tail_pointers;
input first;
begin
    if ((iqentry_stomp[0] & ~iqentry_stomp[7]) | first) begin
        tail0 <= 0;
        tail1 <= 1;
    end
    else if (iqentry_stomp[1] & ~iqentry_stomp[0]) begin
        tail0 <= 1;
        tail1 <= 2;
    end
    else if (iqentry_stomp[2] & ~iqentry_stomp[1]) begin
        tail0 <= 2;
        tail1 <= 3;
    end
    else if (iqentry_stomp[3] & ~iqentry_stomp[2]) begin
        tail0 <= 3;
        tail1 <= 4;
    end
    else if (iqentry_stomp[4] & ~iqentry_stomp[3]) begin
        tail0 <= 4;
        tail1 <= 5;
    end
    else if (iqentry_stomp[5] & ~iqentry_stomp[4]) begin
        tail0 <= 5;
        tail1 <= 6;
    end
    else if (iqentry_stomp[6] & ~iqentry_stomp[5]) begin
        tail0 <= 6;
        tail1 <= 7;
    end
    else if (iqentry_stomp[7] & ~iqentry_stomp[6]) begin
        tail0 <= 7;
        tail1 <= 0;
    end
    // otherwise, it is the last instruction in the queue that has been mispredicted ... do nothing
end
endtask
 
// Increment the head pointers
// Also increments the instruction counter
// Used when instructions are committed.
// Also clear any outstanding state bits that foul things up.
//
task head_inc;
input [2:0] amt;
begin
    head0 <= head0 + amt;
    head1 <= head1 + amt;
    head2 <= head2 + amt;
    head3 <= head3 + amt;
    head4 <= head4 + amt;
    head5 <= head5 + amt;
    head6 <= head6 + amt;
    head7 <= head7 + amt;
    I <= I + amt;
    if (amt==3'd3) begin
    iqentry_agen[head0] <= `INV;
    iqentry_agen[head1] <= `INV;
    iqentry_agen[head2] <= `INV;
    end else if (amt==3'd2) begin
    iqentry_agen[head0] <= `INV;
    iqentry_agen[head1] <= `INV;
    end else if (amt==3'd1)
	    iqentry_agen[head0] <= `INV;
end
endtask
 
 
// set_exception:
// Used to requeue the instruction as an exception if an exception occurs.
 
task set_exception;
input [2:0] id;     // instruction queue id
input [7:0] exc;    // exception number
begin
    iqentry_op [id[2:0] ] <= `INT;
    iqentry_cond [id[2:0]] <= 4'd1;        // always execute
    iqentry_mem[id[2:0]] <= `FALSE;
    iqentry_rfw[id[2:0]] <= `TRUE;            // writes to IPC
    iqentry_a0 [id[2:0]] <= exc;
    iqentry_p_v  [id[2:0]] <= `TRUE;
    iqentry_a1 [id[2:0]] <= cregs[4'hC];    // *** assumes BR12 is static
    iqentry_a1_v [id[2:0]] <= `TRUE;        // Flag arguments as valid
    iqentry_a2_v [id[2:0]] <= `TRUE;
    iqentry_a3_v [id[2:0]] <= `TRUE;
    iqentry_T_v  [id[2:0]] <= `TRUE;
    iqentry_out [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
    exception_set = `TRUE;
end
endtask
 
// The core should really invalidate all the predicate registers when the
// sideways slice of all the pregs is manipulated. But then the problem is
// 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
// and the core does not support this sort of thing.
// So. After manipulating the sideways slice of predicate registers the
// instruction should be followed with a SYNC instruction to ensure that
// the results are picked up.
// To be fixed one day.
task invalidate_pregs;
input [2:0] tail;
input [6:0] Rt;
input mem;
begin
if (Rt==7'h70) begin
    rf_v[7'h40] = `INV;
    rf_v[7'h41] = `INV;
    rf_v[7'h42] = `INV;
    rf_v[7'h43] = `INV;
    rf_v[7'h44] = `INV;
    rf_v[7'h45] = `INV;
    rf_v[7'h46] = `INV;
    rf_v[7'h47] = `INV;
    rf_v[7'h48] = `INV;
    rf_v[7'h49] = `INV;
    rf_v[7'h4A] = `INV;
    rf_v[7'h4B] = `INV;
    rf_v[7'h4C] = `INV;
    rf_v[7'h4D] = `INV;
    rf_v[7'h4E] = `INV;
    rf_v[7'h4F] = `INV;
    rf_source[7'h40] <= { mem, tail };
    rf_source[7'h41] <= { mem, tail };
    rf_source[7'h42] <= { mem, tail };
    rf_source[7'h43] <= { mem, tail };
    rf_source[7'h44] <= { mem, tail };
    rf_source[7'h45] <= { mem, tail };
    rf_source[7'h46] <= { mem, tail };
    rf_source[7'h47] <= { mem, tail };
    rf_source[7'h48] <= { mem, tail };
    rf_source[7'h49] <= { mem, tail };
    rf_source[7'h4A] <= { mem, tail };
    rf_source[7'h4B] <= { mem, tail };
    rf_source[7'h4C] <= { mem, tail };
    rf_source[7'h4D] <= { mem, tail };
    rf_source[7'h4E] <= { mem, tail };
    rf_source[7'h4F] <= { mem, tail };
end
end
endtask
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.