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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [or1200_monitor.v] - Diff between revs 863 and 864

Only display areas with differences | Details | Blame | View Log

Rev 863 Rev 864
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  or1200_monitor.v                                            ////
////  or1200_monitor.v                                            ////
////                                                              ////
////                                                              ////
////  OR1200 processor monitor module                             ////
////  OR1200 processor monitor module                             ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////      - Julius Baxter, julius@opencores.org                   ////
////      - Julius Baxter, julius@opencores.org                   ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG           ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG           ////
////                                                              ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
 
 
`include "timescale.v"
`include "timescale.v"
`include "or1200_defines.v"
`include "or1200_defines.v"
`include "or1200_monitor_defines.v"
`include "or1200_monitor_defines.v"
 
 
 
 
module or1200_monitor;
module or1200_monitor;
 
 
   parameter TEST_NAME_STRING = "unnamed";
   parameter TEST_NAME_STRING = "unnamed";
   parameter LOG_DIR          = ".";
   parameter LOG_DIR          = ".";
 
 
   integer fexe;
   integer fexe;
   integer finsn;
   integer finsn;
 
 
   reg [23:0] ref;
   reg [23:0] ref;
`ifdef OR1200_MONITOR_SPRS
`ifdef OR1200_MONITOR_SPRS
   integer    fspr;
   integer    fspr;
`endif
`endif
   integer    fgeneral;
   integer    fgeneral;
`ifdef OR1200_MONITOR_LOOKUP
`ifdef OR1200_MONITOR_LOOKUP
   integer    flookup;
   integer    flookup;
`endif
`endif
   integer    r3;
   integer    r3;
   integer    insns;
   integer    insns;
 
 
   //Trim \0 characters from str and return a right-adjusted string
   //Trim \0 characters from str and return a right-adjusted string
   function [128*8-1:0] trim;
   function [128*8-1:0] trim;
      input [128*8-1:0] str;
      input [128*8-1:0] str;
      integer           wpos;
      integer           wpos;
      integer           rpos;
      integer           rpos;
      begin
      begin
         trim = 0;
         trim = 0;
         wpos = 0;
         wpos = 0;
         for(rpos=0;rpos<=128*8;rpos=rpos+8)
         for(rpos=0;rpos<=128*8;rpos=rpos+8)
           if(str[rpos+:8] != 0) begin
           if(str[rpos+:8] != 0) begin
              trim[wpos+:8] = str[rpos+:8];
              trim[wpos+:8] = str[rpos+:8];
              wpos = wpos +8;
              wpos = wpos +8;
           end
           end
      end
      end
   endfunction
   endfunction
 
 
   //
   //
   // Initialization
   // Initialization
   //
   //
   reg [64*8-1:0]  testcase; //Maximum 64 characters
   reg [64*8-1:0]  testcase; //Maximum 64 characters
 
 
   initial begin
   initial begin
      ref = 0;
      ref = 0;
      if(!$value$plusargs("testcase=%s", testcase))
      if(!$value$plusargs("testcase=%s", testcase))
        testcase = TEST_NAME_STRING;
        testcase = TEST_NAME_STRING;
 
 
`ifdef OR1200_MONITOR_EXEC_STATE
`ifdef OR1200_MONITOR_EXEC_STATE
      fexe = $fopen(trim({LOG_DIR, "/", testcase, "-executed.log"}));
      fexe = $fopen(trim({LOG_DIR, "/", testcase, "-executed.log"}));
`endif
`endif
`ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
`ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
      finsn = fexe;
      finsn = fexe;
`endif
`endif
      $timeformat (-9, 2, " ns", 12);
      $timeformat (-9, 2, " ns", 12);
`ifdef OR1200_MONITOR_SPRS
`ifdef OR1200_MONITOR_SPRS
      fspr = $fopen(trim({LOG_DIR, "/", testcase, "-sprs.log"}));
      fspr = $fopen(trim({LOG_DIR, "/", testcase, "-sprs.log"}));
`endif
`endif
      fgeneral = $fopen(trim({LOG_DIR, "/", testcase, "-general.log"}));
      fgeneral = $fopen(trim({LOG_DIR, "/", testcase, "-general.log"}));
`ifdef OR1200_MONITOR_LOOKUP
`ifdef OR1200_MONITOR_LOOKUP
      flookup = $fopen(trim({LOG_DIR, "/", testcase, "-lookup.log"}));
      flookup = $fopen(trim({LOG_DIR, "/", testcase, "-lookup.log"}));
`endif
`endif
      insns = 0;
      insns = 0;
 
 
   end
   end
 
 
   //
   //
   // Get GPR
   // Get GPR
   //
   //
   task get_gpr;
   task get_gpr;
      input     [4:0]    gpr_no;
      input     [4:0]    gpr_no;
      output [31:0]      gpr;
      output [31:0]      gpr;
      integer           j;
      integer           j;
      begin
      begin
 
 
`ifdef OR1200_RFRAM_GENERIC
`ifdef OR1200_RFRAM_GENERIC
         for(j = 0; j < 32; j = j + 1) begin
         for(j = 0; j < 32; j = j + 1) begin
            gpr[j] = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no*32+j];
            gpr[j] = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no*32+j];
         end
         end
 
 
`else
`else
         //gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no];
         //gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no];
         gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.get_gpr(gpr_no);
         gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.get_gpr(gpr_no);
 
 
`endif
`endif
 
 
 
 
      end
      end
   endtask
   endtask
 
 
   //
   //
   // Write state of the OR1200 registers into a file
   // Write state of the OR1200 registers into a file
   //
   //
   // Limitation: only a small subset of register file RAMs
   // Limitation: only a small subset of register file RAMs
   // are supported
   // are supported
   //
   //
   task display_arch_state;
   task display_arch_state;
 
      input exception;
 
 
      reg [5:0] i;
      reg [5:0] i;
      reg [31:0] r;
      reg [31:0] r;
      integer    j;
      integer    j;
      begin
      begin
`ifdef OR1200_MONITOR_EXEC_STATE
`ifdef OR1200_MONITOR_EXEC_STATE
         ref = ref + 1;
         ref = ref + 1;
 `ifdef OR1200_MONITOR_LOOKUP
 `ifdef OR1200_MONITOR_LOOKUP
         $fdisplay(flookup, "Instruction %d: %t", insns, $time);
         $fdisplay(flookup, "Instruction %d: %t", insns, $time);
 `endif
 `endif
 
         if(exception)
 
           $fwrite(fexe, "\nEXECUTED(%d): %h:  %h  (exception)", insns,
 
                   `OR1200_TOP.`CPU_cpu.`CPU_except.ex_pc,
 
                   `OR1200_TOP.`CPU_cpu.`CPU_ctrl.ex_insn);
 
         else
         $fwrite(fexe, "\nEXECUTED(%d): %h:  %h", insns,
         $fwrite(fexe, "\nEXECUTED(%d): %h:  %h", insns,
                 `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
                   `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
                 `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
                   `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
 `ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
 `ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
 
         if(!exception) begin
         $fwrite(fexe,"\t");
         $fwrite(fexe,"\t");
         // Decode the instruction, print it out
            // Decode the instruction, print it out
         or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
         or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
 
         end
 `endif
 `endif
         for(i = 0; i < 32; i = i + 1) begin
         for(i = 0; i < 32; i = i + 1) begin
            if (i % 4 == 0)
            if (i % 4 == 0)
              $fdisplay(fexe);
              $fdisplay(fexe);
            get_gpr(i, r);
            get_gpr(i, r);
            $fwrite(fexe, "GPR%d: %h  ", i, r);
            $fwrite(fexe, "GPR%d: %h  ", i, r);
         end
         end
         $fdisplay(fexe);
         $fdisplay(fexe);
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr;
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr;
         $fwrite(fexe, "SR   : %h  ", r);
         $fwrite(fexe, "SR   : %h  ", r);
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr;
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr;
         $fwrite(fexe, "EPCR0: %h  ", r);
         $fwrite(fexe, "EPCR0: %h  ", r);
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear;
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear;
         $fwrite(fexe, "EEAR0: %h  ", r);
         $fwrite(fexe, "EEAR0: %h  ", r);
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.esr;
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.esr;
         $fdisplay(fexe, "ESR0 : %h", r);
         $fdisplay(fexe, "ESR0 : %h", r);
`endif //  `ifdef OR1200_MONITOR_EXEC_STATE
`endif //  `ifdef OR1200_MONITOR_EXEC_STATE
`ifdef OR1200_DISPLAY_EXECUTED
 
         ref = ref + 1;
 
 `ifdef OR1200_MONITOR_LOOKUP
 
         $fdisplay(flookup, "Instruction %d: %t", insns, $time);
 
 `endif
 
         $fwrite(fexe, "\nEXECUTED(%d): %h:  %h", insns, `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc, `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
 
`endif
 
         insns = insns + 1;
         insns = insns + 1;
      end
      end
   endtask // display_arch_state
   endtask // display_arch_state
 
 
   /* Keep a trace buffer of the last lot of instructions and addresses
   /* Keep a trace buffer of the last lot of instructions and addresses
    * "executed",as read from the writeback stage, and cause a $finish if we hit
    * "executed",as read from the writeback stage, and cause a $finish if we hit
    * an instruction that is invalid, such as all zeros.
    * an instruction that is invalid, such as all zeros.
    * Currently, only breaks on an all zero instruction, but should probably be
    * Currently, only breaks on an all zero instruction, but should probably be
    * made to break for anything with an X in it too. And of course ideally this
    * made to break for anything with an X in it too. And of course ideally this
    * shouldn't be needed - but is handy if someone changes something and stops
    * shouldn't be needed - but is handy if someone changes something and stops
    * the test continuing forever.
    * the test continuing forever.
    */
    */
   integer num_nul_inst;
   integer num_nul_inst;
   initial num_nul_inst = 0;
   initial num_nul_inst = 0;
 
 
   task monitor_for_crash;
   task monitor_for_crash;
`define OR1200_MONITOR_CRASH_TRACE_SIZE 32
`define OR1200_MONITOR_CRASH_TRACE_SIZE 32
      //Trace buffer of 32 instructions
      //Trace buffer of 32 instructions
      reg [31:0] insn_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
      reg [31:0] insn_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
      //Trace buffer of the addresses of those instructions
      //Trace buffer of the addresses of those instructions
      reg [31:0] addr_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
      reg [31:0] addr_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
      integer    i;
      integer    i;
 
 
      begin
      begin
         if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h00000000)
         if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h00000000)
           num_nul_inst = num_nul_inst + 1;
           num_nul_inst = num_nul_inst + 1;
         else
         else
           num_nul_inst = 0; // Reset it
           num_nul_inst = 0; // Reset it
 
 
         if (num_nul_inst == 1000) // Sat a loop a bit too long...
         if (num_nul_inst == 1000) // Sat a loop a bit too long...
           begin
           begin
              $fdisplay(fgeneral, "ERROR - no instruction at PC %h",
              $fdisplay(fgeneral, "ERROR - no instruction at PC %h",
                        `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
                        `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
              $fdisplay(fgeneral, "Crash trace: Last %d instructions: ",
              $fdisplay(fgeneral, "Crash trace: Last %d instructions: ",
                        `OR1200_MONITOR_CRASH_TRACE_SIZE);
                        `OR1200_MONITOR_CRASH_TRACE_SIZE);
 
 
              $fdisplay(fgeneral, "PC\t\tINSTR");
              $fdisplay(fgeneral, "PC\t\tINSTR");
              for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>=0;i=i-1) begin
              for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>=0;i=i-1) begin
                 $fdisplay(fgeneral, "%h\t%h",addr_trace[i], insn_trace[i]);
                 $fdisplay(fgeneral, "%h\t%h",addr_trace[i], insn_trace[i]);
              end
              end
              $display("*");
              $display("*");
              $display("* or1200_monitor : OR1200 crash detected (suspected CPU PC corruption)");
              $display("* or1200_monitor : OR1200 crash detected (suspected CPU PC corruption)");
              $display("*");
              $display("*");
 
 
              #100 $finish;
              #100 $finish;
           end
           end
         else
         else
           begin
           begin
              for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>0;i=i-1) begin
              for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>0;i=i-1) begin
                 insn_trace[i] = insn_trace[i-1];
                 insn_trace[i] = insn_trace[i-1];
                 addr_trace[i] = addr_trace[i-1];
                 addr_trace[i] = addr_trace[i-1];
              end
              end
              insn_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn;
              insn_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn;
              addr_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc;
              addr_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc;
           end
           end
 
 
      end
      end
   endtask // monitor_for_crash
   endtask // monitor_for_crash
 
 
 
 
   //
 
   // Write state of the OR1200 registers into a file; version for exception
 
   //
 
   task display_arch_state_except;
 
      reg [5:0] i;
 
      reg [31:0] r;
 
      integer    j;
 
      begin
 
`ifdef OR1200_MONITOR_EXEC_STATE
 
         ref = ref + 1;
 
 `ifdef OR1200_MONITOR_LOOKUP
 
         $fdisplay(flookup, "Instruction %d: %t", insns, $time);
 
 `endif
 
         $fwrite(fexe, "\nEXECUTED(%d): %h:  %h  (exception)", insns, `OR1200_TOP.`CPU_cpu.`CPU_except.ex_pc, `OR1200_TOP.`CPU_cpu.`CPU_ctrl.ex_insn);
 
         for(i = 0; i < 32; i = i + 1) begin
 
            if (i % 4 == 0)
 
              $fdisplay(fexe);
 
            get_gpr(i, r);
 
            $fwrite(fexe, "GPR%d: %h  ", i, r);
 
         end
 
         $fdisplay(fexe);
 
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr;
 
         $fwrite(fexe, "SR   : %h  ", r);
 
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr;
 
         $fwrite(fexe, "EPCR0: %h  ", r);
 
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear;
 
         $fwrite(fexe, "EEAR0: %h  ", r);
 
         r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.esr;
 
         $fdisplay(fexe, "ESR0 : %h", r);
 
         insns = insns + 1;
 
`endif //  `ifdef OR1200_MONITOR_EXEC_STATE
 
`ifdef OR1200_DISPLAY_EXECUTED
 
         ref = ref + 1;
 
 `ifdef OR1200_MONITOR_LOOKUP
 
         $fdisplay(flookup, "Instruction %d: %t", insns, $time);
 
 `endif
 
         $fwrite(fexe, "\nEXECUTED(%d): %h:  %h  (exception)", insns,
 
                 `OR1200_TOP.`CPU_cpu.`CPU_except.ex_pc,
 
                 `OR1200_TOP.`CPU_cpu.`CPU_ctrl.ex_insn);
 
         insns = insns + 1;
 
`endif
 
 
 
      end
 
   endtask
 
 
 
   integer iwb_progress;
   integer iwb_progress;
   reg [31:0] iwb_progress_addr;
   reg [31:0] iwb_progress_addr;
   //
   //
   // WISHBONE bus checker
   // WISHBONE bus checker
   //
   //
   always @(posedge `OR1200_TOP.iwb_clk_i)
   always @(posedge `OR1200_TOP.iwb_clk_i)
     if (`OR1200_TOP.iwb_rst_i) begin
     if (`OR1200_TOP.iwb_rst_i) begin
        iwb_progress = 0;
        iwb_progress = 0;
        iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
        iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
     end
     end
     else begin
     else begin
        if (`OR1200_TOP.iwb_cyc_o && (iwb_progress != 2)) begin
        if (`OR1200_TOP.iwb_cyc_o && (iwb_progress != 2)) begin
           iwb_progress = 1;
           iwb_progress = 1;
        end
        end
        if (`OR1200_TOP.iwb_stb_o) begin
        if (`OR1200_TOP.iwb_stb_o) begin
           if (iwb_progress >= 1) begin
           if (iwb_progress >= 1) begin
              if (iwb_progress == 1)
              if (iwb_progress == 1)
                iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
                iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
              iwb_progress = 2;
              iwb_progress = 2;
           end
           end
           else begin
           else begin
              $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o raised without `OR1200_TOP.iwb_cyc_o, at %t\n", $time);
              $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o raised without `OR1200_TOP.iwb_cyc_o, at %t\n", $time);
              #100 $finish;
              #100 $finish;
           end
           end
        end
        end
        if (`OR1200_TOP.iwb_ack_i & `OR1200_TOP.iwb_err_i) begin
        if (`OR1200_TOP.iwb_ack_i & `OR1200_TOP.iwb_err_i) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i and `OR1200_TOP.iwb_err_i raised at the same time, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i and `OR1200_TOP.iwb_err_i raised at the same time, at %t\n", $time);
        end
        end
        if ((iwb_progress == 2) && (iwb_progress_addr != `OR1200_TOP.iwb_adr_o)) begin
        if ((iwb_progress == 2) && (iwb_progress_addr != `OR1200_TOP.iwb_adr_o)) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_adr_o changed while waiting for `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_adr_o changed while waiting for `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
           #100 $finish;
           #100 $finish;
        end
        end
        if (`OR1200_TOP.iwb_ack_i | `OR1200_TOP.iwb_err_i)
        if (`OR1200_TOP.iwb_ack_i | `OR1200_TOP.iwb_err_i)
          if (iwb_progress == 2) begin
          if (iwb_progress == 2) begin
             iwb_progress = 0;
             iwb_progress = 0;
             iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
             iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
          end
          end
          else begin
          else begin
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i/`OR1200_TOP.iwb_err_i raised without `OR1200_TOP.iwb_cyc_i/`OR1200_TOP.iwb_stb_i, at %t\n", $time);
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i/`OR1200_TOP.iwb_err_i raised without `OR1200_TOP.iwb_cyc_i/`OR1200_TOP.iwb_stb_i, at %t\n", $time);
             #100 $finish;
             #100 $finish;
          end
          end
        if ((iwb_progress == 2) && !`OR1200_TOP.iwb_stb_o) begin
        if ((iwb_progress == 2) && !`OR1200_TOP.iwb_stb_o) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o lowered without `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o lowered without `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
           #100 $finish;
           #100 $finish;
        end
        end
     end
     end
 
 
   integer dwb_progress;
   integer dwb_progress;
   reg [31:0] dwb_progress_addr;
   reg [31:0] dwb_progress_addr;
   //
   //
   // WISHBONE bus checker
   // WISHBONE bus checker
   //
   //
   always @(posedge `OR1200_TOP.dwb_clk_i)
   always @(posedge `OR1200_TOP.dwb_clk_i)
     if (`OR1200_TOP.dwb_rst_i)
     if (`OR1200_TOP.dwb_rst_i)
       dwb_progress = 0;
       dwb_progress = 0;
     else begin
     else begin
        if (`OR1200_TOP.dwb_cyc_o && (dwb_progress != 2))
        if (`OR1200_TOP.dwb_cyc_o && (dwb_progress != 2))
          dwb_progress = 1;
          dwb_progress = 1;
        if (`OR1200_TOP.dwb_stb_o)
        if (`OR1200_TOP.dwb_stb_o)
          if (dwb_progress >= 1) begin
          if (dwb_progress >= 1) begin
             if (dwb_progress == 1)
             if (dwb_progress == 1)
               dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
               dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
             dwb_progress = 2;
             dwb_progress = 2;
          end
          end
          else begin
          else begin
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o raised without `OR1200_TOP.dwb_cyc_o, at %t\n", $time);
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o raised without `OR1200_TOP.dwb_cyc_o, at %t\n", $time);
             #100 $finish;
             #100 $finish;
          end
          end
        if (`OR1200_TOP.dwb_ack_i & `OR1200_TOP.dwb_err_i) begin
        if (`OR1200_TOP.dwb_ack_i & `OR1200_TOP.dwb_err_i) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i and `OR1200_TOP.dwb_err_i raised at the same time, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i and `OR1200_TOP.dwb_err_i raised at the same time, at %t\n", $time);
        end
        end
        if ((dwb_progress == 2) && (dwb_progress_addr != `OR1200_TOP.dwb_adr_o)) begin
        if ((dwb_progress == 2) && (dwb_progress_addr != `OR1200_TOP.dwb_adr_o)) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_adr_o changed while waiting for `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_adr_o changed while waiting for `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
           #100 $finish;
           #100 $finish;
        end
        end
        if (`OR1200_TOP.dwb_ack_i | `OR1200_TOP.dwb_err_i)
        if (`OR1200_TOP.dwb_ack_i | `OR1200_TOP.dwb_err_i)
          if (dwb_progress == 2) begin
          if (dwb_progress == 2) begin
             dwb_progress = 0;
             dwb_progress = 0;
             dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
             dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
          end
          end
          else begin
          else begin
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i/`OR1200_TOP.dwb_err_i raised without `OR1200_TOP.dwb_cyc_i/`OR1200_TOP.dwb_stb_i, at %t\n", $time);
             $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i/`OR1200_TOP.dwb_err_i raised without `OR1200_TOP.dwb_cyc_i/`OR1200_TOP.dwb_stb_i, at %t\n", $time);
             #100 $finish;
             #100 $finish;
          end
          end
        if ((dwb_progress == 2) && !`OR1200_TOP.dwb_stb_o) begin
        if ((dwb_progress == 2) && !`OR1200_TOP.dwb_stb_o) begin
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o lowered without `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
           $fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o lowered without `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
           #100 $finish;
           #100 $finish;
        end
        end
     end
     end
 
 
   //
   //
   // Hooks for:
   // Hooks for:
   // - displaying registers
   // - displaying registers
   // - end of simulation
   // - end of simulation
   // - access to SPRs
   // - access to SPRs
   //
   //
   always @(posedge `CPU_CORE_CLK)
   always @(posedge `CPU_CORE_CLK)
     if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
     if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
        //      #2;
        //      #2;
        if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[31:26] != `OR1200_OR32_NOP)
        if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[31:26] != `OR1200_OR32_NOP)
             | !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
             | !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
            & !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &
            & !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &
                `OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot))
                `OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot))
          begin
          begin
             display_arch_state;
             display_arch_state(0);
             monitor_for_crash;
             monitor_for_crash;
          end
          end
        else
        else
          if (`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe)
          if (`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe)
            display_arch_state_except;
            display_arch_state(1);
        // small hack to stop simulation (l.nop 1):
        // small hack to stop simulation (l.nop 1):
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0001) begin
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0001) begin
           get_gpr(3, r3);
           get_gpr(3, r3);
           $fdisplay(fgeneral, "%t: l.nop exit (%h)", $time, r3);
           $fdisplay(fgeneral, "%t: l.nop exit (%h)", $time, r3);
`ifdef OR1200_MONITOR_VERBOSE_NOPS
`ifdef OR1200_MONITOR_VERBOSE_NOPS
       // Note that the 'expect' scripts in or1ksim's test suite look for strings
       // Note that the 'expect' scripts in or1ksim's test suite look for strings
       // like "exit(1)", therefore something like "exit(  1)" would fail.
       // like "exit(1)", therefore something like "exit(  1)" would fail.
       $display("exit(%0d)",r3);
       $display("exit(%0d)",r3);
`endif
`endif
           $finish;
           $finish;
        end
        end
        // debug if test (l.nop 10)
        // debug if test (l.nop 10)
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_000a) begin
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_000a) begin
           $fdisplay(fgeneral, "%t: l.nop dbg_if_test", $time);
           $fdisplay(fgeneral, "%t: l.nop dbg_if_test", $time);
        end
        end
        // simulation reports (l.nop 2)
        // simulation reports (l.nop 2)
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0002) begin
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0002) begin
           get_gpr(3, r3);
           get_gpr(3, r3);
           $fdisplay(fgeneral, "%t: l.nop report (0x%h)", $time, r3);
           $fdisplay(fgeneral, "%t: l.nop report (0x%h)", $time, r3);
`ifdef OR1200_MONITOR_VERBOSE_NOPS
`ifdef OR1200_MONITOR_VERBOSE_NOPS
           // Note that the 'expect' scripts in or1ksim's test suite look for strings
           // Note that the 'expect' scripts in or1ksim's test suite look for strings
           // like "report(0x7ffffffe);", therefore something like "report (0x7ffffffe);"
           // like "report(0x7ffffffe);", therefore something like "report (0x7ffffffe);"
           // (note the extra space character) would fail.
           // (note the extra space character) would fail.
           $display("report(0x%h);", r3);
           $display("report(0x%h);", r3);
`endif
`endif
        end
        end
        // simulation printfs (l.nop 3)
        // simulation printfs (l.nop 3)
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0003) begin
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0003) begin
           get_gpr(3, r3);
           get_gpr(3, r3);
           $fdisplay(fgeneral, "%t: l.nop printf (%h)", $time, r3);
           $fdisplay(fgeneral, "%t: l.nop printf (%h)", $time, r3);
        end
        end
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0004) begin
        if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0004) begin
           // simulation putc (l.nop 4)
           // simulation putc (l.nop 4)
           get_gpr(3, r3);
           get_gpr(3, r3);
           $write("%c", r3);
           $write("%c", r3);
           $fdisplay(fgeneral, "%t: l.nop putc (%c)", $time, r3);
           $fdisplay(fgeneral, "%t: l.nop putc (%c)", $time, r3);
        end
        end
`ifdef OR1200_MONITOR_SPRS
`ifdef OR1200_MONITOR_SPRS
        if (`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
        if (`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
          $fdisplay(fspr, "%t: Write to SPR : [%h] <- %h", $time,
          $fdisplay(fspr, "%t: Write to SPR : [%h] <- %h", $time,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_dat_o);
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_dat_o);
        if ((|`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_cs) &
        if ((|`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_cs) &
            !`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
            !`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
          $fdisplay(fspr, "%t: Read from SPR: [%h] -> %h", $time,
          $fdisplay(fspr, "%t: Read from SPR: [%h] -> %h", $time,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.to_wbmux);
                    `OR1200_TOP.`CPU_cpu.`CPU_sprs.to_wbmux);
`endif
`endif
     end
     end
 
 
 
 
`ifdef RAM_WB
`ifdef RAM_WB
 `define RAM_WB_TOP `DUT_TOP.ram_wb0.ram_wb_b3_0
 `define RAM_WB_TOP `DUT_TOP.ram_wb0.ram_wb_b3_0
   task get_insn_from_wb_ram;
   task get_insn_from_wb_ram;
      input [31:0] addr;
      input [31:0] addr;
      output [31:0] insn;
      output [31:0] insn;
      begin
      begin
         insn = `RAM_WB_TOP.get_mem32(addr[31:2]);
         insn = `RAM_WB_TOP.get_mem32(addr[31:2]);
      end
      end
   endtask // get_insn_from_wb_ram
   endtask // get_insn_from_wb_ram
`endif
`endif
 
 
`ifdef VERSATILE_SDRAM
`ifdef VERSATILE_SDRAM
 `define SDRAM_TOP `TB_TOP.sdram0
 `define SDRAM_TOP `TB_TOP.sdram0
   // Bit selects to define the bank
   // Bit selects to define the bank
   // 32 MB part with 4 banks
   // 32 MB part with 4 banks
 `define SDRAM_BANK_SEL_BITS 24:23
 `define SDRAM_BANK_SEL_BITS 24:23
 `define SDRAM_WORD_SEL_TOP_BIT 22
 `define SDRAM_WORD_SEL_TOP_BIT 22
   // Gets instruction word from correct bank
   // Gets instruction word from correct bank
   task get_insn_from_sdram;
   task get_insn_from_sdram;
      input [31:0] addr;
      input [31:0] addr;
      output [31:0] insn;
      output [31:0] insn;
      reg [`SDRAM_WORD_SEL_TOP_BIT-1:0] word_addr;
      reg [`SDRAM_WORD_SEL_TOP_BIT-1:0] word_addr;
 
 
      begin
      begin
         word_addr = addr[`SDRAM_WORD_SEL_TOP_BIT:2];
         word_addr = addr[`SDRAM_WORD_SEL_TOP_BIT:2];
         if (addr[`SDRAM_BANK_SEL_BITS] == 2'b00)
         if (addr[`SDRAM_BANK_SEL_BITS] == 2'b00)
           begin
           begin
 
 
              //$display("%t: get_insn_from_sdram bank0, word 0x%h, (%h and %h in SDRAM)", $time, word_addr, `SDRAM_TOP.Bank0[{word_addr,1'b0}], `SDRAM_TOP.Bank0[{word_addr,1'b1}]);
              //$display("%t: get_insn_from_sdram bank0, word 0x%h, (%h and %h in SDRAM)", $time, word_addr, `SDRAM_TOP.Bank0[{word_addr,1'b0}], `SDRAM_TOP.Bank0[{word_addr,1'b1}]);
              insn[15:0] = `SDRAM_TOP.Bank0[{word_addr,1'b1}];
              insn[15:0] = `SDRAM_TOP.Bank0[{word_addr,1'b1}];
              insn[31:16] = `SDRAM_TOP.Bank0[{word_addr,1'b0}];
              insn[31:16] = `SDRAM_TOP.Bank0[{word_addr,1'b0}];
           end
           end
      end
      end
 
 
   endtask // get_insn_from_sdram
   endtask // get_insn_from_sdram
`endif //  `ifdef VERSATILE_SDRAM
`endif //  `ifdef VERSATILE_SDRAM
 
 
`ifdef XILINX_DDR2
`ifdef XILINX_DDR2
 `define DDR2_TOP `TB_TOP.gen_cs[0]
 `define DDR2_TOP `TB_TOP.gen_cs[0]
   // Gets instruction word from correct bank
   // Gets instruction word from correct bank
   task get_insn_from_xilinx_ddr2;
   task get_insn_from_xilinx_ddr2;
      input [31:0] addr;
      input [31:0] addr;
      output [31:0] insn;
      output [31:0] insn;
      reg [16*8-1:0] ddr2_array_line0,ddr2_array_line1,ddr2_array_line2,
      reg [16*8-1:0] ddr2_array_line0,ddr2_array_line1,ddr2_array_line2,
                     ddr2_array_line3;
                     ddr2_array_line3;
      integer        word_in_line_num;
      integer        word_in_line_num;
      begin
      begin
         // Get our 4 128-bit chunks (8 half-words in each!! Confused yet?),
         // Get our 4 128-bit chunks (8 half-words in each!! Confused yet?),
         // 16 words total
         // 16 words total
         `DDR2_TOP.gen[0].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line0);
         `DDR2_TOP.gen[0].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line0);
         `DDR2_TOP.gen[1].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line1);
         `DDR2_TOP.gen[1].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line1);
         `DDR2_TOP.gen[2].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line2);
         `DDR2_TOP.gen[2].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line2);
         `DDR2_TOP.gen[3].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line3);
         `DDR2_TOP.gen[3].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line3);
         case (addr[5:2])
         case (addr[5:2])
           4'h0:
           4'h0:
             begin
             begin
                insn[15:0] = ddr2_array_line0[15:0];
                insn[15:0] = ddr2_array_line0[15:0];
                insn[31:16] = ddr2_array_line1[15:0];
                insn[31:16] = ddr2_array_line1[15:0];
             end
             end
           4'h1:
           4'h1:
             begin
             begin
                insn[15:0] = ddr2_array_line2[15:0];
                insn[15:0] = ddr2_array_line2[15:0];
                insn[31:16] = ddr2_array_line3[15:0];
                insn[31:16] = ddr2_array_line3[15:0];
             end
             end
           4'h2:
           4'h2:
             begin
             begin
                insn[15:0] = ddr2_array_line0[31:16];
                insn[15:0] = ddr2_array_line0[31:16];
                insn[31:16] = ddr2_array_line1[31:16];
                insn[31:16] = ddr2_array_line1[31:16];
             end
             end
           4'h3:
           4'h3:
             begin
             begin
                insn[15:0] = ddr2_array_line2[31:16];
                insn[15:0] = ddr2_array_line2[31:16];
                insn[31:16] = ddr2_array_line3[31:16];
                insn[31:16] = ddr2_array_line3[31:16];
             end
             end
           4'h4:
           4'h4:
             begin
             begin
                insn[15:0] = ddr2_array_line0[47:32];
                insn[15:0] = ddr2_array_line0[47:32];
                insn[31:16] = ddr2_array_line1[47:32];
                insn[31:16] = ddr2_array_line1[47:32];
             end
             end
           4'h5:
           4'h5:
             begin
             begin
                insn[15:0] = ddr2_array_line2[47:32];
                insn[15:0] = ddr2_array_line2[47:32];
                insn[31:16] = ddr2_array_line3[47:32];
                insn[31:16] = ddr2_array_line3[47:32];
             end
             end
           4'h6:
           4'h6:
             begin
             begin
                insn[15:0] = ddr2_array_line0[63:48];
                insn[15:0] = ddr2_array_line0[63:48];
                insn[31:16] = ddr2_array_line1[63:48];
                insn[31:16] = ddr2_array_line1[63:48];
             end
             end
           4'h7:
           4'h7:
             begin
             begin
                insn[15:0] = ddr2_array_line2[63:48];
                insn[15:0] = ddr2_array_line2[63:48];
                insn[31:16] = ddr2_array_line3[63:48];
                insn[31:16] = ddr2_array_line3[63:48];
             end
             end
           4'h8:
           4'h8:
             begin
             begin
                insn[15:0] = ddr2_array_line0[79:64];
                insn[15:0] = ddr2_array_line0[79:64];
                insn[31:16] = ddr2_array_line1[79:64];
                insn[31:16] = ddr2_array_line1[79:64];
             end
             end
           4'h9:
           4'h9:
             begin
             begin
                insn[15:0] = ddr2_array_line2[79:64];
                insn[15:0] = ddr2_array_line2[79:64];
                insn[31:16] = ddr2_array_line3[79:64];
                insn[31:16] = ddr2_array_line3[79:64];
             end
             end
           4'ha:
           4'ha:
             begin
             begin
                insn[15:0] = ddr2_array_line0[95:80];
                insn[15:0] = ddr2_array_line0[95:80];
                insn[31:16] = ddr2_array_line1[95:80];
                insn[31:16] = ddr2_array_line1[95:80];
             end
             end
           4'hb:
           4'hb:
             begin
             begin
                insn[15:0] = ddr2_array_line2[95:80];
                insn[15:0] = ddr2_array_line2[95:80];
                insn[31:16] = ddr2_array_line3[95:80];
                insn[31:16] = ddr2_array_line3[95:80];
             end
             end
           4'hc:
           4'hc:
             begin
             begin
                insn[15:0] = ddr2_array_line0[111:96];
                insn[15:0] = ddr2_array_line0[111:96];
                insn[31:16] = ddr2_array_line1[111:96];
                insn[31:16] = ddr2_array_line1[111:96];
             end
             end
           4'hd:
           4'hd:
             begin
             begin
                insn[15:0] = ddr2_array_line2[111:96];
                insn[15:0] = ddr2_array_line2[111:96];
                insn[31:16] = ddr2_array_line3[111:96];
                insn[31:16] = ddr2_array_line3[111:96];
             end
             end
           4'he:
           4'he:
             begin
             begin
                insn[15:0] = ddr2_array_line0[127:112];
                insn[15:0] = ddr2_array_line0[127:112];
                insn[31:16] = ddr2_array_line1[127:112];
                insn[31:16] = ddr2_array_line1[127:112];
             end
             end
           4'hf:
           4'hf:
             begin
             begin
                insn[15:0] = ddr2_array_line2[127:112];
                insn[15:0] = ddr2_array_line2[127:112];
                insn[31:16] = ddr2_array_line3[127:112];
                insn[31:16] = ddr2_array_line3[127:112];
             end
             end
         endcase // case (addr[5:2])
         endcase // case (addr[5:2])
      end
      end
   endtask // get_insn_from_xilinx_ddr2
   endtask // get_insn_from_xilinx_ddr2
`endif
`endif
 
 
 
 
   task get_insn_from_memory;
   task get_insn_from_memory;
      input [31:0] id_pc;
      input [31:0] id_pc;
      output [31:0] insn;
      output [31:0] insn;
      begin
      begin
         // do a decode of which server we should look in
         // do a decode of which server we should look in
         case (id_pc[31:28])
         case (id_pc[31:28])
`ifdef VERSATILE_SDRAM
`ifdef VERSATILE_SDRAM
           4'h0:
           4'h0:
             get_insn_from_sdram(id_pc, insn);
             get_insn_from_sdram(id_pc, insn);
`endif
`endif
`ifdef XILINX_DDR2
`ifdef XILINX_DDR2
           4'h0:
           4'h0:
             get_insn_from_xilinx_ddr2(id_pc, insn);
             get_insn_from_xilinx_ddr2(id_pc, insn);
`endif
`endif
`ifdef RAM_WB
`ifdef RAM_WB
           4'h0:
           4'h0:
             get_insn_from_wb_ram(id_pc, insn);
             get_insn_from_wb_ram(id_pc, insn);
`endif
`endif
           4'hf:
           4'hf:
             // Flash isn't stored in a memory, it's an FSM so just skip/ignore
             // Flash isn't stored in a memory, it's an FSM so just skip/ignore
             insn = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn;
             insn = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn;
           default:
           default:
             begin
             begin
                $fdisplay(fgeneral, "%t: Unknown memory server for address 0x%h", $time,id_pc);
                $fdisplay(fgeneral, "%t: Unknown memory server for address 0x%h", $time,id_pc);
                insn = 32'hxxxxxxxx; // Unknown server
                insn = 32'hxxxxxxxx; // Unknown server
             end
             end
         endcase // case (id_pc[31:28])
         endcase // case (id_pc[31:28])
      end
      end
   endtask // get_insn_from_memory
   endtask // get_insn_from_memory
 
 
 
 
   //
   //
   // Look in the iMMU TLB MR for this address' page, if MMUs are on and enabled
   // Look in the iMMU TLB MR for this address' page, if MMUs are on and enabled
   //
   //
   task check_for_immu_entry;
   task check_for_immu_entry;
      input [31:0] pc;
      input [31:0] pc;
      output [31:0] physical_pc;
      output [31:0] physical_pc;
      output        mmu_tlb_miss;
      output        mmu_tlb_miss;
      integer       w,x;
      integer       w,x;
 
 
      reg [31:`OR1200_IMMU_PS] pc_vpn;
      reg [31:`OR1200_IMMU_PS] pc_vpn;
 
 
      reg [`OR1200_ITLBTRW-1:0] itlb_tr;
      reg [`OR1200_ITLBTRW-1:0] itlb_tr;
      reg [`OR1200_ITLBMRW-1:0] itlb_mr;
      reg [`OR1200_ITLBMRW-1:0] itlb_mr;
 
 
      integer                   tlb_index;
      integer                   tlb_index;
      reg                       mmu_en;
      reg                       mmu_en;
 
 
 
 
      begin
      begin
         mmu_tlb_miss = 0;
         mmu_tlb_miss = 0;
 
 
`ifdef OR1200_NO_IMMU
`ifdef OR1200_NO_IMMU
         physical_pc = pc;
         physical_pc = pc;
`else
`else
         mmu_en = `OR1200_TOP.`CPU_immu_top.immu_en;
         mmu_en = `OR1200_TOP.`CPU_immu_top.immu_en;
         // If MMU is enabled
         // If MMU is enabled
         if (mmu_en)
         if (mmu_en)
           begin
           begin
 
 
              // Look in the iTLB for mapping - get virtual page number
              // Look in the iTLB for mapping - get virtual page number
              pc_vpn = pc[31:`OR1200_IMMU_PS];
              pc_vpn = pc[31:`OR1200_IMMU_PS];
 
 
              tlb_index = pc[`OR1200_ITLB_INDX];
              tlb_index = pc[`OR1200_ITLB_INDX];
 
 
              // Look at the ITLB match register
              // Look at the ITLB match register
              itlb_mr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_mr_ram.mem[tlb_index];
              itlb_mr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_mr_ram.mem[tlb_index];
 
 
              // Get the translate register here too, in case there's an error, we print it
              // Get the translate register here too, in case there's an error, we print it
              itlb_tr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_tr_ram.mem[tlb_index];
              itlb_tr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_tr_ram.mem[tlb_index];
 
 
              if ((itlb_mr[`OR1200_ITLBMR_V_BITS] === 1'b1) & (itlb_mr[`OR1200_ITLBMRW-1:1] === pc[`OR1200_ITLB_TAG]))
              if ((itlb_mr[`OR1200_ITLBMR_V_BITS] === 1'b1) & (itlb_mr[`OR1200_ITLBMRW-1:1] === pc[`OR1200_ITLB_TAG]))
                begin
                begin
                   // Page number in match register matches page number of virtual PC, so get the physical
                   // Page number in match register matches page number of virtual PC, so get the physical
                   // address from the translate memory
                   // address from the translate memory
                   // Now pull the physical page number out of the tranlsate register (it's after bottom 3 bits)
                   // Now pull the physical page number out of the tranlsate register (it's after bottom 3 bits)
                   physical_pc = {itlb_tr[`OR1200_ITLBTRW-1:`OR1200_ITLBTRW-(32-`OR1200_IMMU_PS)],pc[`OR1200_IMMU_PS-1:0]};
                   physical_pc = {itlb_tr[`OR1200_ITLBTRW-1:`OR1200_ITLBTRW-(32-`OR1200_IMMU_PS)],pc[`OR1200_IMMU_PS-1:0]};
                   //$display("check_for_immu_entry: found match for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, phys. PC = 0x%h", pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr, physical_pc);
                   //$display("check_for_immu_entry: found match for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, phys. PC = 0x%h", pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr, physical_pc);
                end // if ((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
                end // if ((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
              else
              else
                begin
                begin
 
 
                   // Wait a couple of clocks, see if we're doing a miss
                   // Wait a couple of clocks, see if we're doing a miss
                   @(posedge `CPU_CORE_CLK);
                   @(posedge `CPU_CORE_CLK);
                   @(posedge `CPU_CORE_CLK);
                   @(posedge `CPU_CORE_CLK);
                   if (!(`OR1200_TOP.`CPU_immu_top.miss)) // MMU should indicate miss
                   if (!(`OR1200_TOP.`CPU_immu_top.miss)) // MMU should indicate miss
                     begin
                     begin
                        $display("%t: check_for_immu_entry - ERROR - no match found for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, and no miss generated",
                        $display("%t: check_for_immu_entry - ERROR - no match found for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, and no miss generated",
                                 $time, pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr);
                                 $time, pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr);
                        #100;
                        #100;
                        $finish;
                        $finish;
                     end
                     end
                   else
                   else
                     begin
                     begin
                        mmu_tlb_miss = 1; // Started a miss, so ignore this instruction
                        mmu_tlb_miss = 1; // Started a miss, so ignore this instruction
                     end
                     end
                end // else: !if((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
                end // else: !if((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
 
 
           end // if (`OR1200_TOP.`CPU_immu_top.immu_en === 1'b1)
           end // if (`OR1200_TOP.`CPU_immu_top.immu_en === 1'b1)
         else
         else
           physical_pc = pc;
           physical_pc = pc;
`endif // !`ifdef OR1200_NO_IMMU
`endif // !`ifdef OR1200_NO_IMMU
      end
      end
   endtask // check_for_immu_entry
   endtask // check_for_immu_entry
 
 
 
 
   /*
   /*
    Instruction memory coherence checking.
    Instruction memory coherence checking.
 
 
    For new instruction executed in the pipeline - ensure it matches
    For new instruction executed in the pipeline - ensure it matches
    what is in the main program memory. Perform MMU translations if
    what is in the main program memory. Perform MMU translations if
    it is enabled.
    it is enabled.
    */
    */
 
 
   reg [31:0] mem_word;
   reg [31:0] mem_word;
   reg [31:0] last_addr = 0;
   reg [31:0] last_addr = 0;
   reg [31:0] last_mem_word;
   reg [31:0] last_mem_word;
   reg [31:0] physical_pc;
   reg [31:0] physical_pc;
   reg        tlb_miss;
   reg        tlb_miss;
 
 
 
 
`ifdef MEM_COHERENCE_CHECK
`ifdef MEM_COHERENCE_CHECK
 `define MEM_COHERENCE_TRIGGER (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_void === 1'b0)
 `define MEM_COHERENCE_TRIGGER (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_void === 1'b0)
 
 
 `define INSN_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn
 `define INSN_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn
 `define PC_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_except.id_pc
 `define PC_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_except.id_pc
 
 
   // Check instruction in decode stage is what is in the RAM
   // Check instruction in decode stage is what is in the RAM
   always @(posedge `CPU_CORE_CLK)
   always @(posedge `CPU_CORE_CLK)
     begin
     begin
        if (`MEM_COHERENCE_TRIGGER)
        if (`MEM_COHERENCE_TRIGGER)
          begin
          begin
 
 
             check_for_immu_entry(`PC_TO_CHECK, physical_pc, tlb_miss);
             check_for_immu_entry(`PC_TO_CHECK, physical_pc, tlb_miss);
 
 
             // Check if it's a new PC - will also get triggered if the
             // Check if it's a new PC - will also get triggered if the
             // instruction has changed since we last checked it
             // instruction has changed since we last checked it
             if (((physical_pc !== last_addr) ||
             if (((physical_pc !== last_addr) ||
                  (last_mem_word != `INSN_TO_CHECK)) & !tlb_miss)
                  (last_mem_word != `INSN_TO_CHECK)) & !tlb_miss)
               begin
               begin
                  // Decode stage not void, check instruction
                  // Decode stage not void, check instruction
                  // get PC
                  // get PC
                  get_insn_from_memory(physical_pc, mem_word);
                  get_insn_from_memory(physical_pc, mem_word);
 
 
                  if (mem_word !== `INSN_TO_CHECK)
                  if (mem_word !== `INSN_TO_CHECK)
                    begin
                    begin
                       $fdisplay(fgeneral, "%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
                       $fdisplay(fgeneral, "%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
                                 $time, `PC_TO_CHECK, physical_pc, mem_word,
                                 $time, `PC_TO_CHECK, physical_pc, mem_word,
                                 `INSN_TO_CHECK);
                                 `INSN_TO_CHECK);
                       $display("%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
                       $display("%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
                                $time, `PC_TO_CHECK, physical_pc, mem_word,
                                $time, `PC_TO_CHECK, physical_pc, mem_word,
                                `INSN_TO_CHECK);
                                `INSN_TO_CHECK);
                       #200;
                       #200;
                       $finish;
                       $finish;
                    end
                    end
                  last_addr = physical_pc;
                  last_addr = physical_pc;
                  last_mem_word = mem_word;
                  last_mem_word = mem_word;
 
 
               end // if (((physical_pc !== last_addr) || (last_mem_word != `INSN_TO_CHECK))...
               end // if (((physical_pc !== last_addr) || (last_mem_word != `INSN_TO_CHECK))...
          end // if (`MEM_COHERENCE_TRIGGER)
          end // if (`MEM_COHERENCE_TRIGGER)
     end // always @ (posedge `CPU_CORE_CLK)
     end // always @ (posedge `CPU_CORE_CLK)
 
 
`endif //  `ifdef MEM_COHERENCE_CHECK
`endif //  `ifdef MEM_COHERENCE_CHECK
 
 
   // Trigger on each instruction that gets into writeback stage properly
   // Trigger on each instruction that gets into writeback stage properly
   reg exception_coming1, exception_coming2, exception_here;
   reg exception_coming1, exception_coming2, exception_here;
   reg will_jump, jumping, jump_dslot, jumped;
   reg will_jump, jumping, jump_dslot, jumped;
   reg rfe, except_during_rfe;
   reg rfe, except_during_rfe;
   reg dslot_expt;
   reg dslot_expt;
 
 
 
 
   // Maintain a copy of GPRS for previous instruction
   // Maintain a copy of GPRS for previous instruction
   reg [31:0] current_gprs [0:31];
   reg [31:0] current_gprs [0:31];
   reg [31:0] current_epcr, current_eear, current_esr, current_sr;
   reg [31:0] current_epcr, current_eear, current_esr, current_sr;
   reg [31:0] previous_gprs [0:31];
   reg [31:0] previous_gprs [0:31];
   reg [31:0] previous_epcr;
   reg [31:0] previous_epcr;
   reg [31:0] previous_eear;
   reg [31:0] previous_eear;
   reg [31:0] previous_esr;
   reg [31:0] previous_esr;
   reg [31:0] previous_sr;
   reg [31:0] previous_sr;
 
 
   task update_current_gprs;
   task update_current_gprs;
      integer j;
      integer j;
      begin
      begin
         for(j=0;j<32;j=j+1)
         for(j=0;j<32;j=j+1)
           begin
           begin
              get_gpr(j,current_gprs[j]);
              get_gpr(j,current_gprs[j]);
           end
           end
         current_sr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr ;
         current_sr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr ;
         current_esr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr ;
         current_esr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr ;
         current_epcr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr ;
         current_epcr = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr ;
         current_eear = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear ;
         current_eear = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear ;
      end
      end
   endtask
   endtask
 
 
   task update_previous_gprs;
   task update_previous_gprs;
      integer j;
      integer j;
      begin
      begin
         for(j=0;j<32;j=j+1)
         for(j=0;j<32;j=j+1)
           begin
           begin
              previous_gprs[j] = current_gprs[j];
              previous_gprs[j] = current_gprs[j];
           end
           end
         previous_sr = current_sr;
         previous_sr = current_sr;
         previous_esr = current_esr;
         previous_esr = current_esr;
         previous_epcr = current_epcr;
         previous_epcr = current_epcr;
         previous_eear = current_eear;
         previous_eear = current_eear;
      end
      end
   endtask // update_previous_gprs
   endtask // update_previous_gprs
 
 
   // Maintain a list of addresses we expect the processor to execute
   // Maintain a list of addresses we expect the processor to execute
   // Whenever we hit a branch or jump or rfe we add to this list - when we
   // Whenever we hit a branch or jump or rfe we add to this list - when we
   // execute it then we remove it from the list.
   // execute it then we remove it from the list.
   reg [31:0] expected_addresses [0:31];
   reg [31:0] expected_addresses [0:31];
   reg        expected_addresses_waiting [0:31]; // List indicating if address is waiting
   reg        expected_addresses_waiting [0:31]; // List indicating if address is waiting
   reg        duplicate_expected_addresses_waiting [0:31]; // List indicating if a waiting address will be cleared by the single return
   reg        duplicate_expected_addresses_waiting [0:31]; // List indicating if a waiting address will be cleared by the single return
   integer    expected_address_num;
   integer    expected_address_num;
   // Initialise things on reset
   // Initialise things on reset
   always @(`OR1200_TOP.iwb_rst_i)
   always @(`OR1200_TOP.iwb_rst_i)
     begin
     begin
        for (expected_address_num=0;expected_address_num<32;expected_address_num=expected_address_num+1)
        for (expected_address_num=0;expected_address_num<32;expected_address_num=expected_address_num+1)
          begin
          begin
             expected_addresses_waiting[expected_address_num] = 0;
             expected_addresses_waiting[expected_address_num] = 0;
             duplicate_expected_addresses_waiting[expected_address_num] = 0;
             duplicate_expected_addresses_waiting[expected_address_num] = 0;
          end
          end
        expected_address_num = 0;
        expected_address_num = 0;
     end
     end
 
 
   task add_expected_address;
   task add_expected_address;
      input [31:0] expected_pc;
      input [31:0] expected_pc;
      begin
      begin
         if (expected_address_num == 31)
         if (expected_address_num == 31)
           begin
           begin
              $display("%t: Too many branches not reached",$time);
              $display("%t: Too many branches not reached",$time);
              #100;
              #100;
              $finish;
              $finish;
           end
           end
         if (expected_addresses_waiting[expected_address_num])
         if (expected_addresses_waiting[expected_address_num])
           begin
           begin
              $display("%t: expected_addresses tracker bugged out. expected_address_num = %0d",$time,expected_address_num);
              $display("%t: expected_addresses tracker bugged out. expected_address_num = %0d",$time,expected_address_num);
              #100;
              #100;
              $finish;
              $finish;
           end
           end
         else
         else
           begin
           begin
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
              // Debugging output...
              // Debugging output...
              $display("%t: Adding address 0x%h to expected list index %0d",$time, expected_pc,expected_address_num);
              $display("%t: Adding address 0x%h to expected list index %0d",$time, expected_pc,expected_address_num);
`endif
`endif
              // Put the expected PC in the list, increase the index
              // Put the expected PC in the list, increase the index
              expected_addresses[expected_address_num] = expected_pc;
              expected_addresses[expected_address_num] = expected_pc;
              expected_addresses_waiting[expected_address_num] = 1;
              expected_addresses_waiting[expected_address_num] = 1;
              expected_address_num = expected_address_num + 1;
              expected_address_num = expected_address_num + 1;
           end // else: !if(expected_addresses_waiting[expected_address_num])
           end // else: !if(expected_addresses_waiting[expected_address_num])
      end
      end
   endtask // add_address_to_expect
   endtask // add_address_to_expect
 
 
   // Use this in the case that there's an execption after a jump, in which
   // Use this in the case that there's an execption after a jump, in which
   // case we'll have two entries when we finally jump back (the one the
   // case we'll have two entries when we finally jump back (the one the
   // original jump put in, and the one put in by the l.rfe or l.jr/ when
   // original jump put in, and the one put in by the l.rfe or l.jr/ when
   // returning outside of exception handler), so mark this one as OK for
   // returning outside of exception handler), so mark this one as OK for
   // removing the duplicate of
   // removing the duplicate of
   task mark_duplicate_expected_address;
   task mark_duplicate_expected_address;
      begin
      begin
         // This will always be done on the first instruction of an exception
         // This will always be done on the first instruction of an exception
         // that has occured after a delay slot instruction, so
         // that has occured after a delay slot instruction, so
         // expected_address_num will be one past the entry for the one we will
         // expected_address_num will be one past the entry for the one we will
         // get a duplicate return call for
         // get a duplicate return call for
         duplicate_expected_addresses_waiting[expected_address_num-1] = 1;
         duplicate_expected_addresses_waiting[expected_address_num-1] = 1;
      end
      end
   endtask // mark_duplicate_expected_address
   endtask // mark_duplicate_expected_address
 
 
 
 
   task check_expected_address;
   task check_expected_address;
      input [31:0] pc;
      input [31:0] pc;
      input        expecting_hit;
      input        expecting_hit;
      integer      i,j;
      integer      i,j;
      reg          hit;
      reg          hit;
      reg          duplicates;
      reg          duplicates;
 
 
      begin
      begin
         hit = 0;
         hit = 0;
         //$display("%t: check_expected_addr 0x%h, index %0d",
         //$display("%t: check_expected_addr 0x%h, index %0d",
         // $time,pc, expected_address_num);
         // $time,pc, expected_address_num);
         if (expected_address_num > 0)
         if (expected_address_num > 0)
           begin
           begin
              // First check the last jump we did
              // First check the last jump we did
              if (expected_addresses[expected_address_num-1] == pc)
              if (expected_addresses[expected_address_num-1] == pc)
                begin
                begin
                   // Jump address hit
                   // Jump address hit
                   // Debugging printout:
                   // Debugging printout:
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
                   $display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,expected_address_num-1);
                   $display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,expected_address_num-1);
`endif
`endif
                   expected_address_num = expected_address_num-1;
                   expected_address_num = expected_address_num-1;
                   expected_addresses_waiting[expected_address_num] = 0;
                   expected_addresses_waiting[expected_address_num] = 0;
                   hit = 1;
                   hit = 1;
                end
                end
              else
              else
                begin
                begin
                   // Check through the list
                   // Check through the list
                   for(i=0;i<expected_address_num;i=i+1)
                   for(i=0;i<expected_address_num;i=i+1)
                     begin
                     begin
                        if (expected_addresses[i] == pc)
                        if (expected_addresses[i] == pc)
                          begin
                          begin
                             // Jump address hit
                             // Jump address hit
                             // Debugging printout:
                             // Debugging printout:
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
                             $display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,i);
                             $display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,i);
`endif
`endif
                             for(j=i;j<expected_address_num;j=j+1)
                             for(j=i;j<expected_address_num;j=j+1)
                               begin
                               begin
                                  // Pull all of the ones above us down one
                                  // Pull all of the ones above us down one
                                  expected_addresses_waiting[j]
                                  expected_addresses_waiting[j]
                                    = expected_addresses_waiting[j+1];
                                    = expected_addresses_waiting[j+1];
                                  expected_addresses[j]
                                  expected_addresses[j]
                                    = expected_addresses[j+1];
                                    = expected_addresses[j+1];
                                  duplicate_expected_addresses_waiting[j]
                                  duplicate_expected_addresses_waiting[j]
                                    = duplicate_expected_addresses_waiting[j+1];
                                    = duplicate_expected_addresses_waiting[j+1];
                               end
                               end
                             expected_address_num = expected_address_num-1;
                             expected_address_num = expected_address_num-1;
                             hit = 1;
                             hit = 1;
                             // quit out. only allow 1 hit
                             // quit out. only allow 1 hit
                             i = expected_address_num;
                             i = expected_address_num;
                          end
                          end
                     end
                     end
                end // else: !if(expected_addresses[expected_ad...
                end // else: !if(expected_addresses[expected_ad...
           end // if (expected_address_num > 0)
           end // if (expected_address_num > 0)
 
 
         // Check for duplicates this way because of the way we've declared
         // Check for duplicates this way because of the way we've declared
         // the array...
         // the array...
         duplicates=0;
         duplicates=0;
         for(i=0;i<32;i=i+1)
         for(i=0;i<32;i=i+1)
           duplicates = duplicates | duplicate_expected_addresses_waiting[i];
           duplicates = duplicates | duplicate_expected_addresses_waiting[i];
 
 
         if (hit & duplicates)
         if (hit & duplicates)
           begin
           begin
              // If we got a hit, check for duplicates we're also meant to clear
              // If we got a hit, check for duplicates we're also meant to clear
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
              $display;
              $display;
`endif
`endif
              for(i=0;i<expected_address_num;i=i+1)
              for(i=0;i<expected_address_num;i=i+1)
                begin
                begin
                   if(duplicate_expected_addresses_waiting[i] &
                   if(duplicate_expected_addresses_waiting[i] &
                      expected_addresses_waiting[i] &
                      expected_addresses_waiting[i] &
                      expected_addresses[i] == pc)
                      expected_addresses[i] == pc)
                     begin
                     begin
                        // Found a duplicate call address, clear it
                        // Found a duplicate call address, clear it
                        duplicate_expected_addresses_waiting[i] = 0;
                        duplicate_expected_addresses_waiting[i] = 0;
                        expected_addresses_waiting[i] = 0;
                        expected_addresses_waiting[i] = 0;
 
 
                        // Now reorder the list - pull all the ones above us
                        // Now reorder the list - pull all the ones above us
                        // down by one
                        // down by one
                        for(j=i;j<expected_address_num;j=j+1)
                        for(j=i;j<expected_address_num;j=j+1)
                          begin
                          begin
                             expected_addresses_waiting[j] = expected_addresses_waiting[j+1];
                             expected_addresses_waiting[j] = expected_addresses_waiting[j+1];
                             expected_addresses[j] = expected_addresses[j+1];
                             expected_addresses[j] = expected_addresses[j+1];
                             duplicate_expected_addresses_waiting[j] = duplicate_expected_addresses_waiting[j+1];
                             duplicate_expected_addresses_waiting[j] = duplicate_expected_addresses_waiting[j+1];
                          end
                          end
                        expected_address_num = expected_address_num - 1;
                        expected_address_num = expected_address_num - 1;
                     end
                     end
                end // for (i=0;i<expected_address_num;i=i+1)
                end // for (i=0;i<expected_address_num;i=i+1)
           end // if (hit & duplicates)
           end // if (hit & duplicates)
 
 
         if (expecting_hit & !hit)
         if (expecting_hit & !hit)
           begin
           begin
              // Expected this address to be one we're supposed to jump to, but it wasn't!
              // Expected this address to be one we're supposed to jump to, but it wasn't!
              $display("%t: Failed to find current PC, 0x%h, in expected PCs for branches/jumps",$time,pc);
              $display("%t: Failed to find current PC, 0x%h, in expected PCs for branches/jumps",$time,pc);
              #100;
              #100;
              $finish;
              $finish;
           end
           end
 
 
      end
      end
   endtask // check_expected_address
   endtask // check_expected_address
 
 
   // Task to assert value of GPR
   // Task to assert value of GPR
   task assert_gpr_val;
   task assert_gpr_val;
      input [5:0] regnum;
      input [5:0] regnum;
      input [31:0] assert_value;
      input [31:0] assert_value;
      input [31:0] pc;
      input [31:0] pc;
      reg [31:0]   reg_val;
      reg [31:0]   reg_val;
 
 
      begin
      begin
         get_gpr(regnum, reg_val);
         get_gpr(regnum, reg_val);
         if (reg_val !== assert_value)
         if (reg_val !== assert_value)
           begin
           begin
              $display("%t: Assert r%0d value (0x%h) = 0x%h failed. pc=0x%h",
              $display("%t: Assert r%0d value (0x%h) = 0x%h failed. pc=0x%h",
                       $time, regnum, reg_val, assert_value,pc);
                       $time, regnum, reg_val, assert_value,pc);
              #100;
              #100;
              $finish;
              $finish;
           end
           end
      end
      end
   endtask // assert_gpr_val
   endtask // assert_gpr_val
 
 
   // Task to assert something is true
   // Task to assert something is true
   task assert_this;
   task assert_this;
      input assert_result;
      input assert_result;
      input [31:0] pc;
      input [31:0] pc;
      begin
      begin
         if (!assert_result)
         if (!assert_result)
           begin
           begin
              $display("%t: Assert failed for instruction at pc=0x%h",
              $display("%t: Assert failed for instruction at pc=0x%h",
                       $time , pc);
                       $time , pc);
              #100;
              #100;
              $finish;
              $finish;
           end
           end
      end
      end
   endtask // assert_gpr_val
   endtask // assert_gpr_val
 
 
   // The jumping variable doesn't get updated until we do the proper check of
   // The jumping variable doesn't get updated until we do the proper check of
   // the current instruction reaching the writeback stage. We need to know
   // the current instruction reaching the writeback stage. We need to know
   // earlier, eg. in the exception checking part, if this instruction will
   // earlier, eg. in the exception checking part, if this instruction will
   // jump. We do that with this task.
   // jump. We do that with this task.
   task check_for_jump;
   task check_for_jump;
      input [31:0] insn;
      input [31:0] insn;
      reg [5:0]    opcode;
      reg [5:0]    opcode;
      reg          flag;
      reg          flag;
      begin
      begin
         opcode = insn[`OR1K_OPCODE_POS];
         opcode = insn[`OR1K_OPCODE_POS];
         // Use the flag from the previous instruction, as the decision
         // Use the flag from the previous instruction, as the decision
         // is made in the execute stage not in te writeback stage,
         // is made in the execute stage not in te writeback stage,
         // which is where we're getting our instructions.
         // which is where we're getting our instructions.
         flag = previous_sr[`OR1200_SR_F];
         flag = previous_sr[`OR1200_SR_F];
 
 
         case (opcode)
         case (opcode)
           `OR1200_OR32_J,
           `OR1200_OR32_J,
             `OR1200_OR32_JR,
             `OR1200_OR32_JR,
             `OR1200_OR32_JAL,
             `OR1200_OR32_JAL,
             `OR1200_OR32_JALR:
             `OR1200_OR32_JALR:
               will_jump = 1;
               will_jump = 1;
           `OR1200_OR32_BNF:
           `OR1200_OR32_BNF:
             will_jump = !flag;
             will_jump = !flag;
           `OR1200_OR32_BF:
           `OR1200_OR32_BF:
             will_jump = flag;
             will_jump = flag;
           default:
           default:
             will_jump = 0;
             will_jump = 0;
         endcase // case (opcode)
         endcase // case (opcode)
      end
      end
   endtask // check_for_jump
   endtask // check_for_jump
 
 
 
 
 
 
   // Detect exceptions from the processor here
   // Detect exceptions from the processor here
   reg [13:0] except_trig_r;
   reg [13:0] except_trig_r;
   reg        exception_coming;
   reg        exception_coming;
 
 
   always @(posedge `CPU_CORE_CLK)
   always @(posedge `CPU_CORE_CLK)
     if (`OR1200_TOP.iwb_rst_i)
     if (`OR1200_TOP.iwb_rst_i)
       begin
       begin
          except_trig_r = 0;
          except_trig_r = 0;
          exception_coming = 0;
          exception_coming = 0;
          except_during_rfe = 0;
          except_during_rfe = 0;
       end
       end
     else if ((|`OR1200_TOP.`CPU_cpu.`CPU_except.except_trig) && !exception_coming)
     else if ((|`OR1200_TOP.`CPU_cpu.`CPU_except.except_trig) && !exception_coming)
       begin
       begin
          exception_coming  = 1;
          exception_coming  = 1;
          except_trig_r = `OR1200_TOP.`CPU_cpu.`CPU_except.except_trig;
          except_trig_r = `OR1200_TOP.`CPU_cpu.`CPU_except.except_trig;
          except_during_rfe = rfe;
          except_during_rfe = rfe;
       end
       end
 
 
   task check_incoming_exceptions;
   task check_incoming_exceptions;
      begin
      begin
 
 
         // Exception timing  - depends on the trigger.
         // Exception timing  - depends on the trigger.
         // Appears to be:
         // Appears to be:
         // tick timer - dslot - 1 instruction delay, else 2
         // tick timer - dslot - 1 instruction delay, else 2
         // tlb lookasides - 1 instruction for both
         // tlb lookasides - 1 instruction for both
 
 
         casex (except_trig_r)
         casex (except_trig_r)
           13'b1_xxxx_xxxx_xxxx: begin
           13'b1_xxxx_xxxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_TICK;
              //except_type <= #1 `OR1200_EXCEPT_TICK;
              exception_here = exception_coming2;
              exception_here = exception_coming2;
              exception_coming2 = jump_dslot ? exception_coming: exception_coming1 ;
              exception_coming2 = jump_dslot ? exception_coming: exception_coming1 ;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
           end
           end
           13'b0_1xxx_xxxx_xxxx: begin
           13'b0_1xxx_xxxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_INT;
              //except_type <= #1 `OR1200_EXCEPT_INT;
              #1;
              #1;
           end
           end
           13'b0_01xx_xxxx_xxxx: begin
           13'b0_01xx_xxxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_ITLBMISS;
              //except_type <= #1 `OR1200_EXCEPT_ITLBMISS;
              exception_here = exception_coming2;
              exception_here = exception_coming2;
              exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
              exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
           end
           end
           13'b0_001x_xxxx_xxxx: begin
           13'b0_001x_xxxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_IPF;
              //except_type <= #1 `OR1200_EXCEPT_IPF;
              exception_here = exception_coming2;
              exception_here = exception_coming2;
              exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
              exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
              exception_coming1 = jump_dslot ? 0 : exception_coming;
           end
           end
           13'b0_0001_xxxx_xxxx: begin
           13'b0_0001_xxxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_BUSERR;
              //except_type <= #1 `OR1200_EXCEPT_BUSERR;
              exception_here = exception_coming;
              exception_here = exception_coming;
              exception_coming2 = 0;
              exception_coming2 = 0;
              exception_coming1 = 0;
              exception_coming1 = 0;
           end
           end
           13'b0_0000_1xxx_xxxx: begin
           13'b0_0000_1xxx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_ILLEGAL;
              //except_type <= #1 `OR1200_EXCEPT_ILLEGAL;
              if (will_jump)
              if (will_jump)
                begin
                begin
                   // Writeback stage instruction will jump, and we have an
                   // Writeback stage instruction will jump, and we have an
                   // illegal instruction in the decode/execute stage, which is
                   // illegal instruction in the decode/execute stage, which is
                   // the delay slot, so indicate the exception is coming...
                   // the delay slot, so indicate the exception is coming...
                   exception_here = exception_coming2;
                   exception_here = exception_coming2;
                   exception_coming2 = exception_coming;
                   exception_coming2 = exception_coming;
                   exception_coming1 = 0;
                   exception_coming1 = 0;
                end
                end
              else
              else
                begin
                begin
                   exception_here = jump_dslot ?
                   exception_here = jump_dslot ?
                                    exception_coming2 : exception_coming;
                                    exception_coming2 : exception_coming;
                   exception_coming2 = jump_dslot ? exception_coming : 0;
                   exception_coming2 = jump_dslot ? exception_coming : 0;
                   exception_coming1 = 0;
                   exception_coming1 = 0;
                end
                end
           end
           end
           13'b0_0000_01xx_xxxx: begin
           13'b0_0000_01xx_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_ALIGN;
              //except_type <= #1 `OR1200_EXCEPT_ALIGN;
              if(will_jump)
              if(will_jump)
                begin
                begin
                   exception_here = exception_coming2;
                   exception_here = exception_coming2;
                   exception_coming2 = exception_coming;
                   exception_coming2 = exception_coming;
                   exception_coming1 = 0;
                   exception_coming1 = 0;
                end
                end
              else
              else
                begin
                begin
                   exception_here =  (rfe) ? exception_coming : exception_coming2;
                   exception_here =  (rfe) ? exception_coming : exception_coming2;
                   exception_coming2 = (rfe) ? 0 : exception_coming;
                   exception_coming2 = (rfe) ? 0 : exception_coming;
                   exception_coming1 = 0;
                   exception_coming1 = 0;
                end
                end
           end
           end
           13'b0_0000_001x_xxxx: begin
           13'b0_0000_001x_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_DTLBMISS;
              //except_type <= #1 `OR1200_EXCEPT_DTLBMISS;
              // Looks like except_trig goes high here after we check the
              // Looks like except_trig goes high here after we check the
              // instruction before the itlb miss after a delay slot, so we
              // instruction before the itlb miss after a delay slot, so we
              // miss the dslot variable (it gets propegated before we call
              // miss the dslot variable (it gets propegated before we call
              // this task) so we use the jumped variable here to see if we
              // this task) so we use the jumped variable here to see if we
              // are an exception after a delay slot
              // are an exception after a delay slot
              //exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
              //exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
              //exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
              //exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
 
 
              exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
              exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
              exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
              exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
 
 
              exception_coming1 = 0;
              exception_coming1 = 0;
           end
           end
           13'b0_0000_0001_xxxx: begin
           13'b0_0000_0001_xxxx: begin
              //except_type <= #1 `OR1200_EXCEPT_DPF;
              //except_type <= #1 `OR1200_EXCEPT_DPF;
              if (jumped) begin // Jumped onto illegal instruction
              if (jumped) begin // Jumped onto illegal instruction
                 exception_here = exception_coming ;
                 exception_here = exception_coming ;
                 exception_coming2 = 0;
                 exception_coming2 = 0;
                 exception_coming1 = 0;
                 exception_coming1 = 0;
              end
              end
              else begin
              else begin
                 exception_here =  exception_coming2;
                 exception_here =  exception_coming2;
                 exception_coming2 = exception_coming;
                 exception_coming2 = exception_coming;
                 exception_coming1 = 0;
                 exception_coming1 = 0;
              end
              end
           end
           end
           13'b0_0000_0000_1xxx: begin  // Data Bus Error
           13'b0_0000_0000_1xxx: begin  // Data Bus Error
              //except_type <= #1 `OR1200_EXCEPT_BUSERR;
              //except_type <= #1 `OR1200_EXCEPT_BUSERR;
              exception_here = exception_coming2 ;
              exception_here = exception_coming2 ;
              exception_coming2 = exception_coming;
              exception_coming2 = exception_coming;
              exception_coming1 = 0;
              exception_coming1 = 0;
           end
           end
           13'b0_0000_0000_01xx: begin
           13'b0_0000_0000_01xx: begin
              //except_type <= #1 `OR1200_EXCEPT_RANGE;
              //except_type <= #1 `OR1200_EXCEPT_RANGE;
              #1;
              #1;
           end
           end
           13'b0_0000_0000_001x: begin
           13'b0_0000_0000_001x: begin
              // trap
              // trap
              #1;
              #1;
           end
           end
           13'b0_0000_0000_0001: begin
           13'b0_0000_0000_0001: begin
              //except_type <= #1 `OR1200_EXCEPT_SYSCALL;
              //except_type <= #1 `OR1200_EXCEPT_SYSCALL;
              exception_here = exception_coming2;
              exception_here = exception_coming2;
              exception_coming2 = jumped ? exception_coming: exception_coming1 ;
              exception_coming2 = jumped ? exception_coming: exception_coming1 ;
              exception_coming1 = jumped ? 0 : exception_coming;
              exception_coming1 = jumped ? 0 : exception_coming;
           end
           end
         endcase // casex (except_trig_r)
         endcase // casex (except_trig_r)
 
 
         exception_coming = 0;
         exception_coming = 0;
         except_during_rfe = 0;
         except_during_rfe = 0;
 
 
      end
      end
   endtask // check_incoming_exceptions
   endtask // check_incoming_exceptions
 
 
 
 
 
 
 
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
   // Execution tracking task
   // Execution tracking task
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
 
 
 
`ifdef OR1200_SYSTEM_CHECKER
`ifdef OR1200_SYSTEM_CHECKER
   always @(posedge `CPU_CORE_CLK)
   always @(posedge `CPU_CORE_CLK)
     begin
     begin
        if (`OR1200_TOP.iwb_rst_i)
        if (`OR1200_TOP.iwb_rst_i)
          begin
          begin
             exception_coming1 = 0;exception_coming2 = 0;exception_here= 0;
             exception_coming1 = 0;exception_coming2 = 0;exception_here= 0;
             jumping = 0; jump_dslot = 0; jumped = 0;
             jumping = 0; jump_dslot = 0; jumped = 0;
             rfe = 0;
             rfe = 0;
          end
          end
        if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
        if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
           //#2 ;
           //#2 ;
           // If instruction isn't a l.nop with bit 16 set (implementation's
           // If instruction isn't a l.nop with bit 16 set (implementation's
           // filler instruction in pipeline), and do not have an exception
           // filler instruction in pipeline), and do not have an exception
           // signaled with a dslot instruction in the execute stage
           // signaled with a dslot instruction in the execute stage
           if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[`OR1K_OPCODE_POS] !=
           if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[`OR1K_OPCODE_POS] !=
                 `OR1200_OR32_NOP) || !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
                 `OR1200_OR32_NOP) || !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
               && !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &&
               && !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &&
                    `OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot)) // and not except start
                    `OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot)) // and not except start
             begin
             begin
 
 
                // Propegate jump-tracking variables
                // Propegate jump-tracking variables
                // If was exception in delay slot, we didn't actually jump
                // If was exception in delay slot, we didn't actually jump
                // so don't set jumped in this case.
                // so don't set jumped in this case.
                jumped = exception_here ? 0 : jump_dslot;
                jumped = exception_here ? 0 : jump_dslot;
                jump_dslot = jumping;
                jump_dslot = jumping;
                jumping = 0;
                jumping = 0;
                rfe = 0;
                rfe = 0;
 
 
                // Now, check if current instruction will jump/branch, this is
                // Now, check if current instruction will jump/branch, this is
                // needed by the exception checking code, sets will_jump=1
                // needed by the exception checking code, sets will_jump=1
                check_for_jump(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
                check_for_jump(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
 
 
                // Now check if it's an exception this instruction
                // Now check if it's an exception this instruction
                check_incoming_exceptions;
                check_incoming_exceptions;
 
 
                // Case where we just went to an exception after a jump, so we
                // Case where we just went to an exception after a jump, so we
                // mark the address we were meant to jump to as a place which will
                // mark the address we were meant to jump to as a place which will
                // have duplicate return entries in the expected address list
                // have duplicate return entries in the expected address list
                if (exception_here & (jumped | jump_dslot))
                if (exception_here & (jumped | jump_dslot))
                  begin
                  begin
                     $display("%t: marked as jump address with exception (dup)"
                     $display("%t: marked as jump address with exception (dup)"
                              ,$time);
                              ,$time);
                     mark_duplicate_expected_address;
                     mark_duplicate_expected_address;
                  end
                  end
 
 
                or1200_check_execution(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn,
                or1200_check_execution(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn,
                                       `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
                                       `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
                                       exception_here);
                                       exception_here);
                //$write("%t: pc:0x%h\t",$time,
                //$write("%t: pc:0x%h\t",$time,
                //       `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
                //       `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
                // Decode the instruction, print it out
                // Decode the instruction, print it out
                //or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
                //or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
                //$write("\t exc:%0h dsl:%0h\n",exception_here,jump_dslot);
                //$write("\t exc:%0h dsl:%0h\n",exception_here,jump_dslot);
 
 
 
 
 
 
             end
             end
        end // if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze)
        end // if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze)
     end // always @ (posedge `CPU_CORE_CLK)
     end // always @ (posedge `CPU_CORE_CLK)
`endif
`endif
 
 
 
 
   task or1200_check_execution;
   task or1200_check_execution;
      input [31:0] insn;
      input [31:0] insn;
      input [31:0] pc;
      input [31:0] pc;
      input        exception;
      input        exception;
 
 
      reg [5:0]    opcode;
      reg [5:0]    opcode;
 
 
      reg [25:0]   j_imm;
      reg [25:0]   j_imm;
      reg [25:0]   br_imm;
      reg [25:0]   br_imm;
 
 
      reg [4:0]    rD_num, rA_num, rB_num;
      reg [4:0]    rD_num, rA_num, rB_num;
      reg [31:0]   rD_val, rA_val, rB_val;
      reg [31:0]   rD_val, rA_val, rB_val;
      reg [15:0]   imm_16bit;
      reg [15:0]   imm_16bit;
 
 
      reg [15:0]   mtspr_imm;
      reg [15:0]   mtspr_imm;
 
 
      reg [3:0]    alu_op;
      reg [3:0]    alu_op;
      reg [1:0]    shrot_op;
      reg [1:0]    shrot_op;
 
 
      reg [5:0]    shroti_imm;
      reg [5:0]    shroti_imm;
 
 
      reg [5:0]    sf_op;
      reg [5:0]    sf_op;
 
 
      reg [5:0]    xsync_op;
      reg [5:0]    xsync_op;
 
 
      reg          flag;
      reg          flag;
 
 
      reg [31:0]   br_j_ea; // Branch/jump effective address
      reg [31:0]   br_j_ea; // Branch/jump effective address
 
 
 
 
      begin
      begin
 
 
         // Instruction opcode
         // Instruction opcode
         opcode = insn[`OR1K_OPCODE_POS];
         opcode = insn[`OR1K_OPCODE_POS];
         // Immediates for jump or branch instructions
         // Immediates for jump or branch instructions
         j_imm = insn[`OR1K_J_BR_IMM_POS];
         j_imm = insn[`OR1K_J_BR_IMM_POS];
         br_imm = insn[`OR1K_J_BR_IMM_POS];
         br_imm = insn[`OR1K_J_BR_IMM_POS];
         // Register numbers (D, A and B)
         // Register numbers (D, A and B)
         rD_num = insn[`OR1K_RD_POS];
         rD_num = insn[`OR1K_RD_POS];
         rA_num = insn[`OR1K_RA_POS];
         rA_num = insn[`OR1K_RA_POS];
         rB_num = insn[`OR1K_RB_POS];
         rB_num = insn[`OR1K_RB_POS];
         // Bottom 16 bits when used as immediates in various instructions
         // Bottom 16 bits when used as immediates in various instructions
         imm_16bit = insn[15:0];
         imm_16bit = insn[15:0];
         // 16-bit immediate for mtspr instructions
         // 16-bit immediate for mtspr instructions
         mtspr_imm = {insn[25:21],insn[10:0]};
         mtspr_imm = {insn[25:21],insn[10:0]};
         // ALU op for ALU instructions
         // ALU op for ALU instructions
         alu_op = insn[`OR1K_ALU_OP_POS];
         alu_op = insn[`OR1K_ALU_OP_POS];
         // Shift-rotate op for SHROT ALU instructions
         // Shift-rotate op for SHROT ALU instructions
         shrot_op = insn[`OR1K_SHROT_OP_POS];
         shrot_op = insn[`OR1K_SHROT_OP_POS];
         shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
         shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
 
 
         // Set flag op
         // Set flag op
         sf_op = insn[`OR1K_SF_OP];
         sf_op = insn[`OR1K_SF_OP];
 
 
         // Xsync/syscall/trap opcode
         // Xsync/syscall/trap opcode
         xsync_op = insn[`OR1K_XSYNC_OP_POS];
         xsync_op = insn[`OR1K_XSYNC_OP_POS];
 
 
         // Use the flag from the previous instruction, as the decision
         // Use the flag from the previous instruction, as the decision
         // is made in the execute stage not in te writeback stage,
         // is made in the execute stage not in te writeback stage,
         // which is where we're getting our instructions.
         // which is where we're getting our instructions.
         flag = previous_sr[`OR1200_SR_F];
         flag = previous_sr[`OR1200_SR_F];
 
 
         update_current_gprs;
         update_current_gprs;
 
 
         // Check MSbit of the immediate, sign extend if set
         // Check MSbit of the immediate, sign extend if set
         br_j_ea = j_imm[25] ? pc + {4'hf,j_imm,2'b00} :
         br_j_ea = j_imm[25] ? pc + {4'hf,j_imm,2'b00} :
                   pc + {4'h0,j_imm,2'b00};
                   pc + {4'h0,j_imm,2'b00};
 
 
         if (exception)
         if (exception)
           begin
           begin
              $display("%t: exception - at 0x%x",$time, pc);
              $display("%t: exception - at 0x%x",$time, pc);
              // get epcr, put it in the addresses we expect to jump
              // get epcr, put it in the addresses we expect to jump
              // back to
              // back to
              // Maybe DON'T do this. Because maybe in linux things we
              // Maybe DON'T do this. Because maybe in linux things we
              // interrupt out of, we don't want to execute them again?
              // interrupt out of, we don't want to execute them again?
              //add_expected_address(current_epcr);
              //add_expected_address(current_epcr);
           end
           end
 
 
 
 
         check_expected_address(pc, (jumped & !exception));
         check_expected_address(pc, (jumped & !exception));
 
 
         rfe = 0;
         rfe = 0;
 
 
         case (opcode)
         case (opcode)
           `OR1200_OR32_J:
           `OR1200_OR32_J:
             begin
             begin
                //
                //
                // PC < - exts(Immediate < < 2) + JumpInsnAddr
                // PC < - exts(Immediate < < 2) + JumpInsnAddr
                //
                //
                //The immediate value is shifted left two bits, sign-extended
                //The immediate value is shifted left two bits, sign-extended
                // to program counter width, and then added to the address of
                // to program counter width, and then added to the address of
                // the jump instruction. The result is the effective address
                // the jump instruction. The result is the effective address
                // of the jump. The program unconditionally jumps to EA with
                // of the jump. The program unconditionally jumps to EA with
                // a delay of one instruction.
                // a delay of one instruction.
 
 
                add_expected_address(br_j_ea);
                add_expected_address(br_j_ea);
 
 
                jumping = 1;
                jumping = 1;
             end
             end
           `OR1200_OR32_JAL:
           `OR1200_OR32_JAL:
             begin
             begin
                //
                //
                //PC < - exts(Immediate < < 2) + JumpInsnAddr
                //PC < - exts(Immediate < < 2) + JumpInsnAddr
                //LR < - DelayInsnAddr + 4
                //LR < - DelayInsnAddr + 4
                //
                //
                // Link reg is r9, check it is PC+8
                // Link reg is r9, check it is PC+8
                //
                //
                add_expected_address(br_j_ea);
                add_expected_address(br_j_ea);
                assert_gpr_val(9, pc+8, pc);
                assert_gpr_val(9, pc+8, pc);
                jumping = 1;    //
                jumping = 1;    //
             end
             end
           `OR1200_OR32_BNF:
           `OR1200_OR32_BNF:
             begin
             begin
                //EA < - exts(Immediate < < 2) + BranchInsnAddr
                //EA < - exts(Immediate < < 2) + BranchInsnAddr
                //PC < - EA if SR[F] cleared
                //PC < - EA if SR[F] cleared
                if (!flag)
                if (!flag)
                  begin
                  begin
                     add_expected_address(br_j_ea);
                     add_expected_address(br_j_ea);
                     jumping = 1;
                     jumping = 1;
                  end
                  end
             end
             end
           `OR1200_OR32_BF:
           `OR1200_OR32_BF:
             begin
             begin
                //EA < - exts(Immediate < < 2) + BranchInsnAddr
                //EA < - exts(Immediate < < 2) + BranchInsnAddr
                //PC < - EA if SR[F] set
                //PC < - EA if SR[F] set
                if (flag)
                if (flag)
                  begin
                  begin
                     add_expected_address(br_j_ea);
                     add_expected_address(br_j_ea);
                     jumping = 1;
                     jumping = 1;
                  end
                  end
             end
             end
           `OR1200_OR32_RFE:
           `OR1200_OR32_RFE:
             begin
             begin
                add_expected_address(current_epcr);
                add_expected_address(current_epcr);
                // jumping variable keeps track of jumps/branches with delay
                // jumping variable keeps track of jumps/branches with delay
                // slot - there is none for l.rfe
                // slot - there is none for l.rfe
                rfe = 1;
                rfe = 1;
             end
             end
           `OR1200_OR32_JR:
           `OR1200_OR32_JR:
             begin
             begin
                //PC < - rB
                //PC < - rB
                get_gpr(rB_num, rB_val);
                get_gpr(rB_num, rB_val);
                add_expected_address(rB_val);
                add_expected_address(rB_val);
                jumping = 1;
                jumping = 1;
             end
             end
           `OR1200_OR32_JALR:
           `OR1200_OR32_JALR:
             begin
             begin
                //PC < - rB
                //PC < - rB
                //LR < - DelayInsnAddr + 4
                //LR < - DelayInsnAddr + 4
                get_gpr(rB_num, rB_val);
                get_gpr(rB_num, rB_val);
                add_expected_address(rB_val);
                add_expected_address(rB_val);
                assert_gpr_val(9, pc+8, pc);
                assert_gpr_val(9, pc+8, pc);
                jumping = 1;
                jumping = 1;
             end
             end
           /*
           /*
            `OR1200_OR32_LWZ,
            `OR1200_OR32_LWZ,
            `OR1200_OR32_LBZ,
            `OR1200_OR32_LBZ,
            `OR1200_OR32_LBS,
            `OR1200_OR32_LBS,
            `OR1200_OR32_LHZ,
            `OR1200_OR32_LHZ,
            `OR1200_OR32_LHS,
            `OR1200_OR32_LHS,
            `OR1200_OR32_SW,
            `OR1200_OR32_SW,
            `OR1200_OR32_SB,
            `OR1200_OR32_SB,
            `OR1200_OR32_SH:
            `OR1200_OR32_SH:
            begin
            begin
            // Should result in databus access if data cache disabled
            // Should result in databus access if data cache disabled
            $display("%t: lsu instruction",$time);
            $display("%t: lsu instruction",$time);
end
end
 
 
            `OR1200_OR32_MFSPR,
            `OR1200_OR32_MFSPR,
            `OR1200_OR32_MTSPR:
            `OR1200_OR32_MTSPR:
            begin
            begin
            // Confirm RF values end up in the correct SPR
            // Confirm RF values end up in the correct SPR
            $display("%t: mxspr",$time);
            $display("%t: mxspr",$time);
end
end
 
 
            `OR1200_OR32_MOVHI,
            `OR1200_OR32_MOVHI,
            `OR1200_OR32_ADDI,
            `OR1200_OR32_ADDI,
            `OR1200_OR32_ADDIC,
            `OR1200_OR32_ADDIC,
            `OR1200_OR32_ANDI,
            `OR1200_OR32_ANDI,
            `OR1200_OR32_ORI,
            `OR1200_OR32_ORI,
            `OR1200_OR32_XORI,
            `OR1200_OR32_XORI,
            `OR1200_OR32_MULI,
            `OR1200_OR32_MULI,
            `OR1200_OR32_ALU:
            `OR1200_OR32_ALU:
            begin
            begin
            // Double check operations done on RF and immediate values
            // Double check operations done on RF and immediate values
            $display("%t: ALU op",$time);
            $display("%t: ALU op",$time);
end
end
 
 
            `OR1200_OR32_SH_ROTI:
            `OR1200_OR32_SH_ROTI:
            begin
            begin
            // Rotate according to immediate - maybe should be in ALU ops
            // Rotate according to immediate - maybe should be in ALU ops
            $display("%t: rotate op",$time);
            $display("%t: rotate op",$time);
end
end
 
 
            `OR1200_OR32_SFXXI,
            `OR1200_OR32_SFXXI,
            `OR1200_OR32_SFXX:
            `OR1200_OR32_SFXX:
            begin
            begin
            // Set flag - do the check oursevles, check flag
            // Set flag - do the check oursevles, check flag
            $display("%t: set flag op",$time);
            $display("%t: set flag op",$time);
end
end
 
 
            `OR1200_OR32_MACI,
            `OR1200_OR32_MACI,
            `OR1200_OR32_MACMSB:
            `OR1200_OR32_MACMSB:
            begin
            begin
            // Either, multiply signed and accumulate, l.mac
            // Either, multiply signed and accumulate, l.mac
            // or multiply signed and subtract, l.msb
            // or multiply signed and subtract, l.msb
            $display("%t: MAC op",$time);
            $display("%t: MAC op",$time);
end
end
            */
            */
 
 
           /*default:
           /*default:
            begin
            begin
            $display("%t: Unknown opcode 0x%h at pc 0x%x\n",
            $display("%t: Unknown opcode 0x%h at pc 0x%x\n",
            $time,opcode, pc);
            $time,opcode, pc);
end
end
            */
            */
         endcase // case (opcode)
         endcase // case (opcode)
 
 
         update_previous_gprs;
         update_previous_gprs;
 
 
      end
      end
   endtask // or1200_check_execution
   endtask // or1200_check_execution
 
 
 
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
   // Instruction decode task
   // Instruction decode task
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
 
   task or1200_print_op;
   task or1200_print_op;
      input [31:0] insn;
      input [31:0] insn;
 
 
      reg [5:0]    opcode;
      reg [5:0]    opcode;
 
 
      reg [25:0]   j_imm;
      reg [25:0]   j_imm;
      reg [25:0]   br_imm;
      reg [25:0]   br_imm;
 
 
      reg [4:0]    rD_num, rA_num, rB_num;
      reg [4:0]    rD_num, rA_num, rB_num;
      reg [31:0]   rA_val, rB_val;
      reg [31:0]   rA_val, rB_val;
      reg [15:0]   imm_16bit;
      reg [15:0]   imm_16bit;
      reg [10:0]   imm_split16bit;
      reg [10:0]   imm_split16bit;
 
 
      reg [3:0]    alu_op;
      reg [3:0]    alu_op;
      reg [1:0]    shrot_op;
      reg [1:0]    shrot_op;
 
 
      reg [5:0]    shroti_imm;
      reg [5:0]    shroti_imm;
 
 
      reg [5:0]    sf_op;
      reg [5:0]    sf_op;
 
 
      reg [5:0]    xsync_op;
      reg [5:0]    xsync_op;
 
 
      begin
      begin
         // Instruction opcode
         // Instruction opcode
         opcode = insn[`OR1K_OPCODE_POS];
         opcode = insn[`OR1K_OPCODE_POS];
         // Immediates for jump or branch instructions
         // Immediates for jump or branch instructions
         j_imm = insn[`OR1K_J_BR_IMM_POS];
         j_imm = insn[`OR1K_J_BR_IMM_POS];
         br_imm = insn[`OR1K_J_BR_IMM_POS];
         br_imm = insn[`OR1K_J_BR_IMM_POS];
         // Register numbers (D, A and B)
         // Register numbers (D, A and B)
         rD_num = insn[`OR1K_RD_POS];
         rD_num = insn[`OR1K_RD_POS];
         rA_num = insn[`OR1K_RA_POS];
         rA_num = insn[`OR1K_RA_POS];
         rB_num = insn[`OR1K_RB_POS];
         rB_num = insn[`OR1K_RB_POS];
         // Bottom 16 bits when used as immediates in various instructions
         // Bottom 16 bits when used as immediates in various instructions
         imm_16bit = insn[15:0];
         imm_16bit = insn[15:0];
         // Bottom 11 bits used as immediates for l.sX instructions
         // Bottom 11 bits used as immediates for l.sX instructions
 
 
         // Split 16-bit immediate for l.mtspr/l.sX instructions
         // Split 16-bit immediate for l.mtspr/l.sX instructions
         imm_split16bit = {insn[25:21],insn[10:0]};
         imm_split16bit = {insn[25:21],insn[10:0]};
         // ALU op for ALU instructions
         // ALU op for ALU instructions
         alu_op = insn[`OR1K_ALU_OP_POS];
         alu_op = insn[`OR1K_ALU_OP_POS];
         // Shift-rotate op for SHROT ALU instructions
         // Shift-rotate op for SHROT ALU instructions
         shrot_op = insn[`OR1K_SHROT_OP_POS];
         shrot_op = insn[`OR1K_SHROT_OP_POS];
         shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
         shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
 
 
         // Set flag op
         // Set flag op
         sf_op = insn[`OR1K_SF_OP];
         sf_op = insn[`OR1K_SF_OP];
 
 
         // Xsync/syscall/trap opcode
         // Xsync/syscall/trap opcode
         xsync_op = insn[`OR1K_XSYNC_OP_POS];
         xsync_op = insn[`OR1K_XSYNC_OP_POS];
 
 
         case (opcode)
         case (opcode)
           `OR1200_OR32_J:
           `OR1200_OR32_J:
             begin
             begin
                $fwrite(finsn,"l.j 0x%h", {j_imm,2'b00});
                $fwrite(finsn,"l.j 0x%h", {j_imm,2'b00});
             end
             end
 
 
           `OR1200_OR32_JAL:
           `OR1200_OR32_JAL:
             begin
             begin
                $fwrite(finsn,"l.jal 0x%h", {j_imm,2'b00});
                $fwrite(finsn,"l.jal 0x%h", {j_imm,2'b00});
             end
             end
 
 
           `OR1200_OR32_BNF:
           `OR1200_OR32_BNF:
             begin
             begin
                $fwrite(finsn,"l.bnf 0x%h", {br_imm,2'b00});
                $fwrite(finsn,"l.bnf 0x%h", {br_imm,2'b00});
             end
             end
 
 
           `OR1200_OR32_BF:
           `OR1200_OR32_BF:
             begin
             begin
                $fwrite(finsn,"l.bf 0x%h", {br_imm,2'b00});
                $fwrite(finsn,"l.bf 0x%h", {br_imm,2'b00});
             end
             end
 
 
           `OR1200_OR32_RFE:
           `OR1200_OR32_RFE:
             begin
             begin
                $fwrite(finsn,"l.rfe");
                $fwrite(finsn,"l.rfe");
             end
             end
 
 
           `OR1200_OR32_JR:
           `OR1200_OR32_JR:
             begin
             begin
                $fwrite(finsn,"l.jr r%0d",rB_num);
                $fwrite(finsn,"l.jr r%0d",rB_num);
             end
             end
 
 
           `OR1200_OR32_JALR:
           `OR1200_OR32_JALR:
             begin
             begin
                $fwrite(finsn,"l.jalr r%0d",rB_num);
                $fwrite(finsn,"l.jalr r%0d",rB_num);
             end
             end
 
 
           `OR1200_OR32_LWZ:
           `OR1200_OR32_LWZ:
             begin
             begin
                $fwrite(finsn,"l.lwz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
                $fwrite(finsn,"l.lwz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
             end
             end
 
 
           `OR1200_OR32_LBZ:
           `OR1200_OR32_LBZ:
             begin
             begin
                $fwrite(finsn,"l.lbz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
                $fwrite(finsn,"l.lbz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
             end
             end
 
 
           `OR1200_OR32_LBS:
           `OR1200_OR32_LBS:
             begin
             begin
                $fwrite(finsn,"l.lbs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
                $fwrite(finsn,"l.lbs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
             end
             end
 
 
           `OR1200_OR32_LHZ:
           `OR1200_OR32_LHZ:
             begin
             begin
                $fwrite(finsn,"l.lhz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
                $fwrite(finsn,"l.lhz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
             end
             end
 
 
           `OR1200_OR32_LHS:
           `OR1200_OR32_LHS:
             begin
             begin
                $fwrite(finsn,"l.lhs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
                $fwrite(finsn,"l.lhs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
             end
             end
 
 
           `OR1200_OR32_SW:
           `OR1200_OR32_SW:
             begin
             begin
                $fwrite(finsn,"l.sw 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
                $fwrite(finsn,"l.sw 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
             end
             end
 
 
           `OR1200_OR32_SB:
           `OR1200_OR32_SB:
             begin
             begin
                $fwrite(finsn,"l.sb 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
                $fwrite(finsn,"l.sb 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
             end
             end
 
 
           `OR1200_OR32_SH:
           `OR1200_OR32_SH:
             begin
             begin
                $fwrite(finsn,"l.sh 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
                $fwrite(finsn,"l.sh 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
             end
             end
 
 
           `OR1200_OR32_MFSPR:
           `OR1200_OR32_MFSPR:
             begin
             begin
                $fwrite(finsn,"l.mfspr r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit,);
                $fwrite(finsn,"l.mfspr r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit,);
             end
             end
 
 
           `OR1200_OR32_MTSPR:
           `OR1200_OR32_MTSPR:
             begin
             begin
                $fwrite(finsn,"l.mtspr r%0d,r%0d,0x%h",rA_num,rB_num,imm_split16bit);
                $fwrite(finsn,"l.mtspr r%0d,r%0d,0x%h",rA_num,rB_num,imm_split16bit);
             end
             end
 
 
           `OR1200_OR32_MOVHI:
           `OR1200_OR32_MOVHI:
             begin
             begin
                if (!insn[16])
                if (!insn[16])
                  $fwrite(finsn,"l.movhi r%0d,0x%h",rD_num,imm_16bit);
                  $fwrite(finsn,"l.movhi r%0d,0x%h",rD_num,imm_16bit);
                else
                else
                  $fwrite(finsn,"l.macrc r%0d",rD_num);
                  $fwrite(finsn,"l.macrc r%0d",rD_num);
             end
             end
 
 
           `OR1200_OR32_ADDI:
           `OR1200_OR32_ADDI:
             begin
             begin
                $fwrite(finsn,"l.addi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.addi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_ADDIC:
           `OR1200_OR32_ADDIC:
             begin
             begin
                $fwrite(finsn,"l.addic r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.addic r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_ANDI:
           `OR1200_OR32_ANDI:
             begin
             begin
                $fwrite(finsn,"l.andi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.andi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_ORI:
           `OR1200_OR32_ORI:
             begin
             begin
                $fwrite(finsn,"l.ori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.ori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_XORI:
           `OR1200_OR32_XORI:
             begin
             begin
                $fwrite(finsn,"l.xori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.xori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_MULI:
           `OR1200_OR32_MULI:
             begin
             begin
                $fwrite(finsn,"l.muli r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
                $fwrite(finsn,"l.muli r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_ALU:
           `OR1200_OR32_ALU:
             begin
             begin
                case(alu_op)
                case(alu_op)
                  `OR1200_ALUOP_ADD:
                  `OR1200_ALUOP_ADD:
                    $fwrite(finsn,"l.add ");
                    $fwrite(finsn,"l.add ");
                  `OR1200_ALUOP_ADDC:
                  `OR1200_ALUOP_ADDC:
                    $fwrite(finsn,"l.addc ");
                    $fwrite(finsn,"l.addc ");
                  `OR1200_ALUOP_SUB:
                  `OR1200_ALUOP_SUB:
                    $fwrite(finsn,"l.sub ");
                    $fwrite(finsn,"l.sub ");
                  `OR1200_ALUOP_AND:
                  `OR1200_ALUOP_AND:
                    $fwrite(finsn,"l.and ");
                    $fwrite(finsn,"l.and ");
                  `OR1200_ALUOP_OR:
                  `OR1200_ALUOP_OR:
                    $fwrite(finsn,"l.or ");
                    $fwrite(finsn,"l.or ");
                  `OR1200_ALUOP_XOR:
                  `OR1200_ALUOP_XOR:
                    $fwrite(finsn,"l.xor ");
                    $fwrite(finsn,"l.xor ");
                  `OR1200_ALUOP_MUL:
                  `OR1200_ALUOP_MUL:
                    $fwrite(finsn,"l.mul ");
                    $fwrite(finsn,"l.mul ");
                  `OR1200_ALUOP_SHROT:
                  `OR1200_ALUOP_SHROT:
                    begin
                    begin
                       case(shrot_op)
                       case(shrot_op)
                         `OR1200_SHROTOP_SLL:
                         `OR1200_SHROTOP_SLL:
                           $fwrite(finsn,"l.sll ");
                           $fwrite(finsn,"l.sll ");
                         `OR1200_SHROTOP_SRL:
                         `OR1200_SHROTOP_SRL:
                           $fwrite(finsn,"l.srl ");
                           $fwrite(finsn,"l.srl ");
                         `OR1200_SHROTOP_SRA:
                         `OR1200_SHROTOP_SRA:
                           $fwrite(finsn,"l.sra ");
                           $fwrite(finsn,"l.sra ");
                         `OR1200_SHROTOP_ROR:
                         `OR1200_SHROTOP_ROR:
                           $fwrite(finsn,"l.ror ");
                           $fwrite(finsn,"l.ror ");
                       endcase // case (shrot_op)
                       endcase // case (shrot_op)
                    end
                    end
                  `OR1200_ALUOP_DIV:
                  `OR1200_ALUOP_DIV:
                    $fwrite(finsn,"l.div ");
                    $fwrite(finsn,"l.div ");
                  `OR1200_ALUOP_DIVU:
                  `OR1200_ALUOP_DIVU:
                    $fwrite(finsn,"l.divu ");
                    $fwrite(finsn,"l.divu ");
                  `OR1200_ALUOP_CMOV:
                  `OR1200_ALUOP_CMOV:
                    $fwrite(finsn,"l.cmov ");
                    $fwrite(finsn,"l.cmov ");
                endcase // case (alu_op)
                endcase // case (alu_op)
                $fwrite(finsn,"r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
                $fwrite(finsn,"r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
             end
             end
 
 
           `OR1200_OR32_SH_ROTI:
           `OR1200_OR32_SH_ROTI:
             begin
             begin
                case(shrot_op)
                case(shrot_op)
                  `OR1200_SHROTOP_SLL:
                  `OR1200_SHROTOP_SLL:
                    $fwrite(finsn,"l.slli ");
                    $fwrite(finsn,"l.slli ");
                  `OR1200_SHROTOP_SRL:
                  `OR1200_SHROTOP_SRL:
                    $fwrite(finsn,"l.srli ");
                    $fwrite(finsn,"l.srli ");
                  `OR1200_SHROTOP_SRA:
                  `OR1200_SHROTOP_SRA:
                    $fwrite(finsn,"l.srai ");
                    $fwrite(finsn,"l.srai ");
                  `OR1200_SHROTOP_ROR:
                  `OR1200_SHROTOP_ROR:
                    $fwrite(finsn,"l.rori ");
                    $fwrite(finsn,"l.rori ");
                endcase // case (shrot_op)
                endcase // case (shrot_op)
                $fwrite(finsn,"r%0d,r%0d,0x%h",rD_num,rA_num,shroti_imm);
                $fwrite(finsn,"r%0d,r%0d,0x%h",rD_num,rA_num,shroti_imm);
             end
             end
 
 
           `OR1200_OR32_SFXXI:
           `OR1200_OR32_SFXXI:
             begin
             begin
                case(sf_op[2:0])
                case(sf_op[2:0])
                  `OR1200_COP_SFEQ:
                  `OR1200_COP_SFEQ:
                    $fwrite(finsn,"l.sfeqi ");
                    $fwrite(finsn,"l.sfeqi ");
                  `OR1200_COP_SFNE:
                  `OR1200_COP_SFNE:
                    $fwrite(finsn,"l.sfnei ");
                    $fwrite(finsn,"l.sfnei ");
                  `OR1200_COP_SFGT:
                  `OR1200_COP_SFGT:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfgtsi ");
                         $fwrite(finsn,"l.sfgtsi ");
                       else
                       else
                         $fwrite(finsn,"l.sfgtui ");
                         $fwrite(finsn,"l.sfgtui ");
                    end
                    end
                  `OR1200_COP_SFGE:
                  `OR1200_COP_SFGE:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfgesi ");
                         $fwrite(finsn,"l.sfgesi ");
                       else
                       else
                         $fwrite(finsn,"l.sfgeui ");
                         $fwrite(finsn,"l.sfgeui ");
                    end
                    end
                  `OR1200_COP_SFLT:
                  `OR1200_COP_SFLT:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfltsi ");
                         $fwrite(finsn,"l.sfltsi ");
                       else
                       else
                         $fwrite(finsn,"l.sfltui ");
                         $fwrite(finsn,"l.sfltui ");
                    end
                    end
                  `OR1200_COP_SFLE:
                  `OR1200_COP_SFLE:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sflesi ");
                         $fwrite(finsn,"l.sflesi ");
                       else
                       else
                         $fwrite(finsn,"l.sfleui ");
                         $fwrite(finsn,"l.sfleui ");
                    end
                    end
                endcase // case (sf_op[2:0])
                endcase // case (sf_op[2:0])
 
 
                $fwrite(finsn,"r%0d,0x%h",rA_num, imm_16bit);
                $fwrite(finsn,"r%0d,0x%h",rA_num, imm_16bit);
 
 
             end // case: `OR1200_OR32_SFXXI
             end // case: `OR1200_OR32_SFXXI
 
 
           `OR1200_OR32_SFXX:
           `OR1200_OR32_SFXX:
             begin
             begin
                case(sf_op[2:0])
                case(sf_op[2:0])
                  `OR1200_COP_SFEQ:
                  `OR1200_COP_SFEQ:
                    $fwrite(finsn,"l.sfeq ");
                    $fwrite(finsn,"l.sfeq ");
                  `OR1200_COP_SFNE:
                  `OR1200_COP_SFNE:
                    $fwrite(finsn,"l.sfne ");
                    $fwrite(finsn,"l.sfne ");
                  `OR1200_COP_SFGT:
                  `OR1200_COP_SFGT:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfgts ");
                         $fwrite(finsn,"l.sfgts ");
                       else
                       else
                         $fwrite(finsn,"l.sfgtu ");
                         $fwrite(finsn,"l.sfgtu ");
                    end
                    end
                  `OR1200_COP_SFGE:
                  `OR1200_COP_SFGE:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfges ");
                         $fwrite(finsn,"l.sfges ");
                       else
                       else
                         $fwrite(finsn,"l.sfgeu ");
                         $fwrite(finsn,"l.sfgeu ");
                    end
                    end
                  `OR1200_COP_SFLT:
                  `OR1200_COP_SFLT:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sflts ");
                         $fwrite(finsn,"l.sflts ");
                       else
                       else
                         $fwrite(finsn,"l.sfltu ");
                         $fwrite(finsn,"l.sfltu ");
                    end
                    end
                  `OR1200_COP_SFLE:
                  `OR1200_COP_SFLE:
                    begin
                    begin
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                       if (sf_op[`OR1200_SIGNED_COMPARE])
                         $fwrite(finsn,"l.sfles ");
                         $fwrite(finsn,"l.sfles ");
                       else
                       else
                         $fwrite(finsn,"l.sfleu ");
                         $fwrite(finsn,"l.sfleu ");
                    end
                    end
 
 
                endcase // case (sf_op[2:0])
                endcase // case (sf_op[2:0])
 
 
                $fwrite(finsn,"r%0d,r%0d",rA_num, rB_num);
                $fwrite(finsn,"r%0d,r%0d",rA_num, rB_num);
 
 
             end
             end
 
 
           `OR1200_OR32_MACI:
           `OR1200_OR32_MACI:
             begin
             begin
                $fwrite(finsn,"l.maci r%0d,0x%h",rA_num,imm_16bit);
                $fwrite(finsn,"l.maci r%0d,0x%h",rA_num,imm_16bit);
             end
             end
 
 
           `OR1200_OR32_MACMSB:
           `OR1200_OR32_MACMSB:
             begin
             begin
                if(insn[3:0] == 4'h1)
                if(insn[3:0] == 4'h1)
                  $fwrite(finsn,"l.mac ");
                  $fwrite(finsn,"l.mac ");
                else if(insn[3:0] == 4'h2)
                else if(insn[3:0] == 4'h2)
                  $fwrite(finsn,"l.msb ");
                  $fwrite(finsn,"l.msb ");
 
 
                $fwrite(finsn,"r%0d,r%0d",rA_num,rB_num);
                $fwrite(finsn,"r%0d,r%0d",rA_num,rB_num);
             end
             end
 
 
           `OR1200_OR32_NOP:
           `OR1200_OR32_NOP:
             begin
             begin
                $fwrite(finsn,"l.nop 0x%0h",imm_16bit);
                $fwrite(finsn,"l.nop 0x%0h",imm_16bit);
             end
             end
 
 
           `OR1200_OR32_XSYNC:
           `OR1200_OR32_XSYNC:
             begin
             begin
                case (xsync_op)
                case (xsync_op)
                  5'd0:
                  5'd0:
                    $fwrite(finsn,"l.sys 0x%h",imm_16bit);
                    $fwrite(finsn,"l.sys 0x%h",imm_16bit);
                  5'd8:
                  5'd8:
                    $fwrite(finsn,"l.trap 0x%h",imm_16bit);
                    $fwrite(finsn,"l.trap 0x%h",imm_16bit);
                  5'd16:
                  5'd16:
                    $fwrite(finsn,"l.msync");
                    $fwrite(finsn,"l.msync");
                  5'd20:
                  5'd20:
                    $fwrite(finsn,"l.psync");
                    $fwrite(finsn,"l.psync");
                  5'd24:
                  5'd24:
                    $fwrite(finsn,"l.csync");
                    $fwrite(finsn,"l.csync");
                  default:
                  default:
                    begin
                    begin
                       $display("%t: Instruction with opcode 0x%h has bad specific type information: 0x%h",$time,opcode,insn);
                       $display("%t: Instruction with opcode 0x%h has bad specific type information: 0x%h",$time,opcode,insn);
                       $fwrite(finsn,"%t: Instruction with opcode 0x%h has has bad specific type information: 0x%h",$time,opcode,insn);
                       $fwrite(finsn,"%t: Instruction with opcode 0x%h has has bad specific type information: 0x%h",$time,opcode,insn);
                    end
                    end
                endcase // case (xsync_op)
                endcase // case (xsync_op)
             end
             end
 
 
           default:
           default:
             begin
             begin
                $display("%t: Unknown opcode 0x%h",$time,opcode);
                $display("%t: Unknown opcode 0x%h",$time,opcode);
                $fwrite(finsn,"%t: Unknown opcode 0x%h",$time,opcode);
                $fwrite(finsn,"%t: Unknown opcode 0x%h",$time,opcode);
             end
             end
 
 
         endcase // case (opcode)
         endcase // case (opcode)
 
 
      end
      end
   endtask // or1200_print_op
   endtask // or1200_print_op
 
 
 
 
 
 
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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