mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
		
						commit
						3618a39087
					
				@ -38,6 +38,7 @@
 | 
			
		||||
`define U_SUPPORTED ((`MISA >> 20) % 2 == 1)
 | 
			
		||||
`define ZCSR_SUPPORTED 1
 | 
			
		||||
`define ZCOUNTERS_SUPPORTED 1
 | 
			
		||||
`define COUNTERS 31
 | 
			
		||||
// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21
 | 
			
		||||
//`define N_SUPPORTED ((MISA >> 13) % 2 == 1)
 | 
			
		||||
`define N_SUPPORTED 0
 | 
			
		||||
 | 
			
		||||
@ -27,9 +27,9 @@ def test_config(config, print_res=True):
 | 
			
		||||
    cmd = "echo 'quit' | vsim -do wally-busybear.do -c >" + logname
 | 
			
		||||
    os.system(cmd)
 | 
			
		||||
    # check for success.  grep returns 0 if found, 1 if not found
 | 
			
		||||
    passed = search_log_for_text("no more .* to read", logname)
 | 
			
		||||
    passed = search_log_for_text("# loaded 100000 instructions", logname)
 | 
			
		||||
  else:
 | 
			
		||||
    cmd = "vsim -c >" + logname +" <<!\ndo wally-pipelined-batch-parallel.do ../config/" + config + " " + config + "\n!\n"
 | 
			
		||||
    cmd = "vsim -c >" + logname +" <<!\ndo wally-pipelined-batch.do ../config/" + config + " " + config + "\n!\n"
 | 
			
		||||
    print(cmd)
 | 
			
		||||
    os.system(cmd)
 | 
			
		||||
    # check for success.  grep returns 0 if found, 1 if not found
 | 
			
		||||
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
# wally-pipelined-batch.do 
 | 
			
		||||
#
 | 
			
		||||
# Modification by Oklahoma State University & Harvey Mudd College
 | 
			
		||||
# Use with Testbench 
 | 
			
		||||
# James Stine, 2008; David Harris 2021
 | 
			
		||||
# Go Cowboys!!!!!!
 | 
			
		||||
#
 | 
			
		||||
# Takes 1:10 to run RV64IC tests using gui
 | 
			
		||||
# 11 seconds to run batch mode
 | 
			
		||||
 | 
			
		||||
# Use this wally-pipelined.do file to run this example.
 | 
			
		||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
 | 
			
		||||
#     do wally-pipelined.do ../config/rv64ic
 | 
			
		||||
# or, to run from a shell, type the following at the shell prompt:
 | 
			
		||||
#     vsim -c -do wally-pipelined.do ../config/rv64ic
 | 
			
		||||
# (omit the "-c" to see the GUI while running from the shell)
 | 
			
		||||
 | 
			
		||||
onbreak {resume}
 | 
			
		||||
 | 
			
		||||
# create library
 | 
			
		||||
if [file exists work$2] {
 | 
			
		||||
    vdel -lib work$2 -all
 | 
			
		||||
}
 | 
			
		||||
vlib work$2
 | 
			
		||||
 | 
			
		||||
# compile source files
 | 
			
		||||
# suppress spurious warnngs about 
 | 
			
		||||
# "Extra checking for conflicts with always_comb done at vopt time"
 | 
			
		||||
# because vsim will run vopt
 | 
			
		||||
vlog +incdir+$1 ../testbench/testbench-imperas.sv ../testbench/function_radix.sv ../src/*/*.sv -suppress 2583
 | 
			
		||||
 | 
			
		||||
# start and run simulation
 | 
			
		||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
 | 
			
		||||
vopt work.testbench -o workopt
 | 
			
		||||
vsim workopt
 | 
			
		||||
 | 
			
		||||
run -all
 | 
			
		||||
quit
 | 
			
		||||
@ -17,10 +17,10 @@
 | 
			
		||||
onbreak {resume}
 | 
			
		||||
 | 
			
		||||
# create library
 | 
			
		||||
if [file exists work] {
 | 
			
		||||
    vdel -all
 | 
			
		||||
if [file exists work_$2] {
 | 
			
		||||
    vdel -lib work_$2 -all
 | 
			
		||||
}
 | 
			
		||||
vlib work
 | 
			
		||||
vlib work_$2
 | 
			
		||||
 | 
			
		||||
# compile source files
 | 
			
		||||
# suppress spurious warnngs about 
 | 
			
		||||
@ -28,15 +28,16 @@ vlib work
 | 
			
		||||
# because vsim will run vopt
 | 
			
		||||
 | 
			
		||||
# default to config/rv64ic, but allow this to be overridden at the command line.  For example:
 | 
			
		||||
# do wally-pipelined-batch.do ../config/rv32ic
 | 
			
		||||
# do wally-pipelined-batch.do ../config/rv32ic rv32ic
 | 
			
		||||
switch $argc {
 | 
			
		||||
    0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
 | 
			
		||||
    1 {vlog +incdir+$1 ../testbench/testbench-imperas.sv  ../src/*/*.sv -suppress 2583}
 | 
			
		||||
    2 {vlog -work work_$2 +incdir+$1 ../testbench/testbench-imperas.sv  ../src/*/*.sv -suppress 2583}
 | 
			
		||||
}
 | 
			
		||||
# start and run simulation
 | 
			
		||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
 | 
			
		||||
vopt work.testbench -o workopt 
 | 
			
		||||
vsim workopt
 | 
			
		||||
vopt work_$2.testbench -work work_$2 -o workopt_$2
 | 
			
		||||
vsim -lib work_$2 workopt_$2
 | 
			
		||||
 | 
			
		||||
run -all
 | 
			
		||||
quit
 | 
			
		||||
 | 
			
		||||
@ -106,6 +106,7 @@ module testbench_busybear();
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  integer warningCount = 0;
 | 
			
		||||
  integer instrs;
 | 
			
		||||
 | 
			
		||||
  //logic[63:0] adrTranslation[4:0];
 | 
			
		||||
  //string translationType[4:0] = {"rf", "writeAdr", "PCW", "PC", "readAdr"};
 | 
			
		||||
@ -249,6 +250,15 @@ module testbench_busybear();
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  always @(dut.hart.priv.csr.genblk1.csrm.MCAUSE_REGW) begin
 | 
			
		||||
    if (dut.hart.priv.csr.genblk1.csrm.MCAUSE_REGW == 5 && instrs != 0) begin
 | 
			
		||||
      $display("!!!!!!illegal (physical) memory access !!!!!!!!!!");
 | 
			
		||||
      $display("(as a reminder, MCAUSE and MEPC are set by this)");
 | 
			
		||||
      $display("at %0t ps, instr %0d, HADDR %x", $time, instrs, HADDR);
 | 
			
		||||
      `ERROR
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  `define CHECK_CSR2(CSR, PATH) \
 | 
			
		||||
    string CSR; \
 | 
			
		||||
    logic [63:0] expected``CSR``; \
 | 
			
		||||
@ -340,7 +350,6 @@ module testbench_busybear();
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  string PCtext, PCtext2;
 | 
			
		||||
  integer instrs;
 | 
			
		||||
  initial begin
 | 
			
		||||
    instrs = 0;
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										305
									
								
								wally-pipelined/testbench/testbench-privileged.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								wally-pipelined/testbench/testbench-privileged.sv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,305 @@
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
// testbench-privileged.sv
 | 
			
		||||
//
 | 
			
		||||
// Written: Ben Bracker (bbracker@hmc.edu) 11 Feb. 2021, Tiny Modifications: Domenico Ottolia (dottolia@hmc.edu) 16 Mar. 2021 
 | 
			
		||||
// Based on: testbench-imperas.sv by David Harris
 | 
			
		||||
//
 | 
			
		||||
// Purpose: Wally Testbench and helper modules
 | 
			
		||||
//          Applies test programs meant to test peripherals
 | 
			
		||||
//          These tests assume the processor itself is already working!
 | 
			
		||||
// 
 | 
			
		||||
// A component of the Wally configurable RISC-V project.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
 | 
			
		||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 | 
			
		||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 | 
			
		||||
// is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 | 
			
		||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 | 
			
		||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 | 
			
		||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
`include "wally-config.vh"
 | 
			
		||||
 | 
			
		||||
module testbench();
 | 
			
		||||
  logic        clk;
 | 
			
		||||
  logic        reset;
 | 
			
		||||
 | 
			
		||||
  int test, i, errors, totalerrors;
 | 
			
		||||
  logic [31:0] sig32[0:10000];
 | 
			
		||||
  logic [`XLEN-1:0] signature[0:10000];
 | 
			
		||||
  logic [`XLEN-1:0] testadr;
 | 
			
		||||
  string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
 | 
			
		||||
  logic [31:0] InstrW;
 | 
			
		||||
  logic [`XLEN-1:0] meminit;
 | 
			
		||||
 | 
			
		||||
  string tests[] = '{                 
 | 
			
		||||
    "privileged/WALLY-CAUSE-64", "0"
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  logic [`AHBW-1:0] HRDATAEXT;
 | 
			
		||||
  logic             HREADYEXT, HRESPEXT;
 | 
			
		||||
  logic [31:0]      HADDR;
 | 
			
		||||
  logic [`AHBW-1:0] HWDATA;
 | 
			
		||||
  logic             HWRITE;
 | 
			
		||||
  logic [2:0]       HSIZE;
 | 
			
		||||
  logic [2:0]       HBURST;
 | 
			
		||||
  logic [3:0]       HPROT;
 | 
			
		||||
  logic [1:0]       HTRANS;
 | 
			
		||||
  logic             HMASTLOCK;
 | 
			
		||||
  logic             HCLK, HRESETn;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // pick tests based on modes supported
 | 
			
		||||
  // *** actually I no longer support this
 | 
			
		||||
  // would need to put this back in if you wanted to test anything other than rv64i
 | 
			
		||||
 | 
			
		||||
  string signame, memfilename;
 | 
			
		||||
 | 
			
		||||
  logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
 | 
			
		||||
  logic UARTSin, UARTSout;
 | 
			
		||||
 | 
			
		||||
  // instantiate device to be tested
 | 
			
		||||
  assign GPIOPinsIn = 0;
 | 
			
		||||
  assign UARTSin = 1;
 | 
			
		||||
  assign HREADYEXT = 1;
 | 
			
		||||
  assign HRESPEXT = 0;
 | 
			
		||||
  assign HRDATAEXT = 0;
 | 
			
		||||
 | 
			
		||||
  wallypipelinedsoc dut(.*); 
 | 
			
		||||
 | 
			
		||||
  // Track names of instructions
 | 
			
		||||
  instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
 | 
			
		||||
                dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
 | 
			
		||||
                dut.hart.ifu.InstrM,  InstrW,
 | 
			
		||||
                InstrDName, InstrEName, InstrMName, InstrWName);
 | 
			
		||||
 | 
			
		||||
  // initialize tests
 | 
			
		||||
  initial
 | 
			
		||||
    begin
 | 
			
		||||
      test = 0;
 | 
			
		||||
      totalerrors = 0;
 | 
			
		||||
      testadr = 0;
 | 
			
		||||
      // fill memory with defined values to reduce Xs in simulation
 | 
			
		||||
      if (`XLEN == 32) meminit = 32'hFEDC0123;
 | 
			
		||||
      else meminit = 64'hFEDCBA9876543210;
 | 
			
		||||
      for (i=0; i<=65535; i = i+1) begin
 | 
			
		||||
        //dut.imem.RAM[i] = meminit;
 | 
			
		||||
       // dut.uncore.RAM[i] = meminit;
 | 
			
		||||
      end
 | 
			
		||||
      // read test vectors into memory
 | 
			
		||||
      memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
 | 
			
		||||
      $readmemh(memfilename, dut.imem.RAM);
 | 
			
		||||
      $readmemh(memfilename, dut.uncore.dtim.RAM);
 | 
			
		||||
      reset = 1; # 22; reset = 0;
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  // generate clock to sequence tests
 | 
			
		||||
  always
 | 
			
		||||
    begin
 | 
			
		||||
      clk = 1; # 5; clk = 0; # 5;
 | 
			
		||||
    end
 | 
			
		||||
   
 | 
			
		||||
  // check results
 | 
			
		||||
  always @(negedge clk)
 | 
			
		||||
    begin    
 | 
			
		||||
      if (dut.hart.priv.EcallFaultM && 
 | 
			
		||||
          (dut.hart.ieu.dp.regf.rf[3] == 1 || (dut.hart.ieu.dp.regf.we3 && dut.hart.ieu.dp.regf.a3 == 3 && dut.hart.ieu.dp.regf.wd3 == 1))) begin
 | 
			
		||||
        $display("Code ended with ecall with gp = 1");
 | 
			
		||||
        #60; // give time for instructions in pipeline to finish
 | 
			
		||||
        // clear signature to prevent contamination from previous tests
 | 
			
		||||
        for(i=0; i<10000; i=i+1) begin
 | 
			
		||||
          sig32[i] = 'bx;
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        // read signature, reformat in 64 bits if necessary
 | 
			
		||||
        signame = {"../../imperas-riscv-tests/work/", tests[test], ".signature.output"};
 | 
			
		||||
        $readmemh(signame, sig32);
 | 
			
		||||
        i = 0;
 | 
			
		||||
        while (i < 10000) begin
 | 
			
		||||
          if (`XLEN == 32) begin
 | 
			
		||||
            signature[i] = sig32[i];
 | 
			
		||||
            i = i+1;
 | 
			
		||||
          end else begin
 | 
			
		||||
            signature[i/2] = {sig32[i+1], sig32[i]};
 | 
			
		||||
            i = i + 2;
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        // Check errors
 | 
			
		||||
        i = 0;
 | 
			
		||||
        errors = 0;
 | 
			
		||||
        if (`XLEN == 32)
 | 
			
		||||
          testadr = (`TIMBASE+tests[test+1].atohex())/4;
 | 
			
		||||
        else
 | 
			
		||||
          testadr = (`TIMBASE+tests[test+1].atohex())/8;
 | 
			
		||||
        /* verilator lint_off INFINITELOOP */
 | 
			
		||||
        while (signature[i] !== 'bx) begin
 | 
			
		||||
          //$display("signature[%h] = %h", i, signature[i]);
 | 
			
		||||
          if (signature[i] !== dut.uncore.dtim.RAM[testadr+i]) begin
 | 
			
		||||
            if (signature[i+4] !== 'bx || signature[i] !== 32'hFFFFFFFF) begin
 | 
			
		||||
              // report errors unless they are garbage at the end of the sim
 | 
			
		||||
              // kind of hacky test for garbage right now
 | 
			
		||||
              errors = errors+1;
 | 
			
		||||
              $display("  Error on test %s result %d: adr = %h sim = %h, signature = %h", 
 | 
			
		||||
                    tests[test], i, (testadr+i)*`XLEN/8, dut.uncore.dtim.RAM[testadr+i], signature[i]);
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          i = i + 1;
 | 
			
		||||
        end
 | 
			
		||||
        /* verilator lint_on INFINITELOOP */
 | 
			
		||||
        if (errors == 0) $display("%s succeeded.  Brilliant!!!", tests[test]);
 | 
			
		||||
        else begin
 | 
			
		||||
          $display("%s failed with %d errors. :(", tests[test], errors);
 | 
			
		||||
          totalerrors = totalerrors+1;
 | 
			
		||||
        end
 | 
			
		||||
        test = test + 2;
 | 
			
		||||
        if (test == tests.size()) begin
 | 
			
		||||
          if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
 | 
			
		||||
          else $display("FAIL: %d test programs had errors", totalerrors);
 | 
			
		||||
          $stop;
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
          memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
 | 
			
		||||
          $readmemh(memfilename, dut.imem.RAM);
 | 
			
		||||
          $readmemh(memfilename, dut.uncore.dtim.RAM);
 | 
			
		||||
          $display("Read memfile %s", memfilename);
 | 
			
		||||
          reset = 1; # 17; reset = 0;
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
/* verilator lint_on STMTDLY */
 | 
			
		||||
/* verilator lint_on WIDTH */
 | 
			
		||||
 | 
			
		||||
module instrTrackerTB(
 | 
			
		||||
  input  logic            clk, reset, FlushE,
 | 
			
		||||
  input  logic [31:0]     InstrD,
 | 
			
		||||
  input  logic [31:0]     InstrE, InstrM,
 | 
			
		||||
  output logic [31:0]     InstrW,
 | 
			
		||||
  output string           InstrDName, InstrEName, InstrMName, InstrWName);
 | 
			
		||||
        
 | 
			
		||||
  // stage Instr to Writeback for visualization
 | 
			
		||||
  flopr  #(32) InstrWReg(clk, reset, InstrM, InstrW);
 | 
			
		||||
 | 
			
		||||
  instrNameDecTB ddec(InstrD, InstrDName);
 | 
			
		||||
  instrNameDecTB edec(InstrE, InstrEName);
 | 
			
		||||
  instrNameDecTB mdec(InstrM, InstrMName);
 | 
			
		||||
  instrNameDecTB wdec(InstrW, InstrWName);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
// decode the instruction name, to help the test bench
 | 
			
		||||
module instrNameDecTB(
 | 
			
		||||
  input  logic [31:0] instr,
 | 
			
		||||
  output string       name);
 | 
			
		||||
 | 
			
		||||
  logic [6:0] op;
 | 
			
		||||
  logic [2:0] funct3;
 | 
			
		||||
  logic [6:0] funct7;
 | 
			
		||||
  logic [11:0] imm;
 | 
			
		||||
 | 
			
		||||
  assign op = instr[6:0];
 | 
			
		||||
  assign funct3 = instr[14:12];
 | 
			
		||||
  assign funct7 = instr[31:25];
 | 
			
		||||
  assign imm = instr[31:20];
 | 
			
		||||
 | 
			
		||||
  // it would be nice to add the operands to the name 
 | 
			
		||||
  // create another variable called decoded
 | 
			
		||||
 | 
			
		||||
  always_comb 
 | 
			
		||||
    casez({op, funct3})
 | 
			
		||||
      10'b0000000_000: name = "BAD";
 | 
			
		||||
      10'b0000011_000: name = "LB";
 | 
			
		||||
      10'b0000011_001: name = "LH";
 | 
			
		||||
      10'b0000011_010: name = "LW";
 | 
			
		||||
      10'b0000011_011: name = "LD";
 | 
			
		||||
      10'b0000011_100: name = "LBU";
 | 
			
		||||
      10'b0000011_101: name = "LHU";
 | 
			
		||||
      10'b0000011_110: name = "LWU";
 | 
			
		||||
      10'b0010011_000: if (instr[31:15] == 0 && instr[11:7] ==0) name = "NOP/FLUSH";
 | 
			
		||||
                       else                                      name = "ADDI";
 | 
			
		||||
      10'b0010011_001: if (funct7[6:1] == 6'b000000) name = "SLLI";
 | 
			
		||||
                       else                      name = "ILLEGAL";
 | 
			
		||||
      10'b0010011_010: name = "SLTI";
 | 
			
		||||
      10'b0010011_011: name = "SLTIU";
 | 
			
		||||
      10'b0010011_100: name = "XORI";
 | 
			
		||||
      10'b0010011_101: if (funct7[6:1] == 6'b000000)      name = "SRLI";
 | 
			
		||||
                       else if (funct7[6:1] == 6'b010000) name = "SRAI"; 
 | 
			
		||||
                       else                           name = "ILLEGAL"; 
 | 
			
		||||
      10'b0010011_110: name = "ORI";
 | 
			
		||||
      10'b0010011_111: name = "ANDI";
 | 
			
		||||
      10'b0010111_???: name = "AUIPC";
 | 
			
		||||
      10'b0100011_000: name = "SB";
 | 
			
		||||
      10'b0100011_001: name = "SH";
 | 
			
		||||
      10'b0100011_010: name = "SW";
 | 
			
		||||
      10'b0100011_011: name = "SD";
 | 
			
		||||
      10'b0011011_000: name = "ADDIW";
 | 
			
		||||
      10'b0011011_001: name = "SLLIW";
 | 
			
		||||
      10'b0011011_101: if      (funct7 == 7'b0000000) name = "SRLIW";
 | 
			
		||||
                       else if (funct7 == 7'b0100000) name = "SRAIW";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0111011_000: if      (funct7 == 7'b0000000) name = "ADDW";
 | 
			
		||||
                       else if (funct7 == 7'b0100000) name = "SUBW";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0111011_001: name = "SLLW";
 | 
			
		||||
      10'b0111011_101: if      (funct7 == 7'b0000000) name = "SRLW";
 | 
			
		||||
                       else if (funct7 == 7'b0100000) name = "SRAW";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_000: if      (funct7 == 7'b0000000) name = "ADD";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "MUL";
 | 
			
		||||
                       else if (funct7 == 7'b0100000) name = "SUB"; 
 | 
			
		||||
                       else                           name = "ILLEGAL"; 
 | 
			
		||||
      10'b0110011_001: if      (funct7 == 7'b0000000) name = "SLL";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "MULH";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_010: if      (funct7 == 7'b0000000) name = "SLT";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "MULHSU";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_011: if      (funct7 == 7'b0000000) name = "SLTU";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "DIV";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_100: if      (funct7 == 7'b0000000) name = "XOR";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "MUL";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_101: if      (funct7 == 7'b0000000) name = "SRL";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "DIVU";
 | 
			
		||||
                       else if (funct7 == 7'b0100000) name = "SRA";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_110: if      (funct7 == 7'b0000000) name = "OR";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "REM";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110011_111: if      (funct7 == 7'b0000000) name = "AND";
 | 
			
		||||
                       else if (funct7 == 7'b0000001) name = "REMU";
 | 
			
		||||
                       else                           name = "ILLEGAL";
 | 
			
		||||
      10'b0110111_???: name = "LUI";
 | 
			
		||||
      10'b1100011_000: name = "BEQ";
 | 
			
		||||
      10'b1100011_001: name = "BNE";
 | 
			
		||||
      10'b1100011_100: name = "BLT";
 | 
			
		||||
      10'b1100011_101: name = "BGE";
 | 
			
		||||
      10'b1100011_110: name = "BLTU";
 | 
			
		||||
      10'b1100011_111: name = "BGEU";
 | 
			
		||||
      10'b1100111_000: name = "JALR";
 | 
			
		||||
      10'b1101111_???: name = "JAL";
 | 
			
		||||
      10'b1110011_000: if      (imm == 0) name = "ECALL";
 | 
			
		||||
                       else if (imm == 1) name = "EBREAK";
 | 
			
		||||
                       else if (imm == 2) name = "URET";
 | 
			
		||||
                       else if (imm == 258) name = "SRET";
 | 
			
		||||
                       else if (imm == 770) name = "MRET";
 | 
			
		||||
                       else              name = "ILLEGAL";
 | 
			
		||||
      10'b1110011_001: name = "CSRRW";
 | 
			
		||||
      10'b1110011_010: name = "CSRRS";
 | 
			
		||||
      10'b1110011_011: name = "CSRRC";
 | 
			
		||||
      10'b1110011_101: name = "CSRRWI";
 | 
			
		||||
      10'b1110011_110: name = "CSRRSI";
 | 
			
		||||
      10'b1110011_111: name = "CSRRCI";
 | 
			
		||||
      10'b0001111_???: name = "FENCE";
 | 
			
		||||
      default:         name = "ILLEGAL";
 | 
			
		||||
    endcase
 | 
			
		||||
endmodule
 | 
			
		||||
							
								
								
									
										22
									
								
								wally-pipelined/testgen/privileged/run.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								wally-pipelined/testgen/privileged/run.sh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
clear
 | 
			
		||||
printf "\n\n#####\nStarting tests for $1\n#####\n\n"
 | 
			
		||||
 | 
			
		||||
if [[ "$2" != "-simonly" ]]
 | 
			
		||||
then
 | 
			
		||||
	cd ~/riscv-wally/wally-pipelined/testgen/privileged
 | 
			
		||||
	python3 "testgen-$1.py"
 | 
			
		||||
	printf "\n\n#####\nRan testgen-$1.py Making...\n#####\n\n\n"
 | 
			
		||||
 | 
			
		||||
	cd ~/riscv-wally/imperas-riscv-tests
 | 
			
		||||
	make privileged
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ "$2" == "-sim" || "$2" == "-simonly" ]]
 | 
			
		||||
then
 | 
			
		||||
	printf "\n\n\n#####\nSimulating!\n#####\n\n"
 | 
			
		||||
	cd ~/riscv-wally/wally-pipelined/regression
 | 
			
		||||
	vsim -do wally-privileged.do -c
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cd ~/riscv-wally
 | 
			
		||||
printf "\n\n\n#####\nDone!\n#####\n\n"
 | 
			
		||||
							
								
								
									
										270
									
								
								wally-pipelined/testgen/privileged/testgen-CAUSE.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								wally-pipelined/testgen/privileged/testgen-CAUSE.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,270 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
##################################
 | 
			
		||||
# testgen-CAUSE.py
 | 
			
		||||
#
 | 
			
		||||
# dottolia@hmc.edu 16 Mar 2021
 | 
			
		||||
#
 | 
			
		||||
# Generate directed and random test vectors for RISC-V Design Validation.
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
##################################
 | 
			
		||||
# libraries
 | 
			
		||||
##################################
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from random import randint 
 | 
			
		||||
from random import seed
 | 
			
		||||
from enum import Enum
 | 
			
		||||
from random import getrandbits
 | 
			
		||||
 | 
			
		||||
##################################
 | 
			
		||||
# functions
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
# def computeExpected(a, b, test):
 | 
			
		||||
#   if (test == "ADD"):
 | 
			
		||||
#     return a + b
 | 
			
		||||
#   elif (test == "SUB"):
 | 
			
		||||
#     return a - b
 | 
			
		||||
#   else:
 | 
			
		||||
#     die("bad test name ", test)
 | 
			
		||||
#   #  exit(1)
 | 
			
		||||
 | 
			
		||||
def randRegs():
 | 
			
		||||
  reg1 = randint(1,30)
 | 
			
		||||
  reg2 = randint(1,30)
 | 
			
		||||
  reg3 = randint(1,30)
 | 
			
		||||
  if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
 | 
			
		||||
    return randRegs()
 | 
			
		||||
  else:
 | 
			
		||||
      return reg1, reg2, reg3
 | 
			
		||||
 | 
			
		||||
def writeVectors(storecmd):  
 | 
			
		||||
  global testnum
 | 
			
		||||
  reg1, reg2, reg3 = randRegs()
 | 
			
		||||
 | 
			
		||||
  # t5 gets written with mtvec?
 | 
			
		||||
 | 
			
		||||
  # lines = f"""
 | 
			
		||||
 | 
			
		||||
  # li x{reg1}, 0
 | 
			
		||||
  # csrwi mtvec, 80002000
 | 
			
		||||
  # .data 00000000
 | 
			
		||||
  # j _done{testnum}
 | 
			
		||||
 | 
			
		||||
  # _trap{testnum}:
 | 
			
		||||
  # csrrs x{reg1}, mcause, x0
 | 
			
		||||
  # ecall
 | 
			
		||||
 | 
			
		||||
  # _done{testnum}:
 | 
			
		||||
  # add x0, x0, x0
 | 
			
		||||
  # """
 | 
			
		||||
 | 
			
		||||
  #lines = 
 | 
			
		||||
 | 
			
		||||
  lines = f"""
 | 
			
		||||
  j _setup
 | 
			
		||||
  csrrs x31, mcause, x0
 | 
			
		||||
  ecall
 | 
			
		||||
 | 
			
		||||
  _setup:
 | 
			
		||||
  li x2, 0x80000004
 | 
			
		||||
  csrrw x0, mtvec, x2
 | 
			
		||||
 | 
			
		||||
  """
 | 
			
		||||
  f.write(lines)
 | 
			
		||||
 | 
			
		||||
  # User Software Interrupt
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x3, 0x8000000
 | 
			
		||||
    {storecmd} x2, 0(x3)
 | 
			
		||||
  """, storecmd, True, 0, "u")
 | 
			
		||||
 | 
			
		||||
  # Supervisor Software Interrupt
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x3, 0x8000000
 | 
			
		||||
    {storecmd} x2, 0(x3)
 | 
			
		||||
  """, storecmd, True, 0, "s")
 | 
			
		||||
 | 
			
		||||
  # Machine Software Interrupt
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x3, 0x8000000
 | 
			
		||||
    {storecmd} x2, 0(x3)
 | 
			
		||||
  """, storecmd, True, 3)
 | 
			
		||||
 | 
			
		||||
  # User Timer Interrupt
 | 
			
		||||
  #write(f"""
 | 
			
		||||
  #  lw x2, mtimecmp
 | 
			
		||||
  #  {storecmd} x2, mtimecmp
 | 
			
		||||
  #""", storecmd, True, 4, "u")
 | 
			
		||||
 | 
			
		||||
 # # Supervisor Timer Interrupt
 | 
			
		||||
  #write(f"""
 | 
			
		||||
  #  lw x2, mtimecmp
 | 
			
		||||
  #  {storecmd} x2, mtimecmp
 | 
			
		||||
  #""", storecmd, True, 5, "s")
 | 
			
		||||
 | 
			
		||||
  # Machine Timer Interrupt
 | 
			
		||||
  #write(f"""
 | 
			
		||||
  #  lw x2, mtimecmp
 | 
			
		||||
  #  {storecmd} x2, mtimecmp
 | 
			
		||||
  #""", storecmd, True, 6)
 | 
			
		||||
 | 
			
		||||
  # User external interrupt True, 8
 | 
			
		||||
  # Supervisor external interrupt True, 9
 | 
			
		||||
 | 
			
		||||
  # Instr Addr Misalign
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x2, 0x00000000
 | 
			
		||||
    lw x3, 11(x2)
 | 
			
		||||
  """, storecmd, False, 0)
 | 
			
		||||
 | 
			
		||||
  # Instr Access Fault False, 1
 | 
			
		||||
  # Not possible in machine mode, because we can access all memory
 | 
			
		||||
 | 
			
		||||
  # Illegal Instruction
 | 
			
		||||
  write(f"""
 | 
			
		||||
    .data 00000000
 | 
			
		||||
  """, storecmd, False, 2)
 | 
			
		||||
 | 
			
		||||
  # Breakpoint
 | 
			
		||||
  write(f"""
 | 
			
		||||
    ebreak
 | 
			
		||||
  """, storecmd, False, 3)
 | 
			
		||||
 | 
			
		||||
  # Load Addr Misalign
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x2, 0x00000000
 | 
			
		||||
    lw x3, 11(x2)
 | 
			
		||||
  """, storecmd, False, 4)
 | 
			
		||||
 | 
			
		||||
  # Load Access Fault False, 5
 | 
			
		||||
    # Not possible in machine mode, because we can access all memory
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # Store/AMO address misaligned
 | 
			
		||||
  write(f"""
 | 
			
		||||
    li x2, 0x00000000
 | 
			
		||||
    {storecmd} x3, 11(x2)
 | 
			
		||||
  """, storecmd, False, 6)
 | 
			
		||||
 | 
			
		||||
  # Store/AMO access fault False, 7
 | 
			
		||||
  # Not possible in machine mode, because we can access all memory
 | 
			
		||||
 | 
			
		||||
  # Environment call from U-mode
 | 
			
		||||
  # Environment call from S-mode
 | 
			
		||||
 | 
			
		||||
def write(lines, storecmd, interrupt, code, mode = "m"):
 | 
			
		||||
  global testnum
 | 
			
		||||
 | 
			
		||||
  # generate expected interrupt code
 | 
			
		||||
  expected = (0 if not interrupt else (2**31 if xlen == 32 else 2**63)) + code
 | 
			
		||||
 | 
			
		||||
  lines = f"""
 | 
			
		||||
    # Testcase {testnum}
 | 
			
		||||
    li x31, 0
 | 
			
		||||
    {lines}
 | 
			
		||||
 | 
			
		||||
    {storecmd} x31, {str(wordsize*testnum)}(x6)
 | 
			
		||||
    # RVTEST_IO_ASSERT_GPR_EQ(x0, 0, {formatstr.format(expected)})
 | 
			
		||||
  """
 | 
			
		||||
 | 
			
		||||
  #if mode == "s":
 | 
			
		||||
    # go to supervisor mode
 | 
			
		||||
  #elif mode == "u":
 | 
			
		||||
    # go to user mode
 | 
			
		||||
 | 
			
		||||
  f.write(lines)
 | 
			
		||||
 | 
			
		||||
  if (xlen == 32):
 | 
			
		||||
    line = formatrefstr.format(expected)+"\n"
 | 
			
		||||
  else:
 | 
			
		||||
    line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n"
 | 
			
		||||
  r.write(line)
 | 
			
		||||
  testnum = testnum+1
 | 
			
		||||
 | 
			
		||||
##################################
 | 
			
		||||
# main body
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
# name: (interrupt?, code)
 | 
			
		||||
# tests = {
 | 
			
		||||
#  'User software interrupt': (1, '0'),
 | 
			
		||||
#  'Supervisor software interrupt': (1, '1'),
 | 
			
		||||
#  'Machine software interrupt': (1, '3'),
 | 
			
		||||
#  'User timer interrupt': (1, '4'),
 | 
			
		||||
#  'Supervisor timer interrupt': (1, '5'),
 | 
			
		||||
#  'Machine timer interrupt': (1, '7'),
 | 
			
		||||
#  'User external interrupt': (1, '8'),
 | 
			
		||||
#  'Supervisor external interrupt': (1, '9'),
 | 
			
		||||
#  'Machine external interrupt': (1, '11'),
 | 
			
		||||
#  'Instruction address misaligned': (0, '0'),
 | 
			
		||||
#  'Instruction access fault': (0, '1'),
 | 
			
		||||
#  'Illegal instruction': (0, '2'),
 | 
			
		||||
#  'Breakpoint': (0, '3'),
 | 
			
		||||
#  'Load address misaligned': (0, '4'),
 | 
			
		||||
#  'Load access fault': (0, '5'),
 | 
			
		||||
#  'Store/AMO address misaligned': (0, '6'),
 | 
			
		||||
#  'Store/AMO access fault': (0, '7'),
 | 
			
		||||
#  'Environment call from U-mode': (0, '8'),
 | 
			
		||||
#  'Environment call from S-mode': (0, '9'),
 | 
			
		||||
#  'Environment call from M-mode': (0, '11'),
 | 
			
		||||
#  'Instruction page fault': (0, '12'),
 | 
			
		||||
#  'Load page fault': (0, '13'),
 | 
			
		||||
#  'Store/AMO page fault': (0, '15'),
 | 
			
		||||
# }
 | 
			
		||||
author = "dottolia@hmc.edu"
 | 
			
		||||
xlens = [32, 64]
 | 
			
		||||
numrand = 60;
 | 
			
		||||
 | 
			
		||||
# setup
 | 
			
		||||
seed(0xC395DDEB9173AD42) # make tests reproducible
 | 
			
		||||
 | 
			
		||||
# generate files for each test
 | 
			
		||||
for xlen in xlens:
 | 
			
		||||
  formatstrlen = str(int(xlen/4))
 | 
			
		||||
  formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
 | 
			
		||||
  formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
 | 
			
		||||
  if (xlen == 32):
 | 
			
		||||
    storecmd = "sw"
 | 
			
		||||
    wordsize = 4
 | 
			
		||||
  else:
 | 
			
		||||
    storecmd = "sd"
 | 
			
		||||
    wordsize = 8
 | 
			
		||||
 | 
			
		||||
  imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/privileged/"
 | 
			
		||||
  basename = "WALLY-CAUSE-" + str(xlen)
 | 
			
		||||
  fname = imperaspath + "src/" + basename + ".S"
 | 
			
		||||
  refname = imperaspath + "references/" + basename + ".reference_output"
 | 
			
		||||
  testnum = 0
 | 
			
		||||
 | 
			
		||||
  # print custom header part
 | 
			
		||||
  f = open(fname, "w")
 | 
			
		||||
  r = open(refname, "w")
 | 
			
		||||
  line = "///////////////////////////////////////////\n"
 | 
			
		||||
  f.write(line)
 | 
			
		||||
  lines="// "+fname+ "\n// " + author + "\n"
 | 
			
		||||
  f.write(lines)
 | 
			
		||||
  line ="// Created " + str(datetime.now()) 
 | 
			
		||||
  f.write(line)
 | 
			
		||||
 | 
			
		||||
  # insert generic header
 | 
			
		||||
  # h = open("../testgen_header.S", "r")
 | 
			
		||||
  # for line in h:  
 | 
			
		||||
  #   f.write(line)
 | 
			
		||||
 | 
			
		||||
  # print directed and random test vectors
 | 
			
		||||
  writeVectors(storecmd)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # print footer
 | 
			
		||||
  # h = open("../testgen_footer.S", "r")
 | 
			
		||||
  # for line in h:  
 | 
			
		||||
  #   f.write(line)
 | 
			
		||||
 | 
			
		||||
  # Finish
 | 
			
		||||
  # lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n"
 | 
			
		||||
  # lines = lines + "\nRV_COMPLIANCE_DATA_END\n" 
 | 
			
		||||
  # f.write(lines)
 | 
			
		||||
  f.close()
 | 
			
		||||
  r.close()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user