Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

import mor1kx_monitor from mor1kx-dev-env

This file is useful for other verification set-ups than mor1kx-dev-env,
by adding it to the mor1kx project we can provide them with the file
without the overhead of acquring the whole mor1kx-dev-env.
  • Loading branch information...
commit f43340ea27954e1e64760489149538c8f7393db6 1 parent 3324116
@skristiansson skristiansson authored
Showing with 923 additions and 0 deletions.
  1. +923 −0 bench/verilog/mor1kx_monitor.v
View
923 bench/verilog/mor1kx_monitor.v
@@ -0,0 +1,923 @@
+/* ****************************************************************************
+ This Source Code Form is subject to the terms of the
+ Open Hardware Description License, v. 1.0. If a copy
+ of the OHDL was not distributed with this file, You
+ can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
+
+ Description: mor1kx monitor module
+
+ Attaches to hooks provided in the mor1kx pipeline wrapper and provides
+ execution trace, disassembly, and l.nop instruction functions.
+
+ Copyright (C) 2012, 2013 Authors
+
+ Author(s): Julius Baxter <juliusbaxter@gmail.com>
+
+***************************************************************************** */
+
+/* Configure these defines to point to the mor1kx instantiation */
+`ifndef MOR1KX_INST
+ `define MOR1KX_INST dut.mor1kx0
+`endif
+
+/* The rest of these shouldn't need changing if the wrapper hooks have been
+ set up correctly in mor1kx_cpu. */
+`ifndef CPU_WRAPPER
+ `define CPU_WRAPPER `MOR1KX_INST.mor1kx_cpu
+`endif
+`define CPU_INST `CPU_WRAPPER.`MOR1KX_CPU_PIPELINE.mor1kx_cpu
+`define EXECUTE_STAGE_INSN `CPU_WRAPPER.monitor_execute_insn
+`define EXECUTE_STAGE_ADV `CPU_WRAPPER.monitor_execute_advance
+`define CPU_clk `CPU_WRAPPER.monitor_clk
+`define CPU_FLAG `CPU_WRAPPER.monitor_flag
+`define CPU_SR `CPU_WRAPPER.monitor_spr_sr
+`define EXECUTE_PC `CPU_WRAPPER.monitor_execute_pc
+`define GPR_GET(x) `CPU_INST.get_gpr(x)
+`define GPR_SET(x, y) `CPU_INST.set_gpr(x, y)
+
+`include "mor1kx-defines.v"
+
+// Pull in an ORPSoC-specific file
+`include "test-defines.v" // indicate if we should trace or not
+
+// OR1K ISA defines used in this file
+
+`define OR1K_OPCODE_POS 31:26
+`define OR1K_J_BR_IMM_POS 25:0
+`define OR1K_RD_POS 25:21
+`define OR1K_RA_POS 20:16
+`define OR1K_RB_POS 15:11
+`define OR1K_ALU_OP_POS 3:0
+`define OR1K_SF_OP 25:21
+`define OR1K_XSYNC_OP_POS 25:21
+
+module mor1kx_monitor #(parameter LOG_DIR= "../out") ();
+
+ // General output file descriptor
+ integer fgeneral = 0;
+ integer ftrace = 0;
+ integer insns = 0;
+
+ wire clk;
+
+ parameter OPTION_OPERAND_WIDTH = 32;
+
+ reg TRACE_ENABLE;
+ initial TRACE_ENABLE = $test$plusargs("trace_enable");
+
+ reg TRACE_TO_SCREEN;
+ initial TRACE_TO_SCREEN = $test$plusargs("trace_to_screen");
+
+ assign clk = `CPU_clk;
+
+ reg [63:0] cycle_counter = 0 ;
+
+ /* Log file management code */
+ initial
+ begin
+ $timeformat (-9, 2, " ns", 12);
+ fgeneral = $fopen({LOG_DIR,"/",`TEST_NAME_STRING,"-general.log"});
+ ftrace = $fopen({LOG_DIR,"/",`TEST_NAME_STRING,"-trace.log"});
+ end
+
+ /* Simulation support code */
+
+ reg [1:80*8] decode_insn_disas;
+ reg [1:80*8] execute_insn_disas;
+ reg [OPTION_OPERAND_WIDTH-1:0] decode_pc;
+ reg [OPTION_OPERAND_WIDTH-1:0] execute_pc;
+
+ reg [`OR1K_INSN_WIDTH-1:0] execute_insn;
+ reg flag_4stage;
+
+ always @(`EXECUTE_STAGE_INSN)
+ mor1k_insn_to_string(`EXECUTE_STAGE_INSN, execute_insn_disas);
+ //$write("%tns: decode insn PC %08h %08h %s\n",$time, pc_decode_i,
+ // decode_insn_i, insn_disassembled_string);
+
+ always @(negedge `CPU_clk) begin
+
+ cycle_counter = cycle_counter + 1;
+
+ if (`EXECUTE_STAGE_ADV)
+ begin
+ insns = insns + 1;
+ execute_insn = `EXECUTE_STAGE_INSN;
+
+ if(TRACE_ENABLE)
+ mor1k_trace_print(execute_insn, `CPU_SR, `EXECUTE_PC, `CPU_FLAG);
+
+ // Check instructions for simulation controls
+ if (execute_insn == 32'h15_00_00_01)
+ begin
+ $fdisplay(fgeneral,"%0t:exit(0x%08h);",$time,`GPR_GET(3));
+ $fdisplay(ftrace,"exit(0x%08h);",`GPR_GET(3));
+ $display("exit(0x%08h);",`GPR_GET(3));
+ $finish;
+ end
+ if (execute_insn == 32'h15_00_00_02)
+ begin
+ $fdisplay(fgeneral,"%0t:report(0x%08h);",$time,`GPR_GET(3));
+ $fdisplay(ftrace,"report(0x%08h);",`GPR_GET(3));
+ $display("report(0x%08h);",`GPR_GET(3));
+ end
+ if (execute_insn == 32'h15_00_00_04)
+ begin
+ $write("%c",`GPR_GET(3));
+ $fdisplay(fgeneral, "%0t: l.nop putc (%c)", $time,`GPR_GET(3));
+ end
+ if (execute_insn == 32'h15_00_00_05)
+ begin
+ cycle_counter = 0;
+ $fdisplay(fgeneral, "%0t: l.nop reset counter", $time);
+ end
+ if (execute_insn == 32'h15_00_00_06)
+ begin
+ $fdisplay(fgeneral, "%0t: l.nop report cycle counter: %d", $time, cycle_counter);
+ `GPR_SET(11,cycle_counter[31:0]);
+ `GPR_SET(12,cycle_counter[63:32]);
+ end
+
+ if (execute_insn == 32'h15_00_00_0c)
+ begin
+ // Silent exit
+ $finish;
+
+ end
+
+ end // if (`EXECUTE_STAGE_ADV)
+ end
+
+ task mor1k_trace_print;
+ input [31:0] insn;
+ input [31:0] sr;
+ input [31:0] pc;
+ input flag;
+
+
+ reg rD_used;
+ reg [4:0] rD_num, rA_num, rB_num;
+ reg [15:0] imm_16bit;
+ reg [25:0] imm_26bit;
+ reg [31:0] signext_imm_16bit;
+
+ reg [1:80*8] insn_disas;
+ // Actual things happening
+ reg [15:0] regimm_chars;
+ reg [31:0] addr_result;
+ begin
+
+ // Get instruction info
+ mor1kx_insn_info(insn,rA_num,rB_num,rD_num,rD_used,imm_16bit,
+ imm_26bit,regimm_chars);
+
+ /* Sign-extend the 16-bit immediate to 32-bit so we can add it to other
+ 32-bit numbers and it should subtract if necessary */
+ signext_imm_16bit = {{16{imm_16bit[15]}},imm_16bit};
+
+ // Display useful line of stuff, like or1ksim trace
+ if (sr[`OR1K_SPR_SR_SM] === 1'b0)
+ begin
+ $fwrite(ftrace,"U ");
+ if(TRACE_TO_SCREEN)
+ $write("U ");
+ end
+ else
+ begin
+ $fwrite(ftrace,"S ");
+ if(TRACE_TO_SCREEN)
+ $write("S ");
+ end
+
+ // PC next
+ $fwrite(ftrace,"%08h: ", pc);
+ if(TRACE_TO_SCREEN)
+ $write("%08h: ", pc);
+
+ // Instruction raw
+ $fwrite(ftrace,"%08h ",insn);
+ if(TRACE_TO_SCREEN)
+ $write("%08h ",insn);
+
+ mor1k_insn_to_string(insn, insn_disas);
+
+ // Instruction, disassembled
+ $fwrite(ftrace,"%0s", insn_disas);
+ if(TRACE_TO_SCREEN)
+ $write("%0s", insn_disas);
+
+ for (regimm_chars=regimm_chars;
+ regimm_chars < 16; regimm_chars = regimm_chars + 1)
+ begin
+ $fwrite(ftrace," ");
+ if(TRACE_TO_SCREEN)
+ $write(" ");
+ end
+
+ if (rD_used)
+ begin
+ if (insn[`OR1K_OPCODE_SELECT]===`OR1K_OPCODE_MFSPR)
+ begin
+ // Wait 1 cycle for MFSPR result
+ @(posedge `CPU_clk);
+ $fwrite(ftrace,"r%0d",rD_num);
+ if(TRACE_TO_SCREEN)
+ $write("r%0d",rD_num);
+ end
+ else
+ begin
+ $fwrite(ftrace,"r%0d",rD_num);
+ if(TRACE_TO_SCREEN)
+ $write("r%0d",rD_num);
+ end // else: !if(insn[`OR1K_OPCODE_SELECT]===`OR1K_OPCODE_MFSPR)
+
+ // Tab 1 more if we're a single-number register
+ if (rD_num < 10) begin
+ $fwrite(ftrace,"\t\t");
+ if(TRACE_TO_SCREEN)
+ $write("\t\t");
+ end
+ else begin
+ $fwrite(ftrace,"\t");
+ if(TRACE_TO_SCREEN)
+ $write("\t");
+ end
+
+ // Finally write what ended up in the in rD
+ $fwrite(ftrace,"= %08h ",`GPR_GET(rD_num));
+ if(TRACE_TO_SCREEN)
+ $write("= %08h ",`GPR_GET(rD_num));
+ end
+ else if (insn[`OR1K_OPCODE_SELECT]===`OR1K_OPCODE_MTSPR)
+ begin
+ // Clobber imm_16bit here to calculate MTSPR
+ imm_16bit = imm_16bit | `GPR_GET(rA_num);
+ $fwrite(ftrace,"SPR[%04x] = %08h ", imm_16bit, `GPR_GET(rB_num));
+ if(TRACE_TO_SCREEN)
+ $write("SPR[%04x] = %08h ", imm_16bit, `GPR_GET(rB_num));
+
+ end // if (insn[`OR1K_OPCODE_SELECT]===`OR1K_OPCODE_MTSPR)
+ else if (insn[`OR1K_OPCODE_SELECT]>=`OR1K_OPCODE_SD &&
+ insn[`OR1K_OPCODE_SELECT]<=`OR1K_OPCODE_SH)
+ begin
+ addr_result = signext_imm_16bit + `GPR_GET(rA_num);
+ $fwrite(ftrace,"[%08h] = %08h ",addr_result[31:0],
+ `GPR_GET(rB_num));
+ if(TRACE_TO_SCREEN)
+ $write("[%08h] = %08h ",addr_result[31:0],
+ `GPR_GET(rB_num));
+ end
+ else
+ begin
+ // Skip destination field
+ $fwrite(ftrace,"\t\t\t ");
+ if(TRACE_TO_SCREEN)
+ $write("\t\t\t ");
+ end
+
+ /* Write flag */
+ $fwrite(ftrace,"flag: %0d", flag);
+ if(TRACE_TO_SCREEN)
+ $write("flag: %0d", flag);
+
+ /* End of line */
+ $fwrite(ftrace,"\n");
+ if(TRACE_TO_SCREEN)
+ $write("\n");
+
+ end
+ endtask // mor1k_trace_print
+
+ task mor1kx_insn_info;
+ input [31:0] insn;
+ output [4:0] rA_num;
+ output [4:0] rB_num;
+ output [4:0] rD_num;
+ output rD_used;
+ output [15:0] imm_16bit;
+ output [25:0] imm_26bit;
+
+ output [7:0] num_chars;
+
+ // To count how long disassembled immediates/regs
+ // are - what a pain!
+ reg rA_used, rB_used, imm_16bit_used,
+ imm_26bit_used;
+
+ reg [5:0] opcode;
+
+ reg opc_store;
+
+ begin
+
+ // Register numbers (D, A and B)
+ rD_num = insn[`OR1K_RD_POS];
+ rA_num = insn[`OR1K_RA_POS];
+ rB_num = insn[`OR1K_RB_POS];
+
+ opcode = insn[`OR1K_OPCODE_POS];
+
+
+ opc_store = (opcode==`OR1K_OPCODE_SD) ||
+ (opcode==`OR1K_OPCODE_SW) ||
+ (opcode==`OR1K_OPCODE_SB) ||
+ (opcode==`OR1K_OPCODE_SH);
+
+ case (opcode)
+ `OR1K_OPCODE_LWZ,
+ `OR1K_OPCODE_LBZ,
+ `OR1K_OPCODE_LBS,
+ `OR1K_OPCODE_LHZ,
+ `OR1K_OPCODE_LHS,
+ `OR1K_OPCODE_MFSPR,
+ `OR1K_OPCODE_MOVHI,
+ `OR1K_OPCODE_ADDI,
+ `OR1K_OPCODE_ADDIC,
+ `OR1K_OPCODE_ANDI,
+ `OR1K_OPCODE_ORI,
+ `OR1K_OPCODE_XORI,
+ `OR1K_OPCODE_MULI,
+ `OR1K_OPCODE_ALU,
+ `OR1K_OPCODE_SHRTI:
+ rD_used = 1;
+ default:
+ rD_used=0;
+ endcase // case (opcode)
+
+ case (opcode)
+ `OR1K_OPCODE_J ,
+ `OR1K_OPCODE_JAL ,
+ `OR1K_OPCODE_BNF ,
+ `OR1K_OPCODE_BF ,
+ `OR1K_OPCODE_NOP ,
+ `OR1K_OPCODE_MOVHI,
+ `OR1K_OPCODE_MACRC,
+ `OR1K_OPCODE_SYSTRAPSYNC,
+ `OR1K_OPCODE_RFE,
+ `OR1K_OPCODE_JR,
+ `OR1K_OPCODE_JALR:
+ /*
+ rD of store insns, is in rA field
+ `OR1K_OPCODE_SD,
+ `OR1K_OPCODE_SW,
+ `OR1K_OPCODE_SB,
+ `OR1K_OPCODE_SH
+ */
+ rA_used = 0;
+ default:
+ rA_used=1;
+ endcase // case (opcode)
+
+ case (opcode)
+ `OR1K_OPCODE_JR,
+ `OR1K_OPCODE_JALR,
+ `OR1K_OPCODE_MTSPR,
+ `OR1K_OPCODE_MAC,
+ `OR1K_OPCODE_MSB,
+ `OR1K_OPCODE_SD,
+ `OR1K_OPCODE_SW,
+ `OR1K_OPCODE_SB,
+ `OR1K_OPCODE_SH,
+ `OR1K_OPCODE_SF:
+ rB_used = 1;
+ `OR1K_OPCODE_ALU:
+ case(insn[`OR1K_ALU_OPC_SELECT])
+ `OR1K_ALU_OPC_EXTBH,
+ `OR1K_ALU_OPC_EXTW,
+ `OR1K_ALU_OPC_FFL1:
+ rB_used = 0;
+ default:
+ rB_used = 1;
+ endcase // case (insn[`OR1K_ALU_OPC_SELECT])
+ default:
+ rB_used = 0;
+ endcase // case (opcode)
+
+ case (opcode)
+ `OR1K_OPCODE_MOVHI,
+ `OR1K_OPCODE_NOP,
+ `OR1K_OPCODE_SD,
+ `OR1K_OPCODE_SW,
+ `OR1K_OPCODE_SB,
+ `OR1K_OPCODE_SH,
+ `OR1K_OPCODE_LD ,
+ `OR1K_OPCODE_LWZ ,
+ `OR1K_OPCODE_LWS ,
+ `OR1K_OPCODE_LBZ ,
+ `OR1K_OPCODE_LBS ,
+ `OR1K_OPCODE_LHZ ,
+ `OR1K_OPCODE_LHS ,
+ `OR1K_OPCODE_ADDI ,
+ `OR1K_OPCODE_ADDIC,
+ `OR1K_OPCODE_ANDI ,
+ `OR1K_OPCODE_ORI ,
+ `OR1K_OPCODE_XORI ,
+ `OR1K_OPCODE_MULI ,
+ `OR1K_OPCODE_MACI ,
+ `OR1K_OPCODE_SFIMM,
+ `OR1K_OPCODE_MTSPR,
+ `OR1K_OPCODE_MFSPR:
+ imm_16bit_used = 1;
+ default:
+ imm_16bit_used = 0;
+ endcase // case (opcode)
+
+ case (opcode)
+ `OR1K_OPCODE_J ,
+ `OR1K_OPCODE_JAL,
+ `OR1K_OPCODE_BNF,
+ `OR1K_OPCODE_BF:
+ imm_26bit_used = 1;
+ default:
+ imm_26bit_used = 0;
+ endcase
+
+ // Extract immediate
+ case (opcode)
+ `OR1K_OPCODE_SW,
+ `OR1K_OPCODE_SB,
+ `OR1K_OPCODE_SH,
+ `OR1K_OPCODE_SD,
+ `OR1K_OPCODE_MTSPR:
+ imm_16bit = {insn[25:21],insn[10:0]};
+ default:
+ imm_16bit = insn[15:0];
+ endcase // case (opcode)
+
+ imm_26bit = insn[25:0];
+
+ // Extra chars (commas, brackets)
+ case (opcode)
+/*
+ `OR1K_OPCODE_J :
+ num_chars = 0;
+ `OR1K_OPCODE_JAL :
+ num_chars = 0;
+ `OR1K_OPCODE_BNF :
+ num_chars = 0;
+ `OR1K_OPCODE_BF :
+ num_chars = 0;
+ `OR1K_OPCODE_MACRC:
+ num_chars = 0;
+ `OR1K_OPCODE_SYSTRAPSYNC:
+ num_chars = 0;
+ `OR1K_OPCODE_RFE:
+ num_chars = 0;
+ `OR1K_OPCODE_JR :
+ num_chars = 0;
+ `OR1K_OPCODE_JALR :
+ num_chars = 0;
+ `OR1K_OPCODE_CUST1:
+ num_chars = 0;
+ `OR1K_OPCODE_CUST2:
+ num_chars = 0;
+ `OR1K_OPCODE_CUST3:
+ num_chars = 0;
+ `OR1K_OPCODE_CUST4:
+ num_chars = 0;
+ `OR1K_OPCODE_NOP :
+ num_chars = 0;
+ */
+ `OR1K_OPCODE_MOVHI:
+ num_chars = 1;
+ `OR1K_OPCODE_MACI :
+ num_chars = 1;
+ `OR1K_OPCODE_LD :
+ num_chars = 3;
+ `OR1K_OPCODE_LWZ :
+ num_chars = 3;
+ `OR1K_OPCODE_LWS :
+ num_chars = 3;
+ `OR1K_OPCODE_LBZ :
+ num_chars = 3;
+ `OR1K_OPCODE_LBS :
+ num_chars = 3;
+ `OR1K_OPCODE_LHZ :
+ num_chars = 3;
+ `OR1K_OPCODE_LHS :
+ num_chars = 3;
+ `OR1K_OPCODE_ADDI :
+ num_chars = 2;
+ `OR1K_OPCODE_ADDIC:
+ num_chars = 2;
+ `OR1K_OPCODE_ANDI :
+ num_chars = 2;
+ `OR1K_OPCODE_ORI :
+ num_chars = 2;
+ `OR1K_OPCODE_XORI :
+ num_chars = 2;
+ `OR1K_OPCODE_MULI :
+ num_chars = 2;
+ `OR1K_OPCODE_MFSPR:
+ num_chars = 2;
+ `OR1K_OPCODE_SFIMM:
+ num_chars = 1;
+ `OR1K_OPCODE_MTSPR :
+ num_chars = 2;
+ `OR1K_OPCODE_MAC :
+ num_chars = 1;
+ `OR1K_OPCODE_MSB :
+ num_chars = 1;
+ `OR1K_OPCODE_SD :
+ num_chars = 3;
+ `OR1K_OPCODE_SW :
+ num_chars = 3;
+ `OR1K_OPCODE_SB :
+ num_chars = 3;
+ `OR1K_OPCODE_SH:
+ num_chars = 3;
+ `OR1K_OPCODE_ALU:
+ case(insn[`OR1K_ALU_OPC_SELECT])
+ `OR1K_ALU_OPC_EXTBH,
+ `OR1K_ALU_OPC_EXTW,
+ `OR1K_ALU_OPC_FFL1:
+ num_chars = 1;
+ default:
+ num_chars = 2;
+ endcase // case (insn[`OR1K_ALU_OPC_SELECT])
+ `OR1K_OPCODE_SF:
+ num_chars =1;
+ `OR1K_OPCODE_SHRTI:
+ /*
+ if (insn[5:0] < 6'h10)
+ num_chars = 5;
+ else
+ */
+ num_chars = 6;
+
+ default:
+ num_chars = 0;
+
+ endcase // case (opcode)
+
+
+ // Determine length of register/immediate
+ // disassembly in characters
+ if (rA_used)
+ num_chars = (rA_num > 9) ? num_chars + 3 :
+ num_chars + 2;
+
+ if (rB_used)
+ num_chars = (rB_num > 9) ? num_chars + 3 :
+ num_chars + 2;
+
+ if (rD_used)
+ num_chars = (rD_num > 9) ? num_chars + 3 :
+ num_chars + 2;
+
+ if (imm_16bit_used)
+ num_chars = num_chars + 6;
+
+ if (imm_26bit_used)
+ num_chars = num_chars + 9;
+
+ /*
+ $write("%b %b %b %b %b\n",rA_used, rB_used, rD_used, imm_16bit_used,
+ imm_26bit_used);
+ */
+ //$write("%0d\n",num_chars);
+
+ end
+ endtask // mor1k_insn_info
+
+
+
+
+
+ task mor1k_insn_to_string;
+ input [31:0] insn;
+ output [80*8:1] insnstring;
+
+ reg [5:0] opcode;
+
+ reg [25:0] j_imm;
+
+ reg [25:0] br_imm;
+
+ reg [31:0] rA_val, rB_val;
+
+ reg [3:0] alu_op;
+
+ reg [5:0] sf_op;
+
+ reg [5:0] xsync_op;
+
+ reg [4:0] rD_num, rA_num, rB_num;
+
+ reg [15:0] imm_16bit;
+ reg [15:0] imm_split16bit;
+
+
+ begin
+
+ // Instruction opcode
+ opcode = insn[`OR1K_OPCODE_POS];
+ // Immediates for jump or branch instructions
+ j_imm = insn[`OR1K_J_BR_IMM_POS];
+ br_imm = insn[`OR1K_J_BR_IMM_POS];
+ // Register numbers (D, A and B)
+ rD_num = insn[`OR1K_RD_POS];
+ rA_num = insn[`OR1K_RA_POS];
+ rB_num = insn[`OR1K_RB_POS];
+ // Bottom 16 bits when used as immediates in various instructions
+ imm_16bit = insn[15:0];
+ // Bottom 11 bits used as immediates for l.sX instructions
+
+ // Split 16-bit immediate for l.mtspr/l.sX instructions
+ imm_split16bit = {insn[25:21],insn[10:0]};
+ // ALU op for ALU instructions
+ alu_op = insn[`OR1K_ALU_OP_POS];
+
+
+ // Set flag op
+ sf_op = insn[`OR1K_SF_OP];
+
+ // Xsync/syscall/trap opcode
+ xsync_op = insn[`OR1K_XSYNC_OP_POS];
+
+ case (opcode)
+ `OR1K_OPCODE_J:
+ begin
+ $sformat(insnstring, "l.j 0x%07h", j_imm);
+ end
+
+ `OR1K_OPCODE_JAL:
+ begin
+ $sformat(insnstring, "l.jal 0x%07h", j_imm);
+ end
+
+ `OR1K_OPCODE_BNF:
+ begin
+ $sformat(insnstring, "l.bnf 0x%07h", br_imm);
+ end
+
+ `OR1K_OPCODE_BF:
+ begin
+ $sformat(insnstring, "l.bf 0x%07h", br_imm);
+ end
+
+ `OR1K_OPCODE_RFE:
+ begin
+ $sformat(insnstring, "l.rfe ");
+ end
+
+ `OR1K_OPCODE_JR:
+ begin
+ $sformat(insnstring, "l.jr r%0d",rB_num);
+ end
+
+ `OR1K_OPCODE_JALR:
+ begin
+ $sformat(insnstring, "l.jalr r%0d",rB_num);
+ end
+
+ `OR1K_OPCODE_LWZ:
+ begin
+ $sformat(insnstring, "l.lwz r%0d,0x%04h(r%0d)",rD_num,imm_16bit,rA_num);
+ end
+
+ `OR1K_OPCODE_LBZ:
+ begin
+ $sformat(insnstring, "l.lbz r%0d,0x%04h(r%0d)",rD_num,imm_16bit,rA_num);
+ end
+
+ `OR1K_OPCODE_LBS:
+ begin
+ $sformat(insnstring, "l.lbs r%0d,0x%04h(r%0d)",rD_num,imm_16bit,rA_num);
+ end
+
+ `OR1K_OPCODE_LHZ:
+ begin
+ $sformat(insnstring, "l.lhz r%0d,0x%04h(r%0d)",rD_num,imm_16bit,rA_num);
+ end
+
+ `OR1K_OPCODE_LHS:
+ begin
+ $sformat(insnstring, "l.lhs r%0d,0x%04h(r%0d)",rD_num,imm_16bit,rA_num);
+ end
+
+ `OR1K_OPCODE_SW:
+ begin
+ $sformat(insnstring, "l.sw 0x%04h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
+ end
+
+ `OR1K_OPCODE_SB:
+ begin
+ $sformat(insnstring, "l.sb 0x%04h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
+ end
+
+ `OR1K_OPCODE_SH:
+ begin
+ $sformat(insnstring, "l.sh 0x%04h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
+ end
+
+ `OR1K_OPCODE_MFSPR:
+ begin
+ $sformat(insnstring, "l.mfspr r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_MTSPR:
+ begin
+ $sformat(insnstring, "l.mtspr r%0d,r%0d,0x%04h",rA_num,rB_num,imm_split16bit);
+ end
+
+ `OR1K_OPCODE_MOVHI:
+ begin
+ if (!insn[16])begin
+ $sformat(insnstring, "l.movhi r%0d,0x%04h",rD_num,imm_16bit);
+ end
+ else
+ $sformat(insnstring, "l.macrc r%0d",rD_num);
+ end
+
+ `OR1K_OPCODE_ADDI:
+ begin
+ $sformat(insnstring, "l.addi r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_ADDIC:
+ begin
+ $sformat(insnstring, "l.addic r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_ANDI:
+ begin
+ $sformat(insnstring, "l.andi r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_ORI:
+ begin
+ $sformat(insnstring, "l.ori r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_XORI:
+ begin
+ $sformat(insnstring, "l.xori r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_MULI:
+ begin
+ $sformat(insnstring, "l.muli r%0d,r%0d,0x%04h",rD_num,rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_ALU:
+ begin
+ case(insn[`OR1K_ALU_OPC_SELECT])
+ `OR1K_ALU_OPC_ADD:
+ $sformat(insnstring, "l.add r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_ADDC:
+ $sformat(insnstring, "l.addc r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_SUB:
+ $sformat(insnstring, "l.sub r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_AND:
+ $sformat(insnstring, "l.and r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_OR:
+ $sformat(insnstring, "l.or r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_XOR:
+ $sformat(insnstring, "l.xor r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_MUL:
+ $sformat(insnstring, "l.mul r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_SHRT:
+ begin
+ case(insn[`OR1K_ALU_OPC_SECONDARY_SELECT])
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SLL:
+ $sformat(insnstring, "l.sll r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SRL:
+ $sformat(insnstring, "l.srl r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SRA:
+ $sformat(insnstring, "l.sra r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_ROR:
+ $sformat(insnstring, "l.ror r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ endcase // case (insn[`OR1K_ALU_OPC_SECONDARY_SELECT])
+ end
+ `OR1K_ALU_OPC_DIV:
+ $sformat(insnstring, "l.div r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_DIVU:
+ $sformat(insnstring, "l.divu r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_MULU:
+ $sformat(insnstring, "l.mulu r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_CMOV:
+ $sformat(insnstring, "l.cmov r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ `OR1K_ALU_OPC_FFL1:
+ begin
+ case(insn[8])
+ 0:
+ $sformat(insnstring, "l.ff1 r%0d,r%0d",rD_num,rA_num);
+ 1:
+ $sformat(insnstring, "l.fl1 r%0d,r%0d",rD_num,rA_num);
+ endcase // case (insn[8])
+ end
+
+ endcase // case (alu_op)
+ //$sformat(insnstring, "r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
+ end
+
+ `OR1K_OPCODE_SHRTI:
+ begin
+ case(insn[`OR1K_ALU_OPC_SECONDARY_SELECT])
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SLL:
+ $sformat(insnstring, "l.slli r%0d,r%0d,0x%01h",rD_num,rA_num,insn[5:0]);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SRL:
+ $sformat(insnstring, "l.srli r%0d,r%0d,0x%01h",rD_num,rA_num,insn[5:0]);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_SRA:
+ $sformat(insnstring, "l.srai r%0d,r%0d,0x%01h",rD_num,rA_num,insn[5:0]);
+ `OR1K_ALU_OPC_SECONDARY_SHRT_ROR:
+ $sformat(insnstring, "l.rori r%0d,r%0d,0x%01h",rD_num,rA_num,insn[5:0]);
+ endcase // case (insn[`OR1K_ALU_OPC_SECONDARY_SELECT])
+ //$sformat(insnstring, "r%0d,r%0d,0x%0h",rD_num,rA_num,insn[5:0]);
+ end // case: `OR1K_OPCODE_SHRTI
+
+ `OR1K_OPCODE_SFIMM:
+ begin
+ case(insn[`OR1K_COMP_OPC_SELECT])
+ `OR1K_COMP_OPC_EQ:
+ $sformat(insnstring, "l.sfeqi r%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_NE:
+ $sformat(insnstring, "l.sfnei r%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_GTU:
+ $sformat(insnstring, "l.sfgtuir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_GEU:
+ $sformat(insnstring, "l.sfgeuir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_LTU:
+ $sformat(insnstring, "l.sfltuir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_LEU:
+ $sformat(insnstring, "l.sfleuir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_GTS:
+ $sformat(insnstring, "l.sfgtsir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_GES:
+ $sformat(insnstring, "l.sfgesir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_LTS:
+ $sformat(insnstring, "l.sfltsir%0d,0x%04h",rA_num, imm_16bit);
+ `OR1K_COMP_OPC_LES:
+ $sformat(insnstring, "l.sflesir%0d,0x%04h",rA_num, imm_16bit);
+ endcase // case (sf_op[2:0])
+
+ //$sformat(insnstring, "r%0d,0x%0h",rA_num, imm_16bit);
+
+ end // case: `OR1K_OPCODE_SFXXI
+
+ `OR1K_OPCODE_SF:
+ begin
+ case(insn[`OR1K_COMP_OPC_SELECT])
+ `OR1K_COMP_OPC_EQ:
+ $sformat(insnstring, "l.sfeq r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_NE:
+ $sformat(insnstring, "l.sfne r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_GTU:
+ $sformat(insnstring, "l.sfgtu r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_GEU:
+ $sformat(insnstring, "l.sfgeu r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_LTU:
+ $sformat(insnstring, "l.sfltu r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_LEU:
+ $sformat(insnstring, "l.sfleu r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_GTS:
+ $sformat(insnstring, "l.sfgts r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_GES:
+ $sformat(insnstring, "l.sfges r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_LTS:
+ $sformat(insnstring, "l.sflts r%0d,r%0d",rA_num, rB_num);
+ `OR1K_COMP_OPC_LES:
+ $sformat(insnstring, "l.sfles r%0d,r%0d",rA_num, rB_num);
+ endcase // case (sf_op[2:0])
+ //$sformat(insnstring, "r%0d,r%0d",rA_num, rB_num);
+
+ end
+
+ `OR1K_OPCODE_MACI:
+ begin
+ $sformat(insnstring, "l.maci r%0d,0x%04h",rA_num,imm_16bit);
+ end
+
+ `OR1K_OPCODE_NOP:
+ begin
+ $sformat(insnstring, "l.nop 0x%04h",imm_16bit);
+ end
+
+ `OR1K_OPCODE_SYSTRAPSYNC:
+ begin
+ case (insn[`OR1K_SYSTRAPSYNC_OPC_SELECT])
+ `OR1K_SYSTRAPSYNC_OPC_SYSCALL:
+ $sformat(insnstring, "l.sys 0x%04h",imm_16bit);
+ `OR1K_SYSTRAPSYNC_OPC_TRAP:
+ $sformat(insnstring, "l.trap 0x%04h",imm_16bit);
+ `OR1K_SYSTRAPSYNC_OPC_MSYNC:
+ $sformat(insnstring, "l.msync");
+ `OR1K_SYSTRAPSYNC_OPC_PSYNC:
+ $sformat(insnstring, "l.psync");
+ `OR1K_SYSTRAPSYNC_OPC_CSYNC:
+ $sformat(insnstring, "l.csync");
+ endcase // case (insn[`OR1K_SYSTRAPSYNC_OPC_SELECT])
+ end
+ default:
+ begin
+ $sformat(insnstring, "%t: Unknown opcode 0x%0h",$time,opcode);
+ $sformat(insnstring, "%t: Unknown opcode 0x%0h",$time,opcode);
+ end
+
+ endcase // case (opcode)
+
+ end
+ endtask // mor1k_insn_to_string
+
+endmodule // mor1kx_module
Please sign in to comment.
Something went wrong with that request. Please try again.