mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-02 17:55:19 +00:00
Merge remote-tracking branch 'origin/tlb_toy' into busybear
This commit is contained in:
commit
e146946e58
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,6 +1,3 @@
|
||||
[submodule "riscv-o3"]
|
||||
path = riscv-o3
|
||||
url = git@github.com:stineje/riscv-o3.git
|
||||
[submodule "sky130/sky130_osu_sc_t12"]
|
||||
path = sky130/sky130_osu_sc_t12
|
||||
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12/
|
||||
|
1
riscv-o3
1
riscv-o3
@ -1 +0,0 @@
|
||||
Subproject commit afb27bd558a9b6fabb6b768ae81ef122b4db9eea
|
@ -27,7 +27,7 @@
|
||||
// RV32 or RV64: XLEN = 32 or 64
|
||||
`define XLEN 32
|
||||
|
||||
`define MISA (32'h00000104)
|
||||
`define MISA (32'h00000104 | 1 << 12)
|
||||
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
|
||||
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
|
||||
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
|
||||
|
@ -28,7 +28,7 @@
|
||||
`define XLEN 64
|
||||
|
||||
//`define MISA (32'h00000104)
|
||||
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20)
|
||||
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20 | 1 << 12)
|
||||
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
|
||||
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
|
||||
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
|
||||
|
89
wally-pipelined/config/rv64icfd/wally-config.vh
Normal file
89
wally-pipelined/config/rv64icfd/wally-config.vh
Normal file
@ -0,0 +1,89 @@
|
||||
//////////////////////////////////////////
|
||||
// wally-config.vh
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 4 January 2021
|
||||
// Modified: Brett Mathis
|
||||
//
|
||||
// Purpose: Specify which features are configured
|
||||
// Macros to determine which modes are supported based on MISA
|
||||
//
|
||||
// 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.
|
||||
///////////////////////////////////////////
|
||||
|
||||
// RV32 or RV64: XLEN = 32 or 64
|
||||
`define XLEN 64
|
||||
|
||||
//`define MISA (32'h00000104)
|
||||
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20)
|
||||
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
|
||||
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
|
||||
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
|
||||
`define F_SUPPORTED ((`MISA >> 5) % 2 == 1)
|
||||
`define M_SUPPORTED ((`MISA >> 12) % 2 == 1)
|
||||
`define S_SUPPORTED ((`MISA >> 18) % 2 == 1)
|
||||
`define U_SUPPORTED ((`MISA >> 20) % 2 == 1)
|
||||
`define ZCSR_SUPPORTED 1
|
||||
`define ZCOUNTERS_SUPPORTED 1
|
||||
// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21
|
||||
//`define N_SUPPORTED ((MISA >> 13) % 2 == 1)
|
||||
`define N_SUPPORTED 0
|
||||
|
||||
`define M_MODE (2'b11)
|
||||
`define S_MODE (2'b01)
|
||||
`define U_MODE (2'b00)
|
||||
|
||||
// Microarchitectural Features
|
||||
`define UARCH_PIPELINED 1
|
||||
`define UARCH_SUPERSCALR 0
|
||||
`define UARCH_SINGLECYCLE 0
|
||||
`define MEM_DCACHE 0
|
||||
`define MEM_DTIM 1
|
||||
`define MEM_ICACHE 0
|
||||
`define MEM_VIRTMEM 0
|
||||
|
||||
// Address space
|
||||
`define RESET_VECTOR 64'h0000000080000000
|
||||
|
||||
// Bus Interface width
|
||||
`define AHBW 64
|
||||
|
||||
// Peripheral Addresses
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h0007FFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
`define GPIO_LOOPBACK_TEST 0
|
||||
|
||||
|
||||
// Hardware configuration
|
||||
`define UART_PRESCALE 1
|
||||
|
||||
/* verilator lint_off STMTDLY */
|
||||
/* verilator lint_off WIDTH */
|
||||
/* verilator lint_off ASSIGNDLY */
|
||||
/* verilator lint_off PINCONNECTEMPTY */
|
@ -1,7 +1,8 @@
|
||||
# check for warnings in Verilog code
|
||||
# The verilator lint tool is faster and better than Modelsim so it is best to run this first.
|
||||
|
||||
verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv
|
||||
verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv
|
||||
#verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv src/*/div/*.sv
|
||||
|
||||
# --lint-only just runs lint rather than trying to compile and simulate
|
||||
# -I points to the include directory where files such as `include wally-config.vh are found
|
||||
|
@ -17,10 +17,10 @@
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
if [file exists work-busybear] {
|
||||
vdel -all -lib work-busybear
|
||||
}
|
||||
vlib work
|
||||
vlib work-busybear
|
||||
|
||||
# compile source files
|
||||
# suppress spurious warnngs about
|
||||
|
101
wally-pipelined/regression/wally-coremark.do
Normal file
101
wally-pipelined/regression/wally-coremark.do
Normal file
@ -0,0 +1,101 @@
|
||||
# wally-coremark.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
|
||||
|
||||
# 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
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do wally-pipelined.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
# suppress spurious warnngs about
|
||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||
# because vsim will run vopt
|
||||
|
||||
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
|
||||
# do wally-pipelined.do ../config/rv32ic
|
||||
switch $argc {
|
||||
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-coremark.sv ../src/*/*.sv -suppress 2583}
|
||||
1 {vlog +incdir+$1 ../testbench/testbench-coremark.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 +acc work.testbench -o workopt
|
||||
vsim workopt
|
||||
|
||||
view wave
|
||||
|
||||
-- display input and output signals as hexidecimal values
|
||||
# Diplays All Signals recursively
|
||||
add wave /testbench/clk
|
||||
add wave /testbench/reset
|
||||
add wave -divider
|
||||
add wave /testbench/dut/hart/ebu/IReadF
|
||||
add wave /testbench/dut/hart/DataStall
|
||||
add wave /testbench/dut/hart/InstrStall
|
||||
add wave /testbench/dut/hart/StallF
|
||||
add wave /testbench/dut/hart/StallD
|
||||
add wave /testbench/dut/hart/FlushD
|
||||
add wave /testbench/dut/hart/FlushE
|
||||
add wave /testbench/dut/hart/FlushM
|
||||
add wave /testbench/dut/hart/FlushW
|
||||
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrF
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCD
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||
add wave -divider
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCE
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||
add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
||||
add wave -divider
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCM
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave /testbench/dut/uncore/dtim/memwrite
|
||||
add wave -hex /testbench/dut/uncore/HADDR
|
||||
add wave -hex /testbench/dut/uncore/HWDATA
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCW
|
||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||
add wave -divider
|
||||
#add ww
|
||||
add wave -hex -r /testbench/*
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {100 ps}
|
||||
configure wave -namecolwidth 250
|
||||
configure wave -valuecolwidth 120
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
set DefaultRadix hexadecimal
|
||||
|
||||
-- Run the Simulation
|
||||
#run 1000
|
||||
run -all
|
||||
#quit
|
108
wally-pipelined/regression/wally-peripherals.do
Normal file
108
wally-pipelined/regression/wally-peripherals.do
Normal file
@ -0,0 +1,108 @@
|
||||
# wally-peripherals.do
|
||||
#
|
||||
# Created by Ben Bracker (bbracker@hmc.edu) on 11 Feb. 2021
|
||||
#
|
||||
# Based on wally-pipelined.do by
|
||||
# James Stine, 2008; David Harris 2021
|
||||
# Go Cowboys!!!!!!
|
||||
|
||||
# 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
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do wally-pipelined.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
# suppress spurious warnngs about
|
||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||
# because vsim will run vopt
|
||||
|
||||
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
|
||||
# do wally-pipelined.do ../config/rv32ic
|
||||
# That said, I don't think there are any peripherals that use anything but rv64i just yet.
|
||||
switch $argc {
|
||||
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-peripherals.sv ../src/*/*.sv -suppress 2583}
|
||||
1 {vlog +incdir+$1 ../testbench/testbench-peripherals.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 +acc work.testbench -o workopt
|
||||
vsim workopt
|
||||
|
||||
view wave
|
||||
|
||||
-- display input and output signals as hexidecimal values
|
||||
# Diplays All Signals recursively
|
||||
add wave /testbench/clk
|
||||
add wave /testbench/reset
|
||||
add wave -divider
|
||||
add wave /testbench/dut/hart/ebu/IReadF
|
||||
add wave /testbench/dut/hart/DataStall
|
||||
add wave /testbench/dut/hart/InstrStall
|
||||
add wave /testbench/dut/hart/StallF
|
||||
add wave /testbench/dut/hart/StallD
|
||||
add wave /testbench/dut/hart/FlushD
|
||||
add wave /testbench/dut/hart/FlushE
|
||||
add wave /testbench/dut/hart/FlushM
|
||||
add wave /testbench/dut/hart/FlushW
|
||||
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrF
|
||||
add wave /testbench/InstrFName
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCD
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||
add wave /testbench/InstrDName
|
||||
add wave -divider
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCE
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||
add wave /testbench/InstrEName
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||
add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
||||
add wave -divider
|
||||
#add wave -hex /testbench/dut/hart/ifu/PCM
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave /testbench/InstrMName
|
||||
add wave /testbench/dut/uncore/dtim/memwrite
|
||||
add wave -hex /testbench/dut/uncore/HADDR
|
||||
add wave -hex /testbench/dut/uncore/HWDATA
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCW
|
||||
add wave /testbench/InstrWName
|
||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/uncore/uart/u/*
|
||||
add wave -divider
|
||||
#add ww
|
||||
add wave -hex -r /testbench/*
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {100 ps}
|
||||
configure wave -namecolwidth 250
|
||||
configure wave -valuecolwidth 120
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
set DefaultRadix hexadecimal
|
||||
|
||||
-- Run the Simulation
|
||||
run 5000
|
||||
#run -all
|
||||
#quit
|
29
wally-pipelined/src/fpu/build_temp/fcsr.sv
Normal file
29
wally-pipelined/src/fpu/build_temp/fcsr.sv
Normal file
@ -0,0 +1,29 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module fcsr(
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic write,
|
||||
input logic [4:0] flags,
|
||||
output logic [31:0] readData);
|
||||
|
||||
//register I/O assignment
|
||||
logic [31:0] regInput;
|
||||
logic [31:0] regOutput;
|
||||
|
||||
//no L instruction support
|
||||
//only last 8 bits used for FCSR
|
||||
|
||||
//latching input to write signal
|
||||
//AND clk and write and remove latch
|
||||
//for clk-based write
|
||||
assign regInput = (write) ? {24'h0,frm,flags} : regInput;
|
||||
|
||||
floprc #(32) (.clk(clk), .reset(reset), .clear(clear), .d(regInput), .q(regOutput));
|
||||
|
||||
assign readData = regOutput;
|
||||
|
||||
|
||||
endmodule
|
143
wally-pipelined/src/fpu/build_temp/fctrl.sv
Normal file
143
wally-pipelined/src/fpu/build_temp/fctrl.sv
Normal file
@ -0,0 +1,143 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module fctrl (
|
||||
input logic [6:0] Funct7D,
|
||||
input logic [6:0] OpD,
|
||||
input logic [4:0] Rs2D,
|
||||
input logic [4:0] Rs1D,
|
||||
input logic [2:0] FrmW,
|
||||
output logic WriteEnD,
|
||||
output logic DivSqrtStartD,
|
||||
output logic [2:0] regSelD,
|
||||
output logic [2:0] writeSelD,
|
||||
output logic [3:0] OpCtrlD,
|
||||
output logic FmtD,
|
||||
output logic WriteIntD);
|
||||
|
||||
|
||||
|
||||
//precision is taken directly from instruction
|
||||
assign FmtD = Funct7D[0];
|
||||
|
||||
//all subsequent logic is based on the table present
|
||||
//in Section 5 of Wally Architecture Specification
|
||||
|
||||
//write is enabled for all fp instruciton op codes
|
||||
//sans fp load
|
||||
logic isFP, isFPLD;
|
||||
always_comb begin
|
||||
//case statement is easier to modify
|
||||
//in case of errors
|
||||
case(OpD)
|
||||
//fp instructions sans load
|
||||
7'b1010011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
7'b1000011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
7'b1000111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
7'b1001011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
7'b1001111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
7'b0100111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||||
//fp load
|
||||
7'b1010011 : begin isFP = 1'b1; isFPLD = 1'b1; end
|
||||
default : begin isFP = 1'b0; isFPLD = 1'b0; end
|
||||
endcase
|
||||
end
|
||||
|
||||
assign WriteEnD = isFP & ~isFPLD;
|
||||
|
||||
//useful intermediary signals
|
||||
//
|
||||
//(mult only not supported in current datapath)
|
||||
//set third FMA operand to zero in this case
|
||||
//(or equivalent)
|
||||
logic isAddSub, isFMA, isMult, isDivSqrt, isCvt, isCmp, isFPSTR;
|
||||
|
||||
always_comb begin
|
||||
//checks all but FMA/store/load
|
||||
if(OpD == 7'b1010011) begin
|
||||
case(Funct7D)
|
||||
//compare
|
||||
7'b10100?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b1; isFPSTR = 1'b0; end
|
||||
//div/sqrt
|
||||
7'b0?011?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b1; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
//add/sub
|
||||
7'b0000??? : begin isAddSub = 1'b1; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
//mult
|
||||
7'b00010?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b1; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
//convert (not precision)
|
||||
7'b110?0?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b1; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
//convert (precision)
|
||||
7'b010000? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b1; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
endcase
|
||||
end
|
||||
//FMA/store/load
|
||||
else begin
|
||||
case(OpD)
|
||||
//4 FMA instructions
|
||||
7'b1000011 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
7'b1000111 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
7'b1001011 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
7'b1001111 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||||
//store (load already found)
|
||||
7'b0100111 : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b1; end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//register is chosen based on operation performed
|
||||
//----
|
||||
//write selection is chosen in the same way as
|
||||
//register selection
|
||||
//
|
||||
|
||||
// reg/write sel logic and assignment
|
||||
//
|
||||
// 3'b000 = add/sub/cvt
|
||||
// 3'b001 = sign
|
||||
// 3'b010 = fma
|
||||
// 3'b011 = cmp
|
||||
// 3'b100 = div/sqrt
|
||||
//
|
||||
//reg select
|
||||
|
||||
//this value is used enough to be shorthand
|
||||
logic isSign;
|
||||
assign isSign = ~Funct7D[6] & ~Funct7D[5] & Funct7D[4] & ~Funct7D[3] & ~Funct7D[2];
|
||||
|
||||
|
||||
assign regSelD[2] = isDivSqrt & ~isFMA;
|
||||
assign regSelD[1] = isFMA | isCmp;
|
||||
//AND of Funct7 for sign
|
||||
assign regSelD[0] = isCmp | isSign;
|
||||
|
||||
//write select
|
||||
assign writeSelD[2] = isDivSqrt & ~isFMA;
|
||||
assign writeSelD[1] = isFMA | isCmp;
|
||||
//AND of Funct7 for sign
|
||||
assign writeSelD[0] = isCmp | isSign;
|
||||
|
||||
//if op is div/sqrt - start div/sqrt
|
||||
assign DivSqrtStartD = isDivSqrt & ~isFMA;
|
||||
|
||||
//operation control for each fp operation
|
||||
//has to be expanded over standard to account for
|
||||
//integrated fpadd/cvt
|
||||
//
|
||||
//will integrate FMA opcodes into design later
|
||||
//
|
||||
//conversion instructions will
|
||||
//also need to be added later as I find the opcode
|
||||
//version I used for this repo
|
||||
|
||||
assign OpCtrlD[3] = 1'b0;
|
||||
//if is positive sign injection OR is precision convert
|
||||
assign OpCtrlD[2] = (isSign & ~FrmW[0]) | (~Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||||
//if is precision convert OR is sign xor
|
||||
assign OpCtrlD[1] = (isSign & FrmW[1]) | (~Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||||
//if is sqrt OR is sub OR is single-precision cmp OR negation
|
||||
assign OpCtrlD[0] = (isDivSqrt & ~isFMA & Funct7D[6]) | (isAddSub & ~isFMA & Funct7D[2]) | (isCmp & ~isFMA & Funct7D[0]) | (isSign & FrmW[0]);
|
||||
|
||||
//write to integer source if conv to int occurs
|
||||
//AND of Funct7 for int results
|
||||
assign WriteIntD = isCvt & (Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||||
|
||||
endmodule
|
65
wally-pipelined/src/fpu/build_temp/fputop.sv
Normal file
65
wally-pipelined/src/fpu/build_temp/fputop.sv
Normal file
@ -0,0 +1,65 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module fputop (
|
||||
input logic [2:0] FrmW,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [31:0] InstrD,
|
||||
input logic [`XLEN-1:0] SrcAE,
|
||||
input logic [`XLEN-1:0] SrcAW,
|
||||
output logic [31:0] FSROutW,
|
||||
output logic DivSqrtDoneE,
|
||||
output logic FInvalInstrD,
|
||||
output logic [`XLEN-1:0] FPUResultW);
|
||||
|
||||
/*fctrl ();
|
||||
|
||||
//regfile instantiation and decode stage
|
||||
|
||||
//write signal mux
|
||||
|
||||
//address signal mux
|
||||
|
||||
//parallel floating-point registers are
|
||||
//used for modularity and future performance
|
||||
//comparisons between operation sets
|
||||
freg1adr ();
|
||||
|
||||
freg2adr ();
|
||||
|
||||
freg2adr ();
|
||||
|
||||
freg2adr ();
|
||||
|
||||
freg3adr ();
|
||||
|
||||
//can easily be merged into privledged core
|
||||
//if necessary
|
||||
fcsr ();
|
||||
|
||||
//E pipe and execution stage
|
||||
|
||||
fpdivsqrt ();
|
||||
|
||||
fma1 ();
|
||||
|
||||
fpaddcvt1 ();
|
||||
|
||||
fpcmp1 ();
|
||||
|
||||
fpsign ();
|
||||
|
||||
//M pipe and memory stage
|
||||
|
||||
fma2 ();
|
||||
|
||||
fpaddcvt2 ();
|
||||
|
||||
fpcmp2 ();
|
||||
|
||||
//W pipe and writeback stage
|
||||
|
||||
//flag signal mux
|
||||
*/
|
||||
endmodule
|
513
wally-pipelined/src/fpu/build_temp/freg.sv
Normal file
513
wally-pipelined/src/fpu/build_temp/freg.sv
Normal file
@ -0,0 +1,513 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module freg1adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//this could be done with:
|
||||
//
|
||||
//assign readData = regOutput[adr1];
|
||||
//
|
||||
//but always_comb allows for finer control
|
||||
|
||||
|
||||
//address decoder
|
||||
//only 1 for this fp register set
|
||||
//used with fpsign
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
case(adr1)
|
||||
5'b00000 : readData = regOutput[0];
|
||||
5'b00001 : readData = regOutput[1];
|
||||
5'b00010 : readData = regOutput[2];
|
||||
5'b00011 : readData = regOutput[3];
|
||||
5'b00100 : readData = regOutput[4];
|
||||
5'b00101 : readData = regOutput[5];
|
||||
5'b00110 : readData = regOutput[6];
|
||||
5'b00111 : readData = regOutput[7];
|
||||
5'b01000 : readData = regOutput[8];
|
||||
5'b01001 : readData = regOutput[9];
|
||||
5'b01010 : readData = regOutput[10];
|
||||
5'b01011 : readData = regOutput[11];
|
||||
5'b01100 : readData = regOutput[12];
|
||||
5'b01101 : readData = regOutput[13];
|
||||
5'b01110 : readData = regOutput[14];
|
||||
5'b01111 : readData = regOutput[15];
|
||||
5'b10000 : readData = regOutput[16];
|
||||
5'b10001 : readData = regOutput[17];
|
||||
5'b10010 : readData = regOutput[18];
|
||||
5'b10011 : readData = regOutput[19];
|
||||
5'b10100 : readData = regOutput[20];
|
||||
5'b10101 : readData = regOutput[21];
|
||||
5'b10110 : readData = regOutput[22];
|
||||
5'b10111 : readData = regOutput[23];
|
||||
5'b11000 : readData = regOutput[24];
|
||||
5'b11001 : readData = regOutput[25];
|
||||
5'b11010 : readData = regOutput[26];
|
||||
5'b11011 : readData = regOutput[27];
|
||||
5'b11100 : readData = regOutput[28];
|
||||
5'b11101 : readData = regOutput[29];
|
||||
5'b11110 : readData = regOutput[30];
|
||||
5'b11111 : readData = regOutput[31];
|
||||
default : readData = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//********
|
||||
//formatting separation
|
||||
//********
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module freg2adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [4:0] adr2,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData1,
|
||||
output logic [`XLEN-1:0] readData2);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//address decoder
|
||||
//2 are used for this fp register set
|
||||
//used with fpadd/cvt, fpdiv/sqrt, and fpcmp
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
|
||||
//adderss 1 decoder
|
||||
case(adr1)
|
||||
5'b00000 : readData1 = regOutput[0];
|
||||
5'b00001 : readData1 = regOutput[1];
|
||||
5'b00010 : readData1 = regOutput[2];
|
||||
5'b00011 : readData1 = regOutput[3];
|
||||
5'b00100 : readData1 = regOutput[4];
|
||||
5'b00101 : readData1 = regOutput[5];
|
||||
5'b00110 : readData1 = regOutput[6];
|
||||
5'b00111 : readData1 = regOutput[7];
|
||||
5'b01000 : readData1 = regOutput[8];
|
||||
5'b01001 : readData1 = regOutput[9];
|
||||
5'b01010 : readData1 = regOutput[10];
|
||||
5'b01011 : readData1 = regOutput[11];
|
||||
5'b01100 : readData1 = regOutput[12];
|
||||
5'b01101 : readData1 = regOutput[13];
|
||||
5'b01110 : readData1 = regOutput[14];
|
||||
5'b01111 : readData1 = regOutput[15];
|
||||
5'b10000 : readData1 = regOutput[16];
|
||||
5'b10001 : readData1 = regOutput[17];
|
||||
5'b10010 : readData1 = regOutput[18];
|
||||
5'b10011 : readData1 = regOutput[19];
|
||||
5'b10100 : readData1 = regOutput[20];
|
||||
5'b10101 : readData1 = regOutput[21];
|
||||
5'b10110 : readData1 = regOutput[22];
|
||||
5'b10111 : readData1 = regOutput[23];
|
||||
5'b11000 : readData1 = regOutput[24];
|
||||
5'b11001 : readData1 = regOutput[25];
|
||||
5'b11010 : readData1 = regOutput[26];
|
||||
5'b11011 : readData1 = regOutput[27];
|
||||
5'b11100 : readData1 = regOutput[28];
|
||||
5'b11101 : readData1 = regOutput[29];
|
||||
5'b11110 : readData1 = regOutput[30];
|
||||
5'b11111 : readData1 = regOutput[31];
|
||||
default : readData1 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 2 decoder
|
||||
case(adr2)
|
||||
5'b00000 : readData2 = regOutput[0];
|
||||
5'b00001 : readData2 = regOutput[1];
|
||||
5'b00010 : readData2 = regOutput[2];
|
||||
5'b00011 : readData2 = regOutput[3];
|
||||
5'b00100 : readData2 = regOutput[4];
|
||||
5'b00101 : readData2 = regOutput[5];
|
||||
5'b00110 : readData2 = regOutput[6];
|
||||
5'b00111 : readData2 = regOutput[7];
|
||||
5'b01000 : readData2 = regOutput[8];
|
||||
5'b01001 : readData2 = regOutput[9];
|
||||
5'b01010 : readData2 = regOutput[10];
|
||||
5'b01011 : readData2 = regOutput[11];
|
||||
5'b01100 : readData2 = regOutput[12];
|
||||
5'b01101 : readData2 = regOutput[13];
|
||||
5'b01110 : readData2 = regOutput[14];
|
||||
5'b01111 : readData2 = regOutput[15];
|
||||
5'b10000 : readData2 = regOutput[16];
|
||||
5'b10001 : readData2 = regOutput[17];
|
||||
5'b10010 : readData2 = regOutput[18];
|
||||
5'b10011 : readData2 = regOutput[19];
|
||||
5'b10100 : readData2 = regOutput[20];
|
||||
5'b10101 : readData2 = regOutput[21];
|
||||
5'b10110 : readData2 = regOutput[22];
|
||||
5'b10111 : readData2 = regOutput[23];
|
||||
5'b11000 : readData2 = regOutput[24];
|
||||
5'b11001 : readData2 = regOutput[25];
|
||||
5'b11010 : readData2 = regOutput[26];
|
||||
5'b11011 : readData2 = regOutput[27];
|
||||
5'b11100 : readData2 = regOutput[28];
|
||||
5'b11101 : readData2 = regOutput[29];
|
||||
5'b11110 : readData2 = regOutput[30];
|
||||
5'b11111 : readData2 = regOutput[31];
|
||||
default : readData2 = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//********
|
||||
//formatting separation
|
||||
//********
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module freg3adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [4:0] adr2,
|
||||
input logic [4:0] adr3,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData1,
|
||||
output logic [`XLEN-1:0] readData2,
|
||||
output logic [`XLEN-1:0] readData3);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//address decoder
|
||||
//3 are used for this fp register set
|
||||
//used exclusively for fma
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
|
||||
//adderss 1 decoder
|
||||
case(adr1)
|
||||
5'b00000 : readData1 = regOutput[0];
|
||||
5'b00001 : readData1 = regOutput[1];
|
||||
5'b00010 : readData1 = regOutput[2];
|
||||
5'b00011 : readData1 = regOutput[3];
|
||||
5'b00100 : readData1 = regOutput[4];
|
||||
5'b00101 : readData1 = regOutput[5];
|
||||
5'b00110 : readData1 = regOutput[6];
|
||||
5'b00111 : readData1 = regOutput[7];
|
||||
5'b01000 : readData1 = regOutput[8];
|
||||
5'b01001 : readData1 = regOutput[9];
|
||||
5'b01010 : readData1 = regOutput[10];
|
||||
5'b01011 : readData1 = regOutput[11];
|
||||
5'b01100 : readData1 = regOutput[12];
|
||||
5'b01101 : readData1 = regOutput[13];
|
||||
5'b01110 : readData1 = regOutput[14];
|
||||
5'b01111 : readData1 = regOutput[15];
|
||||
5'b10000 : readData1 = regOutput[16];
|
||||
5'b10001 : readData1 = regOutput[17];
|
||||
5'b10010 : readData1 = regOutput[18];
|
||||
5'b10011 : readData1 = regOutput[19];
|
||||
5'b10100 : readData1 = regOutput[20];
|
||||
5'b10101 : readData1 = regOutput[21];
|
||||
5'b10110 : readData1 = regOutput[22];
|
||||
5'b10111 : readData1 = regOutput[23];
|
||||
5'b11000 : readData1 = regOutput[24];
|
||||
5'b11001 : readData1 = regOutput[25];
|
||||
5'b11010 : readData1 = regOutput[26];
|
||||
5'b11011 : readData1 = regOutput[27];
|
||||
5'b11100 : readData1 = regOutput[28];
|
||||
5'b11101 : readData1 = regOutput[29];
|
||||
5'b11110 : readData1 = regOutput[30];
|
||||
5'b11111 : readData1 = regOutput[31];
|
||||
default : readData1 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 2 decoder
|
||||
case(adr2)
|
||||
5'b00000 : readData2 = regOutput[0];
|
||||
5'b00001 : readData2 = regOutput[1];
|
||||
5'b00010 : readData2 = regOutput[2];
|
||||
5'b00011 : readData2 = regOutput[3];
|
||||
5'b00100 : readData2 = regOutput[4];
|
||||
5'b00101 : readData2 = regOutput[5];
|
||||
5'b00110 : readData2 = regOutput[6];
|
||||
5'b00111 : readData2 = regOutput[7];
|
||||
5'b01000 : readData2 = regOutput[8];
|
||||
5'b01001 : readData2 = regOutput[9];
|
||||
5'b01010 : readData2 = regOutput[10];
|
||||
5'b01011 : readData2 = regOutput[11];
|
||||
5'b01100 : readData2 = regOutput[12];
|
||||
5'b01101 : readData2 = regOutput[13];
|
||||
5'b01110 : readData2 = regOutput[14];
|
||||
5'b01111 : readData2 = regOutput[15];
|
||||
5'b10000 : readData2 = regOutput[16];
|
||||
5'b10001 : readData2 = regOutput[17];
|
||||
5'b10010 : readData2 = regOutput[18];
|
||||
5'b10011 : readData2 = regOutput[19];
|
||||
5'b10100 : readData2 = regOutput[20];
|
||||
5'b10101 : readData2 = regOutput[21];
|
||||
5'b10110 : readData2 = regOutput[22];
|
||||
5'b10111 : readData2 = regOutput[23];
|
||||
5'b11000 : readData2 = regOutput[24];
|
||||
5'b11001 : readData2 = regOutput[25];
|
||||
5'b11010 : readData2 = regOutput[26];
|
||||
5'b11011 : readData2 = regOutput[27];
|
||||
5'b11100 : readData2 = regOutput[28];
|
||||
5'b11101 : readData2 = regOutput[29];
|
||||
5'b11110 : readData2 = regOutput[30];
|
||||
5'b11111 : readData2 = regOutput[31];
|
||||
default : readData2 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 3 decoder
|
||||
case(adr3)
|
||||
5'b00000 : readData3 = regOutput[0];
|
||||
5'b00001 : readData3 = regOutput[1];
|
||||
5'b00010 : readData3 = regOutput[2];
|
||||
5'b00011 : readData3 = regOutput[3];
|
||||
5'b00100 : readData3 = regOutput[4];
|
||||
5'b00101 : readData3 = regOutput[5];
|
||||
5'b00110 : readData3 = regOutput[6];
|
||||
5'b00111 : readData3 = regOutput[7];
|
||||
5'b01000 : readData3 = regOutput[8];
|
||||
5'b01001 : readData3 = regOutput[9];
|
||||
5'b01010 : readData3 = regOutput[10];
|
||||
5'b01011 : readData3 = regOutput[11];
|
||||
5'b01100 : readData3 = regOutput[12];
|
||||
5'b01101 : readData3 = regOutput[13];
|
||||
5'b01110 : readData3 = regOutput[14];
|
||||
5'b01111 : readData3 = regOutput[15];
|
||||
5'b10000 : readData3 = regOutput[16];
|
||||
5'b10001 : readData3 = regOutput[17];
|
||||
5'b10010 : readData3 = regOutput[18];
|
||||
5'b10011 : readData3 = regOutput[19];
|
||||
5'b10100 : readData3 = regOutput[20];
|
||||
5'b10101 : readData3 = regOutput[21];
|
||||
5'b10110 : readData3 = regOutput[22];
|
||||
5'b10111 : readData3 = regOutput[23];
|
||||
5'b11000 : readData3 = regOutput[24];
|
||||
5'b11001 : readData3 = regOutput[25];
|
||||
5'b11010 : readData3 = regOutput[26];
|
||||
5'b11011 : readData3 = regOutput[27];
|
||||
5'b11100 : readData3 = regOutput[28];
|
||||
5'b11101 : readData3 = regOutput[29];
|
||||
5'b11110 : readData3 = regOutput[30];
|
||||
5'b11111 : readData3 = regOutput[31];
|
||||
default : readData3 = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -51,4 +51,12 @@ module mux4 #(parameter WIDTH = 8) (
|
||||
assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0);
|
||||
endmodule
|
||||
|
||||
module mux5 #(parameter WIDTH = 8) (
|
||||
input logic [WIDTH-1:0] d0, d1, d2, d3, d4,
|
||||
input logic [2:0] s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s[2] ? d4 : (s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0));
|
||||
endmodule
|
||||
|
||||
/* verilator lint_on DECLFILENAME */
|
||||
|
@ -31,7 +31,7 @@ module hazard(
|
||||
// input logic MemReadE,
|
||||
// input logic RegWriteM, RegWriteW,
|
||||
input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM,
|
||||
input logic LoadStallD,
|
||||
input logic LoadStallD, MulDivStallD,
|
||||
input logic InstrStall, DataStall,
|
||||
// Stall outputs
|
||||
output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW
|
||||
@ -54,7 +54,7 @@ module hazard(
|
||||
|
||||
assign BranchFlushDE = PCSrcE | RetM | TrapM;
|
||||
|
||||
assign StallDCause = LoadStallD;
|
||||
assign StallDCause = LoadStallD | MulDivStallD;
|
||||
assign StallFCause = InstrStall | CSRWritePendingDEM;
|
||||
assign StallWCause = DataStall; // *** not yet used
|
||||
|
||||
|
@ -29,21 +29,23 @@
|
||||
module controller(
|
||||
input logic clk, reset,
|
||||
// Decode stage control signals
|
||||
input logic [6:0] OpD,
|
||||
input logic [2:0] Funct3D,
|
||||
input logic Funct7b5D,
|
||||
input logic [6:0] OpD,
|
||||
input logic [2:0] Funct3D,
|
||||
input logic [6:0] Funct7D,
|
||||
output logic [2:0] ImmSrcD,
|
||||
input logic StallD, FlushD,
|
||||
input logic IllegalIEUInstrFaultD,
|
||||
input logic StallD, FlushD,
|
||||
input logic IllegalIEUInstrFaultD,
|
||||
output logic IllegalBaseInstrFaultD,
|
||||
// Execute stage control signals
|
||||
input logic FlushE,
|
||||
input logic [2:0] FlagsE,
|
||||
input logic FlushE,
|
||||
input logic [2:0] FlagsE,
|
||||
output logic PCSrcE, // for datapath and Hazard Unit
|
||||
output logic [4:0] ALUControlE,
|
||||
output logic ALUSrcAE, ALUSrcBE,
|
||||
output logic TargetSrcE,
|
||||
output logic MemReadE, // for Hazard Unit
|
||||
output logic [2:0] Funct3E,
|
||||
output logic MulDivE, W64E,
|
||||
// Memory stage control signals
|
||||
input logic FlushM,
|
||||
input logic DataMisalignedM,
|
||||
@ -54,7 +56,7 @@ module controller(
|
||||
// Writeback stage control signals
|
||||
input logic FlushW,
|
||||
output logic RegWriteW, // for datapath and Hazard Unit
|
||||
output logic [1:0] ResultSrcW,
|
||||
output logic [2:0] ResultSrcW,
|
||||
output logic InstrValidW,
|
||||
// Stall during CSRs
|
||||
output logic CSRWritePendingDEM
|
||||
@ -62,64 +64,75 @@ module controller(
|
||||
|
||||
// pipelined control signals
|
||||
logic RegWriteD, RegWriteE;
|
||||
logic [1:0] ResultSrcD, ResultSrcE, ResultSrcM;
|
||||
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM;
|
||||
logic [1:0] MemRWD, MemRWE;
|
||||
logic JumpD, JumpE;
|
||||
logic BranchD, BranchE;
|
||||
logic [1:0] ALUOpD;
|
||||
logic [4:0] ALUControlD;
|
||||
logic ALUSrcAD, ALUSrcBD;
|
||||
logic TargetSrcD, W64D;
|
||||
logic TargetSrcD, W64D, MulDivD;
|
||||
logic CSRWriteD, CSRWriteE;
|
||||
logic [2:0] Funct3E;
|
||||
logic InstrValidE, InstrValidM;
|
||||
logic PrivilegedD, PrivilegedE;
|
||||
logic [18:0] ControlsD;
|
||||
logic [20:0] ControlsD;
|
||||
logic aluc3D;
|
||||
logic subD, sraD, sltD, sltuD;
|
||||
logic BranchTakenE;
|
||||
logic zeroE, ltE, ltuE;
|
||||
logic unused;
|
||||
|
||||
|
||||
// Main Instruction Decoder
|
||||
// *** decoding of non-IEU instructions should also go here, and should be gated by MISA bits in a generate so
|
||||
// they don't get generated if that mode is disabled
|
||||
always_comb
|
||||
case(OpD)
|
||||
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_TargetSrc_W64_CSRWrite_Privileged_Illegal
|
||||
7'b0000011: ControlsD = 19'b1_000_01_10_01_0_00_0_0_0_0_0_0; // lw
|
||||
7'b0100011: ControlsD = 19'b0_001_01_01_00_0_00_0_0_0_0_0_0; // sw
|
||||
7'b0110011: ControlsD = 19'b1_000_00_00_00_0_10_0_0_0_0_0_0; // R-type
|
||||
7'b0111011: ControlsD = 19'b1_000_00_00_00_0_10_0_0_1_0_0_0; // R-type W instructions for RV64i
|
||||
7'b1100011: ControlsD = 19'b0_010_00_00_00_1_01_0_0_0_0_0_0; // beq
|
||||
7'b0010011: ControlsD = 19'b1_000_01_00_00_0_10_0_0_0_0_0_0; // I-type ALU
|
||||
7'b0011011: ControlsD = 19'b1_000_01_00_00_0_10_0_0_1_0_0_0; // IW-type ALU for RV64i
|
||||
7'b1101111: ControlsD = 19'b1_011_00_00_10_0_00_1_0_0_0_0_0; // jal
|
||||
7'b1100111: ControlsD = 19'b1_000_00_00_10_0_00_1_1_0_0_0_0; // jalr
|
||||
7'b0010111: ControlsD = 19'b1_100_11_00_00_0_00_0_0_0_0_0_0; // auipc
|
||||
7'b0110111: ControlsD = 19'b1_100_01_00_00_0_11_0_0_0_0_0_0; // lui
|
||||
7'b0001111: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_0; // fence = nop
|
||||
7'b1110011: if (Funct3D == 3'b000)
|
||||
ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_1_0; // privileged; decoded further in priveleged modules
|
||||
else
|
||||
ControlsD = 19'b1_000_00_00_11_0_00_0_0_0_1_0_0; // csrs
|
||||
7'b0000000: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_1; // illegal instruction
|
||||
default: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_1; // non-implemented instruction
|
||||
endcase
|
||||
generate
|
||||
always_comb
|
||||
case(OpD)
|
||||
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_TargetSrc_W64_CSRWrite_Privileged_MulDiv_Illegal
|
||||
7'b0000011: ControlsD = 21'b1_000_01_10_001_0_00_0_0_0_0_0_0_0; // lw
|
||||
7'b0100011: ControlsD = 21'b0_001_01_01_000_0_00_0_0_0_0_0_0_0; // sw
|
||||
7'b0110011: if (Funct7D == 7'b0000000 || Funct7D == 7'b0100000)
|
||||
ControlsD = 21'b1_000_00_00_000_0_10_0_0_0_0_0_0_0; // R-type
|
||||
else
|
||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
||||
7'b0111011: if ((Funct7D == 7'b0000000 || Funct7D == 7'b0100000) && `XLEN == 64)
|
||||
ControlsD = 21'b1_000_00_00_000_0_10_0_0_1_0_0_0_0; // R-type W instructions for RV64i
|
||||
else
|
||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
||||
7'b1100011: ControlsD = 21'b0_010_00_00_000_1_01_0_0_0_0_0_0_0; // beq
|
||||
7'b0010011: ControlsD = 21'b1_000_01_00_000_0_10_0_0_0_0_0_0_0; // I-type ALU
|
||||
7'b0011011: if (`XLEN == 64)
|
||||
ControlsD = 21'b1_000_01_00_000_0_10_0_0_1_0_0_0_0; // IW-type ALU for RV64i
|
||||
else
|
||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
||||
7'b1101111: ControlsD = 21'b1_011_00_00_010_0_00_1_0_0_0_0_0_0; // jal
|
||||
7'b1100111: ControlsD = 21'b1_000_00_00_010_0_00_1_1_0_0_0_0_0; // jalr
|
||||
7'b0010111: ControlsD = 21'b1_100_11_00_000_0_00_0_0_0_0_0_0_0; // auipc
|
||||
7'b0110111: ControlsD = 21'b1_100_01_00_000_0_11_0_0_0_0_0_0_0; // lui
|
||||
7'b0001111: ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_0; // fence = nop
|
||||
7'b1110011: if (Funct3D == 3'b000)
|
||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_1_0_0; // privileged; decoded further in priveleged modules
|
||||
else
|
||||
ControlsD = 21'b1_000_00_00_011_0_00_0_0_0_1_0_0_0; // csrs
|
||||
7'b0000000: ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // illegal instruction
|
||||
default: ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
||||
endcase
|
||||
endgenerate
|
||||
|
||||
// unswizzle control bits
|
||||
// squash control signals if coming from an illegal compressed instruction
|
||||
assign IllegalBaseInstrFaultD = ControlsD[0];
|
||||
assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD,
|
||||
ResultSrcD, BranchD, ALUOpD, JumpD, TargetSrcD, W64D, CSRWriteD,
|
||||
PrivilegedD} = ControlsD[18:1] & ~IllegalIEUInstrFaultD;
|
||||
ResultSrcD, BranchD, ALUOpD, JumpD, TargetSrcD, W64D, CSRWriteD,
|
||||
PrivilegedD, MulDivD, unused} = ControlsD & ~IllegalIEUInstrFaultD;
|
||||
// *** move Privileged, CSRwrite?? Or move controller out of IEU into datapath and handle all instructions
|
||||
|
||||
// ALU Decoding
|
||||
// ALU Decoding *** should move to ALU for better modularity
|
||||
assign sltD = (Funct3D == 3'b010);
|
||||
assign sltuD = (Funct3D == 3'b011);
|
||||
assign subD = (Funct3D == 3'b000 & Funct7b5D & OpD[5]);
|
||||
assign sraD = (Funct3D == 3'b101 & Funct7b5D);
|
||||
assign subD = (Funct3D == 3'b000 & Funct7D[5] & OpD[5]);
|
||||
assign sraD = (Funct3D == 3'b101 & Funct7D[5]);
|
||||
|
||||
assign aluc3D = subD | sraD | sltD | sltuD; // TRUE for R-type subtracts and sra, slt, sltu
|
||||
|
||||
@ -132,9 +145,9 @@ module controller(
|
||||
endcase
|
||||
|
||||
// Execute stage pipeline control register and logic
|
||||
floprc #(21) controlregE(clk, reset, FlushE,
|
||||
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, 1'b1},
|
||||
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE});
|
||||
floprc #(24) controlregE(clk, reset, FlushE,
|
||||
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, 1'b1},
|
||||
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, InstrValidE});
|
||||
|
||||
// Branch Logic
|
||||
assign {zeroE, ltE, ltuE} = FlagsE;
|
||||
@ -155,12 +168,12 @@ module controller(
|
||||
assign MemReadE = MemRWE[1];
|
||||
|
||||
// Memory stage pipeline control register
|
||||
floprc #(11) controlregM(clk, reset, FlushM,
|
||||
floprc #(12) controlregM(clk, reset, FlushM,
|
||||
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE},
|
||||
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM});
|
||||
|
||||
// Writeback stage pipeline control register
|
||||
floprc #(4) controlregW(clk, reset, FlushW,
|
||||
floprc #(5) controlregW(clk, reset, FlushW,
|
||||
{RegWriteM, ResultSrcM, InstrValidM},
|
||||
{RegWriteW, ResultSrcW, InstrValidW});
|
||||
|
||||
|
@ -41,19 +41,19 @@ module datapath (
|
||||
input logic [`XLEN-1:0] PCE,
|
||||
output logic [2:0] FlagsE,
|
||||
output logic [`XLEN-1:0] PCTargetE,
|
||||
output logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||
// Memory stage signals
|
||||
input logic FlushM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [`XLEN-1:0] CSRReadValW,
|
||||
input logic [`XLEN-1:0] ReadDataW,
|
||||
input logic RetM, TrapM,
|
||||
output logic [`XLEN-1:0] SrcAM,
|
||||
output logic [`XLEN-1:0] WriteDataM, MemAdrM,
|
||||
// Writeback stage signals
|
||||
input logic FlushW,
|
||||
input logic RegWriteW,
|
||||
input logic [1:0] ResultSrcW,
|
||||
input logic [2:0] ResultSrcW,
|
||||
input logic [`XLEN-1:0] PCLinkW,
|
||||
input logic [`XLEN-1:0] CSRReadValW, ReadDataW, MulDivResultW,
|
||||
// Hazard Unit signals
|
||||
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
|
||||
output logic [4:0] RdE, RdM, RdW
|
||||
@ -67,7 +67,7 @@ module datapath (
|
||||
// Execute stage signals
|
||||
logic [`XLEN-1:0] RD1E, RD2E;
|
||||
logic [`XLEN-1:0] ExtImmE;
|
||||
logic [`XLEN-1:0] PreSrcAE, SrcAE, SrcBE;
|
||||
logic [`XLEN-1:0] PreSrcAE;
|
||||
logic [`XLEN-1:0] ALUResultE;
|
||||
logic [`XLEN-1:0] WriteDataE;
|
||||
logic [`XLEN-1:0] TargetBaseE;
|
||||
@ -111,5 +111,5 @@ module datapath (
|
||||
floprc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW);
|
||||
floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW);
|
||||
|
||||
mux4 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, ResultSrcW, ResultW);
|
||||
mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW);
|
||||
endmodule
|
||||
|
@ -28,11 +28,11 @@
|
||||
module forward(
|
||||
// Detect hazards
|
||||
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
|
||||
input logic MemReadE,
|
||||
input logic MemReadE, MulDivE,
|
||||
input logic RegWriteM, RegWriteW,
|
||||
// Forwaring controls
|
||||
output logic [1:0] ForwardAE, ForwardBE,
|
||||
output logic LoadStallD
|
||||
output logic LoadStallD, MulDivStallD
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
@ -48,5 +48,6 @@ module forward(
|
||||
end
|
||||
|
||||
assign LoadStallD = MemReadE & ((Rs1D == RdE) | (Rs2D == RdE));
|
||||
assign MulDivStallD = MulDivE & & ((Rs1D == RdE) | (Rs2D == RdE)); // *** extend with stalls for divide
|
||||
|
||||
endmodule
|
||||
|
@ -34,6 +34,9 @@ module ieu (
|
||||
// Execute Stage interface
|
||||
input logic [`XLEN-1:0] PCE,
|
||||
output logic [`XLEN-1:0] PCTargetE,
|
||||
output logic MulDivE, W64E,
|
||||
output logic [2:0] Funct3E,
|
||||
output logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||
// Memory stage interface
|
||||
input logic DataMisalignedM,
|
||||
input logic DataAccessFaultM,
|
||||
@ -42,14 +45,13 @@ module ieu (
|
||||
output logic [`XLEN-1:0] SrcAM,
|
||||
output logic [2:0] Funct3M,
|
||||
// Writeback stage
|
||||
input logic [`XLEN-1:0] ReadDataW,
|
||||
input logic [`XLEN-1:0] CSRReadValW,
|
||||
input logic [`XLEN-1:0] CSRReadValW, ReadDataW, MulDivResultW,
|
||||
input logic [`XLEN-1:0] PCLinkW,
|
||||
output logic InstrValidW,
|
||||
// hazards
|
||||
input logic StallD, FlushD, FlushE, FlushM, FlushW,
|
||||
input logic RetM, TrapM,
|
||||
output logic LoadStallD,
|
||||
output logic LoadStallD, MulDivStallD,
|
||||
output logic PCSrcE,
|
||||
|
||||
output logic CSRWriteM, PrivilegedM,
|
||||
@ -60,7 +62,7 @@ module ieu (
|
||||
logic [2:0] FlagsE;
|
||||
logic [4:0] ALUControlE;
|
||||
logic ALUSrcAE, ALUSrcBE;
|
||||
logic [1:0] ResultSrcW;
|
||||
logic [2:0] ResultSrcW;
|
||||
logic TargetSrcE;
|
||||
|
||||
// forwarding signals
|
||||
@ -69,7 +71,7 @@ module ieu (
|
||||
logic RegWriteM, RegWriteW;
|
||||
logic MemReadE;
|
||||
|
||||
controller c(.OpD(InstrD[6:0]), .Funct3D(InstrD[14:12]), .Funct7b5D(InstrD[30]), .*);
|
||||
controller c(.OpD(InstrD[6:0]), .Funct3D(InstrD[14:12]), .Funct7D(InstrD[31:25]), .*);
|
||||
datapath dp(.*);
|
||||
forward fw(.*);
|
||||
endmodule
|
||||
|
1
wally-pipelined/src/muldiv/div/README
Executable file
1
wally-pipelined/src/muldiv/div/README
Executable file
@ -0,0 +1 @@
|
||||
vsim -do iter64.do -c
|
22
wally-pipelined/src/muldiv/div/README.md
Normal file
22
wally-pipelined/src/muldiv/div/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
This is a novel integer divider using r4 division by recurrence. The
|
||||
reference is:
|
||||
|
||||
J. E. Stine and K. Hill, "An Efficient Implementation of Radix-4
|
||||
Integer Division Using Scaling," 2020 IEEE 63rd International Midwest
|
||||
Symposium on Circuits and Systems (MWSCAS), Springfield, MA, USA,
|
||||
2020, pp. 1092-1095, doi: 10.1109/MWSCAS48704.2020.9184631.
|
||||
|
||||
Although this version does not contain scaling, it could do this, if
|
||||
needed. Moreover, a higher radix or overlapped radix can be done
|
||||
easily to expand the the size. Also, the implementations here are
|
||||
initially unsigned but hope to expand for signed, which should be
|
||||
easy.
|
||||
|
||||
There are two types of tests in this directory within each testbench.
|
||||
One tests for 32-bits and the other 64-bits:
|
||||
|
||||
int32div.do and int64div.do = test individual vector for debugging
|
||||
|
||||
iter32.do and iter64.do = do not use any waveform generation and just
|
||||
output lots of tests
|
||||
|
1302
wally-pipelined/src/muldiv/div/divide4x32.sv
Executable file
1302
wally-pipelined/src/muldiv/div/divide4x32.sv
Executable file
File diff suppressed because it is too large
Load Diff
1921
wally-pipelined/src/muldiv/div/divide4x64.sv
Executable file
1921
wally-pipelined/src/muldiv/div/divide4x64.sv
Executable file
File diff suppressed because it is too large
Load Diff
114
wally-pipelined/src/muldiv/div/int32div.do
Executable file
114
wally-pipelined/src/muldiv/div/int32div.do
Executable file
@ -0,0 +1,114 @@
|
||||
# Copyright 1991-2007 Mentor Graphics Corporation
|
||||
#
|
||||
# Modification by Oklahoma State University
|
||||
# Use with Testbench
|
||||
# James Stine, 2008
|
||||
# Go Cowboys!!!!!!
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION
|
||||
# WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION
|
||||
# OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
|
||||
|
||||
# Use this run.do file to run this example.
|
||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||
# do run.do
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do run.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
vlog muxs.sv shifters.sv divide4x32.sv test_int32div.sv
|
||||
|
||||
# start and run simulation
|
||||
vsim -voptargs=+acc work.tb
|
||||
|
||||
view list
|
||||
view wave
|
||||
|
||||
-- display input and output signals as hexidecimal values
|
||||
# Diplays All Signals recursively
|
||||
add wave -noupdate -divider -height 32 "Control Signals"
|
||||
add wave -hex -color gold /tb/clk
|
||||
add wave -hex -color #0080ff /tb/reset
|
||||
add wave -hex -color #0080ff /tb/start
|
||||
add wave -hex -color #0080ff /tb/done
|
||||
add wave -hex -color #0080ff /tb/divdone
|
||||
add wave -noupdate -divider -height 32 "Key Parts"
|
||||
add wave -unsigned /tb/dut/NumIter
|
||||
add wave -unsigned /tb/dut/RemShift
|
||||
add wave -unsigned /tb/dut/Qd2
|
||||
add wave -unsigned /tb/dut/Rd2
|
||||
add wave -unsigned /tb/dut/rem0
|
||||
add wave -unsigned /tb/dut/Q
|
||||
add wave -unsigned /tb/dut/P
|
||||
add wave -unsigned /tb/dut/shiftResult
|
||||
add wave -noupdate -divider -height 32 "FSM"
|
||||
add wave -hex /tb/dut/fsm1/CURRENT_STATE
|
||||
add wave -hex /tb/dut/fsm1/NEXT_STATE
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/start
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/state0
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/done
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/en
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/divdone
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/reset
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/otfzero
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/LT
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/EQ
|
||||
add wave -hex -color gold /tb/dut/fsm1/clk
|
||||
add wave -noupdate -divider -height 32 "Datapath"
|
||||
add wave -hex /tb/dut/N
|
||||
add wave -hex /tb/dut/D
|
||||
add wave -hex /tb/dut/reset
|
||||
add wave -hex /tb/dut/start
|
||||
add wave -hex /tb/dut/Q
|
||||
add wave -hex /tb/dut/rem0
|
||||
add wave -hex /tb/dut/div0
|
||||
add wave -hex /tb/dut/done
|
||||
add wave -hex /tb/dut/divdone
|
||||
add wave -hex /tb/dut/enable
|
||||
add wave -hex /tb/dut/state0
|
||||
add wave -hex /tb/dut/V
|
||||
add wave -hex /tb/dut/Num
|
||||
add wave -hex /tb/dut/P
|
||||
add wave -hex /tb/dut/NumIter
|
||||
add wave -hex /tb/dut/RemShift
|
||||
add wave -hex /tb/dut/op1
|
||||
add wave -hex /tb/dut/op2
|
||||
add wave -hex /tb/dut/op1shift
|
||||
add wave -hex /tb/dut/Rem5
|
||||
add wave -hex /tb/dut/Qd
|
||||
add wave -hex /tb/dut/Rd
|
||||
add wave -hex /tb/dut/Qd2
|
||||
add wave -hex /tb/dut/Rd2
|
||||
add wave -hex /tb/dut/quotient
|
||||
add wave -hex /tb/dut/otfzero
|
||||
add wave -noupdate -divider -height 32 "Divider"
|
||||
add wave -hex -r /tb/dut/p3/*
|
||||
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {75 ns}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
|
||||
-- Run the Simulation
|
||||
run 138ns
|
||||
|
||||
|
114
wally-pipelined/src/muldiv/div/int64div.do
Executable file
114
wally-pipelined/src/muldiv/div/int64div.do
Executable file
@ -0,0 +1,114 @@
|
||||
# Copyright 1991-2007 Mentor Graphics Corporation
|
||||
#
|
||||
# Modification by Oklahoma State University
|
||||
# Use with Testbench
|
||||
# James Stine, 2008
|
||||
# Go Cowboys!!!!!!
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION
|
||||
# WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION
|
||||
# OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
|
||||
|
||||
# Use this run.do file to run this example.
|
||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||
# do run.do
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do run.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
vlog muxs.sv shifters.sv divide4x64.sv test_int64div.sv
|
||||
|
||||
# start and run simulation
|
||||
vsim -voptargs=+acc work.tb
|
||||
|
||||
view list
|
||||
view wave
|
||||
|
||||
-- display input and output signals as hexidecimal values
|
||||
# Diplays All Signals recursively
|
||||
add wave -noupdate -divider -height 32 "Control Signals"
|
||||
add wave -hex -color gold /tb/clk
|
||||
add wave -hex -color #0080ff /tb/reset
|
||||
add wave -hex -color #0080ff /tb/start
|
||||
add wave -hex -color #0080ff /tb/done
|
||||
add wave -hex -color #0080ff /tb/divdone
|
||||
add wave -noupdate -divider -height 32 "Key Parts"
|
||||
add wave -unsigned /tb/dut/NumIter
|
||||
add wave -unsigned /tb/dut/RemShift
|
||||
add wave -unsigned /tb/dut/Qd2
|
||||
add wave -unsigned /tb/dut/Rd2
|
||||
add wave -unsigned /tb/dut/rem0
|
||||
add wave -unsigned /tb/dut/Q
|
||||
add wave -unsigned /tb/dut/P
|
||||
add wave -unsigned /tb/dut/shiftResult
|
||||
add wave -noupdate -divider -height 32 "FSM"
|
||||
add wave -hex /tb/dut/fsm1/CURRENT_STATE
|
||||
add wave -hex /tb/dut/fsm1/NEXT_STATE
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/start
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/state0
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/done
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/en
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/divdone
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/reset
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/otfzero
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/LT
|
||||
add wave -hex -color #0080ff /tb/dut/fsm1/EQ
|
||||
add wave -hex -color gold /tb/dut/fsm1/clk
|
||||
add wave -noupdate -divider -height 32 "Datapath"
|
||||
add wave -hex /tb/dut/N
|
||||
add wave -hex /tb/dut/D
|
||||
add wave -hex /tb/dut/reset
|
||||
add wave -hex /tb/dut/start
|
||||
add wave -hex /tb/dut/Q
|
||||
add wave -hex /tb/dut/rem0
|
||||
add wave -hex /tb/dut/div0
|
||||
add wave -hex /tb/dut/done
|
||||
add wave -hex /tb/dut/divdone
|
||||
add wave -hex /tb/dut/enable
|
||||
add wave -hex /tb/dut/state0
|
||||
add wave -hex /tb/dut/V
|
||||
add wave -hex /tb/dut/Num
|
||||
add wave -hex /tb/dut/P
|
||||
add wave -hex /tb/dut/NumIter
|
||||
add wave -hex /tb/dut/RemShift
|
||||
add wave -hex /tb/dut/op1
|
||||
add wave -hex /tb/dut/op2
|
||||
add wave -hex /tb/dut/op1shift
|
||||
add wave -hex /tb/dut/Rem5
|
||||
add wave -hex /tb/dut/Qd
|
||||
add wave -hex /tb/dut/Rd
|
||||
add wave -hex /tb/dut/Qd2
|
||||
add wave -hex /tb/dut/Rd2
|
||||
add wave -hex /tb/dut/quotient
|
||||
add wave -hex /tb/dut/otfzero
|
||||
add wave -noupdate -divider -height 32 "Divider"
|
||||
add wave -hex -r /tb/dut/p3/*
|
||||
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {75 ns}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
|
||||
-- Run the Simulation
|
||||
run 138ns
|
||||
|
||||
|
50
wally-pipelined/src/muldiv/div/iter32.do
Executable file
50
wally-pipelined/src/muldiv/div/iter32.do
Executable file
@ -0,0 +1,50 @@
|
||||
# Copyright 1991-2007 Mentor Graphics Corporation
|
||||
#
|
||||
# Modification by Oklahoma State University
|
||||
# Use with Testbench
|
||||
# James Stine, 2008
|
||||
# Go Cowboys!!!!!!
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION
|
||||
# WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION
|
||||
# OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
|
||||
|
||||
# Use this run.do file to run this example.
|
||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||
# do run.do
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do run.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
vlog muxs.sv shifters.sv divide4x32.sv test_iter32.sv
|
||||
|
||||
# start and run simulation
|
||||
vsim -voptargs=+acc work.tb
|
||||
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {75 ns}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
|
||||
-- Run the Simulation
|
||||
run 9586700ns
|
||||
quit
|
50
wally-pipelined/src/muldiv/div/iter64.do
Executable file
50
wally-pipelined/src/muldiv/div/iter64.do
Executable file
@ -0,0 +1,50 @@
|
||||
# Copyright 1991-2007 Mentor Graphics Corporation
|
||||
#
|
||||
# Modification by Oklahoma State University
|
||||
# Use with Testbench
|
||||
# James Stine, 2008
|
||||
# Go Cowboys!!!!!!
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION
|
||||
# WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION
|
||||
# OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
|
||||
|
||||
# Use this run.do file to run this example.
|
||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||
# do run.do
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do run.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
vlog muxs.sv shifters.sv divide4x64.sv test_iter64.sv
|
||||
|
||||
# start and run simulation
|
||||
vsim -voptargs=+acc work.tb
|
||||
|
||||
|
||||
-- Set Wave Output Items
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {75 ns}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
|
||||
-- Run the Simulation
|
||||
run 9586700ns
|
||||
quit
|
51
wally-pipelined/src/muldiv/div/muxs.sv
Normal file
51
wally-pipelined/src/muldiv/div/muxs.sv
Normal file
@ -0,0 +1,51 @@
|
||||
module mux2 #(parameter WIDTH = 8)
|
||||
(input logic [WIDTH-1:0] d0, d1,
|
||||
input logic s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s ? d1 : d0;
|
||||
|
||||
endmodule // mux2
|
||||
|
||||
module mux3 #(parameter WIDTH = 8)
|
||||
(input logic [WIDTH-1:0] d0, d1, d2,
|
||||
input logic [1:0] s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s[1] ? d2 : (s[0] ? d1 : d0);
|
||||
|
||||
endmodule // mux3
|
||||
|
||||
module mux4 #(parameter WIDTH = 8)
|
||||
(input logic [WIDTH-1:0] d0, d1, d2, d3,
|
||||
input logic [1:0] s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0);
|
||||
|
||||
endmodule // mux4
|
||||
|
||||
module mux21x32 (Z, A, B, Sel);
|
||||
|
||||
input logic [31:0] A;
|
||||
input logic [31:0] B;
|
||||
input logic Sel;
|
||||
|
||||
output logic [31:0] Z;
|
||||
|
||||
assign Z = Sel ? B : A;
|
||||
|
||||
endmodule // mux21x32
|
||||
|
||||
module mux21x64 (Z, A, B, Sel);
|
||||
|
||||
input logic [63:0] A;
|
||||
input logic [63:0] B;
|
||||
input logic Sel;
|
||||
|
||||
output logic [63:0] Z;
|
||||
|
||||
assign Z = Sel ? B : A;
|
||||
|
||||
endmodule // mux21x64
|
||||
|
106
wally-pipelined/src/muldiv/div/shifters.sv
Normal file
106
wally-pipelined/src/muldiv/div/shifters.sv
Normal file
@ -0,0 +1,106 @@
|
||||
module shifter_l64 (Z, A, Shift);
|
||||
|
||||
input logic [63:0] A;
|
||||
input logic [5:0] Shift;
|
||||
|
||||
logic [63:0] stage1;
|
||||
logic [63:0] stage2;
|
||||
logic [63:0] stage3;
|
||||
logic [63:0] stage4;
|
||||
logic [63:0] stage5;
|
||||
logic [31:0] thirtytwozeros = 32'h0;
|
||||
logic [15:0] sixteenzeros = 16'h0;
|
||||
logic [ 7:0] eightzeros = 8'h0;
|
||||
logic [ 3:0] fourzeros = 4'h0;
|
||||
logic [ 1:0] twozeros = 2'b00;
|
||||
logic onezero = 1'b0;
|
||||
|
||||
output logic [63:0] Z;
|
||||
|
||||
mux21x64 mx01(stage1, A, {A[31:0], thirtytwozeros}, Shift[5]);
|
||||
mux21x64 mx02(stage2, stage1, {stage1[47:0], sixteenzeros}, Shift[4]);
|
||||
mux21x64 mx03(stage3, stage2, {stage2[55:0], eightzeros}, Shift[3]);
|
||||
mux21x64 mx04(stage4, stage3, {stage3[59:0], fourzeros}, Shift[2]);
|
||||
mux21x64 mx05(stage5, stage4, {stage4[61:0], twozeros}, Shift[1]);
|
||||
mux21x64 mx06(Z, stage5, {stage5[62:0], onezero}, Shift[0]);
|
||||
|
||||
endmodule // shifter_l64
|
||||
|
||||
module shifter_r64 (Z, A, Shift);
|
||||
|
||||
input logic [63:0] A;
|
||||
input logic [5:0] Shift;
|
||||
|
||||
logic [63:0] stage1;
|
||||
logic [63:0] stage2;
|
||||
logic [63:0] stage3;
|
||||
logic [63:0] stage4;
|
||||
logic [63:0] stage5;
|
||||
logic [31:0] thirtytwozeros = 32'h0;
|
||||
logic [15:0] sixteenzeros = 16'h0;
|
||||
logic [ 7:0] eightzeros = 8'h0;
|
||||
logic [ 3:0] fourzeros = 4'h0;
|
||||
logic [ 1:0] twozeros = 2'b00;
|
||||
logic onezero = 1'b0;
|
||||
|
||||
output logic [63:0] Z;
|
||||
|
||||
mux21x64 mx01(stage1, A, {thirtytwozeros, A[63:32]}, Shift[5]);
|
||||
mux21x64 mx02(stage2, stage1, {sixteenzeros, stage1[63:16]}, Shift[4]);
|
||||
mux21x64 mx03(stage3, stage2, {eightzeros, stage2[63:8]}, Shift[3]);
|
||||
mux21x64 mx04(stage4, stage3, {fourzeros, stage3[63:4]}, Shift[2]);
|
||||
mux21x64 mx05(stage5, stage4, {twozeros, stage4[63:2]}, Shift[1]);
|
||||
mux21x64 mx06(Z, stage5, {onezero, stage5[63:1]}, Shift[0]);
|
||||
|
||||
endmodule // shifter_r64
|
||||
|
||||
module shifter_l32 (Z, A, Shift);
|
||||
|
||||
input logic [31:0] A;
|
||||
input logic [4:0] Shift;
|
||||
|
||||
logic [31:0] stage1;
|
||||
logic [31:0] stage2;
|
||||
logic [31:0] stage3;
|
||||
logic [31:0] stage4;
|
||||
logic [15:0] sixteenzeros = 16'h0;
|
||||
logic [ 7:0] eightzeros = 8'h0;
|
||||
logic [ 3:0] fourzeros = 4'h0;
|
||||
logic [ 1:0] twozeros = 2'b00;
|
||||
logic onezero = 1'b0;
|
||||
|
||||
output logic [31:0] Z;
|
||||
|
||||
mux21x32 mx01(stage1, A, {A[15:0], sixteenzeros}, Shift[4]);
|
||||
mux21x32 mx02(stage2, stage1, {stage1[23:0], eightzeros}, Shift[3]);
|
||||
mux21x32 mx03(stage3, stage2, {stage2[27:0], fourzeros}, Shift[2]);
|
||||
mux21x32 mx04(stage4, stage3, {stage3[29:0], twozeros}, Shift[1]);
|
||||
mux21x32 mx05(Z , stage4, {stage4[30:0], onezero}, Shift[0]);
|
||||
|
||||
endmodule // shifter_l32
|
||||
|
||||
module shifter_r32 (Z, A, Shift);
|
||||
|
||||
input logic [31:0] A;
|
||||
input logic [4:0] Shift;
|
||||
|
||||
logic [31:0] stage1;
|
||||
logic [31:0] stage2;
|
||||
logic [31:0] stage3;
|
||||
logic [31:0] stage4;
|
||||
logic [15:0] sixteenzeros = 16'h0;
|
||||
logic [ 7:0] eightzeros = 8'h0;
|
||||
logic [ 3:0] fourzeros = 4'h0;
|
||||
logic [ 1:0] twozeros = 2'b00;
|
||||
logic onezero = 1'b0;
|
||||
|
||||
output logic [31:0] Z;
|
||||
|
||||
mux21x32 mx01(stage1, A, {sixteenzeros, A[31:16]}, Shift[4]);
|
||||
mux21x32 mx02(stage2, stage1, {eightzeros, stage1[31:8]}, Shift[3]);
|
||||
mux21x32 mx03(stage3, stage2, {fourzeros, stage2[31:4]}, Shift[2]);
|
||||
mux21x32 mx04(stage4, stage3, {twozeros, stage3[31:2]}, Shift[1]);
|
||||
mux21x32 mx05(Z , stage4, {onezero, stage4[31:1]}, Shift[0]);
|
||||
|
||||
endmodule // shifter_r32
|
||||
|
50
wally-pipelined/src/muldiv/div/test_int32div.sv
Executable file
50
wally-pipelined/src/muldiv/div/test_int32div.sv
Executable file
@ -0,0 +1,50 @@
|
||||
module tb;
|
||||
|
||||
logic [31:0] N, D;
|
||||
logic clk;
|
||||
logic reset;
|
||||
logic start;
|
||||
|
||||
logic [31:0] Q;
|
||||
logic [31:0] rem;
|
||||
logic div0;
|
||||
logic done;
|
||||
logic divdone;
|
||||
|
||||
integer handle3;
|
||||
integer desc3;
|
||||
integer i;
|
||||
|
||||
logic [7:0] count [0:15];
|
||||
|
||||
int32div dut (Q, done, divdone, rem, div0, N, D, clk, reset, start);
|
||||
|
||||
initial
|
||||
begin
|
||||
clk = 1'b0;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
#800 $finish;
|
||||
end
|
||||
|
||||
|
||||
initial
|
||||
begin
|
||||
#0 N = 32'h0;
|
||||
#0 D = 32'h0;
|
||||
#0 start = 1'b0;
|
||||
#0 reset = 1'b1;
|
||||
#22 reset = 1'b0;
|
||||
//#25 N = 32'h9830_07C0;
|
||||
//#0 D = 32'h0000_000C;
|
||||
#25 N = 32'h06b9_7b0d;
|
||||
#0 D = 32'h46df_998d;
|
||||
#0 start = 1'b1;
|
||||
#50 start = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
endmodule // tb
|
51
wally-pipelined/src/muldiv/div/test_int64div.sv
Normal file
51
wally-pipelined/src/muldiv/div/test_int64div.sv
Normal file
@ -0,0 +1,51 @@
|
||||
module tb;
|
||||
|
||||
logic [63:0] N, D;
|
||||
logic clk;
|
||||
logic reset;
|
||||
logic start;
|
||||
|
||||
logic [63:0] Q;
|
||||
logic [63:0] rem;
|
||||
logic div0;
|
||||
logic done;
|
||||
logic divdone;
|
||||
|
||||
integer handle3;
|
||||
integer desc3;
|
||||
integer i;
|
||||
|
||||
logic [7:0] count [0:15];
|
||||
|
||||
int64div dut (Q, done, divdone, rem, div0, N, D, clk, reset, start);
|
||||
|
||||
initial
|
||||
begin
|
||||
clk = 1'b0;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
#800 $finish;
|
||||
end
|
||||
|
||||
|
||||
initial
|
||||
begin
|
||||
#0 N = 64'h0;
|
||||
#0 D = 64'h0;
|
||||
#0 start = 1'b0;
|
||||
#0 reset = 1'b1;
|
||||
#22 reset = 1'b0;
|
||||
//#25 N = 64'h0000_0000_9830_07C0;
|
||||
//#0 D = 64'h0000_0000_0000_000C;
|
||||
#25 N = 64'h0000_0000_06b9_7b0d;
|
||||
#0 D = 64'h0000_0000_46df_998d;
|
||||
#0 start = 1'b1;
|
||||
#50 start = 1'b0;
|
||||
|
||||
|
||||
end
|
||||
|
||||
endmodule // tb
|
74
wally-pipelined/src/muldiv/div/test_iter32.sv
Executable file
74
wally-pipelined/src/muldiv/div/test_iter32.sv
Executable file
@ -0,0 +1,74 @@
|
||||
module tb;
|
||||
|
||||
logic [31:0] N, D;
|
||||
logic clk;
|
||||
logic reset;
|
||||
logic start;
|
||||
|
||||
logic [31:0] Q;
|
||||
logic [31:0] rem0;
|
||||
logic div0;
|
||||
logic done;
|
||||
logic divdone;
|
||||
|
||||
integer handle3;
|
||||
integer desc3;
|
||||
integer i;
|
||||
|
||||
bit [31:0] Ncomp;
|
||||
bit [31:0] Dcomp;
|
||||
bit [31:0] Qcomp;
|
||||
bit [31:0] Rcomp;
|
||||
|
||||
logic [7:0] count [0:15];
|
||||
|
||||
int32div dut (Q, done, divdone, rem0, div0, N, D, clk, reset, start);
|
||||
|
||||
initial
|
||||
begin
|
||||
clk = 1'b0;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
handle3 = $fopen("iter32.out");
|
||||
#8000000 $finish;
|
||||
end
|
||||
|
||||
always @(posedge clk, posedge reset)
|
||||
begin
|
||||
desc3 = handle3;
|
||||
#0 start = 1'b0;
|
||||
#0 reset = 1'b1;
|
||||
#30 reset = 1'b0;
|
||||
for (i=0; i<2; i=i+1)
|
||||
begin
|
||||
N = $random;
|
||||
D = $random;
|
||||
start <= 1'b1;
|
||||
// Wait 2 cycles (to be sure)
|
||||
repeat (2)
|
||||
@(posedge clk);
|
||||
start <= 1'b0;
|
||||
repeat (25)
|
||||
@(posedge clk);
|
||||
Ncomp = N;
|
||||
Dcomp = D;
|
||||
Qcomp = Ncomp/Dcomp;
|
||||
Rcomp = Ncomp%Dcomp;
|
||||
$fdisplay(desc3, "%h %h %h %h || %h %h || %b %b",
|
||||
N, D, Q, rem0, Qcomp, Rcomp,
|
||||
(Q==Qcomp), (rem0==Rcomp));
|
||||
end // for (i=0; i<2, i=i+1)
|
||||
|
||||
|
||||
end
|
||||
|
||||
endmodule // tb
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
72
wally-pipelined/src/muldiv/div/test_iter64.sv
Executable file
72
wally-pipelined/src/muldiv/div/test_iter64.sv
Executable file
@ -0,0 +1,72 @@
|
||||
module tb;
|
||||
|
||||
logic [63:0] N, D;
|
||||
logic clk;
|
||||
logic reset;
|
||||
logic start;
|
||||
|
||||
logic [63:0] Q;
|
||||
logic [63:0] rem0;
|
||||
logic div0;
|
||||
logic done;
|
||||
logic divdone;
|
||||
|
||||
integer handle3;
|
||||
integer desc3;
|
||||
integer i;
|
||||
|
||||
bit [63:0] Ncomp;
|
||||
bit [63:0] Dcomp;
|
||||
bit [63:0] Qcomp;
|
||||
bit [63:0] Rcomp;
|
||||
|
||||
logic [7:0] count [0:15];
|
||||
|
||||
int64div dut (Q, done, divdone, rem0, div0, N, D, clk, reset, start);
|
||||
|
||||
initial
|
||||
begin
|
||||
clk = 1'b0;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
handle3 = $fopen("iter64.out");
|
||||
#8000000 $finish;
|
||||
end
|
||||
|
||||
always @(posedge clk, posedge reset)
|
||||
begin
|
||||
desc3 = handle3;
|
||||
#0 start = 1'b0;
|
||||
#0 reset = 1'b1;
|
||||
#30 reset = 1'b0;
|
||||
for (i=0; i<2; i=i+1)
|
||||
begin
|
||||
N = $random;
|
||||
D = $random;
|
||||
start <= 1'b1;
|
||||
// Wait 2 cycles (to be sure)
|
||||
repeat (2)
|
||||
@(posedge clk);
|
||||
start <= 1'b0;
|
||||
repeat (41)
|
||||
@(posedge clk);
|
||||
Ncomp = N;
|
||||
Dcomp = D;
|
||||
Qcomp = Ncomp/Dcomp;
|
||||
Rcomp = Ncomp%Dcomp;
|
||||
$fdisplay(desc3, "%h %h %h %h || %h %h || %b %b",
|
||||
N, D, Q, rem0, Qcomp, Rcomp,
|
||||
(Q==Qcomp), (rem0==Rcomp));
|
||||
end // for (i=0; i<2, i=i+1)
|
||||
end
|
||||
|
||||
endmodule // tb
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
76
wally-pipelined/src/muldiv/muldiv.sv
Normal file
76
wally-pipelined/src/muldiv/muldiv.sv
Normal file
@ -0,0 +1,76 @@
|
||||
///////////////////////////////////////////
|
||||
// muldiv.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 9 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: M extension multiply and divide
|
||||
//
|
||||
// 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 muldiv (
|
||||
input logic clk, reset,
|
||||
// Decode Stage interface
|
||||
input logic [31:0] InstrD,
|
||||
// Execute Stage interface
|
||||
input logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||
input logic [2:0] Funct3E,
|
||||
input logic MulDivE, W64E,
|
||||
// Writeback stage
|
||||
output logic [`XLEN-1:0] MulDivResultW,
|
||||
// hazards
|
||||
input logic FlushM, FlushW
|
||||
);
|
||||
|
||||
generate
|
||||
if (`M_SUPPORTED) begin
|
||||
logic [`XLEN-1:0] MulDivResultE, MulDivResultM;
|
||||
logic [`XLEN-1:0] PrelimResultE;
|
||||
logic [`XLEN-1:0] QuotE, RemE;
|
||||
logic [`XLEN*2-1:0] ProdE;
|
||||
|
||||
// Select result
|
||||
always_comb
|
||||
case (Funct3E)
|
||||
3'b000: PrelimResultE = ProdE[`XLEN-1:0];
|
||||
3'b001: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b010: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b011: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b100: PrelimResultE = QuotE;
|
||||
3'b101: PrelimResultE = QuotE;
|
||||
3'b110: PrelimResultE = RemE;
|
||||
3'b111: PrelimResultE = RemE;
|
||||
endcase
|
||||
|
||||
// Handle sign extension for W-type instructions
|
||||
if (`XLEN == 64) begin // RV64 has W-type instructions
|
||||
assign MulDivResultE = W64E ? {{32{PrelimResultE[31]}}, PrelimResultE[31:0]} : PrelimResultE;
|
||||
end else begin // RV32 has no W-type instructions
|
||||
assign MulDivResultE = PrelimResultE;
|
||||
end
|
||||
|
||||
floprc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, MulDivResultE, MulDivResultM);
|
||||
floprc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, MulDivResultM, MulDivResultW);
|
||||
end else begin // no M instructions supported
|
||||
assign MulDivResultW = 0;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
53
wally-pipelined/src/tlb_toy/tlb_testbench.sv
Normal file
53
wally-pipelined/src/tlb_toy/tlb_testbench.sv
Normal file
@ -0,0 +1,53 @@
|
||||
module testbench();
|
||||
logic clk, reset;
|
||||
|
||||
// DUT inputs
|
||||
logic [31:0] PCF;
|
||||
logic [31:0] PageTableEntryF;
|
||||
logic ITLBWriteF, ITLBFlushF;
|
||||
|
||||
// DUT outputs
|
||||
logic [31:0] PCPF;
|
||||
logic ITLBMissF, ITLBHitF;
|
||||
|
||||
// Testbench signals
|
||||
logic [33:0] expected;
|
||||
logic [31:0] vectornum, errors;
|
||||
logic [99:0] testvectors[10000:0];
|
||||
|
||||
// instantiate device under test
|
||||
tlb_toy dut(.*);
|
||||
|
||||
// generate clock
|
||||
always begin
|
||||
clk=1; #5; clk=0; #5;
|
||||
end
|
||||
|
||||
// at start of test, load vectors and pulse reset
|
||||
initial begin
|
||||
$readmemb("tlb_toy.tv", testvectors);
|
||||
vectornum = 0; errors = 0; reset = 1; #22; reset = 0;
|
||||
end
|
||||
|
||||
// apply test vectors on rising edge of clk
|
||||
always @(posedge clk) begin
|
||||
#1; {PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF, expected} = testvectors[vectornum];
|
||||
end
|
||||
|
||||
// check results on falling edge of clk
|
||||
always @(negedge clk)
|
||||
if (~reset) begin // skip during reset
|
||||
if ({PCPF, ITLBMissF, ITLBHitF} !== expected) begin // check result
|
||||
$display("Error: PCF = %b, write = %b, data = %b, flush = %b", PCF,
|
||||
ITLBWriteF, PageTableEntryF, ITLBFlushF);
|
||||
$display(" outputs = %b %b %b (%b expected)",
|
||||
PCPF, ITLBMissF, ITLBHitF, expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
vectornum = vectornum + 1;
|
||||
if (testvectors[vectornum] === 100'bx) begin
|
||||
$display("%d tests completed with %d errors", vectornum, errors);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
endmodule
|
208
wally-pipelined/src/tlb_toy/tlb_toy.sv
Normal file
208
wally-pipelined/src/tlb_toy/tlb_toy.sv
Normal file
@ -0,0 +1,208 @@
|
||||
///////////////////////////////////////////
|
||||
// tlb_toy.sv
|
||||
//
|
||||
// Written: jtorrey@hmc.edu 16 February 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Example translation lookaside buffer
|
||||
// Cache of virtural-to-physical address translations
|
||||
//
|
||||
// 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"
|
||||
|
||||
/**
|
||||
* sv32 specs
|
||||
* ----------
|
||||
* Virtual address [31:0] (32 bits)
|
||||
* [________________________________]
|
||||
* |--VPN1--||--VPN0--||----OFF---|
|
||||
* 10 10 12
|
||||
*
|
||||
* Physical address [33:0] (34 bits)
|
||||
* [__________________________________]
|
||||
* |---PPN1---||--PPN0--||----OFF---|
|
||||
* 12 10 12
|
||||
*
|
||||
* Page Table Entry [31:0] (32 bits)
|
||||
* [________________________________]
|
||||
* |---PPN1---||--PPN0--|||DAGUXWRV
|
||||
* 12 10 ^^
|
||||
* RSW(2) -- for OS
|
||||
*/
|
||||
|
||||
/* *** TODO:
|
||||
* - add LRU algorithm (select the write index based on which entry was used
|
||||
* least recently)
|
||||
* - rename signals to use .* notation in CAM and RAM
|
||||
*/
|
||||
|
||||
module tlb_toy (
|
||||
input clk, reset,
|
||||
|
||||
// Virtual address input
|
||||
input [31:0] PCF,
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
input [31:0] PageTableEntryF,
|
||||
input ITLBWriteF,
|
||||
|
||||
// Invalidate all TLB entries
|
||||
input ITLBFlushF,
|
||||
|
||||
// Physical address outputs
|
||||
output [31:0] PCPF,
|
||||
output ITLBMissF,
|
||||
output ITLBHitF
|
||||
);
|
||||
// Index (currently random) to write the next TLB entry
|
||||
logic [2:0] WriteIndexF;
|
||||
|
||||
// Sections of the virtual and physical addresses
|
||||
logic [19:0] VirtualPageNumberF;
|
||||
logic [21:0] PhysicalPageNumberF;
|
||||
logic [11:0] PageOffsetF;
|
||||
logic [33:0] PhysicalAddressF;
|
||||
|
||||
// Pattern and pattern location in the CAM
|
||||
logic [2:0] VPNIndexF;
|
||||
|
||||
// RAM access location
|
||||
logic [2:0] ITLBEntryIndex;
|
||||
|
||||
// Page table entry matching the virtual address
|
||||
logic [31:0] PTEMatchF;
|
||||
|
||||
assign VirtualPageNumberF = PCF[31:12];
|
||||
assign PageOffsetF = PCF[11:0];
|
||||
|
||||
// Choose a read or write location to the entry list
|
||||
mux2 #(3) indexmux(VPNIndexF, WriteIndexF, ITLBWriteF, ITLBEntryIndex);
|
||||
|
||||
// Currently use random replacement algorithm
|
||||
rand3 rdm(clk, reset, WriteIndexF);
|
||||
|
||||
ram8x32 ram(clk, reset, ITLBEntryIndex, PageTableEntryF, ITLBWriteF, PTEMatchF);
|
||||
cam8x21 cam(clk, reset, ITLBWriteF, VirtualPageNumberF, WriteIndexF,
|
||||
ITLBFlushF, VPNIndexF, ITLBHitF);
|
||||
|
||||
always_comb begin
|
||||
assign PhysicalPageNumberF = PTEMatchF[31:10];
|
||||
|
||||
if (ITLBHitF) begin
|
||||
assign PhysicalAddressF = {PhysicalPageNumberF, PageOffsetF};
|
||||
end else begin
|
||||
assign PhysicalAddressF = 34'b0;
|
||||
end
|
||||
end
|
||||
|
||||
assign PCPF = PhysicalAddressF[31:0];
|
||||
assign ITLBMissF = ~ITLBHitF & ~(ITLBWriteF | ITLBFlushF);
|
||||
|
||||
endmodule
|
||||
|
||||
// *** Add parameter for number of tlb lines (currently 8)
|
||||
module ram8x32 (
|
||||
input clk, reset,
|
||||
input [2:0] address,
|
||||
input [31:0] data,
|
||||
input we,
|
||||
|
||||
output [31:0] out_data
|
||||
);
|
||||
|
||||
logic [31:0] ram [0:7];
|
||||
always @(posedge clk) begin
|
||||
if (we) ram[address] <= data;
|
||||
end
|
||||
|
||||
assign out_data = ram[address];
|
||||
|
||||
initial begin
|
||||
for (int i = 0; i < 8; i++)
|
||||
ram[i] = 32'h0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module cam8x21 (
|
||||
input clk, reset, we,
|
||||
input [19:0] pattern,
|
||||
input [2:0] write_address,
|
||||
input ITLBFlushF,
|
||||
output [2:0] matched_address,
|
||||
output match_found
|
||||
);
|
||||
|
||||
logic [20:0] ram [0:7];
|
||||
logic [7:0] match_line;
|
||||
|
||||
logic [2:0] matched_address_comb;
|
||||
logic match_found_comb;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (we) ram[write_address] <= {1'b1,pattern};
|
||||
if (ITLBFlushF) begin
|
||||
for (int i = 0; i < 8; i++)
|
||||
ram[i][20] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// *** Check whether this for loop synthesizes correctly
|
||||
always_comb begin
|
||||
match_found_comb = 1'b0;
|
||||
matched_address_comb = 3'b0;
|
||||
for (int i = 0; i < 8; i++) begin
|
||||
if (ram[i] == {1'b1,pattern} && !match_found_comb) begin
|
||||
matched_address_comb = i;
|
||||
match_found_comb = 1;
|
||||
end else begin
|
||||
matched_address_comb = matched_address_comb;
|
||||
match_found_comb = match_found_comb;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign matched_address = matched_address_comb;
|
||||
assign match_found = match_found_comb & ~(we | ITLBFlushF);
|
||||
|
||||
initial begin
|
||||
for (int i = 0; i < 8; i++)
|
||||
ram[i] <= 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module mux2 #(parameter WIDTH = 8) (
|
||||
input logic [WIDTH-1:0] d0, d1,
|
||||
input logic s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s ? d1 : d0;
|
||||
endmodule
|
||||
|
||||
module rand3 (
|
||||
input clk, reset,
|
||||
output [2:0] WriteIndexF
|
||||
);
|
||||
|
||||
logic [31:0] data;
|
||||
assign data = $urandom;
|
||||
assign WriteIndexF = data[2:0];
|
||||
|
||||
endmodule
|
11
wally-pipelined/src/tlb_toy/tlb_toy.tv
Normal file
11
wally-pipelined/src/tlb_toy/tlb_toy.tv
Normal file
@ -0,0 +1,11 @@
|
||||
// tlb_toy.tv
|
||||
// PCF _ PageTableEntryF _ ITLBWriteF _ ITLBFlushF ___ PCPF _ ITLBMissF _ ITLBHitF
|
||||
10101010101010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0
|
||||
// Write test: Add translation aaaaa -> 044444 to TLB
|
||||
10101010101010101010101010101010_00010001000100010001001100110010_1_0___00000000000000000000000000000000_0_0
|
||||
10101010101010101010101010101010_00000000000000000000000000000000_0_0___01000100010001000100101010101010_0_1
|
||||
10101010101010101010101010101010_00000000000000000000000000000000_0_0___01000100010001000100101010101010_0_1
|
||||
10101010100010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0
|
||||
// Flush test: should invalidate all entries
|
||||
00000000000000000000000000000000_00000000000000000000000000000000_0_1___00000000000000000000000000000000_0_0
|
||||
10101010101010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0
|
@ -76,7 +76,6 @@ module uartPC16550D(
|
||||
|
||||
// shift registrs and FIFOs
|
||||
logic [9:0] rxshiftreg;
|
||||
logic [11:0] txshiftreg;
|
||||
logic [10:0] rxfifo[15:0];
|
||||
logic [7:0] txfifo[15:0];
|
||||
logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel;
|
||||
@ -323,7 +322,7 @@ module uartPC16550D(
|
||||
txbitssent <= 0;
|
||||
end else if ((txstate == UART_IDLE) && txsrfull) begin // start transmitting
|
||||
txstate <= UART_ACTIVE;
|
||||
txoversampledcnt <= 0;
|
||||
txoversampledcnt <= 1;
|
||||
txbitssent <= 0;
|
||||
end else if (txbaudpulse & (txstate == UART_ACTIVE)) begin
|
||||
txoversampledcnt <= txoversampledcnt + 1;
|
||||
@ -366,7 +365,7 @@ module uartPC16550D(
|
||||
// registers & FIFO
|
||||
always_ff @(posedge HCLK, negedge HRESETn)
|
||||
if (~HRESETn) begin
|
||||
txfifohead <= 0; txfifotail <= 0; txhrfull <= 0; txsrfull <= 0; TXHR <= 0; txsr <= 0;
|
||||
txfifohead <= 0; txfifotail <= 0; txhrfull <= 0; txsrfull <= 0; TXHR <= 0; txsr <= 12'hfff;
|
||||
end else begin
|
||||
if (~MEMWb && A == 3'b000 && ~DLAB) begin // writing transmit holding register or fifo
|
||||
if (fifoenabled) begin
|
||||
@ -378,19 +377,19 @@ module uartPC16550D(
|
||||
end
|
||||
$display("UART transmits: %c",Din); // for testbench
|
||||
end
|
||||
if (txstate == UART_IDLE) // move data into tx shift register if available
|
||||
if (fifoenabled)
|
||||
if (txstate == UART_IDLE) begin // move data into tx shift register if available
|
||||
if (fifoenabled) begin
|
||||
if (~txfifoempty) begin
|
||||
txsr <= txdata;
|
||||
txfifotail <= txfifotail+1;
|
||||
txsrfull <= 1;
|
||||
end
|
||||
else if (txhrfull) begin
|
||||
end else if (txhrfull) begin
|
||||
txsr <= txdata;
|
||||
txhrfull <= 0;
|
||||
txsrfull <= 1;
|
||||
end
|
||||
else if (txstate == UART_DONE) txsrfull <= 0; // done transmitting shift register
|
||||
end else if (txstate == UART_DONE) txsrfull <= 0; // done transmitting shift register
|
||||
else if (txstate == UART_ACTIVE && txnextbit) txsr <= {txsr[10:0], 1'b1}; // shift txhr
|
||||
if (!MEMWb && A == 3'b010) // writes to FIFO control register
|
||||
if (Din[2] | ~Din[0]) begin // tx FIFO reste or FIFO disable clears FIFO contents
|
||||
|
@ -58,7 +58,7 @@ module uncore (
|
||||
logic HSELTim, HSELCLINT, HSELGPIO, PreHSELUART, HSELUART;
|
||||
logic HRESPTim, HRESPCLINT, HRESPGPIO, HRESPUART;
|
||||
logic HREADYTim, HREADYCLINT, HREADYGPIO, HREADYUART;
|
||||
logic MemRW;
|
||||
logic [1:0] MemRW;
|
||||
logic [1:0] MemRWtim, MemRWclint, MemRWgpio, MemRWuart;
|
||||
logic UARTIntr;// *** will need to tie INTR to an interrupt handler
|
||||
|
||||
|
@ -53,13 +53,16 @@ module wallypipelinedhart (
|
||||
logic RetM, TrapM;
|
||||
|
||||
// new signals that must connect through DP
|
||||
logic MulDivE, W64E;
|
||||
logic CSRWriteM, PrivilegedM;
|
||||
logic [`XLEN-1:0] SrcAE, SrcBE;
|
||||
logic [`XLEN-1:0] SrcAM;
|
||||
logic [2:0] Funct3E;
|
||||
// logic [31:0] InstrF;
|
||||
logic [31:0] InstrD, InstrM;
|
||||
logic [`XLEN-1:0] PCE, PCM, PCLinkW;
|
||||
logic [`XLEN-1:0] PCTargetE;
|
||||
logic [`XLEN-1:0] CSRReadValW;
|
||||
logic [`XLEN-1:0] CSRReadValW, MulDivResultW;
|
||||
logic [`XLEN-1:0] PrivilegedNextPCM;
|
||||
logic [1:0] MemRWM;
|
||||
logic InstrValidW;
|
||||
@ -73,7 +76,7 @@ module wallypipelinedhart (
|
||||
|
||||
logic PCSrcE;
|
||||
logic CSRWritePendingDEM;
|
||||
logic LoadStallD;
|
||||
logic LoadStallD, MulDivStallD;
|
||||
logic [4:0] SetFflagsM;
|
||||
logic [2:0] FRM_REGW;
|
||||
logic FloatRegWriteW;
|
||||
@ -100,9 +103,9 @@ module wallypipelinedhart (
|
||||
.*);
|
||||
//assign InstrF = ReadDataM[31:0];
|
||||
|
||||
/*
|
||||
mdu mdu(.*); // multiply and divide unit
|
||||
fpu fpu(.*); // floating point unit
|
||||
|
||||
muldiv mdu(.*); // multiply and divide unit
|
||||
/* fpu fpu(.*); // floating point unit
|
||||
*/
|
||||
hazard hzu(.*); // global stall and flush control
|
||||
|
||||
|
47
wally-pipelined/testbench/testbench-coremark.sv
Normal file
47
wally-pipelined/testbench/testbench-coremark.sv
Normal file
@ -0,0 +1,47 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module testbench();
|
||||
logic clk;
|
||||
logic reset;
|
||||
|
||||
string memfilename;
|
||||
|
||||
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;
|
||||
|
||||
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(.*);
|
||||
|
||||
// initialize tests
|
||||
initial
|
||||
begin
|
||||
memfilename = "../../imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/coremark.RV64I.bare.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
|
||||
endmodule
|
@ -37,6 +37,21 @@ module testbench();
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
logic [31:0] InstrW;
|
||||
logic [`XLEN-1:0] meminit;
|
||||
string tests64m[] = '{
|
||||
"rv64m/I-MUL-01", "3000",
|
||||
"rv64m/I-MULH-01", "3000",
|
||||
"rv64m/I-MULHSU-01", "3000",
|
||||
"rv64m/I-MULHU-01", "3000",
|
||||
"rv64m/I-MULW-01", "3000"
|
||||
// "rv64m/I-DIV-01", "3000",
|
||||
// "rv64m/I-DIVU-01", "3000",
|
||||
// "rv64m/I-DIVUW-01", "3000",
|
||||
// "rv64m/I-DIVW-01", "3000",
|
||||
// "rv64m/I-REM-01", "3000",
|
||||
// "rv64m/I-REMU-01", "3000",
|
||||
// "rv64m/I-REMUW-01", "3000",
|
||||
// "rv64m/I-REMW-01", "3000"
|
||||
};
|
||||
string tests64ic[] = '{
|
||||
|
||||
"rv64ic/I-C-ADD-01", "3000",
|
||||
@ -136,7 +151,51 @@ string tests64iNOc[] = {
|
||||
"rv64i/I-XOR-01", "3000",
|
||||
"rv64i/I-XORI-01", "3000",
|
||||
"rv64i/WALLY-ADD", "4000",
|
||||
"rv64i/WALLY-SUB", "4000"
|
||||
"rv64i/WALLY-SUB", "4000",
|
||||
"rv64i/WALLY-ADDI", "3000",
|
||||
"rv64i/WALLY-ANDI", "3000",
|
||||
"rv64i/WALLY-ORI", "3000",
|
||||
"rv64i/WALLY-XORI", "3000",
|
||||
"rv64i/WALLY-SLTI", "3000",
|
||||
"rv64i/WALLY-SLTIU", "3000",
|
||||
"rv64i/WALLY-SLLI", "3000",
|
||||
"rv64i/WALLY-SRLI", "3000",
|
||||
"rv64i/WALLY-SRAI", "3000",
|
||||
"rv64i/WALLY-LOAD", "11bf0",
|
||||
"rv64i/WALLY-JAL", "4000",
|
||||
"rv64i/WALLY-STORE", "3000",
|
||||
"rv64i/WALLY-ADDIW", "3000",
|
||||
"rv64i/WALLY-SLLIW", "3000",
|
||||
"rv64i/WALLY-SRLIW", "3000",
|
||||
"rv64i/WALLY-SRAIW", "3000",
|
||||
"rv64i/WALLY-ADDW", "4000",
|
||||
"rv64i/WALLY-SUBW", "4000",
|
||||
"rv64i/WALLY-SLLW", "3000",
|
||||
"rv64i/WALLY-SRLW", "3000",
|
||||
"rv64i/WALLY-SRAW", "3000",
|
||||
"rv64i/WALLY-BEQ" ,"5000",
|
||||
"rv64i/WALLY-BNE", "5000 ",
|
||||
"rv64i/WALLY-BLTU", "5000 ",
|
||||
"rv64i/WALLY-BLT", "5000",
|
||||
"rv64i/WALLY-BGE", "5000 ",
|
||||
"rv64i/WALLY-BGEU", "5000 ",
|
||||
"rv64i/WALLY-CSRRW", "4000",
|
||||
"rv64i/WALLY-CSRRS", "4000",
|
||||
"rv64i/WALLY-CSRRC", "5000",
|
||||
"rv64i/WALLY-CSRRWI", "4000",
|
||||
"rv64i/WALLY-CSRRSI", "4000",
|
||||
"rv64i/WALLY-CSRRCI", "4000"
|
||||
|
||||
};
|
||||
string tests32m[] = '{
|
||||
"rv32m/I-MUL-01", "2000",
|
||||
"rv32m/I-MULH-01", "2000",
|
||||
"rv32m/I-MULHSU-01", "2000",
|
||||
"rv32m/I-MULHU-01", "2000"
|
||||
// "rv32m/I-DIV-01", "2000",
|
||||
// "rv32m/I-DIVU-01", "2000",
|
||||
// "rv32m/I-REM-01", "2000",
|
||||
// "rv32m/I-REMU-01", "2000"
|
||||
};
|
||||
string tests32ic[] = '{
|
||||
// "rv32ic/WALLY-C-ADHOC-01", "2000",
|
||||
@ -217,10 +276,35 @@ string tests32i[] = {
|
||||
"rv32i/I-XOR-01","2000",
|
||||
"rv32i/I-XORI-01","2000",
|
||||
"rv32i/WALLY-ADD", "3000",
|
||||
"rv32i/WALLY-SUB", "3000"
|
||||
"rv32i/WALLY-SUB", "3000",
|
||||
"rv32i/WALLY-ADDI", "2000",
|
||||
"rv32i/WALLY-ANDI", "2000",
|
||||
"rv32i/WALLY-ORI", "2000",
|
||||
"rv32i/WALLY-XORI", "2000",
|
||||
"rv32i/WALLY-SLTI", "2000",
|
||||
"rv32i/WALLY-SLTIU", "2000",
|
||||
"rv32i/WALLY-SLLI", "2000",
|
||||
"rv32i/WALLY-SRLI", "2000",
|
||||
"rv32i/WALLY-SRAI", "2000",
|
||||
"rv32i/WALLY-LOAD", "11c00",
|
||||
"rv32i/WALLY-SUB", "3000",
|
||||
"rv32i/WALLY-STORE", "2000",
|
||||
"rv32i/WALLY-JAL", "3000",
|
||||
"rv32i/WALLY-BEQ" ,"4000",
|
||||
"rv32i/WALLY-BNE", "4000 ",
|
||||
"rv32i/WALLY-BLTU", "4000 ",
|
||||
"rv32i/WALLY-BLT", "4000",
|
||||
"rv32i/WALLY-BGE", "4000 ",
|
||||
"rv32i/WALLY-BGEU", "4000 ",
|
||||
"rv32i/WALLY-CSRRW", "3000",
|
||||
"rv32i/WALLY-CSRRS", "3000",
|
||||
"rv32i/WALLY-CSRRC", "4000",
|
||||
"rv32i/WALLY-CSRRWI", "3000",
|
||||
"rv32i/WALLY-CSRRSI", "3000",
|
||||
"rv32i/WALLY-CSRRCI", "3000"
|
||||
|
||||
};
|
||||
string tests[];
|
||||
|
||||
logic [`AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
logic [31:0] HADDR;
|
||||
@ -240,10 +324,12 @@ string tests32i[] = {
|
||||
tests = {tests64i};
|
||||
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests64ic};
|
||||
else tests = {tests, tests64iNOc};
|
||||
if (`M_SUPPORTED % 2 == 1) tests = {tests64m, tests};
|
||||
end else begin // RV32
|
||||
tests = {tests32i};
|
||||
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
|
||||
else tests = {tests, tests32iNOc};
|
||||
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
|
||||
end
|
||||
string signame, memfilename;
|
||||
|
||||
@ -432,10 +518,18 @@ module instrNameDecTB(
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_000: if (funct7 == 7'b0000000) name = "ADDW";
|
||||
else if (funct7 == 7'b0100000) name = "SUBW";
|
||||
else if (funct7 == 7'b0000001) name = "MULW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_001: if (funct7 == 7'b0000000) name = "SLLW";
|
||||
else if (funct7 == 7'b0000001) name = "DIVW";
|
||||
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 if (funct7 == 7'b0000001) name = "DIVUW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_110: if (funct7 == 7'b0000001) name = "REMW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_111: if (funct7 == 7'b0000001) name = "REMUW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_000: if (funct7 == 7'b0000000) name = "ADD";
|
||||
else if (funct7 == 7'b0000001) name = "MUL";
|
||||
@ -448,10 +542,10 @@ module instrNameDecTB(
|
||||
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 if (funct7 == 7'b0000001) name = "MULHU";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
|
||||
else if (funct7 == 7'b0000001) name = "MUL";
|
||||
else if (funct7 == 7'b0000001) name = "DIV";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_101: if (funct7 == 7'b0000000) name = "SRL";
|
||||
else if (funct7 == 7'b0000001) name = "DIVU";
|
||||
|
305
wally-pipelined/testbench/testbench-peripherals.sv
Normal file
305
wally-pipelined/testbench/testbench-peripherals.sv
Normal file
@ -0,0 +1,305 @@
|
||||
///////////////////////////////////////////
|
||||
// testbench-peripherals.sv
|
||||
//
|
||||
// Written: Ben Bracker (bbracker@hmc.edu) 11 Feb. 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[] = '{
|
||||
"peripherals/WALLY-UART", "2000"
|
||||
};
|
||||
|
||||
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 = tests[test+1].atohex()/4;
|
||||
else
|
||||
testadr = 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
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
# testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 2021
|
||||
#
|
||||
@ -19,11 +19,34 @@ from random import getrandbits
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
def twoscomp(a):
|
||||
amsb = a >> (xlen-1)
|
||||
alsbs = ((1 << (xlen-1)) - 1) & a
|
||||
if (amsb):
|
||||
asigned = a - (1<<xlen)
|
||||
else:
|
||||
asigned = a
|
||||
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
||||
return asigned
|
||||
|
||||
def computeExpected(a, b, test, xlen):
|
||||
asigned = twoscomp(a)
|
||||
bsigned = twoscomp(b)
|
||||
|
||||
if (test == "ADD"):
|
||||
return a + b
|
||||
elif (test == "SUB"):
|
||||
return a - b
|
||||
elif (test == "SLT"):
|
||||
return asigned < bsigned
|
||||
elif (test == "SLTU"):
|
||||
return a < b
|
||||
elif (test == "XOR"):
|
||||
return a ^ b
|
||||
elif (test == "OR"):
|
||||
return a | b
|
||||
elif (test == "AND"):
|
||||
return a & b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
@ -37,9 +60,9 @@ def randRegs():
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
def writeVector(a, b, storecmd, xlen):
|
||||
global testnum
|
||||
expected = computeExpected(a, b, test)
|
||||
expected = computeExpected(a, b, test, xlen)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
@ -65,7 +88,7 @@ def writeVector(a, b, storecmd):
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["ADD", "SUB"]
|
||||
tests = ["ADD", "SUB", "SLT", "SLTU", "XOR", "OR", "AND"]
|
||||
author = "David_Harris@hmc.edu & Katherine Parry"
|
||||
xlens = [32, 64]
|
||||
numrand = 100;
|
||||
@ -111,11 +134,11 @@ for xlen in xlens:
|
||||
# print directed and random test vectors
|
||||
for a in corners:
|
||||
for b in corners:
|
||||
writeVector(a, b, storecmd)
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, storecmd)
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
|
||||
|
||||
# print footer
|
161
wally-pipelined/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py
Normal file
161
wally-pipelined/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 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 random import getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "ADDI"):
|
||||
return a + b
|
||||
elif (test == "XORI"):
|
||||
return a ^ b
|
||||
elif (test == "ORI"):
|
||||
return a | b
|
||||
elif (test == "ANDI"):
|
||||
return a & b
|
||||
elif (test == "SLTI"):
|
||||
return a < b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
|
||||
def evaluateTwoComplement(b, bits):
|
||||
if (b & (1 << (bits -1))!= 0):
|
||||
b = b - (1 << bits)
|
||||
return b
|
||||
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg3 == 6):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
|
||||
|
||||
|
||||
expected = computeExpected(evaluateTwoComplement(a,xlen), evaluateTwoComplement(b, 12), test)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
|
||||
|
||||
|
||||
reg1, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), imm12:" + "(" +formatstrimm12.format(b)
|
||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n"
|
||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["ADDI", "XORI", "ORI", "ANDI", "SLTI"]
|
||||
author = "Shriya Nadgauda & Ethan Falicov"
|
||||
xlens = [32, 64]
|
||||
numrand = 100
|
||||
|
||||
|
||||
# setup
|
||||
seed(0) # 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
|
||||
|
||||
formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number
|
||||
if (xlen == 32):
|
||||
storecmd = "sw"
|
||||
wordsize = 4
|
||||
else:
|
||||
storecmd = "sd"
|
||||
wordsize = 8
|
||||
|
||||
for test in tests:
|
||||
corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
|
||||
immBitSize = 12
|
||||
corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
||||
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
for a in corners1:
|
||||
for b in corners2:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(12)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
182
wally-pipelined/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
Executable file
182
wally-pipelined/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
Executable file
@ -0,0 +1,182 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
|
||||
#
|
||||
# ehedenberg@hmc.edu 4 February 2021
|
||||
# heavily influenced by Prof Harris Code
|
||||
#
|
||||
# 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 random import getrandbits
|
||||
import sys
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
def logical_rshift(signed_integer, places):
|
||||
unsigned_integer=signed_integer%(1<<32)
|
||||
return unsigned_integer >> places
|
||||
|
||||
def toSigned12bit(n):
|
||||
n=n & 0xfff
|
||||
if (n&(1<<11)):
|
||||
n=n|0xfffffffffffff000
|
||||
return n
|
||||
|
||||
def toSigned32bit(n):
|
||||
n=n & 0xffffffff
|
||||
if (n&(1<<31)):
|
||||
n=n|0xffffffff00000000
|
||||
return n
|
||||
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "ADDIW"):
|
||||
b=toSigned12bit(b)
|
||||
return a + b
|
||||
elif (test == "SLLIW"):
|
||||
return (a << b)
|
||||
elif (test == "SRLIW"):
|
||||
return logical_rshift(a, b)
|
||||
elif(test == "SRAIW"):
|
||||
a= toSigned32bit(a)
|
||||
return a >> b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg2 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
expected = computeExpected(a, b, test)
|
||||
expected = expected % 2**64 # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**64 + expected
|
||||
#expected=expected+2^32<<32
|
||||
if (expected >= (2**32)):
|
||||
expected=expected%(2**32)
|
||||
expected=toSigned32bit(expected)
|
||||
reg1, reg2, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), imm:"+formatstr.format(b)
|
||||
lines = lines + ", result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
#lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
#lines = lines + str(b)+"\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]
|
||||
author = "Eizabeth Hedenberg"
|
||||
xlens = [64]
|
||||
shiftlen=5
|
||||
addlen=12
|
||||
numrand = 100
|
||||
|
||||
# setup
|
||||
seed(0) # make tests reproducible
|
||||
|
||||
# generate files for each test
|
||||
for xlen in xlens:
|
||||
formatstrlen = str(int(xlen/4))
|
||||
#formatstrlen6=str(int())
|
||||
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
|
||||
#formatstr6 = "0x{:0" + "2" + "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
|
||||
for test in tests:
|
||||
cornersa = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
#test both confined to top 32 and not
|
||||
cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110]
|
||||
#6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46
|
||||
cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111]
|
||||
#12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
if test=="ADDIW":
|
||||
for a in cornersa:
|
||||
for b in cornersadd:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(12)
|
||||
writeVector(a, b, storecmd)
|
||||
else:
|
||||
for a in cornersa:
|
||||
for b in cornersshift:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(5)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
||||
|
174
wally-pipelined/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py
Executable file
174
wally-pipelined/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py
Executable file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py
|
||||
#
|
||||
# trao@g.hmc.edu 11 February 2021
|
||||
# Based on testgen-ADD-SUB.py by Prof. David Harris
|
||||
#
|
||||
# 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 random import getrandbits
|
||||
import sys
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
def logical_rshift(signed_integer, places):
|
||||
unsigned_integer=signed_integer%(1<<32)
|
||||
return unsigned_integer >> places
|
||||
|
||||
def toSigned12bit(n):
|
||||
n=n & 0xfff
|
||||
if (n&(1<<11)):
|
||||
n=n|0xfffffffffffff000
|
||||
return n
|
||||
|
||||
def toSigned32bit(n):
|
||||
n=n & 0xffffffff
|
||||
if (n&(1<<31)):
|
||||
n=n|0xffffffff00000000
|
||||
return n
|
||||
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "ADDW"):
|
||||
return toSigned32bit(a + b)
|
||||
elif (test == "SUBW"):
|
||||
return toSigned32bit(a - b)
|
||||
elif (test == "SLLW"):
|
||||
b = b & 0x1F
|
||||
return toSigned32bit(a << b)
|
||||
elif (test == "SRLW"):
|
||||
b = b & 0x1F
|
||||
return toSigned32bit(logical_rshift(a, b))
|
||||
elif(test == "SRAW"):
|
||||
a= toSigned32bit(a)
|
||||
b = b & 0x1F
|
||||
return toSigned32bit(a >> b)
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg2 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
expected = computeExpected(a, b, test)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
reg1, reg2, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
f.write(lines)
|
||||
line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n"
|
||||
r.write(line)
|
||||
testnum = testnum+1
|
||||
|
||||
##################################
|
||||
# main body
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW"]
|
||||
author = "Tejus Rao"
|
||||
xlens = [64]
|
||||
shiftlen=5
|
||||
addlen=32
|
||||
numrand = 100
|
||||
|
||||
# setup
|
||||
seed(0) # make tests reproducible
|
||||
|
||||
# generate files for each test
|
||||
for xlen in xlens:
|
||||
formatstrlen = str(int(xlen/4))
|
||||
#formatstrlen6=str(int())
|
||||
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
|
||||
#formatstr6 = "0x{:0" + "2" + "x}" # format as xlen-bit hexadecimal number
|
||||
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
|
||||
storecmd = "sd"
|
||||
wordsize = 8
|
||||
for test in tests:
|
||||
cornersa = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
#test both confined to top 32 and not
|
||||
cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110]
|
||||
#6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46
|
||||
cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111]
|
||||
#12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
if test=="ADDW" or test == "SUBW":
|
||||
for a in cornersa:
|
||||
for b in cornersadd:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, storecmd)
|
||||
else:
|
||||
for a in cornersa:
|
||||
for b in cornersshift:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(5)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
||||
|
155
wally-pipelined/testgen/testgen-BRANCH.py
Executable file
155
wally-pipelined/testgen/testgen-BRANCH.py
Executable file
@ -0,0 +1,155 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-branch.py
|
||||
#
|
||||
# ssanghai@hmc.edu 13th Feb 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 random import getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "BEQ"):
|
||||
return 0xcccc if a==b else 0xeeee
|
||||
elif (test == "BNE"):
|
||||
return 0xeeee if a==b else 0xcccc
|
||||
elif (test == "BGEU"):
|
||||
return 0xcccc if a>=b else 0xeeee
|
||||
elif (test == "BLT"):
|
||||
if (1<<(xlen-1)) & a:
|
||||
a = a -(2**xlen)
|
||||
if (1<<(xlen-1)) & b:
|
||||
b = b - (2**xlen)
|
||||
return 0xcccc if a<b else 0xeeee
|
||||
elif (test == "BLTU"):
|
||||
return 0xcccc if a<b else 0xeeee
|
||||
elif (test == "BGE"):
|
||||
if (1<<(xlen-1)) & a:
|
||||
a = a - (2**xlen)
|
||||
if (1<<(xlen-1)) & b:
|
||||
b = b - (2**xlen)
|
||||
return 0xcccc if a>=b else 0xeeee
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(2,31)
|
||||
reg2 = randint(2,31)
|
||||
if (reg1 == 6 or reg2 == 6 or reg1 == reg2):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg2
|
||||
|
||||
label = 0
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
global label
|
||||
expected = computeExpected(a, b, test)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
reg1, reg2 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b) + "\n"
|
||||
lines = lines + "li x1, MASK_XLEN(0xcccc)\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + test + " x" + str(reg1) + ", x" + str(reg2) + ", " + str(label) + "f\n"
|
||||
lines = lines + "li x1, MASK_XLEN(0xeeee)\n"
|
||||
lines = lines + str(label) + ":\n"
|
||||
lines = lines + storecmd + " x1, " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x1, "+formatstr.format(expected)+")\n"
|
||||
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)
|
||||
label += 1
|
||||
testnum = testnum+1
|
||||
|
||||
##################################
|
||||
# main body
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["BEQ", "BNE", "BLT", "BGE", "BGEU", "BLTU"]
|
||||
author = "Shreya Sanghai"
|
||||
xlens = [32, 64]
|
||||
numrand = 100
|
||||
|
||||
# setup
|
||||
seed(0) # 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
|
||||
for test in tests:
|
||||
corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
for a in corners:
|
||||
for b in corners:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
||||
|
194
wally-pipelined/testgen/testgen-CSR.py
Normal file
194
wally-pipelined/testgen/testgen-CSR.py
Normal file
@ -0,0 +1,194 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
#
|
||||
# ushakya@hmc.edu & dottolia@hmc.edu 14 Feb 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 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,31)
|
||||
reg2 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
#expected = computeExpected(a, b, test)
|
||||
#expected = expected % 2**xlen # drop carry if necessary
|
||||
#if (expected < 0): # take twos complement
|
||||
# expected = 2**xlen + expected
|
||||
csr = "mscratch"
|
||||
|
||||
reg1, reg2, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": " + csr + "\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(0)\n"
|
||||
|
||||
# Page 6 of unpriviledged spec
|
||||
# For both CSRRS and CSRRC, if rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects
|
||||
|
||||
expected = a
|
||||
|
||||
if test == "csrrw":
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
|
||||
elif test == "csrrs": # at some point, try writing a non-zero value first
|
||||
lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0
|
||||
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
elif test == "csrrc": # at some point, try writing a non-one value first
|
||||
allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF"
|
||||
|
||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n"
|
||||
lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones
|
||||
|
||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
||||
|
||||
expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF
|
||||
elif test == "csrrwi":
|
||||
a = a & 0x1F # imm is only 5 bits
|
||||
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
|
||||
expected = a
|
||||
elif test == "csrrsi": # at some point, try writing a non-zero value first
|
||||
a = a & 0x1F
|
||||
|
||||
lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0
|
||||
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
|
||||
expected = a
|
||||
elif test == "csrrci": # at some point, try writing a non-one value first
|
||||
a = a & 0x1F
|
||||
allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF"
|
||||
|
||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n"
|
||||
lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones
|
||||
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
||||
|
||||
expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
|
||||
lines += storecmd + " x" + str(reg2) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci
|
||||
tests = ["csrrw", "csrrs", "csrrc", "csrrwi", "csrrsi", "csrrci"]
|
||||
author = "ushakya@hmc.edu & dottolia@hmc.edu"
|
||||
xlens = [32, 64]
|
||||
numrand = 60;
|
||||
|
||||
# setup
|
||||
seed(0xC365DDEB9173AB42) # 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
|
||||
for test in tests:
|
||||
corners = [
|
||||
0, 1, 2, 0x1E, 0x1F, 0xFF,
|
||||
0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1
|
||||
]
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test.upper()
|
||||
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
|
||||
for a in corners:
|
||||
for b in corners:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
||||
|
260
wally-pipelined/testgen/testgen-JAL.py
Executable file
260
wally-pipelined/testgen/testgen-JAL.py
Executable file
@ -0,0 +1,260 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-JAL.py
|
||||
#
|
||||
# Ben Bracker (bbracker@hmc.edu) 19 January 2021
|
||||
# Based on testgen-ADD-SUB.py by David Harris
|
||||
#
|
||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
||||
##################################
|
||||
|
||||
##################################
|
||||
# libraries
|
||||
##################################
|
||||
from datetime import datetime
|
||||
from random import randint
|
||||
from random import choice
|
||||
from random import seed
|
||||
from random import getrandbits
|
||||
from copy import deepcopy
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def InitTestGroup():
|
||||
global TestGroup,TestGroupSizes,AllRegs,UnusedRegs,StoreAdrReg
|
||||
TestGroup += 1
|
||||
TestGroupSizes.append(0)
|
||||
UnusedRegs = deepcopy(AllRegs)
|
||||
oldStoreAdrReg = StoreAdrReg
|
||||
while ((StoreAdrReg == oldStoreAdrReg) or (StoreAdrReg == 0) or (StoreAdrReg == 31)):
|
||||
StoreAdrReg = choice(UnusedRegs)
|
||||
UnusedRegs.remove(StoreAdrReg)
|
||||
f.write("\n # ---------------------------------------------------------------------------------------------\n")
|
||||
f.write(" # new register for address of test results\n")
|
||||
addInst(" la x"+str(StoreAdrReg)+", test_1_res\n")
|
||||
f.write(" # ---------------------------------------------------------------------------------------------\n")
|
||||
|
||||
def registerSelect():
|
||||
# ensures that rd experiences all possible registers
|
||||
# *** does not yet ensure that rs experiences all possible registers
|
||||
# ensures that at least once rd = rs
|
||||
global UnusedRegs
|
||||
if len(UnusedRegs)==0:
|
||||
InitTestGroup()
|
||||
rd = choice(UnusedRegs)
|
||||
rs = choice(UnusedRegs)
|
||||
UnusedRegs.remove(rd)
|
||||
OtherRegs = deepcopy(AllRegs)
|
||||
OtherRegs.remove(StoreAdrReg)
|
||||
OtherRegs.remove(rd)
|
||||
try:
|
||||
OtherRegs.remove(0)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
OtherRegs.remove(rs)
|
||||
except:
|
||||
pass
|
||||
DataReg = choice(OtherRegs)
|
||||
OtherRegs.remove(DataReg)
|
||||
OtherRd = choice(OtherRegs)
|
||||
return (rd,rs,DataReg,OtherRd)
|
||||
|
||||
def addInst(line):
|
||||
global CurrAdr
|
||||
f.write(line)
|
||||
if ("li x" in line):
|
||||
CurrAdr += 8 if (xlen == 32) else 20
|
||||
elif ("la x" in line):
|
||||
CurrAdr += 8
|
||||
else:
|
||||
CurrAdr += 4
|
||||
|
||||
def writeForwardsJumpVector(spacers):
|
||||
global TestNum
|
||||
rd, rs, DataReg, OtherRd = registerSelect()
|
||||
if (xlen==64):
|
||||
expected = int("fedbca9876540000",16)
|
||||
unexpected = int("ffff0000ffff0000",16)
|
||||
else:
|
||||
expected = int("fedbca98",16)
|
||||
unexpected = int("ff00ff00",16)
|
||||
|
||||
|
||||
f.write("\n")
|
||||
f.write(" # Testcase "+str(TestNum)+" address cmp result rd:x"+str(rd)+"("+formatstr.format(CurrAdr+44)+") data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
||||
addInst(" JAL x"+str(rd)+", 1f\n")
|
||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
||||
for i in range(spacers):
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
||||
f.write("1:\n")
|
||||
addInst(" "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
|
||||
addInst(" "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
|
||||
writeExpectedToRef(LinkAdr)
|
||||
writeExpectedToRef(expected)
|
||||
TestNum = TestNum+1
|
||||
|
||||
def writeBackwardsJumpVector(spacers):
|
||||
global TestNum
|
||||
rd, rs, DataReg,OtherRd = registerSelect()
|
||||
if (xlen==64):
|
||||
expected = int("fedbca9876540000",16)
|
||||
unexpected = int("ffff0000ffff0000",16)
|
||||
else:
|
||||
expected = int("fedbca98",16)
|
||||
unexpected = int("ff00ff00",16)
|
||||
|
||||
f.write("\n")
|
||||
f.write(" # Testcase "+str(TestNum)+" address cmp result rd:x"+str(rd)+"("+formatstr.format(CurrAdr+20+8*spacers)+") data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
|
||||
addInst(" JAL x"+str(OtherRd)+", 2f\n")
|
||||
f.write("1:\n")
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
||||
addInst(" JAL x"+str(OtherRd)+", 3f\n")
|
||||
f.write("2:\n")
|
||||
for i in range(spacers):
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
||||
addInst(" JAL x"+str(rd)+", 1b\n")
|
||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
||||
f.write("3:\n")
|
||||
addInst(" "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
|
||||
addInst(" "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
|
||||
writeExpectedToRef(LinkAdr)
|
||||
writeExpectedToRef(expected)
|
||||
TestNum = TestNum+1
|
||||
|
||||
def writeChainVector(repetitions,spacers):
|
||||
global TestNum
|
||||
rd, rs, DataReg,OtherRd = registerSelect()
|
||||
if (xlen==64):
|
||||
expected = int("fedbca9876540000",16)
|
||||
unexpected = int("ffff0000ffff0000",16)
|
||||
else:
|
||||
expected = int("fedbca98",16)
|
||||
unexpected = int("ff00ff00",16)
|
||||
|
||||
f.write("\n")
|
||||
f.write(" # Testcase "+str(TestNum)+" address cmp result rd:x"+str(rd)+"(ugh; if you really wanted to, you could figure it out) data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
||||
for i in range(repetitions):
|
||||
addInst(" JAL x"+str(OtherRd)+", "+str(3*i+2)+"f\n")
|
||||
if spacers:
|
||||
for j in range(i):
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
||||
f.write(str(3*i+1)+":\n")
|
||||
addInst(" JAL x"+str(OtherRd)+", "+str(3*i+3)+"f\n")
|
||||
if spacers:
|
||||
for j in range(i):
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
||||
f.write(str(3*i+2)+":\n")
|
||||
addInst(" JAL x"+str(rd)+", "+str(3*i+1)+"b\n")
|
||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
||||
if spacers:
|
||||
for j in range(i):
|
||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
||||
f.write(str(3*i+3)+":\n")
|
||||
addInst(" "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
|
||||
addInst(" "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
|
||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
|
||||
writeExpectedToRef(LinkAdr)
|
||||
writeExpectedToRef(expected)
|
||||
TestNum = TestNum+1
|
||||
|
||||
|
||||
def writeExpectedToRef(expected):
|
||||
global TestGroupSizes
|
||||
TestGroupSizes[TestGroup-1] += 1
|
||||
if (xlen == 32):
|
||||
r.write(formatrefstr.format(expected)+"\n")
|
||||
else:
|
||||
r.write(formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32)+"\n")
|
||||
|
||||
##################################
|
||||
# main body
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["JAL"]
|
||||
author = "Ben Bracker (bbracker@hmc.edu)"
|
||||
xlens = [32,64]
|
||||
numtests = 100;
|
||||
|
||||
# setup
|
||||
seed(0) # make tests reproducible
|
||||
|
||||
# generate files for each test
|
||||
for xlen in xlens:
|
||||
CurrAdr = int("80000108",16)
|
||||
TestNum = 0
|
||||
TestGroup = 1
|
||||
TestGroupSizes = [0]
|
||||
AllRegs = list(range(0,32))
|
||||
UnusedRegs = deepcopy(AllRegs)
|
||||
StoreAdrReg = 6 # matches what's in header script
|
||||
UnusedRegs.remove(6)
|
||||
|
||||
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
|
||||
for test in tests:
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
fname = imperaspath + "src/" + basename + ".S"
|
||||
refname = imperaspath + "references/" + basename + ".reference_output"
|
||||
|
||||
# print custom header part
|
||||
f = open(fname, "w")
|
||||
r = open(refname, "w")
|
||||
f.write("///////////////////////////////////////////\n")
|
||||
f.write("// "+fname+ "\n")
|
||||
f.write("//\n")
|
||||
f.write("// This file can be used to test the RISC-V JAL instruction.\n")
|
||||
f.write("// But be warned that altering the test environment may break this test!\n")
|
||||
f.write("// In order to work, this test expects that the first instruction (la)\n")
|
||||
f.write("// be allocated at 0x80000100.\n")
|
||||
f.write("//\n")
|
||||
f.write("// " + author + "\n")
|
||||
f.write("// Created "+str(datetime.now())+"\n")
|
||||
|
||||
# insert generic header
|
||||
h = open("testgen_header.S", "r")
|
||||
for line in h:
|
||||
f.write(line)
|
||||
|
||||
# print directed test vectors
|
||||
for i in range(0,31):
|
||||
writeForwardsJumpVector(randint(0,4))
|
||||
for i in range(0,31):
|
||||
writeBackwardsJumpVector(randint(0,4))
|
||||
writeForwardsJumpVector(100)
|
||||
writeBackwardsJumpVector(100)
|
||||
writeChainVector(6,True)
|
||||
writeChainVector(16,False)
|
||||
|
||||
# print footer
|
||||
h = open("testgen_footer.S", "r")
|
||||
for line in h:
|
||||
f.write(line)
|
||||
|
||||
# Finish
|
||||
f.write(".fill "+str(sum(TestGroupSizes))+", "+str(wordsize)+", -1\n")
|
||||
f.write("\nRV_COMPLIANCE_DATA_END\n")
|
||||
f.close()
|
||||
r.close()
|
||||
|
||||
|
||||
|
||||
|
227
wally-pipelined/testgen/testgen-LOAD.py
Executable file
227
wally-pipelined/testgen/testgen-LOAD.py
Executable file
@ -0,0 +1,227 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-LOAD.py
|
||||
#
|
||||
# Jarred Allen <jaallen@g.hmc.edu> 02 February 2021
|
||||
#
|
||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
||||
##################################
|
||||
|
||||
##################################
|
||||
# libraries
|
||||
##################################
|
||||
from datetime import datetime
|
||||
from random import randint, seed, getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def rand_reg():
|
||||
"""Produce a random register (skipping 6 and 31, since they're used for other things)"""
|
||||
r = randint(1,29)
|
||||
if r >= 6:
|
||||
r += 1
|
||||
return r
|
||||
|
||||
def rand_value(width):
|
||||
"""Generate a random value which fits in the given width"""
|
||||
return randint(0, (1 << width) - 1)
|
||||
|
||||
def rand_offset():
|
||||
"""Generate a random offset"""
|
||||
ret = rand_value(12)
|
||||
# print("Random offset: %d" % ret)
|
||||
return ret
|
||||
|
||||
def rand_source():
|
||||
"""Generate a random value for the source register, such that the load address is in the test data"""
|
||||
ret = randint(1 << 12, (1 << 12) + (1 << 10))
|
||||
# print("Random source: %d" % ret)
|
||||
return ret
|
||||
|
||||
def add_offset_to_source(source, offset):
|
||||
"""Find the address from the given source value and offset"""
|
||||
if offset & 0x800:
|
||||
offset -= 0x1000
|
||||
return source + offset
|
||||
|
||||
def insert_into_data(test_data, source, offset, value, width, xlen):
|
||||
"""Insert the given value into the given location of the test data"""
|
||||
address = add_offset_to_source(source, offset)
|
||||
# print("Test #%d" % testcase_num)
|
||||
# print(f"Source: {source}, Offset: {offset}, Value: {value}, Width: {width}, xlen: {xlen}, Addr: {address}")
|
||||
if address < 0:
|
||||
return False
|
||||
word_offset = address % (xlen // 8)
|
||||
word_address = address - word_offset
|
||||
if word_address in test_data:
|
||||
return False
|
||||
test_data[word_address] = value * (1 << (word_offset*8)) + ((~(((1 << width)-1) << (word_offset*8))) & rand_value(xlen))
|
||||
# print(f"Word: {hex(test_data[word_address])}")
|
||||
return True
|
||||
|
||||
def align(address, width):
|
||||
"""Align the address to the given width, in bits"""
|
||||
return address - (address % (width // 8))
|
||||
|
||||
testcase_num = 0
|
||||
def generate_case(xlen, instruction, load_register, source_register, source_register_value, offset, expected):
|
||||
"""Produce the specified test case and return it as a pair of strings, where the first is the test case and the second is the output"""
|
||||
global testcase_num
|
||||
if xlen == 64:
|
||||
store = "sd"
|
||||
elif xlen == 32:
|
||||
if instruction in ["lwu", "ld"]:
|
||||
raise Exception("Instruction %s not supported in RV32I" % instruction)
|
||||
store = "sw"
|
||||
else:
|
||||
raise Exception("Unknown xlen value: %s" % xlen)
|
||||
if offset >= 0x800:
|
||||
offset -= 0x1000
|
||||
if widths[instruction] != xlen:
|
||||
expected = expected % (1 << widths[instruction])
|
||||
if 'u' not in instruction:
|
||||
if expected & (1 << (widths[instruction] - 1)):
|
||||
expected = (expected + ~((1 << widths[instruction]) - 1)) & ((1 << xlen) - 1)
|
||||
data = f"""# Testcase {testcase_num}: source {offset}(x{source_register} == {source_register_value}), result: x{load_register} == {expected}
|
||||
la x31, test_data
|
||||
lui x{source_register}, {source_register_value // (1 << 12)}
|
||||
addi x{source_register}, x{source_register}, {source_register_value % (1 << 12)}
|
||||
add x{source_register}, x{source_register}, x31
|
||||
{instruction} x{load_register}, {offset}(x{source_register})
|
||||
{store} x{load_register}, {(testcase_num*xlen//8) % 0x800}(x6)
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x8, x{load_register}, {expected})
|
||||
|
||||
"""
|
||||
testcase_num += 1
|
||||
if testcase_num*xlen//8 % 0x800 == 0:
|
||||
data += "# Adjust x6 because we're storing too many things\naddi x6, x6, 1024\naddi x6, x6, 1024\n\n"
|
||||
if xlen == 32:
|
||||
reference_output = "{:08x}\n".format(expected)
|
||||
elif xlen == 64:
|
||||
reference_output = "{:08x}\n{:08x}\n".format(expected % (1 << 32), expected >> 32)
|
||||
return (data, reference_output)
|
||||
|
||||
def write_header(outfile):
|
||||
outfile.write(f"""///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-LOAD
|
||||
//
|
||||
// Author: {author}
|
||||
//
|
||||
// Created {str(datetime.now())}
|
||||
//
|
||||
""")
|
||||
outfile.write(open("testgen_header.S", "r").read())
|
||||
|
||||
def write_test_data(outfile, test_data, xlen):
|
||||
# print("Begin writing test data:")
|
||||
# print("{} entries, from address {} to {}".format(len(test_data), min(test_data.keys()), max(test_data.keys())))
|
||||
# print(test_data)
|
||||
outfile.write("""
|
||||
.align 16
|
||||
test_data:
|
||||
|
||||
""")
|
||||
if xlen == 32:
|
||||
data_word = ".word"
|
||||
elif xlen == 64:
|
||||
data_word = ".dword"
|
||||
else:
|
||||
raise Exception("Unknown xlen: %d" % xlen)
|
||||
byte_width = xlen // 8
|
||||
for addr in [0] + sorted(test_data.keys()):
|
||||
if addr in test_data:
|
||||
word = f" {data_word} {hex(test_data[addr] % (1 << xlen))} # test_data+{hex(addr)}\n"
|
||||
else:
|
||||
word = ""
|
||||
try:
|
||||
fill_len = (min(k for k in test_data.keys() if k > addr) - addr) // byte_width - 1
|
||||
if word == "":
|
||||
fill_len += 1
|
||||
fill = f" .fill {fill_len}, {byte_width}, 0x0\n"
|
||||
except:
|
||||
fill = ""
|
||||
case = word+fill
|
||||
outfile.write(case)
|
||||
|
||||
##################################
|
||||
# main body
|
||||
##################################
|
||||
|
||||
widths = {
|
||||
"lb": 8,
|
||||
"lbu": 8,
|
||||
"lh": 16,
|
||||
"lhu": 16,
|
||||
"lw": 32,
|
||||
"lwu": 32,
|
||||
"ld": 64,
|
||||
}
|
||||
instructions = [i for i in widths]
|
||||
author = "Jarred Allen"
|
||||
xlens = [32, 64]
|
||||
numrand = 100;
|
||||
|
||||
# setup
|
||||
seed(0) # make tests reproducible
|
||||
|
||||
for xlen in xlens:
|
||||
testcase_num = 0
|
||||
fname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/src/WALLY-LOAD.S".format(xlen)
|
||||
refname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/references/WALLY-LOAD.reference_output".format(xlen)
|
||||
f = open(fname, "w")
|
||||
r = open(refname, "w")
|
||||
write_header(f)
|
||||
test_data = dict()
|
||||
corner_values = [0x00, 0xFFFFFFFF, 0x7F, 0x7FFF, 0x7FFFFFFF]
|
||||
if xlen == 64:
|
||||
corner_values += [0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF]
|
||||
corner_offsets = [0x800, 0x000, 0x7FF]
|
||||
for instruction in instructions:
|
||||
print("Running xlen: %d, instruction: %s" % (xlen, instruction))
|
||||
if xlen == 32:
|
||||
if instruction in ["lwu", "ld"]:
|
||||
continue
|
||||
for value in corner_values + [rand_value(widths[instruction]) for _ in range(3)]:
|
||||
value = value % (1 << widths[instruction])
|
||||
source_reg = rand_source()
|
||||
for offset in corner_offsets + [rand_offset() for _ in range(3)]:
|
||||
offset = align(offset, widths[instruction])
|
||||
source_reg = align(source_reg, widths[instruction])
|
||||
if insert_into_data(test_data, source_reg, offset, value, widths[instruction], xlen):
|
||||
data, output = generate_case(xlen, instruction, rand_reg(), rand_reg(), source_reg, offset, value)
|
||||
f.write(data)
|
||||
r.write(output)
|
||||
while testcase_num % 4:
|
||||
source = rand_source()
|
||||
offset = rand_offset()
|
||||
value = rand_value(widths[instruction])
|
||||
if insert_into_data(test_data, source, offset, value, widths['lb'], xlen):
|
||||
data, output = generate_case(xlen, 'lb', rand_reg(), rand_reg(), source, offset, value)
|
||||
f.write(data)
|
||||
r.write(output)
|
||||
f.write("""# ---------------------------------------------------------------------------------------------
|
||||
|
||||
RVTEST_IO_WRITE_STR(x31, "Test End\\n")
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
RV_COMPLIANCE_HALT
|
||||
|
||||
RV_COMPLIANCE_CODE_END
|
||||
|
||||
.data
|
||||
# Input data section
|
||||
""")
|
||||
write_test_data(f, test_data, xlen)
|
||||
f.write("""# Output data section.
|
||||
RV_COMPLIANCE_DATA_BEGIN
|
||||
|
||||
test_1_res:
|
||||
""")
|
||||
f.write(f".fill {testcase_num}, {xlen//8}, -1\n")
|
||||
f.write("\nRV_COMPLIANCE_DATA_END\n")
|
||||
f.close()
|
||||
r.close()
|
154
wally-pipelined/testgen/testgen-SLL-SRL-SRA.py
Executable file
154
wally-pipelined/testgen/testgen-SLL-SRL-SRA.py
Executable file
@ -0,0 +1,154 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-SLL-SRL-SRA.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 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 random import getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def twoscomp(a):
|
||||
amsb = a >> (xlen-1)
|
||||
alsbs = ((1 << (xlen-1)) - 1) & a
|
||||
if (amsb):
|
||||
asigned = a - (1<<xlen)
|
||||
else:
|
||||
asigned = a
|
||||
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
||||
return asigned
|
||||
|
||||
def computeExpected(a, b, test, xlen):
|
||||
asigned = twoscomp(a)
|
||||
b = b % xlen
|
||||
if (test == "SLL"):
|
||||
return a << b
|
||||
elif (test == "SRL"):
|
||||
return a >> b
|
||||
elif (test == "SRA"):
|
||||
return asigned >> b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg2 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd, xlen):
|
||||
global testnum
|
||||
expected = computeExpected(a, b, test, xlen)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
reg1, reg2, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["SLL", "SRL", "SRA"]
|
||||
author = "David_Harris@hmc.edu"
|
||||
xlens = [32, 64]
|
||||
numrand = 48
|
||||
|
||||
# setup
|
||||
seed(0) # 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
|
||||
for test in tests:
|
||||
corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
if (xlen == 32):
|
||||
shamt = [0, 1, 2, 3, 4, 8, 15, 16, 29, 30, 31]
|
||||
else:
|
||||
shamt = [0, 1, 3, 8, 15, 16, 29, 31, 32, 47, 48, 62, 63]
|
||||
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
for a in corners:
|
||||
for b in shamt:
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
|
||||
|
||||
# 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()
|
||||
|
||||
|
||||
|
||||
|
189
wally-pipelined/testgen/testgen-SLLI-SRLI-SRAI.py
Normal file
189
wally-pipelined/testgen/testgen-SLLI-SRLI-SRAI.py
Normal file
@ -0,0 +1,189 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 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 random import getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "SLLI"):
|
||||
return a << b
|
||||
elif (test == "SRLI"):
|
||||
return srli(a,b)
|
||||
elif (test == "SRAI"):
|
||||
return a >> b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def signExt(b, bits):
|
||||
a_str = bin(b)[2::]
|
||||
if (a_str[0] == "b"):
|
||||
a_str = a_str[1:]
|
||||
|
||||
if (len(a_str) < 12):
|
||||
zeroPadding = "0" * (bits - len(a_str))
|
||||
a_str = zeroPadding + a_str
|
||||
|
||||
print( "{:x}, {:s} ".format(b, a_str))
|
||||
padding = a_str[len(a_str)-1] * (bits - len(a_str))
|
||||
return int(padding + a_str, 2)
|
||||
|
||||
|
||||
def evaluateTwoComplement(b, bits):
|
||||
if (b & (1 << (bits -1))!= 0):
|
||||
b = b - (1 << bits)
|
||||
return b
|
||||
|
||||
|
||||
def srli(a,b):
|
||||
if (a < 0):
|
||||
a = 2**xlen + a
|
||||
if (b==0):
|
||||
return a
|
||||
a_str = bin(a)[2:]
|
||||
if a_str[0]== "b":
|
||||
a_str = a_str[1:]
|
||||
# print(a_str)
|
||||
numZeroPad = (len(a_str)-abs(b))
|
||||
out = a_str[:numZeroPad]
|
||||
if (numZeroPad <= 0):
|
||||
return 0
|
||||
print("a: {:b}, b: {:d}, out:{:b}".format(a, b, int(out,2)))
|
||||
return int(out,2)
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg3 == 6):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
|
||||
|
||||
|
||||
|
||||
expected = computeExpected(evaluateTwoComplement(a, xlen), b, test)
|
||||
# print( "original {:x}, sign Extended {:x} ".format(b, signExt(b,xlen)))
|
||||
# print (str(a) + "<" + str(signExt(b,xlen)) + " : " + str(expected))
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
|
||||
|
||||
|
||||
reg1, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), imm5:" + "(" +formatstrimm5.format(b)
|
||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", " + formatstrimm5.format(b) + "\n"
|
||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["SLLI", "SRLI", "SRAI"]
|
||||
author = "Shriya Nadgauda & Ethan Falicov"
|
||||
xlens = [32, 64]
|
||||
numrand = 100
|
||||
|
||||
|
||||
# setup
|
||||
seed(0) # 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
|
||||
|
||||
formatstrimm5 = "0b{:05b}" # format as 5-bit binary number
|
||||
if (xlen == 32):
|
||||
storecmd = "sw"
|
||||
wordsize = 4
|
||||
else:
|
||||
storecmd = "sd"
|
||||
wordsize = 8
|
||||
|
||||
for test in tests:
|
||||
corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
|
||||
immBitSize = 5
|
||||
corners2 = [0, 1, 2, 0x07, 0x14 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0x06 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
||||
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
for a in corners1:
|
||||
for b in corners2:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(5)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
173
wally-pipelined/testgen/testgen-SLTIU.py
Normal file
173
wally-pipelined/testgen/testgen-SLTIU.py
Normal file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 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 random import getrandbits
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def computeExpected(a, b, test):
|
||||
if (test == "SLTIU"):
|
||||
return a < b
|
||||
else:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
|
||||
def signExt(b, bits):
|
||||
a_str = bin(b)[2::]
|
||||
if (a_str[0] == "b"):
|
||||
a_str = a_str[1:]
|
||||
|
||||
if (len(a_str) < 12):
|
||||
zeroPadding = "0" * (12 - len(a_str))
|
||||
a_str = zeroPadding + a_str
|
||||
|
||||
|
||||
padding = a_str[0] * (bits - len(a_str))
|
||||
print( "b {:x}, sign extended {:s} ".format(b, padding + a_str))
|
||||
return int(padding + a_str, 2)
|
||||
|
||||
|
||||
|
||||
def evaluateTwoComplement(b, bits):
|
||||
if (b & (1 << (bits -1))!= 0):
|
||||
b = b - (1 << bits)
|
||||
return b
|
||||
|
||||
|
||||
def randRegs():
|
||||
reg1 = randint(1,31)
|
||||
reg3 = randint(1,31)
|
||||
if (reg1 == 6 or reg3 == 6):
|
||||
return randRegs()
|
||||
else:
|
||||
return reg1, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
global testnum
|
||||
|
||||
|
||||
|
||||
signExtImm = signExt(b,xlen)
|
||||
if signExtImm < 0:
|
||||
signExtImm = signExtImm + 2 ** xlen
|
||||
expected = computeExpected(a, signExtImm, test)
|
||||
# s
|
||||
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
|
||||
|
||||
|
||||
reg1, reg3 = randRegs()
|
||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||
lines = lines + "), imm12:" + "(" +formatstrimm12.format(b)
|
||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n"
|
||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||
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
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["SLTIU"]
|
||||
author = "Shriya Nadgauda & Ethan Falicov"
|
||||
xlens = [32, 64]
|
||||
numrand = 100
|
||||
|
||||
|
||||
# setup
|
||||
seed(0) # 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
|
||||
|
||||
formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number
|
||||
if (xlen == 32):
|
||||
storecmd = "sw"
|
||||
wordsize = 4
|
||||
else:
|
||||
storecmd = "sd"
|
||||
wordsize = 8
|
||||
|
||||
for test in tests:
|
||||
corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||
|
||||
immBitSize = 12
|
||||
corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
||||
|
||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||
basename = "WALLY-" + test
|
||||
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
|
||||
for a in corners1:
|
||||
for b in corners2:
|
||||
writeVector(a, b, storecmd)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(12)
|
||||
writeVector(a, b, 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()
|
||||
|
||||
|
||||
|
282
wally-pipelined/testgen/testgen-STORE.py
Executable file
282
wally-pipelined/testgen/testgen-STORE.py
Executable file
@ -0,0 +1,282 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-STORE.py
|
||||
#
|
||||
# Jessica Torrey <jtorrey@hmc.edu> 03 February 2021
|
||||
# Thomas Fleming <tfleming@hmc.edu> 03 February 2021
|
||||
#
|
||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
||||
##################################
|
||||
|
||||
##################################
|
||||
# libraries
|
||||
##################################
|
||||
from datetime import datetime
|
||||
from random import randint, seed, getrandbits
|
||||
from textwrap import dedent
|
||||
|
||||
##################################
|
||||
# global structures
|
||||
##################################
|
||||
size_to_store = {8: "sd", 4: "sw", 2: "sh", 1: "sb"}
|
||||
size_to_load = {8: "ld", 4: "lw", 2: "lh", 1: "lb"}
|
||||
store_to_size = {"sd": 8, "sw": 4, "sh": 2, "sb": 1}
|
||||
testcase_num = 0
|
||||
signature_len = 2000
|
||||
signature = [0xff for _ in range(signature_len)]
|
||||
|
||||
##################################
|
||||
# functions
|
||||
##################################
|
||||
|
||||
def rand_reg():
|
||||
"""
|
||||
Produce a random register from 1 to 31 (skipping 6, since r6 is used for
|
||||
other things).
|
||||
"""
|
||||
r = randint(1,30)
|
||||
if r >= 6:
|
||||
r += 1
|
||||
return r
|
||||
|
||||
def rand_regs():
|
||||
"""
|
||||
Generate two random, unequal register numbers (skipping x6).
|
||||
"""
|
||||
rs1 = rand_reg()
|
||||
rs2 = rand_reg()
|
||||
while rs1 == rs2:
|
||||
rs2 = rand_reg()
|
||||
|
||||
return rs1, rs2
|
||||
|
||||
def generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta):
|
||||
"""
|
||||
Create assembly code for a given STORE test case, returned as a string.
|
||||
|
||||
Generates an `xlen`-bit test case for `instruction` (one of sb, sh, sw, or
|
||||
sd) that loads `value` into `value_register`, then attempts to store that
|
||||
value in memory at address (x6 + `base_delta`). The test case
|
||||
assumes the current base address for the signature is in register x6.
|
||||
|
||||
The form of the STORE instruction is as follows:
|
||||
|
||||
`instruction` `value_register` `offset`(`addr_register`)
|
||||
"""
|
||||
global testcase_num
|
||||
|
||||
hex_value = f"{value:0{xlen // 4}x}"
|
||||
|
||||
data = f"""# Testcase {testcase_num}: source: x{value_register} (value 0x{hex_value}), destination: {offset}(x{addr_register}) ({base_delta} bytes into signature)
|
||||
addi x{addr_register}, x6, {base_delta}
|
||||
li x{value_register}, MASK_XLEN({-offset})
|
||||
add x{addr_register}, x{addr_register}, x{value_register}
|
||||
li x{value_register}, 0x{hex_value}
|
||||
{instruction} x{value_register}, {offset}(x{addr_register})
|
||||
"""
|
||||
|
||||
update_signature(store_to_size[instruction], value, base_delta)
|
||||
|
||||
testcase_num += 1
|
||||
return data
|
||||
|
||||
def validate_memory(scratch_register, value_register, value, base_delta, length):
|
||||
"""
|
||||
Create assembly code to verify that `length` bytes at mem[x6 + `base_delta`]
|
||||
store `value`.
|
||||
|
||||
Assumes x6 stores the current base address for the signature.
|
||||
"""
|
||||
truncated_value = value & (2**(length * 8) - 1)
|
||||
hex_value = f"{truncated_value:0{length * 2}x}"
|
||||
|
||||
load = size_to_load[length]
|
||||
data = f"""addi x{scratch_register}, x6, {base_delta}
|
||||
{load} x{value_register}, 0(x{scratch_register})
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x{scratch_register}, x{value_register}, 0x{hex_value})
|
||||
|
||||
"""
|
||||
return data
|
||||
|
||||
def update_signature(length, value, base_delta):
|
||||
"""
|
||||
Write the lower `length` bytes of `value` to the little-endian signature
|
||||
array, starting at byte `base_delta`.
|
||||
"""
|
||||
truncated_value = value & (2**(length * 8) - 1)
|
||||
value_bytes = truncated_value.to_bytes(length, 'little')
|
||||
#print("n: {}, value: {:x}, trunc: {:x}, length: {}, bd: {:x}".format(testcase_num, value, truncated_value, length, base_delta))
|
||||
for i in range(length):
|
||||
signature[base_delta + i] = value_bytes[i]
|
||||
|
||||
def write_signature(outfile):
|
||||
"""
|
||||
Writes successive 32-bit words from the signature array into a given file.
|
||||
"""
|
||||
for i in range(0, signature_len, 4):
|
||||
word = list(reversed(signature[i:i+4]))
|
||||
hexword = bytearray(word).hex()
|
||||
outfile.write(f"{hexword}\n")
|
||||
|
||||
def write_header(outfile):
|
||||
"""
|
||||
Write the name of the test file, authors, and creation date.
|
||||
"""
|
||||
outfile.write(dedent(f"""\
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-STORE
|
||||
//
|
||||
// Author: {author}
|
||||
//
|
||||
// Created {str(datetime.now())}
|
||||
"""))
|
||||
outfile.write(open("testgen_header.S", "r").read())
|
||||
|
||||
def write_footer(outfile):
|
||||
"""
|
||||
Write necessary closing code, including a data section for the signature.
|
||||
"""
|
||||
outfile.write(open("testgen_footer.S", 'r').read())
|
||||
data_section = dedent(f"""\
|
||||
\t.fill {signature_len}, 1, -1
|
||||
RV_COMPLIANCE_DATA_END
|
||||
""")
|
||||
outfile.write(data_section)
|
||||
|
||||
##################################
|
||||
# test cases
|
||||
##################################
|
||||
|
||||
def write_basic_tests(outfile, xlen, instr_len, num, base_delta):
|
||||
"""
|
||||
Test basic functionality of STORE, using random registers, offsets, and
|
||||
values.
|
||||
|
||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
||||
writing to memory at consecutive locations, starting `base_delta` bytes from
|
||||
the start of the signature.
|
||||
|
||||
Returns the number of bytes from the start of the signature where testing
|
||||
ended.
|
||||
"""
|
||||
instruction = size_to_store[instr_len]
|
||||
for i in range(num):
|
||||
value_register, addr_register = rand_regs()
|
||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
||||
value = randint(0, 2**(instr_len * 8) - 1)
|
||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
||||
outfile.write(test)
|
||||
outfile.write(validate)
|
||||
base_delta += instr_len
|
||||
return base_delta
|
||||
|
||||
def write_random_store_tests(outfile, xlen, instr_len, num, min_base_delta):
|
||||
"""
|
||||
Test random access of STORE, using random registers, offsets, values, and
|
||||
memory locations.
|
||||
|
||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
||||
writing to memory at random locations between `min_base_delta` bytes past
|
||||
the start of the signature to the end of the signature.
|
||||
"""
|
||||
instruction = size_to_store[instr_len]
|
||||
for i in range(num):
|
||||
base_delta = randint(min_base_delta, signature_len - 1)
|
||||
base_delta -= (base_delta % instr_len)
|
||||
value_register, addr_register = rand_regs()
|
||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
||||
value = randint(0, 2**(instr_len * 8) - 1)
|
||||
|
||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
||||
outfile.write(test)
|
||||
outfile.write(validate)
|
||||
|
||||
def write_repeated_store_tests(outfile, xlen, instr_len, num, base_delta):
|
||||
"""
|
||||
Test repeated access of STORE, using random registers, offsets, values, and a
|
||||
single memory location.
|
||||
|
||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
||||
writing to memory `base_delta` bytes past the start of the signature.
|
||||
"""
|
||||
instruction = size_to_store[instr_len]
|
||||
for i in range(num):
|
||||
value_register, addr_register = rand_regs()
|
||||
offset = 0
|
||||
value = (1 << ((2 * i) % xlen))
|
||||
|
||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
||||
|
||||
outfile.write(test)
|
||||
outfile.write(validate)
|
||||
|
||||
def write_corner_case_tests(outfile, xlen, instr_len, base_delta):
|
||||
instruction = size_to_store[instr_len]
|
||||
|
||||
corner_cases_32 = [0x0, 0x10000001, 0x01111111]
|
||||
corner_cases_64 = [0x1000000000000001, 0x0111111111111111]
|
||||
corner_cases = corner_cases_32
|
||||
if xlen == 64:
|
||||
corner_cases += corner_cases_64
|
||||
|
||||
for offset in corner_cases:
|
||||
for value in corner_cases:
|
||||
value_register, addr_register = rand_regs()
|
||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
||||
|
||||
outfile.write(test)
|
||||
outfile.write(validate)
|
||||
|
||||
base_delta += instr_len
|
||||
|
||||
return base_delta
|
||||
|
||||
##################################
|
||||
# main body
|
||||
##################################
|
||||
|
||||
instructions = ["sd", "sw", "sh", "sb"]
|
||||
author = "Jessica Torrey <jtorrey@hmc.edu> & Thomas Fleming <tfleming@hmc.edu>"
|
||||
xlens = [32, 64]
|
||||
numrand = 100
|
||||
|
||||
# setup
|
||||
seed(0) # make tests reproducible
|
||||
|
||||
for xlen in xlens:
|
||||
if (xlen == 32):
|
||||
wordsize = 4
|
||||
else:
|
||||
wordsize = 8
|
||||
|
||||
fname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/src/WALLY-STORE.S"
|
||||
refname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/references/WALLY-STORE.reference_output"
|
||||
f = open(fname, "w")
|
||||
r = open(refname, "w")
|
||||
|
||||
write_header(f)
|
||||
|
||||
base_delta = 0
|
||||
|
||||
for instruction in instructions:
|
||||
if xlen == 32 and instruction == 'sd':
|
||||
continue
|
||||
instr_len = store_to_size[instruction]
|
||||
base_delta = write_basic_tests(f, xlen, instr_len, 5, base_delta)
|
||||
write_repeated_store_tests(f, xlen, instr_len, 32, base_delta)
|
||||
write_random_store_tests(f, xlen, instr_len, 5, base_delta + wordsize)
|
||||
|
||||
write_footer(f)
|
||||
|
||||
write_signature(r)
|
||||
f.close()
|
||||
r.close()
|
||||
|
||||
# Reset testcase_num and signature
|
||||
testcase_num = 0
|
||||
signature = [0xff for _ in range(signature_len)]
|
Loading…
Reference in New Issue
Block a user