mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
merged with main to integrate with AHB
This commit is contained in:
commit
e8b306bcba
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,9 +1,3 @@
|
|||||||
[submodule "sky130/sky130_osu_sc_t12"]
|
[submodule "sky130/sky130_osu_sc_t12"]
|
||||||
path = 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/
|
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12/
|
||||||
[submodule "sky130/sky130_osu_sc_t15"]
|
|
||||||
path = sky130/sky130_osu_sc_t15
|
|
||||||
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t15/
|
|
||||||
[submodule "sky130/sky130_osu_sc_t18"]
|
|
||||||
path = sky130/sky130_osu_sc_t18
|
|
||||||
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t18/
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 87ca77795004bea5525b25badd7ec36cbc8222e1
|
Subproject commit f60f2d0395053c4df362a97d7e2099721b6face6
|
@ -1 +0,0 @@
|
|||||||
Subproject commit dae3c2282e10d72f57af61d1dd73a1b0aead63f9
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 6c20402bf853e6bf3985fce49fe88ca25502cc63
|
|
90
wally-pipelined/config/coremark/wally-config.vh
Normal file
90
wally-pipelined/config/coremark/wally-config.vh
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//////////////////////////////////////////
|
||||||
|
// wally-config.vh
|
||||||
|
//
|
||||||
|
// Written: David_Harris@hmc.edu 4 January 2021
|
||||||
|
// Modified:
|
||||||
|
//
|
||||||
|
// 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 | 1 << 12)
|
||||||
|
`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
|
||||||
|
`define RESET_VECTOR 64'h0000000000000000
|
||||||
|
|
||||||
|
// 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'h00000000
|
||||||
|
`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 */
|
@ -61,7 +61,7 @@
|
|||||||
// Bus Interface width
|
// Bus Interface width
|
||||||
`define AHBW 64
|
`define AHBW 64
|
||||||
|
|
||||||
// Peripheral Addresses
|
// Peripheral Physiccal Addresses
|
||||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
// 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
|
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||||
|
|
||||||
|
102
wally-pipelined/ppa/ppa.sv
Normal file
102
wally-pipelined/ppa/ppa.sv
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// ppa.sv
|
||||||
|
// Teo Ene & David_Harris@hmc.edu 25 Feb 2021
|
||||||
|
// Measure PPA of various building blocks
|
||||||
|
|
||||||
|
// replace this with the tools setting a library path to a config/skl130 directory containing config.vh
|
||||||
|
`define LIB SKL130
|
||||||
|
|
||||||
|
module top(
|
||||||
|
input logic a1,
|
||||||
|
input logic [7:0] a8, b8,
|
||||||
|
input logic [15:0] a16, b16,
|
||||||
|
input logic [31:0] a32, b32,
|
||||||
|
input logic [63:0] a64, b64,
|
||||||
|
output logic yinv,
|
||||||
|
output logic [63:0] y1, y2, y3, y4
|
||||||
|
);
|
||||||
|
|
||||||
|
// fo4 inverter
|
||||||
|
myinv myinv(a1, yinv);)
|
||||||
|
|
||||||
|
// adders
|
||||||
|
add #(8) add8(a8, b8, yadd8);
|
||||||
|
add #(16) add16(a16, b16, yadd16);
|
||||||
|
add #(32) add32(a32, b32, yadd32);
|
||||||
|
add #(64) add64(a64, b64, yadd64);
|
||||||
|
|
||||||
|
// mux2, mux3, mux4 of 1, 8, 16, 32, 64
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module myinv(input a, output y);
|
||||||
|
driver #(1) drive(a, in1);
|
||||||
|
assign out = ~in;
|
||||||
|
load #(1) load(out, y);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module add #(parameter WIDTH=8) (
|
||||||
|
input logic [7:0] a, b,
|
||||||
|
output logic [7:0] y
|
||||||
|
);
|
||||||
|
logic [WIDTH-1:0] in1, in2, out;
|
||||||
|
|
||||||
|
driver #(WIDTH) drive1(a, in1);
|
||||||
|
driver #(WIDTH) drive2(b, in2);
|
||||||
|
assign out = in1 + in2;
|
||||||
|
load #(WIDTH) load(out, y);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module INVX2(input logic a, output logic y);
|
||||||
|
generate
|
||||||
|
if (LIB == SKL130)
|
||||||
|
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
|
||||||
|
else if (LIB == SKL90)
|
||||||
|
scc9gena_inv_2 inv(a, y)
|
||||||
|
else if (LIB == GF14)
|
||||||
|
INV_X2N_A10P5PP84TSL_C14(a, y)
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module driver #(parameter WDITH=1) (
|
||||||
|
input [WIDTH-1:0] logic a,
|
||||||
|
output [WIDTH-1:0] logic y
|
||||||
|
);
|
||||||
|
logic [WIDTH-1:0] ab;
|
||||||
|
|
||||||
|
INVX2 i1[WIDTH-1:0](a, ab);
|
||||||
|
INVX2 i2[WIDTH-1:0](ab, y);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module inv4(input logic a, output logic y);
|
||||||
|
logic [3:0] b
|
||||||
|
INVX2 i0(a, b[0]);
|
||||||
|
INVX2 i1(a, b[1]);
|
||||||
|
INVX2 i2(a, b[2]);
|
||||||
|
INVX2 i3(a, b[3]);
|
||||||
|
INVX2 i00(b[0], y;
|
||||||
|
INVX2 i01(b[0], y);
|
||||||
|
INVX2 i02(b[0], y);
|
||||||
|
INVX2 i03(b[0], y);
|
||||||
|
INVX2 i10(b[1], y;
|
||||||
|
INVX2 i11(b[1], y);
|
||||||
|
INVX2 i12(b[1], y);
|
||||||
|
INVX2 i13(b[1], y);
|
||||||
|
INVX2 i20(b[2], y;
|
||||||
|
INVX2 i21(b[2], y);
|
||||||
|
INVX2 i22(b[2], y);
|
||||||
|
INVX2 i23(b[2], y);
|
||||||
|
INVX2 i30(b[3], y;
|
||||||
|
INVX2 i31(b[3], y);
|
||||||
|
INVX2 i32(b[3], y);
|
||||||
|
INVX2 i33(b[3], y);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module load #(parameter WDITH=1) (
|
||||||
|
input [WIDTH-1:0] logic a,
|
||||||
|
output [WIDTH-1:0] logic y
|
||||||
|
);
|
||||||
|
logic [WIDTH-1:0] ab;
|
||||||
|
|
||||||
|
inv4 load[WIDTH-1:0](a, y);
|
||||||
|
endmodule
|
@ -7,11 +7,11 @@
|
|||||||
#
|
#
|
||||||
# Takes 1:10 to run RV64IC tests using gui
|
# Takes 1:10 to run RV64IC tests using gui
|
||||||
|
|
||||||
# Use this wally-pipelined.do file to run this example.
|
# Use this wally-coremark.do file to run this example.
|
||||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||||
# do wally-pipelined.do
|
# do wally-coremark.do
|
||||||
# or, to run from a shell, type the following at the shell prompt:
|
# or, to run from a shell, type the following at the shell prompt:
|
||||||
# vsim -do wally-pipelined.do -c
|
# vsim -do wally-coremark.do -c
|
||||||
# (omit the "-c" to see the GUI while running from the shell)
|
# (omit the "-c" to see the GUI while running from the shell)
|
||||||
|
|
||||||
onbreak {resume}
|
onbreak {resume}
|
||||||
@ -27,12 +27,9 @@ vlib work
|
|||||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||||
# because vsim will run vopt
|
# because vsim will run vopt
|
||||||
|
|
||||||
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
|
# default to config/coremark, but allow this to be overridden at the command line. For example:
|
||||||
# do wally-pipelined.do ../config/rv32ic
|
vlog +incdir+../config/coremark ../testbench/testbench-coremark.sv ../src/*/*.sv -suppress 2583
|
||||||
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
|
# start and run simulation
|
||||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
||||||
vopt +acc work.testbench -o workopt
|
vopt +acc work.testbench -o workopt
|
||||||
@ -45,7 +42,7 @@ view wave
|
|||||||
add wave /testbench/clk
|
add wave /testbench/clk
|
||||||
add wave /testbench/reset
|
add wave /testbench/reset
|
||||||
add wave -divider
|
add wave -divider
|
||||||
add wave /testbench/dut/hart/ebu/IReadF
|
#add wave /testbench/dut/hart/ebu/IReadF
|
||||||
add wave /testbench/dut/hart/DataStall
|
add wave /testbench/dut/hart/DataStall
|
||||||
add wave /testbench/dut/hart/InstrStall
|
add wave /testbench/dut/hart/InstrStall
|
||||||
add wave /testbench/dut/hart/StallF
|
add wave /testbench/dut/hart/StallF
|
||||||
@ -58,11 +55,14 @@ add wave /testbench/dut/hart/FlushW
|
|||||||
add wave -divider
|
add wave -divider
|
||||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||||
add wave -hex /testbench/dut/hart/ifu/InstrF
|
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/PCD
|
||||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||||
|
add wave /testbench/InstrDName
|
||||||
add wave -divider
|
add wave -divider
|
||||||
#add wave -hex /testbench/dut/hart/ifu/PCE
|
#add wave -hex /testbench/dut/hart/ifu/PCE
|
||||||
#add wave -hex /testbench/dut/hart/ifu/InstrE
|
#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/SrcAE
|
||||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||||
@ -70,11 +70,13 @@ add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
|||||||
add wave -divider
|
add wave -divider
|
||||||
#add wave -hex /testbench/dut/hart/ifu/PCM
|
#add wave -hex /testbench/dut/hart/ifu/PCM
|
||||||
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||||
|
add wave /testbench/InstrMName
|
||||||
add wave /testbench/dut/uncore/dtim/memwrite
|
add wave /testbench/dut/uncore/dtim/memwrite
|
||||||
add wave -hex /testbench/dut/uncore/HADDR
|
add wave -hex /testbench/dut/uncore/HADDR
|
||||||
add wave -hex /testbench/dut/uncore/HWDATA
|
add wave -hex /testbench/dut/uncore/HWDATA
|
||||||
add wave -divider
|
add wave -divider
|
||||||
add wave -hex /testbench/dut/hart/ifu/PCW
|
add wave -hex /testbench/dut/hart/ifu/PCW
|
||||||
|
add wave /testbench/InstrWName
|
||||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
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/ResultW
|
||||||
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||||
|
@ -45,11 +45,14 @@ view wave
|
|||||||
add wave /testbench/clk
|
add wave /testbench/clk
|
||||||
add wave /testbench/reset
|
add wave /testbench/reset
|
||||||
add wave -divider
|
add wave -divider
|
||||||
add wave /testbench/dut/hart/ebu/IReadF
|
#add wave /testbench/dut/hart/ebu/IReadF
|
||||||
add wave /testbench/dut/hart/DataStall
|
add wave /testbench/dut/hart/DataStall
|
||||||
add wave /testbench/dut/hart/InstrStall
|
add wave /testbench/dut/hart/InstrStall
|
||||||
add wave /testbench/dut/hart/StallF
|
add wave /testbench/dut/hart/StallF
|
||||||
add wave /testbench/dut/hart/StallD
|
add wave /testbench/dut/hart/StallD
|
||||||
|
add wave /testbench/dut/hart/StallE
|
||||||
|
add wave /testbench/dut/hart/StallM
|
||||||
|
add wave /testbench/dut/hart/StallW
|
||||||
add wave /testbench/dut/hart/FlushD
|
add wave /testbench/dut/hart/FlushD
|
||||||
add wave /testbench/dut/hart/FlushE
|
add wave /testbench/dut/hart/FlushE
|
||||||
add wave /testbench/dut/hart/FlushM
|
add wave /testbench/dut/hart/FlushM
|
||||||
@ -59,26 +62,27 @@ add wave -divider
|
|||||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||||
add wave -hex /testbench/dut/hart/ifu/InstrF
|
add wave -hex /testbench/dut/hart/ifu/InstrF
|
||||||
add wave /testbench/InstrFName
|
add wave /testbench/InstrFName
|
||||||
#add wave -hex /testbench/dut/hart/ifu/PCD
|
add wave -hex /testbench/dut/hart/ifu/PCD
|
||||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||||
add wave /testbench/InstrDName
|
add wave /testbench/InstrDName
|
||||||
add wave -divider
|
add wave -divider
|
||||||
#add wave -hex /testbench/dut/hart/ifu/PCE
|
add wave -hex /testbench/dut/hart/ifu/PCE
|
||||||
#add wave -hex /testbench/dut/hart/ifu/InstrE
|
add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||||
add wave /testbench/InstrEName
|
add wave /testbench/InstrEName
|
||||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
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/SrcBE
|
||||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||||
add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
||||||
add wave -divider
|
add wave -divider
|
||||||
#add wave -hex /testbench/dut/hart/ifu/PCM
|
add wave -hex /testbench/dut/hart/ifu/PCM
|
||||||
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||||
add wave /testbench/InstrMName
|
add wave /testbench/InstrMName
|
||||||
add wave /testbench/dut/uncore/dtim/memwrite
|
add wave /testbench/dut/uncore/dtim/memwrite
|
||||||
add wave -hex /testbench/dut/uncore/HADDR
|
add wave -hex /testbench/dut/uncore/HADDR
|
||||||
add wave -hex /testbench/dut/uncore/HWDATA
|
add wave -hex /testbench/dut/uncore/HWDATA
|
||||||
add wave -divider
|
add wave -divider
|
||||||
add wave -hex /testbench/dut/hart/ifu/PCW
|
add wave -hex /testbench/dut/hart/ifu/PCW
|
||||||
|
add wave -hex /testbench/dut/hart/ifu/InstrW
|
||||||
add wave /testbench/InstrWName
|
add wave /testbench/InstrWName
|
||||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
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/ResultW
|
||||||
@ -101,6 +105,6 @@ configure wave -childrowmargin 2
|
|||||||
set DefaultRadix hexadecimal
|
set DefaultRadix hexadecimal
|
||||||
|
|
||||||
-- Run the Simulation
|
-- Run the Simulation
|
||||||
#run 1000
|
#run 2000
|
||||||
run -all
|
run -all
|
||||||
#quit
|
#quit
|
||||||
|
@ -30,19 +30,19 @@
|
|||||||
module dmem (
|
module dmem (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic FlushW,
|
input logic FlushW,
|
||||||
output logic DataStall,
|
//output logic DataStall,
|
||||||
// Memory Stage
|
// Memory Stage
|
||||||
input logic [1:0] MemRWM,
|
input logic [1:0] MemRWM,
|
||||||
input logic [`XLEN-1:0] MemAdrM,
|
input logic [`XLEN-1:0] MemAdrM,
|
||||||
input logic [2:0] Funct3M,
|
input logic [2:0] Funct3M,
|
||||||
input logic [`XLEN-1:0] ReadDataM,
|
//input logic [`XLEN-1:0] ReadDataW,
|
||||||
input logic [`XLEN-1:0] WriteDataM,
|
input logic [`XLEN-1:0] WriteDataM,
|
||||||
output logic [`XLEN-1:0] MemPAdrM,
|
output logic [`XLEN-1:0] MemPAdrM,
|
||||||
output logic [1:0] MemRWAlignedM,
|
output logic MemReadM, MemWriteM,
|
||||||
output logic DataMisalignedM,
|
output logic DataMisalignedM,
|
||||||
// Writeback Stage
|
// Writeback Stage
|
||||||
input logic MemAckW,
|
input logic MemAckW,
|
||||||
output logic [`XLEN-1:0] ReadDataW,
|
input logic [`XLEN-1:0] ReadDataW,
|
||||||
// faults
|
// faults
|
||||||
input logic DataAccessFaultM,
|
input logic DataAccessFaultM,
|
||||||
output logic LoadMisalignedFaultM, LoadAccessFaultM,
|
output logic LoadMisalignedFaultM, LoadAccessFaultM,
|
||||||
@ -52,9 +52,6 @@ module dmem (
|
|||||||
// Initially no MMU
|
// Initially no MMU
|
||||||
assign MemPAdrM = MemAdrM;
|
assign MemPAdrM = MemAdrM;
|
||||||
|
|
||||||
// Pipeline register *** AHB data will eventually come back in W anyway
|
|
||||||
floprc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataM, ReadDataW);
|
|
||||||
|
|
||||||
// Determine if an Unaligned access is taking place
|
// Determine if an Unaligned access is taking place
|
||||||
always_comb
|
always_comb
|
||||||
case(Funct3M[1:0])
|
case(Funct3M[1:0])
|
||||||
@ -66,7 +63,8 @@ module dmem (
|
|||||||
|
|
||||||
// Squash unaligned data accesses
|
// Squash unaligned data accesses
|
||||||
// *** this is also the place to squash if the cache is hit
|
// *** this is also the place to squash if the cache is hit
|
||||||
assign MemRWAlignedM = MemRWM & {2{~DataMisalignedM}};
|
assign MemReadM = MemRWM[1] & ~DataMisalignedM;
|
||||||
|
assign MemWriteM = MemRWM[0] & ~DataMisalignedM;
|
||||||
|
|
||||||
// Determine if address is valid
|
// Determine if address is valid
|
||||||
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
|
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
|
||||||
@ -75,7 +73,7 @@ module dmem (
|
|||||||
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
|
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
|
||||||
|
|
||||||
// Data stall
|
// Data stall
|
||||||
assign DataStall = 0;
|
//assign DataStall = 0;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -32,21 +32,20 @@
|
|||||||
|
|
||||||
module ahblite (
|
module ahblite (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
|
input logic StallW, FlushW,
|
||||||
// Load control
|
// Load control
|
||||||
input logic UnsignedLoadM,
|
input logic UnsignedLoadM,
|
||||||
// Signals from Instruction Cache
|
// Signals from Instruction Cache
|
||||||
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
|
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
|
||||||
input logic IReadF,
|
input logic InstrReadF,
|
||||||
output logic [`XLEN-1:0] IRData,
|
output logic [`XLEN-1:0] InstrRData,
|
||||||
// output logic IReady,
|
|
||||||
// Signals from Data Cache
|
// Signals from Data Cache
|
||||||
input logic [`XLEN-1:0] MemPAdrM,
|
input logic [`XLEN-1:0] MemPAdrM,
|
||||||
input logic DReadM, DWriteM,
|
input logic MemReadM, MemWriteM,
|
||||||
input logic [`XLEN-1:0] WriteDataM,
|
input logic [`XLEN-1:0] WriteDataM,
|
||||||
input logic [1:0] DSizeM,
|
input logic [1:0] MemSizeM,
|
||||||
// Return from bus
|
// Return from bus
|
||||||
output logic [`XLEN-1:0] DRData,
|
output logic [`XLEN-1:0] ReadDataW,
|
||||||
// output logic DReady,
|
|
||||||
// AHB-Lite external signals
|
// AHB-Lite external signals
|
||||||
input logic [`AHBW-1:0] HRDATA,
|
input logic [`AHBW-1:0] HRDATA,
|
||||||
input logic HREADY, HRESP,
|
input logic HREADY, HRESP,
|
||||||
@ -59,57 +58,91 @@ module ahblite (
|
|||||||
output logic [3:0] HPROT,
|
output logic [3:0] HPROT,
|
||||||
output logic [1:0] HTRANS,
|
output logic [1:0] HTRANS,
|
||||||
output logic HMASTLOCK,
|
output logic HMASTLOCK,
|
||||||
// Acknowledge
|
// Delayed signals for writes
|
||||||
output logic InstrAckD, MemAckW
|
output logic [2:0] HADDRD,
|
||||||
|
output logic [3:0] HSIZED,
|
||||||
|
output logic HWRITED,
|
||||||
// Stalls
|
// Stalls
|
||||||
// output logic InstrStall, DataStall
|
output logic InstrStall,/*InstrUpdate, */DataStall
|
||||||
);
|
);
|
||||||
|
|
||||||
logic GrantData;
|
logic GrantData;
|
||||||
logic [2:0] ISize;
|
logic [2:0] ISize;
|
||||||
logic [`AHBW-1:0] HRDATAMasked;
|
logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataPreW;
|
||||||
logic IReady, DReady;
|
logic IReady, DReady;
|
||||||
|
logic CaptureDataM;
|
||||||
|
|
||||||
assign HCLK = clk;
|
assign HCLK = clk;
|
||||||
assign HRESETn = ~reset;
|
assign HRESETn = ~reset;
|
||||||
|
|
||||||
// Arbitrate requests by giving data priority over instructions
|
|
||||||
assign GrantData = DReadM | DWriteM;
|
|
||||||
|
|
||||||
// *** initially support HABW = XLEN
|
// *** initially support HABW = XLEN
|
||||||
|
|
||||||
// Choose ISize based on XLen
|
// track bus state
|
||||||
generate
|
// Data accesses have priority over instructions. However, if a data access comes
|
||||||
if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers
|
// while an instruction read is occuring, the instruction read finishes before
|
||||||
else assign ISize = 3'b011; // 64-bit transfers
|
// the data access can take place.
|
||||||
endgenerate
|
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING} statetype;
|
||||||
|
statetype BusState, NextBusState;
|
||||||
|
|
||||||
// drive bus outputs
|
always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
if (~HRESETn) BusState <= #1 IDLE;
|
||||||
assign HWDATA = WriteDataM;
|
else BusState <= #1 NextBusState;
|
||||||
//flop #(`XLEN) wdreg(HCLK, DWDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
|
||||||
assign HWRITE = DWriteM;
|
always_comb
|
||||||
assign HSIZE = GrantData ? {1'b0, DSizeM} : ISize;
|
case (BusState)
|
||||||
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfHPROT
|
IDLE: if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions
|
||||||
|
else if (MemWriteM) NextBusState = MEMWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
INSTRREAD: //if (~HREADY & (MemReadM | MemWriteM)) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
|
||||||
|
if (~HREADY) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
INSTRREADMEMPENDING: if (~HREADY) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
|
||||||
|
else if (MemReadM) NextBusState = MEMREAD;
|
||||||
|
else NextBusState = MEMWRITE; // must be write if not a read. Don't return to idle.
|
||||||
|
endcase
|
||||||
|
|
||||||
|
// stall signals
|
||||||
|
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == INSTRREADMEMPENDING);
|
||||||
|
assign #1 InstrStall = (NextBusState == INSTRREAD);
|
||||||
|
|
||||||
|
// DH 2/20/22: A cyclic path presently exists
|
||||||
|
// HREADY->NextBusState->GrantData->HSIZE->HSELUART->HREADY
|
||||||
|
// This is because the peripherals assert HREADY on the same cycle
|
||||||
|
// When memory is working, also fix the peripherals to respond on the subsequent cycle
|
||||||
|
// and this path should be fixed.
|
||||||
|
|
||||||
|
// bus outputs
|
||||||
|
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE);
|
||||||
|
assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
||||||
|
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
|
||||||
|
assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize;
|
||||||
|
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
|
||||||
assign HPROT = 4'b0011; // not used; see Section 3.7
|
assign HPROT = 4'b0011; // not used; see Section 3.7
|
||||||
assign HTRANS = IReadF | DReadM | DWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
||||||
assign HMASTLOCK = 0; // no locking supported
|
assign HMASTLOCK = 0; // no locking supported
|
||||||
|
assign HWRITE = (NextBusState == MEMWRITE);
|
||||||
// Route signals to Instruction and Data Caches
|
// delay write data by one cycle for
|
||||||
|
flop #(`XLEN) wdreg(HCLK, WriteDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
||||||
|
// delay signals for subword writes
|
||||||
|
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
|
||||||
|
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
|
||||||
|
flop #(1) writereg(HCLK, HWRITE, HWRITED);
|
||||||
|
|
||||||
|
// Route signals to Instruction and Data Caches
|
||||||
// *** assumes AHBW = XLEN
|
// *** assumes AHBW = XLEN
|
||||||
assign IRData = HRDATAMasked;
|
|
||||||
assign IReady = HREADY & IReadF & ~GrantData; // maybe unused?***
|
|
||||||
assign DRData = HRDATAMasked;
|
|
||||||
assign DReady = HREADY & GrantData; // ***unused?
|
|
||||||
|
|
||||||
// stalls
|
assign InstrRData = HRDATA;
|
||||||
// Stall MEM stage if data is being accessed and bus isn't yet ready
|
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
||||||
//assign DataStall = GrantData & ~HREADY;
|
assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD);
|
||||||
// Stall Fetch stage if instruction should be read but reading data or bus isn't ready
|
flopenr #(`XLEN) ReadDataPreWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataPreW); // *** this may break when there is no instruction read after data read
|
||||||
//assign InstrStall = IReadF & (GrantData | ~HREADY);
|
flopenr #(`XLEN) ReadDataWReg(clk, reset, ~StallW, ReadDataPreW, ReadDataW);
|
||||||
|
|
||||||
// *** consider adding memory access faults based on HRESP being high
|
|
||||||
// InstrAccessFaultF, DataAccessFaultM,
|
|
||||||
|
|
||||||
subwordread swr(.*);
|
subwordread swr(.*);
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
module subwordread (
|
module subwordread (
|
||||||
// from AHB Interface
|
// from AHB Interface
|
||||||
input logic [`XLEN-1:0] HRDATA,
|
input logic [`XLEN-1:0] HRDATA,
|
||||||
input logic [31:0] HADDR,
|
input logic [2:0] HADDRD,
|
||||||
input logic UnsignedLoadM,
|
//input logic UnsignedLoadM,
|
||||||
input logic [2:0] HSIZE,
|
input logic [3:0] HSIZED,
|
||||||
// to ifu/dmems
|
// to ifu/dmems
|
||||||
output logic [`XLEN-1:0] HRDATAMasked
|
output logic [`XLEN-1:0] HRDATAMasked
|
||||||
);
|
);
|
||||||
@ -42,7 +42,7 @@ module subwordread (
|
|||||||
if (`XLEN == 64) begin
|
if (`XLEN == 64) begin
|
||||||
// ByteMe mux
|
// ByteMe mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDR[2:0])
|
case(HADDRD[2:0])
|
||||||
3'b000: ByteM = HRDATA[7:0];
|
3'b000: ByteM = HRDATA[7:0];
|
||||||
3'b001: ByteM = HRDATA[15:8];
|
3'b001: ByteM = HRDATA[15:8];
|
||||||
3'b010: ByteM = HRDATA[23:16];
|
3'b010: ByteM = HRDATA[23:16];
|
||||||
@ -55,7 +55,7 @@ module subwordread (
|
|||||||
|
|
||||||
// halfword mux
|
// halfword mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDR[2:1])
|
case(HADDRD[2:1])
|
||||||
2'b00: HalfwordM = HRDATA[15:0];
|
2'b00: HalfwordM = HRDATA[15:0];
|
||||||
2'b01: HalfwordM = HRDATA[31:16];
|
2'b01: HalfwordM = HRDATA[31:16];
|
||||||
2'b10: HalfwordM = HRDATA[47:32];
|
2'b10: HalfwordM = HRDATA[47:32];
|
||||||
@ -65,14 +65,14 @@ module subwordread (
|
|||||||
logic [31:0] WordM;
|
logic [31:0] WordM;
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDR[2])
|
case(HADDRD[2])
|
||||||
1'b0: WordM = HRDATA[31:0];
|
1'b0: WordM = HRDATA[31:0];
|
||||||
1'b1: WordM = HRDATA[63:32];
|
1'b1: WordM = HRDATA[63:32];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// sign extension
|
// sign extension
|
||||||
always_comb
|
always_comb
|
||||||
case({UnsignedLoadM, HSIZE[1:0]})
|
case({HSIZED[3], HSIZED[1:0]}) // HSIZED[3] indicates unsigned load
|
||||||
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
|
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
|
||||||
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
||||||
@ -85,7 +85,7 @@ module subwordread (
|
|||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
// byte mux
|
// byte mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDR[1:0])
|
case(HADDRD[1:0])
|
||||||
2'b00: ByteM = HRDATA[7:0];
|
2'b00: ByteM = HRDATA[7:0];
|
||||||
2'b01: ByteM = HRDATA[15:8];
|
2'b01: ByteM = HRDATA[15:8];
|
||||||
2'b10: ByteM = HRDATA[23:16];
|
2'b10: ByteM = HRDATA[23:16];
|
||||||
@ -94,14 +94,14 @@ module subwordread (
|
|||||||
|
|
||||||
// halfword mux
|
// halfword mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDR[1])
|
case(HADDRD[1])
|
||||||
1'b0: HalfwordM = HRDATA[15:0];
|
1'b0: HalfwordM = HRDATA[15:0];
|
||||||
1'b1: HalfwordM = HRDATA[31:16];
|
1'b1: HalfwordM = HRDATA[31:16];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// sign extension
|
// sign extension
|
||||||
always_comb
|
always_comb
|
||||||
case({UnsignedLoadM, HSIZE[1:0]})
|
case({HSIZED[3], HSIZED[1:0]})
|
||||||
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
|
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
|
||||||
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
3'b010: HRDATAMasked = HRDATA; // lw
|
3'b010: HRDATAMasked = HRDATA; // lw
|
||||||
|
61
wally-pipelined/src/fpu/FMA/add.v
Normal file
61
wally-pipelined/src/fpu/FMA/add.v
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Block Name: add.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/12/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block performs the addition of the product and addend. It also
|
||||||
|
// contains logic necessary to adjust the signs for effective subtracts
|
||||||
|
// and negative results.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
module add(r[105:0], s[105:0], t[157:0], sum[157:0],
|
||||||
|
negsum, invz, selsum1, killprod, negsum0, negsum1, proddenorm);
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [105:0] r; // partial product 1
|
||||||
|
input [105:0] s; // partial product 2
|
||||||
|
input [157:0] t; // aligned addend
|
||||||
|
input invz; // invert addend
|
||||||
|
input selsum1; // select +1 mode of compound adder
|
||||||
|
input killprod; // z >> product
|
||||||
|
input negsum; // Negate sum
|
||||||
|
input proddenorm;
|
||||||
|
output [157:0] sum; // sum
|
||||||
|
output negsum0; // sum was negative in +0 mode
|
||||||
|
output negsum1; // sum was negative in +1 mode
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire [105:0] r2; // partial product possibly zeroed out
|
||||||
|
wire [105:0] s2; // partial product possibly zeroed out
|
||||||
|
wire [157:0] t2; // addend after inversion if necessary
|
||||||
|
wire [157:0] sum0; // sum of compound adder +0 mode
|
||||||
|
wire [157:0] sum1; // sum of compound adder +1 mode
|
||||||
|
|
||||||
|
// Invert addend if necessary
|
||||||
|
|
||||||
|
assign t2 = invz ? -t : t;
|
||||||
|
|
||||||
|
// Zero out product if Z >> product or product really should be zero
|
||||||
|
|
||||||
|
assign r2 = ~proddenorm & killprod ? 106'b0 : r;
|
||||||
|
assign s2 = ~proddenorm & killprod ? 106'b0 : s;
|
||||||
|
|
||||||
|
// Compound adder
|
||||||
|
// Consists of 3:2 CSA followed by long compound CPA
|
||||||
|
|
||||||
|
assign sum0 = {52'b0, r2} + {52'b0, s2} + t2 + 158'b0;
|
||||||
|
assign sum1 = {52'b0, r2} + {52'b0, s2} + t2 + 158'b1;
|
||||||
|
|
||||||
|
// Check sign bits in +0/1 modes
|
||||||
|
assign negsum0 = sum0[157];
|
||||||
|
assign negsum1 = sum1[157];
|
||||||
|
|
||||||
|
// Mux proper result (+Oil mode and inversion) using 4:1 mux
|
||||||
|
|
||||||
|
assign sum = selsum1 ? (negsum ? ~sum1 : sum1) : (negsum ? ~sum0 : sum0);
|
||||||
|
|
||||||
|
endmodule
|
99
wally-pipelined/src/fpu/FMA/align.v
Normal file
99
wally-pipelined/src/fpu/FMA/align.v
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: align.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block implements the alignment shifter. It is responsible for
|
||||||
|
// adjusting the fraction portion of the addend relative to the fraction
|
||||||
|
// produced in the multiplier array.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddenorm, t[157:0], bs, ps,
|
||||||
|
killprod, bypsel[1], bypplus1, byppostnorm);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [51:0] z; // Fraction of addend z;
|
||||||
|
input [12:0] ae; // sign of exponent of addend z;
|
||||||
|
input [11:0] aligncnt; // amount to shift
|
||||||
|
input xzero; // Input X = 0
|
||||||
|
input yzero; // Input Y = 0
|
||||||
|
input zzero; // Input Z = 0
|
||||||
|
input zdenorm; // Input Z = denorm
|
||||||
|
input proddenorm;
|
||||||
|
input [1:1] bypsel; // Select bypass to X or Z
|
||||||
|
input bypplus1; // Add one to bypassed result
|
||||||
|
input byppostnorm; // Postnormalize bypassed result
|
||||||
|
output [157:0] t; // aligned addend (54 bits left of bpt)
|
||||||
|
output bs; // sticky bit of addend
|
||||||
|
output ps; // sticky bit of product
|
||||||
|
output killprod; // Z >> product
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
reg [157:0] t; // aligned addend from shifter
|
||||||
|
reg killprod; // Z >> product
|
||||||
|
reg bs; // sticky bit of addend
|
||||||
|
reg ps; // sticky bit of product
|
||||||
|
reg [7:0] i; // temp storage for finding sticky bit
|
||||||
|
wire [52:0] z1; // Z plus 1
|
||||||
|
wire [51:0] z2; // Z selected after handling rounds
|
||||||
|
wire [11:0] align104; // alignment count + 104
|
||||||
|
|
||||||
|
// Increment fraction of Z by one if necessary for prerounded bypass
|
||||||
|
// This incrementor delay is masked by the alignment count computation
|
||||||
|
|
||||||
|
assign z1 = z + 1;
|
||||||
|
assign z2 = bypsel[1] && bypplus1 ? (byppostnorm ? z1[52:1] : z1[51:0]): z;
|
||||||
|
|
||||||
|
// Compute sign of aligncnt + 104 to check for shifting too far right
|
||||||
|
|
||||||
|
assign align104 = aligncnt+104;
|
||||||
|
|
||||||
|
// Shift addend by alignment count. Generate sticky bits from
|
||||||
|
// addend on right shifts. Handle special cases of shifting
|
||||||
|
// by too much.
|
||||||
|
|
||||||
|
always @(z2 or aligncnt or align104 or zzero or xzero or yzero or zdenorm)
|
||||||
|
begin
|
||||||
|
|
||||||
|
// Default to clearing sticky bits
|
||||||
|
bs = 0;
|
||||||
|
ps = 0;
|
||||||
|
|
||||||
|
// And to using product as primary operand in adder I exponent gen
|
||||||
|
killprod = 0;
|
||||||
|
|
||||||
|
if(zzero) begin
|
||||||
|
t = 158'b0;
|
||||||
|
if (xzero || yzero) killprod = 1;
|
||||||
|
end else if ((aligncnt > 53 && ~aligncnt[11]) || xzero || yzero) begin
|
||||||
|
// Left shift by huge amount
|
||||||
|
// or product = 0
|
||||||
|
t = {53'b0, ~zzero, z2, 52'b0};
|
||||||
|
killprod = 1;
|
||||||
|
ps = ~xzero && ~yzero;
|
||||||
|
end else if ((ae[12] && align104[11])) begin //***fix the if statement
|
||||||
|
// KEP if the multiplier's exponent overflows
|
||||||
|
t = {53'b0, ~zzero, z2, 52'b0};
|
||||||
|
killprod = 1;
|
||||||
|
ps = ~xzero && ~yzero;
|
||||||
|
end else if(align104[11]) begin // Right shift by huge amount
|
||||||
|
bs = ~zzero;
|
||||||
|
t = 0;
|
||||||
|
end else if (~aligncnt[11]) begin // Left shift by reasonable amount
|
||||||
|
t = {53'b0, ~zzero, z2, 52'b0} << aligncnt;
|
||||||
|
end else begin // Otherwise right shift
|
||||||
|
t = {53'b0, ~zzero, z2, 52'b0} >> -aligncnt;
|
||||||
|
|
||||||
|
// use some behavioral code to find sticky bit. This is really
|
||||||
|
// done by hardware in the shifter.
|
||||||
|
if (aligncnt < 0)
|
||||||
|
for (i=0; i<-aligncnt-52; i = i+1)
|
||||||
|
bs = bs || z2[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
114
wally-pipelined/src/fpu/FMA/array.sv
Normal file
114
wally-pipelined/src/fpu/FMA/array.sv
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
module array(x, y, xdenorm, ydenorm, r, s, bypsel, bypplus1);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [51:0] x; // Fraction of multiplicand x
|
||||||
|
input [51:0] y; // Fraction of multiplicand y
|
||||||
|
input xdenorm; // is x denormalized
|
||||||
|
input ydenorm; // is y denormalized
|
||||||
|
input bypsel; // Bypass X
|
||||||
|
input bypplus1; // Add 1 to X to handle rounding
|
||||||
|
output [105:0] r; // partial product 1
|
||||||
|
output [105:0] s; // partial product 2
|
||||||
|
|
||||||
|
wire [51:0] xnorm;
|
||||||
|
wire [51:0] ynorm;
|
||||||
|
|
||||||
|
wire [54:0] yExt; //y with appended 0 and assumed 1
|
||||||
|
wire [53:0] xExt; //y with assumed 1
|
||||||
|
wire [26:0][1:0] add1;
|
||||||
|
wire [26:0][54:0] pp;
|
||||||
|
wire [26:0] e;
|
||||||
|
logic [17:0][105:0] lv1add;
|
||||||
|
logic [11:0][105:0] lv2add;
|
||||||
|
logic [7:0][105:0] lv3add;
|
||||||
|
logic [3:0][105:0] lv4add;
|
||||||
|
logic [21:0][106:0] carryTmp;
|
||||||
|
wire [26:0][105:0] acc;
|
||||||
|
// wire [105:0] acc
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
assign xnorm = xdenorm ? {x[50:0], 1'b0} : x; // normalization of denormalized numbers
|
||||||
|
assign ynorm = ydenorm ? {y[50:0], 1'b0} : y;
|
||||||
|
assign yExt = {2'b01,ynorm,1'b0}; // y extended and added assumed 1
|
||||||
|
assign xExt = {2'b01,xnorm}; // x with added assumed 1
|
||||||
|
|
||||||
|
|
||||||
|
//booth encoding
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i=0; i<27; i=i+1) begin
|
||||||
|
booth booth(.xExt(xExt), .choose(yExt[(i*2)+2:i*2]), .add1(add1[i]), .e(e[i]), .pp(pp[i]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign acc[0] = {49'b0,~e[0],e[0],e[0],pp[0]};
|
||||||
|
assign acc[1] = {50'b01,~e[1],pp[1],add1[0]};
|
||||||
|
assign acc[2] = {48'b01,~e[2],pp[2],add1[1], 2'b0};
|
||||||
|
assign acc[3] = {46'b01,~e[3],pp[3],add1[2], 4'b0};
|
||||||
|
assign acc[4] = {44'b01,~e[4],pp[4],add1[3], 6'b0};
|
||||||
|
assign acc[5] = {42'b01,~e[5],pp[5],add1[4], 8'b0};
|
||||||
|
assign acc[6] = {40'b01,~e[6],pp[6],add1[5], 10'b0};
|
||||||
|
assign acc[7] = {38'b01,~e[7],pp[7],add1[6], 12'b0};
|
||||||
|
assign acc[8] = {36'b01,~e[8],pp[8],add1[7], 14'b0};
|
||||||
|
assign acc[9] = {34'b01,~e[9],pp[9],add1[8], 16'b0};
|
||||||
|
assign acc[10] = {32'b01,~e[10],pp[10],add1[9], 18'b0};
|
||||||
|
assign acc[11] = {30'b01,~e[11],pp[11],add1[10], 20'b0};
|
||||||
|
assign acc[12] = {28'b01,~e[12],pp[12],add1[11], 22'b0};
|
||||||
|
assign acc[13] = {26'b01,~e[13],pp[13],add1[12], 24'b0};
|
||||||
|
assign acc[14] = {24'b01,~e[14],pp[14],add1[13], 26'b0};
|
||||||
|
assign acc[15] = {22'b01,~e[15],pp[15],add1[14], 28'b0};
|
||||||
|
assign acc[16] = {20'b01,~e[16],pp[16],add1[15], 30'b0};
|
||||||
|
assign acc[17] = {18'b01,~e[17],pp[17],add1[16], 32'b0};
|
||||||
|
assign acc[18] = {16'b01,~e[18],pp[18],add1[17], 34'b0};
|
||||||
|
assign acc[19] = {14'b01,~e[19],pp[19],add1[18], 36'b0};
|
||||||
|
assign acc[20] = {12'b01,~e[20],pp[20],add1[19], 38'b0};
|
||||||
|
assign acc[21] = {10'b01,~e[21],pp[21],add1[20], 40'b0};
|
||||||
|
assign acc[22] = {8'b01,~e[22],pp[22],add1[21], 42'b0};
|
||||||
|
assign acc[23] = {6'b01,~e[23],pp[23],add1[22], 44'b0};
|
||||||
|
assign acc[24] = {4'b01,~e[24],pp[24],add1[23], 46'b0};
|
||||||
|
assign acc[25] = {~e[25],pp[25],add1[24], 48'b0};
|
||||||
|
assign acc[26] = {pp[26],add1[25], 50'b0};
|
||||||
|
|
||||||
|
//*** resize adders
|
||||||
|
generate
|
||||||
|
for(i=0; i<9; i=i+1) begin
|
||||||
|
add3comp2 #(.BITS(106)) add1(.a(acc[i*3]), .b(acc[i*3+1]), .c(acc[i*3+2]),
|
||||||
|
.carry(carryTmp[i][105:0]), .sum(lv1add[i*2+1]));
|
||||||
|
assign lv1add[i*2] = {carryTmp[i][104:0], 1'b0};
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i=0; i<6; i=i+1) begin
|
||||||
|
add3comp2 #(.BITS(106)) add2(.a(lv1add[i*3]), .b(lv1add[i*3+1]), .c(lv1add[i*3+2]),
|
||||||
|
.carry(carryTmp[i+9][105:0]), .sum(lv2add[i*2+1]));
|
||||||
|
assign lv2add[i*2] = {carryTmp[i+9][104:0], 1'b0};
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i=0; i<4; i=i+1) begin
|
||||||
|
add3comp2 #(.BITS(106)) add3(.a(lv2add[i*3]), .b(lv2add[i*3+1]), .c(lv2add[i*3+2]),
|
||||||
|
.carry(carryTmp[i+15][105:0]), .sum(lv3add[i*2+1]));
|
||||||
|
assign lv3add[i*2] = {carryTmp[i+15][104:0], 1'b0};
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i=0; i<2; i=i+1) begin
|
||||||
|
add4comp2 #(.BITS(106)) add4(.a(lv3add[i*4]), .b(lv3add[i*4+1]), .c(lv3add[i*4+2]), .d(lv3add[i*4+3]),
|
||||||
|
.carry(carryTmp[i+19]), .sum(lv4add[i*2+1]));
|
||||||
|
assign lv4add[i*2] = {carryTmp[i+19][104:0], 1'b0};
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
add4comp2 #(.BITS(106)) add5(.a(lv4add[0]), .b(lv4add[1]), .c(lv4add[2]), .d(lv4add[3]) ,
|
||||||
|
.carry(carryTmp[21]), .sum(s));
|
||||||
|
assign r = {carryTmp[21][104:0], 1'b0};
|
||||||
|
|
||||||
|
// assign r = 106'b0;
|
||||||
|
// assign s = ({54'b1,xnorm} + (bypsel && bypplus1)) * {54'b1,ynorm};
|
||||||
|
|
||||||
|
endmodule
|
55
wally-pipelined/src/fpu/FMA/booth.sv
Normal file
55
wally-pipelined/src/fpu/FMA/booth.sv
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
module booth(xExt, choose, add1, e, pp);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [53:0] xExt; // multiplicand xExt
|
||||||
|
input [2:0] choose; // bits needed to choose which encoding
|
||||||
|
output [1:0] add1; // do you add 1
|
||||||
|
output e;
|
||||||
|
output [54:0] pp; // the resultant encoding
|
||||||
|
|
||||||
|
logic [54:0] pp, temp;
|
||||||
|
logic e;
|
||||||
|
logic [1:0] add1;
|
||||||
|
logic [53:0] negx;
|
||||||
|
//logic temp;
|
||||||
|
|
||||||
|
assign negx = ~xExt;
|
||||||
|
|
||||||
|
always @(choose, xExt, negx)
|
||||||
|
case (choose)
|
||||||
|
3'b000 : pp = 55'b0; // 0
|
||||||
|
3'b001 : pp = {xExt[53], xExt}; // 1
|
||||||
|
3'b010 : pp = {xExt[53], xExt}; // 1
|
||||||
|
3'b011 : pp = {xExt, 1'b0}; // 2
|
||||||
|
3'b100 : pp = {negx, 1'b0}; // -2
|
||||||
|
3'b101 : pp = {negx[53], negx}; // -1
|
||||||
|
3'b110 : pp = {negx[53], negx}; // -1
|
||||||
|
3'b111 : pp = 55'hfffffffffffffff; // -0
|
||||||
|
endcase
|
||||||
|
|
||||||
|
always @(choose, xExt, negx)
|
||||||
|
case (choose)
|
||||||
|
3'b000 : e = 0; // 0
|
||||||
|
3'b001 : e = xExt[53]; // 1
|
||||||
|
3'b010 : e = xExt[53]; // 1
|
||||||
|
3'b011 : e = xExt[53]; // 2
|
||||||
|
3'b100 : e = negx[53]; // -2
|
||||||
|
3'b101 : e = negx[53]; // -1
|
||||||
|
3'b110 : e = negx[53]; // -1
|
||||||
|
3'b111 : e = 1; // -0
|
||||||
|
endcase
|
||||||
|
// assign add1 = (choose[2] == 1'b1) ? ((choose[1:0] == 2'b11) ? 1'b0 : 1'b1) : 1'b0;
|
||||||
|
// assign add1 = choose[2];
|
||||||
|
always @(choose)
|
||||||
|
case (choose)
|
||||||
|
3'b000 : add1 = 2'b0; // 0
|
||||||
|
3'b001 : add1 = 2'b0; // 1
|
||||||
|
3'b010 : add1 = 2'b0; // 1
|
||||||
|
3'b011 : add1 = 2'b0; // 2
|
||||||
|
3'b100 : add1 = 2'b10; // -2
|
||||||
|
3'b101 : add1 = 2'b1; // -1
|
||||||
|
3'b110 : add1 = 2'b1; // -1
|
||||||
|
3'b111 : add1 = 2'b1; // -0
|
||||||
|
endcase
|
||||||
|
|
||||||
|
endmodule
|
30
wally-pipelined/src/fpu/FMA/bypass.v
Normal file
30
wally-pipelined/src/fpu/FMA/bypass.v
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Block Name: bypass.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block contains the bypass muxes which allow fast prerounded
|
||||||
|
// bypass to the X and Z inputs of the FMAC
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module bypass(xrf[63:0], zrf[63:0], wbypass[63:0], bypsel[1:0],
|
||||||
|
x[63:0], z[63:0]);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [63:0] xrf; // X from register file
|
||||||
|
input [63:0] zrf; // Z from register file
|
||||||
|
input [63:0] wbypass; // Prerounded result for bypass
|
||||||
|
input [1:0] bypsel; // Select bypass to X or Z
|
||||||
|
output [63:0] x; // Source X
|
||||||
|
output [63:0] z; // Source Z
|
||||||
|
|
||||||
|
// If bypass select is asserted, bypass source, else take reg file value
|
||||||
|
|
||||||
|
assign x = bypsel[0] ? wbypass : xrf;
|
||||||
|
assign z = bypsel[1] ? wbypass : zrf;
|
||||||
|
|
||||||
|
endmodule
|
90
wally-pipelined/src/fpu/FMA/compressors.sv
Normal file
90
wally-pipelined/src/fpu/FMA/compressors.sv
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
module add3comp2(a, b, c, carry, sum);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//look into diffrent implementations of the compressors?
|
||||||
|
|
||||||
|
parameter BITS = 4;
|
||||||
|
input [BITS-1:0] a;
|
||||||
|
input [BITS-1:0] b;
|
||||||
|
input [BITS-1:0] c;
|
||||||
|
output [BITS-1:0] carry;
|
||||||
|
output [BITS-1:0] sum;
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i= 0; i<BITS; i=i+1) begin
|
||||||
|
sng3comp2 add0(a[i], b[i], c[i], carry[i], sum[i]);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module add4comp2(a, b, c, d, carry, sum);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
parameter BITS = 4;
|
||||||
|
input [BITS-1:0] a;
|
||||||
|
input [BITS-1:0] b;
|
||||||
|
input [BITS-1:0] c;
|
||||||
|
input [BITS-1:0] d;
|
||||||
|
output [BITS:0] carry;
|
||||||
|
output [BITS-1:0] sum;
|
||||||
|
|
||||||
|
logic [BITS-1:0] cout;
|
||||||
|
logic carryTmp;
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
|
||||||
|
sng4comp2 add0(a[0], b[0], c[0], d[0], 1'b0, cout[0], carry[0], sum[0]);
|
||||||
|
|
||||||
|
generate
|
||||||
|
for(i= 1; i<BITS-1; i=i+1) begin
|
||||||
|
sng4comp2 add1(a[i], b[i], c[i], d[i], cout[i-1], cout[i], carry[i], sum[i]);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
|
sng4comp2 add2(a[BITS-1], b[BITS-1], c[BITS-1], d[BITS-1], cout[BITS-2], cout[BITS-1], carryTmp, sum[BITS-1]);
|
||||||
|
|
||||||
|
assign carry[BITS-1] = carryTmp & cout[BITS-1];
|
||||||
|
assign carry[BITS] = carryTmp ^ cout[BITS-1];
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sng3comp2(a, b, c, carry, sum);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//look into diffrent implementations of the compressors?
|
||||||
|
|
||||||
|
input a;
|
||||||
|
input b;
|
||||||
|
input c;
|
||||||
|
output carry;
|
||||||
|
output sum;
|
||||||
|
|
||||||
|
logic axorb;
|
||||||
|
|
||||||
|
assign axorb = a ^ b;
|
||||||
|
assign sum = axorb ^ c;
|
||||||
|
|
||||||
|
assign carry = axorb ? c : a;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sng4comp2(a, b, c, d, cin, cout, carry, sum);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//look into pass gate 4:2 counters?
|
||||||
|
|
||||||
|
input a;
|
||||||
|
input b;
|
||||||
|
input c;
|
||||||
|
input d;
|
||||||
|
input cin;
|
||||||
|
output cout;
|
||||||
|
output carry;
|
||||||
|
output sum;
|
||||||
|
|
||||||
|
logic TmpSum;
|
||||||
|
|
||||||
|
sng3comp2 add1(.carry(cout), .sum(TmpSum),.*);
|
||||||
|
sng3comp2 add2(.a(TmpSum), .b(d), .c(cin), .*);
|
||||||
|
|
||||||
|
endmodule
|
135
wally-pipelined/src/fpu/FMA/expgen.v
Normal file
135
wally-pipelined/src/fpu/FMA/expgen.v
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: expgen.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block implements the exponent path of the FMAC. It performs the
|
||||||
|
// following operations:
|
||||||
|
//
|
||||||
|
// 1) Compute exponent of multiply.
|
||||||
|
// 2) Compare multiply and add exponents to generate alignment shift count
|
||||||
|
// 3) Adjust exponent based on normalization
|
||||||
|
// 4) Increment exponent based on postrounding renormalization
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module expgen(x[62:52], y[62:52], z[62:52],
|
||||||
|
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
|
||||||
|
killprod, sumzero, postnormalize, normcnt, infinity,
|
||||||
|
invalid, overflow, underflow, inf,
|
||||||
|
nan, xnan, ynan, znan, zdenorm, specialsel,
|
||||||
|
aligncnt, w[62:52], wbypass[62:52],
|
||||||
|
prodof, sumof, sumuf, denorm0, ae[12:0]);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [62:52] x; // Exponent of multiplicand x
|
||||||
|
input [62:52] y; // Exponent of multiplicand y
|
||||||
|
input [62:52] z; // Exponent of addend z
|
||||||
|
input [62:52] earlyres; // Result from other FPU block
|
||||||
|
input earlyressel; // Select result from other block
|
||||||
|
input [1:1] bypsel; // Bypass X or Z
|
||||||
|
input byppostnorm; // Postnormalize bypassed result
|
||||||
|
input killprod; // Z >> product
|
||||||
|
input sumzero; // sum exactly equals zero
|
||||||
|
input postnormalize; // postnormalize rounded result
|
||||||
|
input [8:0] normcnt; // normalization shift count
|
||||||
|
input infinity; // generate infinity on overflow
|
||||||
|
input invalid; // Result invalid
|
||||||
|
input overflow; // Result overflowed
|
||||||
|
input underflow; // Result underflowed
|
||||||
|
input inf; // Some input is infinity
|
||||||
|
input nan; // Some input is NaN
|
||||||
|
input xnan; // X is NaN
|
||||||
|
input ynan; // Y is NaN
|
||||||
|
input znan; // Z is NaN
|
||||||
|
input zdenorm; // Z is denorm
|
||||||
|
input specialsel; // Select special result
|
||||||
|
output [11:0] aligncnt; // shift count for alignment shifter
|
||||||
|
output [62:52] w; // Exponent of result
|
||||||
|
output [62:52] wbypass; // Prerounded exponent for bypass
|
||||||
|
output prodof; // X*Y exponent out of bounds
|
||||||
|
output sumof; // X*Y+Z exponent out of bounds
|
||||||
|
output sumuf; // X*Y+Z exponent underflows
|
||||||
|
output denorm0; // exponent = 0 for denorm
|
||||||
|
output [12:0] ae; //exponent of multiply
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire [12:0] aetmp; // Exponent of Multiply
|
||||||
|
wire [12:0] aligncnt0; // Shift count for alignment
|
||||||
|
wire [12:0] aligncnt1; // Shift count for alignment
|
||||||
|
wire [12:0] be; // Exponent of multiply
|
||||||
|
wire [12:0] de0; // Normalized exponent
|
||||||
|
wire [12:0] de1; // Normalized exponent
|
||||||
|
wire [12:0] de; // Normalized exponent
|
||||||
|
wire [10:0] infinityres; // Infinity or max number
|
||||||
|
wire [10:0] nanres; // Nan propagated or generated
|
||||||
|
wire [10:0] specialres; // Exceptional case result
|
||||||
|
|
||||||
|
// Compute exponent of multiply
|
||||||
|
// Note that the exponent does not have to be incremented on a postrounding
|
||||||
|
// normalization of X because the mantissa was already increased. Report
|
||||||
|
// if exponent is out of bounds
|
||||||
|
assign ae = x + y - 1023;
|
||||||
|
|
||||||
|
assign prodof = (ae > 2046 && ~ae[12] && ~killprod);
|
||||||
|
|
||||||
|
// Compute alignment shift count
|
||||||
|
// Adjust for postrounding normalization of Z.
|
||||||
|
// This should not increas the critical path because the time to
|
||||||
|
// check if a round overflows is shorter than the actual round and
|
||||||
|
// is masked by the bypass mux and two 10 bit adder delays.
|
||||||
|
|
||||||
|
assign aligncnt0 = z - ae[10:0] + 13'b0;
|
||||||
|
assign aligncnt1 = z - ae[10:0] + 13'b1;
|
||||||
|
assign aligncnt = bypsel[1] && byppostnorm ? aligncnt1 : aligncnt0;
|
||||||
|
|
||||||
|
// Select exponent (usually from product except in case of huge addend)
|
||||||
|
|
||||||
|
assign be = killprod ? z : ae;
|
||||||
|
|
||||||
|
// Adjust exponent based on normalization
|
||||||
|
// A compound adder takes care of the case of post-rounding normalization
|
||||||
|
// requiring an extra increment
|
||||||
|
|
||||||
|
assign de0 = sumzero ? 13'b0 : be + 53 - normcnt;
|
||||||
|
assign de1 = sumzero ? 13'b0 : be + 53 - normcnt + 13'b1;
|
||||||
|
|
||||||
|
// If the exponent becomes exactly zero (denormalized)
|
||||||
|
// signal such to adjust R bit before rounding
|
||||||
|
|
||||||
|
assign denorm0 = (de0 == 0);
|
||||||
|
|
||||||
|
// check for exponent out of bounds after add
|
||||||
|
|
||||||
|
assign de = postnormalize ? de1 : de0;
|
||||||
|
assign sumof = de > 2046 && ~de[12];
|
||||||
|
assign sumuf = (de == 0 || de[12]) && ~sumzero && ~zdenorm;//KEP ~zdenorm to prevent underflow flag
|
||||||
|
|
||||||
|
// bypass occurs before rounding or taking early results
|
||||||
|
|
||||||
|
assign wbypass = de0[10:0];
|
||||||
|
|
||||||
|
// In a non-critical special mux, we combine the early result from other
|
||||||
|
// FPU blocks with the results of exceptional conditions. Overflow
|
||||||
|
// produces either infinity or the largest finite number, depending on the
|
||||||
|
// rounding mode. NaNs are propagated or generated.
|
||||||
|
|
||||||
|
assign specialres = earlyressel ? earlyres :
|
||||||
|
invalid ? nanres :
|
||||||
|
overflow ? infinityres :
|
||||||
|
inf ? 11'b11111111111 :
|
||||||
|
underflow ? 11'b0 : 11'bx;
|
||||||
|
|
||||||
|
assign infinityres = infinity ? 11'b11111111111 : 11'b11111111110;
|
||||||
|
|
||||||
|
assign nanres = xnan ? x : (ynan ? y : (znan? z : 11'b11111111111));
|
||||||
|
|
||||||
|
// A mux selects the early result from other FPU blocks or the
|
||||||
|
// normalized FMAC result. Special cases are also detected.
|
||||||
|
|
||||||
|
assign w = specialsel ? specialres[10:0] : de;
|
||||||
|
endmodule
|
||||||
|
|
85
wally-pipelined/src/fpu/FMA/flag.v
Normal file
85
wally-pipelined/src/fpu/FMA/flag.v
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: flag.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 12/6/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block generates the flags: invalid, overflow, underflow, inexact.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
|
||||||
|
psign, zsign, xzero, yzero, v[1:0],
|
||||||
|
inf, nan, invalid, overflow, underflow, inexact);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input xnan; // X is NaN
|
||||||
|
input ynan; // Y is NaN
|
||||||
|
input znan; // Z is NaN
|
||||||
|
input xinf; // X is Inf
|
||||||
|
input yinf; // Y is Inf
|
||||||
|
input zinf; // Z is Inf
|
||||||
|
input prodof; // X*Y overflows exponent
|
||||||
|
input sumof; // X*Y + z underflows exponent
|
||||||
|
input sumuf; // X*Y + z underflows exponent
|
||||||
|
input psign; // Sign of product
|
||||||
|
input zsign; // Sign of z
|
||||||
|
input xzero; // x = 0
|
||||||
|
input yzero; // y = 0
|
||||||
|
input [1:0] v; // R and S bits of result
|
||||||
|
output inf; // Some source is Inf
|
||||||
|
output nan; // Some source is NaN
|
||||||
|
output invalid; // Result is invalid
|
||||||
|
output overflow; // Result overflowed
|
||||||
|
output underflow; // Result underflowed
|
||||||
|
output inexact; // Result is not an exact number
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire prodinf; // X*Y larger than max possible
|
||||||
|
wire suminf; // X*Y+Z larger than max possible
|
||||||
|
|
||||||
|
// If any input is NaN, propagate the NaN
|
||||||
|
|
||||||
|
assign nan = xnan || ynan || znan;
|
||||||
|
|
||||||
|
// Same with infinity (inf - inf and O * inf don't propagate inf
|
||||||
|
// but it's ok becaue illegal op takes higher precidence)
|
||||||
|
|
||||||
|
assign inf= xinf || yinf || zinf;
|
||||||
|
|
||||||
|
// Generate infinity checks
|
||||||
|
|
||||||
|
assign prodinf = prodof && ~xnan && ~ynan;
|
||||||
|
assign suminf = sumof && ~xnan && ~ynan && ~znan;
|
||||||
|
|
||||||
|
// Set invalid flag for following cases:
|
||||||
|
// 1) Inf - Inf
|
||||||
|
// 2) 0 * Inf
|
||||||
|
// 3) Output = NaN (this is not part of the IEEE spec, only 486 proj)
|
||||||
|
|
||||||
|
assign invalid = (xinf || yinf || prodinf) && zinf && (psign ^ zsign) ||
|
||||||
|
xzero && yinf || yzero && xinf ||
|
||||||
|
nan;
|
||||||
|
|
||||||
|
// Set the overflow flag for the following cases:
|
||||||
|
// 1) Rounded multiply result would be out of bounds
|
||||||
|
// 2) Rounded add result would be out of bounds
|
||||||
|
|
||||||
|
assign overflow = suminf && ~inf;
|
||||||
|
|
||||||
|
// Set the underflow flag for the following cases:
|
||||||
|
// 1) Any input is denormalized
|
||||||
|
// 2) Output would be denormalized or smaller
|
||||||
|
|
||||||
|
assign underflow = (sumuf && ~inf && ~prodinf && ~nan);
|
||||||
|
|
||||||
|
|
||||||
|
// Set the inexact flag for the following cases:
|
||||||
|
// 1) Multiplication inexact
|
||||||
|
// 2) Addition inexact
|
||||||
|
// One of these cases occurred if the R or S bit is set
|
||||||
|
|
||||||
|
assign inexact = (v[0] || v[1] || suminf) && ~(inf || nan);
|
||||||
|
|
||||||
|
endmodule
|
130
wally-pipelined/src/fpu/FMA/fmac.v
Normal file
130
wally-pipelined/src/fpu/FMA/fmac.v
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: fmac.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This is the top level block of a floating-point multiply/accumulate
|
||||||
|
// unit(FMAC). It instantiates the following sub-blocks:
|
||||||
|
//
|
||||||
|
// array Booth encoding, partial product generation, product summation
|
||||||
|
// expgen Exponent summation, compare, and adjust
|
||||||
|
// align Alignment shifter
|
||||||
|
// add Carry-save adder for accumulate, carry propagate adder
|
||||||
|
// lza Leading zero anticipator to control normalization shifter
|
||||||
|
// normalize Normalization shifter
|
||||||
|
// round Rounding of result
|
||||||
|
// exception Handles exceptional cases
|
||||||
|
// bypass Handles bypass of result to X or Z inputs
|
||||||
|
// sign One bit sign handling block
|
||||||
|
// special Catch special cases (inputs = 0 / infinity / etc.)
|
||||||
|
//
|
||||||
|
// The FMAC computes W=X*Y+Z, rounded with the mode specified by
|
||||||
|
// RN, RZ, RM, or RP. The result is optionally bypassed back to
|
||||||
|
// the X or Z inputs for use on the next cycle. In addition, four signals
|
||||||
|
// are produced: trap, overflow, underflow, and inexact. Trap indicates
|
||||||
|
// an infinity, NaN, or denormalized number to be handled in software;
|
||||||
|
// the other three signals are IEEE flags.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module fmac(xrf, y, zrf, rn, rz, rp, rm,
|
||||||
|
earlyres, earlyressel, bypsel, bypplus1, byppostnorm,
|
||||||
|
w, wbypass, invalid, overflow, underflow, inexact);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [63:0] xrf; // input X from reg file
|
||||||
|
input [63:0] y; // input Y
|
||||||
|
input [63:0] zrf; // input Z from reg file
|
||||||
|
input rn; // Round to Nearest
|
||||||
|
input rz; // Round toward zero
|
||||||
|
input rm; // Round toward minus infinity
|
||||||
|
input rp; // Round toward plus infinity
|
||||||
|
input [63:0] earlyres; // Early result from other FP logic
|
||||||
|
input earlyressel; // Select early result, not W
|
||||||
|
input [1:0] bypsel; // Select W bypass to X, or z
|
||||||
|
input bypplus1; // Add one in bypass
|
||||||
|
input byppostnorm; // postnormalize in bypass
|
||||||
|
output [63:0] w; // output W=X*Y+Z
|
||||||
|
output [63:0] wbypass; // prerounded output W=X*Y+Z for bypass
|
||||||
|
output invalid; // Result is invalid
|
||||||
|
output overflow; // Result overflowed
|
||||||
|
output underflow; // Result underflowed
|
||||||
|
output inexact; // Result is not an exact number
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire [63:0] x; // input X after bypass mux
|
||||||
|
wire [63:0] z; // input Z after bypass mux
|
||||||
|
wire [105:0] r; // one result of partial product sum
|
||||||
|
wire [105:0] s; // other result of partial products
|
||||||
|
wire [157:0] t; // output of alignment shifter
|
||||||
|
wire [157:0] sum; // output of carry prop adder
|
||||||
|
wire [53:0] v; // normalized sum, R, S bits
|
||||||
|
wire [11:0] aligncnt; // shift count for alignment
|
||||||
|
wire [8:0] normcnt; // shift count for normalizer
|
||||||
|
wire [12:0] ae; // multiplier expoent
|
||||||
|
wire bs; // sticky bit of addend
|
||||||
|
wire ps; // sticky bit of product
|
||||||
|
wire killprod; // Z >> product
|
||||||
|
wire negsum; // negate sum
|
||||||
|
wire invz; // invert addend
|
||||||
|
wire selsum1; // select +1 mode of sum
|
||||||
|
wire negsum0; // sum +0 < 0
|
||||||
|
wire negsum1; // sum +1 < 0
|
||||||
|
wire sumzero; // sum = 0
|
||||||
|
wire infinity; // generate infinity on overflow
|
||||||
|
wire prodof; // X*Y out of range
|
||||||
|
wire sumof; // result out of range
|
||||||
|
|
||||||
|
// Instantiate fraction datapath
|
||||||
|
|
||||||
|
array array(x[51:0], y[51:0], xdenorm, ydenorm, r[105:0], s[105:0],
|
||||||
|
bypsel[0], bypplus1);
|
||||||
|
align align(z[51:0], ae, aligncnt, xzero, yzero, zzero, zdenorm, proddenorm,
|
||||||
|
t[157:0], bs, ps, killprod,
|
||||||
|
bypsel[1], bypplus1, byppostnorm);
|
||||||
|
add add(r[105:0], s[105:0], t[157:0], sum[157:0],
|
||||||
|
negsum, invz, selsum1, killprod, negsum0, negsum1, proddenorm);
|
||||||
|
lop lop(sum, normcnt, sumzero);
|
||||||
|
normalize normalize(sum[157:0], normcnt, sumzero, bs, ps, denorm0, zdenorm,
|
||||||
|
v[53:0]);
|
||||||
|
round round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, w[63],
|
||||||
|
invalid, overflow, underflow, inf, nan, xnan, ynan, znan,
|
||||||
|
x[51:0], y[51:0], z[51:0],
|
||||||
|
w[51:0], postnorrnalize, infinity, specialsel);
|
||||||
|
bypass bypass(xrf[63:0], zrf[63:0], wbypass[63:0], bypsel[1:0],
|
||||||
|
x[63:0], z[63:0]);
|
||||||
|
|
||||||
|
// Instantiate exponent datapath
|
||||||
|
|
||||||
|
expgen expgen(x[62:52], y[62:52], z[62:52],
|
||||||
|
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
|
||||||
|
killprod, sumzero, postnorrnalize, normcnt,
|
||||||
|
infinity, invalid, overflow, underflow,
|
||||||
|
inf, nan, xnan, ynan, znan, zdenorm, specialsel,
|
||||||
|
aligncnt, w[62:52], wbypass[62:52],
|
||||||
|
prodof, sumof, sumuf, denorm0, ae);
|
||||||
|
// Instantiate special case detection across datapath & exponent path
|
||||||
|
|
||||||
|
special special(x[63:0], y[63:0], z[63:0], ae, xzero, yzero, zzero,
|
||||||
|
xnan, ynan, znan, xdenorm, ydenorm, zdenorm, proddenorm,
|
||||||
|
xinf, yinf, zinf);
|
||||||
|
|
||||||
|
// Produce W for bypass
|
||||||
|
|
||||||
|
assign wbypass[51:0] = v[53:2];
|
||||||
|
assign wbypass[63] = w[63];
|
||||||
|
|
||||||
|
// Instantiate control logic
|
||||||
|
|
||||||
|
sign sign(x[63], y[63], z[63], negsum0, negsum1, bs, ps,
|
||||||
|
killprod, rm, sumzero, nan, invalid, xinf, yinf, inf,
|
||||||
|
w[63], invz, negsum, selsum1, psign);
|
||||||
|
flag flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
|
||||||
|
psign, z[63], xzero, yzero, v[1:0],
|
||||||
|
inf, nan, invalid, overflow, underflow, inexact);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
41
wally-pipelined/src/fpu/FMA/lop.v
Normal file
41
wally-pipelined/src/fpu/FMA/lop.v
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: lop.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block implements a Leading One Predictor used to determine
|
||||||
|
// the normalization shift count.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module lop(sum, normcnt, sumzero);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [157:0] sum; // sum
|
||||||
|
output [8:0] normcnt; // normalization shift count
|
||||||
|
output sumzero; // sum = 0
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
reg [8:0] i; // loop index
|
||||||
|
reg [8:0] normcnt; // normalization shift count
|
||||||
|
|
||||||
|
// A real LOP uses a fast carry chain to find only the first 0.
|
||||||
|
// It is an example of a parallel prefix algorithm. For the sake
|
||||||
|
// of simplicity, this model is behavioral instead.
|
||||||
|
// A real LOP would also operate on the sources of the adder, not
|
||||||
|
// the result!
|
||||||
|
|
||||||
|
always @ ( sum)
|
||||||
|
begin
|
||||||
|
i = 0;
|
||||||
|
while (~sum[157-i] && i < 157) i = i+1; // search for leading one
|
||||||
|
normcnt = i; // compute shift count
|
||||||
|
end
|
||||||
|
|
||||||
|
// Also check if sum is zero
|
||||||
|
assign sumzero = ~(|sum);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
63
wally-pipelined/src/fpu/FMA/normalize.v
Normal file
63
wally-pipelined/src/fpu/FMA/normalize.v
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: normalize.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block performs the normalization shift. It also
|
||||||
|
// generates the Rands bits for rounding. Finally, it
|
||||||
|
// handles the special case of a zero sum.
|
||||||
|
//
|
||||||
|
// v[53:2] is the fraction component of the prerounded result.
|
||||||
|
// It can be bypassed back to the X or Z inputs of the FMAC
|
||||||
|
// for back-to-back operations.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module normalize(sum[157:0], normcnt, sumzero, bs, ps, denorm0, zdenorm, v[53:0]);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
input [157:0] sum; // sum
|
||||||
|
input [8:0] normcnt; // normalization shift count
|
||||||
|
input sumzero; // sum is zero
|
||||||
|
input bs; // sticky bit for addend
|
||||||
|
input ps; // sticky bit for product
|
||||||
|
input denorm0; // exponent = -1023
|
||||||
|
input zdenorm; // Input Z is denormalized
|
||||||
|
output [53:0] v; // normalized sum, R, S bits
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
reg [53:0] v; // normalized sum, R, S bits
|
||||||
|
wire [157:0] sumshifted; // shifted sum
|
||||||
|
|
||||||
|
// When the sum is zero, normalization does not apply and only the
|
||||||
|
// sticky bit must be computed. Otherwise, the sum is right-shifted
|
||||||
|
// and the Rand S bits (v[1] and v[O], respectively) are assigned.
|
||||||
|
|
||||||
|
// The R bit is also set on denormalized numbers where the exponent
|
||||||
|
// was computed to be exactly -1023 and the L bit was set. This
|
||||||
|
// is required for correct rounding up of multiplication results.
|
||||||
|
|
||||||
|
// The sticky bit calculation is actually built into the shifter and
|
||||||
|
// does not require a true subtraction shown in the model.
|
||||||
|
|
||||||
|
always @(sum or normcnt or sumzero or bs or ps or sumshifted or denorm0)
|
||||||
|
begin
|
||||||
|
if (sumzero) begin // special case
|
||||||
|
v[53:1] = 0;
|
||||||
|
v[0] = ps || bs ;
|
||||||
|
end else begin // extract normalized bits
|
||||||
|
v[53:3] = sumshifted[156:106];
|
||||||
|
// KEP prevent plus1 in round.v when z is denormalized.
|
||||||
|
v[2] = sumshifted[105] || sumshifted[106] && denorm0 && ~zdenorm;
|
||||||
|
v[1] = sumshifted[104] || sumshifted[105] && denorm0 && ~zdenorm;
|
||||||
|
v[0] = |(sumshifted[103:0]) || ps || bs;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// shift sum left by normcnt, filling the right with zeros
|
||||||
|
assign sumshifted = sum << normcnt;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
106
wally-pipelined/src/fpu/FMA/round.v
Normal file
106
wally-pipelined/src/fpu/FMA/round.v
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: round.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 11/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block is responsible for rounding the normalized result of // the FMAC. Because prenormalized results may be bypassed back to // the FMAC X and z inputs, rounding does not appear in the critical // path of most floating point code. This is good because rounding // requires an entire 52 bit carry-propagate half-adder delay.
|
||||||
|
//
|
||||||
|
// The results from other FPU blocks (e.g. FCVT, FDIV, etc) are also
|
||||||
|
// muxed in to form the actual result for register file writeback. This
|
||||||
|
// saves a mux from the writeback path.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, wsign,
|
||||||
|
invalid, overflow, underflow, inf, nan, xnan, ynan, znan,
|
||||||
|
x[51:0], y[51:0], z[51:0],
|
||||||
|
w[51:0], postnormalize, infinity, specialsel);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [53:0] v; // normalized sum, R, S bits
|
||||||
|
input [51:0] earlyres; // result from other FPU blocks
|
||||||
|
input earlyressel; // use result from other FPU blocks
|
||||||
|
input rz; // Round toward zero
|
||||||
|
input rn; // Round toward nearest
|
||||||
|
input rp; // Round toward plus infinity
|
||||||
|
input rm; // Round toward minus infinity
|
||||||
|
input wsign; // Sign of result
|
||||||
|
input invalid; // Trap on infinity, NaN, denorm
|
||||||
|
input overflow; // Result overflowed
|
||||||
|
input underflow; // Result underflowed
|
||||||
|
input inf; // Some input is infinity
|
||||||
|
input nan; // Some input is NaN
|
||||||
|
input xnan; // X is NaN
|
||||||
|
input ynan; // Y is NaN
|
||||||
|
input znan; // Z is NaN
|
||||||
|
input [51:0] x; // Input X
|
||||||
|
input [51:0] y; // Input Y
|
||||||
|
input [51:0] z; // Input Z
|
||||||
|
output [51:0] w; // rounded result of FMAC
|
||||||
|
output postnormalize; // Right shift 1 for post-rounding norm
|
||||||
|
output infinity; // Generate infinity on overflow
|
||||||
|
output specialsel; // Select special result
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire plus1; // Round by adding one
|
||||||
|
wire [52:0] v1; // Result + 1 (for rounding)
|
||||||
|
wire [51:0] specialres; // Result of exceptional case
|
||||||
|
wire [51:0] infinityres; // Infinity or largest real number
|
||||||
|
wire [51:0] nanres; // Propagated or generated NaN
|
||||||
|
|
||||||
|
// Compute if round should occur. This equation is derived from
|
||||||
|
// the rounding tables.
|
||||||
|
|
||||||
|
|
||||||
|
assign plus1 = rn && ((v[1] && v[0]) || (v[2] && (v[1]))) ||
|
||||||
|
rp && ~wsign && (v[1] || v[0]) ||
|
||||||
|
rm && wsign && (v[1] || v[0]);
|
||||||
|
|
||||||
|
// Compute rounded result
|
||||||
|
assign v1 = v[53:2] + 1;
|
||||||
|
// Determine if postnormalization is necessary
|
||||||
|
// Predicted by all bits =1 before round +1
|
||||||
|
|
||||||
|
assign postnormalize = &(v[53:2]) && plus1;
|
||||||
|
|
||||||
|
// Determine special result in event of of selection of a result from
|
||||||
|
// another FPU functional unit, infinity, NAN, or underflow
|
||||||
|
// The special result mux is a 4:1 mux that should not appear in the
|
||||||
|
// critical path of the machine. It is not priority encoded, despite
|
||||||
|
// the code below suggesting otherwise. Also, several of the identical data
|
||||||
|
// inputs to the wide muxes can be combined at the expense of more
|
||||||
|
// complicated non-critical control in the circuit implementation.
|
||||||
|
|
||||||
|
assign specialsel = earlyressel || overflow || underflow || invalid ||
|
||||||
|
nan || inf;
|
||||||
|
assign specialres = earlyressel ? earlyres :
|
||||||
|
invalid ? nanres :
|
||||||
|
overflow ? infinityres :
|
||||||
|
inf ? 52'b0 :
|
||||||
|
underflow ? 52'b0 : 52'bx; // default to undefined
|
||||||
|
|
||||||
|
// Overflow is handled differently for different rounding modes
|
||||||
|
// Round is to either infinity or to maximum finite number
|
||||||
|
|
||||||
|
assign infinity = rn || (rp && ~wsign) || (rm && wsign);
|
||||||
|
assign infinityres = infinity ? 52'b0 : {52{1'b1}};
|
||||||
|
|
||||||
|
// Invalid operations produce a quiet NaN. The result should
|
||||||
|
// propagate an input if the input is NaN. Since we assume all
|
||||||
|
// NaN inputs are already quiet, we don't have to force them quiet.
|
||||||
|
|
||||||
|
// assign nanres = xnan ? x: (ynan ? y : (znan ? z : {1'b1, 51'b0})); // original
|
||||||
|
assign nanres = xnan ? {1'b1, x[50:0]}: (ynan ? {1'b1, y[50:0]} : (znan ? {1'b1, z[50:0]} : {1'b1, 51'b0}));// KEP 210112 add the 1 to make NaNs quiet
|
||||||
|
|
||||||
|
// Select result with 4:1 mux
|
||||||
|
// If the sum is zero and we round up, there is a special case in
|
||||||
|
// which we produce a massive loss of significance and trap to software.
|
||||||
|
// It is handled in the exception unit.
|
||||||
|
|
||||||
|
assign w = specialsel ? specialres : (plus1 ? v1[51:0] : v[53:2]);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
93
wally-pipelined/src/fpu/FMA/sign.v
Normal file
93
wally-pipelined/src/fpu/FMA/sign.v
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: sign.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 12/1/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block manages the signs of the numbers.
|
||||||
|
// 1 = negative
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
|
||||||
|
sumzero, nan, invalid, xinf, yinf, inf, wsign, invz, negsum, selsum1, psign);
|
||||||
|
////////////////////////////////////////////////////////////////////////////I
|
||||||
|
|
||||||
|
input xsign; // Sign of X
|
||||||
|
input ysign; // Sign of Y
|
||||||
|
input zsign; // Sign of Z
|
||||||
|
input negsum0; // Sum in +O mode is negative
|
||||||
|
input negsum1; // Sum in +1 mode is negative
|
||||||
|
input bs; // sticky bit from addend
|
||||||
|
input ps; // sticky bit from product
|
||||||
|
input killprod; // Product forced to zero
|
||||||
|
input rm; // Round toward minus infinity
|
||||||
|
input sumzero; // Sum = O
|
||||||
|
input nan; // Some input is NaN
|
||||||
|
input invalid; // Result invalid
|
||||||
|
input xinf; // X = Inf
|
||||||
|
input yinf; // Y = Inf
|
||||||
|
input inf; // Some input = Inf
|
||||||
|
output wsign; // Sign of W
|
||||||
|
output invz; // Invert addend into adder
|
||||||
|
output negsum; // Negate result of adder
|
||||||
|
output selsum1; // Select +1 mode from compound adder
|
||||||
|
output psign; // sign of product X * Y
|
||||||
|
|
||||||
|
// Internal nodes
|
||||||
|
|
||||||
|
wire zerosign; // sign if result= 0
|
||||||
|
wire infsign; // sign if result= Inf
|
||||||
|
reg negsum; // negate result of adder
|
||||||
|
reg selsum1; // select +1 mode from compound adder
|
||||||
|
|
||||||
|
// Compute sign of product
|
||||||
|
|
||||||
|
assign psign = xsign ^ ysign;
|
||||||
|
|
||||||
|
// Invert addend if sign of Z is different from sign of product assign invz = zsign ^ psign;
|
||||||
|
assign invz = zsign ^ psign;
|
||||||
|
// Select +l mode for adder and compute if result must be negated
|
||||||
|
// This is done according to cases based on the sticky bit.
|
||||||
|
|
||||||
|
always @(invz or negsum0 or negsum1 or bs or ps)
|
||||||
|
begin
|
||||||
|
if (~invz) begin // both inputs have same sign
|
||||||
|
negsum = 0;
|
||||||
|
selsum1 = 0;
|
||||||
|
end else if (bs) begin // sticky bit set on addend
|
||||||
|
selsum1 = 0;
|
||||||
|
negsum = negsum0;
|
||||||
|
end else if (ps) begin // sticky bit set on product
|
||||||
|
selsum1 = 1;
|
||||||
|
negsum = negsum1;
|
||||||
|
end else begin // both sticky bits clear
|
||||||
|
selsum1 = negsum1; // KEP 210113-10:44 Selsum1 was adding 1 to values that were multiplied by 0
|
||||||
|
// selsum1 = ~negsum1; //original
|
||||||
|
negsum = negsum1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Compute sign of result
|
||||||
|
// This involves a special case when the sum is zero:
|
||||||
|
// x+x retains the same sign as x even when x = +/- 0.
|
||||||
|
// otherwise, x-x = +O unless in the RM mode when x-x = -0
|
||||||
|
// There is also a special case for NaNs and invalid results;
|
||||||
|
// the sign of the NaN produced is forced to be 0.
|
||||||
|
// Sign calculation is not in the critical path so the cases
|
||||||
|
// can be tolerated.
|
||||||
|
// IEEE 754-2008 section 6.3 states
|
||||||
|
// "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
|
||||||
|
// also pertaining to negZero it states:
|
||||||
|
// "When the sum/difference of two operands with opposite signs is exactly zero, the sign of that sum/difference
|
||||||
|
// shall be +0 in all rounding attributes EXCEPT roundTowardNegative. Under that attribute, the sign of an exact zero
|
||||||
|
// sum/difference shall be -0. However, x+x = x-(-X) retains the same sign as x even when x is zero."
|
||||||
|
|
||||||
|
assign zerosign = (~invz && killprod) ? zsign : rm;
|
||||||
|
assign infsign = psign; //KEP 210112 keep the correct sign when result is infinity
|
||||||
|
// assign infsign = xinf ? (yinf ? psign : xsign) : yinf ? ysign : zsign;//original
|
||||||
|
assign wsign =invalid? 0 : (inf ? infsign:
|
||||||
|
(sumzero ? zerosign : psign ^ negsum));
|
||||||
|
|
||||||
|
endmodule
|
70
wally-pipelined/src/fpu/FMA/special.v
Normal file
70
wally-pipelined/src/fpu/FMA/special.v
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Block Name: special.v
|
||||||
|
// Author: David Harris
|
||||||
|
// Date: 12/2/1995
|
||||||
|
//
|
||||||
|
// Block Description:
|
||||||
|
// This block implements special case handling for unusual operands (e.g.
|
||||||
|
// 0, NaN, denormalize, infinity). The block consists of zero/one detectors.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
module special(x[63:0], y[63:0], z[63:0], ae, xzero, yzero, zzero,
|
||||||
|
xnan, ynan, znan, xdenorm, ydenorm, zdenorm, proddenorm, xinf, yinf, zinf);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
input [63:0] x; // Input x
|
||||||
|
input [63:0] y; // Input Y
|
||||||
|
input [63:0] z; // Input z
|
||||||
|
input [12:0] ae; // exponent of product
|
||||||
|
output xzero; // Input x = 0
|
||||||
|
output yzero; // Input y = 0
|
||||||
|
output zzero; // Input z = 0
|
||||||
|
output xnan; // x is NaN
|
||||||
|
output ynan; // y is NaN
|
||||||
|
output znan; // z is NaN
|
||||||
|
output xdenorm; // x is denormalized
|
||||||
|
output ydenorm; // y is denormalized
|
||||||
|
output zdenorm; // z is denormalized
|
||||||
|
output proddenorm; // product is denormalized
|
||||||
|
output xinf; // x is infinity
|
||||||
|
output yinf; // y is infinity
|
||||||
|
output zinf; // z is infinity
|
||||||
|
|
||||||
|
// In the actual circuit design, the gates looking at bits
|
||||||
|
// 51:0 and at bits 62:52 should be shared among the various detectors.
|
||||||
|
|
||||||
|
// Check if input is NaN
|
||||||
|
|
||||||
|
assign xnan = &x[62:52] && |x[51:0];
|
||||||
|
assign ynan = &y[62:52] && |y[51:0];
|
||||||
|
assign znan = &z[62:52] && |z[51:0];
|
||||||
|
|
||||||
|
// Check if input is denormalized
|
||||||
|
|
||||||
|
assign xdenorm = ~(|x[62:52]) && |x[51:0];
|
||||||
|
assign ydenorm = ~(|y[62:52]) && |y[51:0];
|
||||||
|
assign zdenorm = ~(|z[62:52]) && |z[51:0];
|
||||||
|
assign proddenorm = &ae & ~xzero & ~yzero; //KEP is the product denormalized
|
||||||
|
|
||||||
|
// Check if input is infinity
|
||||||
|
|
||||||
|
assign xinf = &x[62:52] && ~(|x[51:0]);
|
||||||
|
assign yinf = &y[62:52] && ~(|y[51:0]);
|
||||||
|
assign zinf = &z[62:52] && ~(|z[51:0]);
|
||||||
|
|
||||||
|
// Check if inputs are all zero
|
||||||
|
// Also forces denormalized inputs to zero.
|
||||||
|
// In the circuit implementation, this can be optimized
|
||||||
|
// to just check if the exponent is zero.
|
||||||
|
|
||||||
|
// KATHERINE - commented following (21/01/11)
|
||||||
|
// assign xzero = ~(|x[62:0]) || xdenorm;
|
||||||
|
// assign yzero = ~(|y[62:0]) || ydenorm;
|
||||||
|
// assign zzero = ~(|z[62:0]) || zdenorm;
|
||||||
|
// KATHERINE - removed denorm to prevent outputing zero when computing with a denormalized number
|
||||||
|
assign xzero = ~(|x[62:0]);
|
||||||
|
assign yzero = ~(|y[62:0]);
|
||||||
|
assign zzero = ~(|z[62:0]);
|
||||||
|
endmodule
|
2824
wally-pipelined/src/fpu/FMA/tb.v
Normal file
2824
wally-pipelined/src/fpu/FMA/tb.v
Normal file
File diff suppressed because it is too large
Load Diff
1997
wally-pipelined/src/fpu/FMA/tbgen/StineVectors
Normal file
1997
wally-pipelined/src/fpu/FMA/tbgen/StineVectors
Normal file
File diff suppressed because it is too large
Load Diff
199
wally-pipelined/src/fpu/FMA/tbgen/ans
Normal file
199
wally-pipelined/src/fpu/FMA/tbgen/ans
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
c22000007fffffff 24700000ffffffef a6a00001800007ed
|
||||||
|
bfc00000000011fe 3fdfffffffffff03 bfb000000000117f
|
||||||
|
a83100000007fffe 41e0000effffffff aa21000ff0080004
|
||||||
|
0000000000000000 001ffffffffffffe 0000000000000000
|
||||||
|
400327ca64d70ec7 3ca0000000000001 3cb327ca64d70ec9
|
||||||
|
0000000000000000 43e207ffffffffff 0000000000000000
|
||||||
|
0000000000000000 3fd0000000000000 0000000000000000
|
||||||
|
0000000000000000 3fdfffffffffffff 0000000000000000
|
||||||
|
0000000000000000 3fe0000000000000 0000000000000000
|
||||||
|
c870200000010000 3fefffffffffffff c87020000000ffff
|
||||||
|
c00aaa4fd557ef13 c3b8917384eb32d0 43d478efdc9216d8
|
||||||
|
0000000000000000 7ffc000000000000 7ff8000000000000
|
||||||
|
0000000000000000 c18aca47203438e2 0000000000000000
|
||||||
|
0000000000000000 4000000000000001 0000000000000000
|
||||||
|
47efff0008000000 b1dcb0523546117f b9dcaf6cb9e07bdb
|
||||||
|
43f000ffffff7fff 22300000001fffdf 26300100001f81de
|
||||||
|
402ff000001fffff 40759558e27de226 40b58a8e3622388e
|
||||||
|
0000000000000000 40efdeffffffffff 0000000000000000
|
||||||
|
0000000000000000 434fffffffffffff 0000000000000000
|
||||||
|
7ffc000000000000 7fe0000000000000 7ff8000000000000
|
||||||
|
b35e061abc769f3a c078000003fffffe 33e684941119bac2
|
||||||
|
403a793cfb1e2471 bff0000100007fff c03a793ea2b2c7eb
|
||||||
|
3d1ffffbfe000000 216898822a24af3f 1e98987f158ae1d8
|
||||||
|
bfb00000001bffff 7ffc000000000000 7ff8000000000000
|
||||||
|
37f0000000efffff c3d00007fffffeff bbd0000800efff75
|
||||||
|
0000000000000000 ffefff8000080000 0000000000000000
|
||||||
|
3fb00200000000ff c0000000011fffff bfc00200012024fd
|
||||||
|
41c0000007ffffff 49103fffefffffff 4ae03ffff81ffff6
|
||||||
|
407effbfffffffff 3e00000040001fff 3e8effc07bff3dfd
|
||||||
|
c1f00013fffffffe 7ffc000000000000 7ff8000000000000
|
||||||
|
c3f00004000001ff c3d00bfffffffffe 47d00c04030001ff
|
||||||
|
403b5ab30b28be12 bfdfffffffffffff c02b5ab30b28be11
|
||||||
|
0000000000000000 c1cfffffff87ffff 0000000000000000
|
||||||
|
0000000000000000 bfe0000000000001 0000000000000000
|
||||||
|
801ffc000007ffff bfeffffffffffffe 001ffc000007fffe
|
||||||
|
0000000000000000 ffe0000005fffffe 0000000000000000
|
||||||
|
0000000000000000 bfffffffffffffff 0000000000000000
|
||||||
|
0000000000000000 c000000000000000 0000000000000000
|
||||||
|
c3d09308769f3f51 c00fffffffffffff 43f09308769f3f51
|
||||||
|
0000000000000000 402ffffdfefffffe 0000000000000000
|
||||||
|
0000000000000000 c010000000000001 0000000000000000
|
||||||
|
c01fffffffc00fff c01ffffffffffffe 404fffffffc00ffe
|
||||||
|
c025e14360f49046 412fff0000000003 c165e09456d988a3
|
||||||
|
0000000000000000 43ee59a2f1155c8b 0000000000000000
|
||||||
|
3fe0000000008fff 802ffffff7fffff6 801ffffff8011ff3
|
||||||
|
0000000000000000 ffefffffffffffff 0000000000000000
|
||||||
|
40401007fffffffe fff0000000000000 80401007fffffffe
|
||||||
|
0000000000000000 c0045abb4860cbf3 0000000000000000
|
||||||
|
0000000000000000 7ffc000000000000 7ff8000000000000
|
||||||
|
bffffffec0000000 c000000000003eff 400ffffec0007dfe
|
||||||
|
48000000004001ff 41f331de979ac49e 4a0331de97e78e7e
|
||||||
|
3d0fffffbff7ffff 7ffc000000000000 7ff8000000000000
|
||||||
|
43d3ffffff000000 3caffffffffffffe 4093fffffeffffff
|
||||||
|
7ffc000000000000 43dfff8004000000 7ff8000000000000
|
||||||
|
bcaffe0000000008 3fd00008000000ff bc8ffe0fff000205
|
||||||
|
404ffbfffffffffc c34ffff8003fffff c3affbf8013ff7fb
|
||||||
|
43e0000000000082 3db000003ffffeff 41a000003fffff82
|
||||||
|
c1d004000ffffffe 4000000000000000 c1e004000ffffffe
|
||||||
|
c00fffffc000007e c02ffffdfffffbff 404ffffdc000007e
|
||||||
|
409dfffbffffffff 4010000000000001 40bdfffc00000001
|
||||||
|
c120000003ffffe0 c06000fffbffffff 4190010000003fde
|
||||||
|
3fd1f7ffffffffff c01000001dffffff bff1f80021b0fffd
|
||||||
|
2e0fefdfffffffff 4030000020000040 2e4fefe03fdfc07f
|
||||||
|
43c0000803ffffff 3fcfffffffffffff 43a0000803ffffff
|
||||||
|
c0afffffbffffdfe 3fc07ffdffffffff c0807ffddf0002f5
|
||||||
|
c0fffffffeffffee 55139bb9349e058c d6239bb9340127b7
|
||||||
|
41ffdbaf18ce06bd 8010000000000000 821fdbaf18ce06bd
|
||||||
|
c0e1000000080000 801ffffffffffffe 011100000007ffff
|
||||||
|
3fbffffff0000007 c807dfffffffffff c7d7dffff4100004
|
||||||
|
c357b53537b96da5 bfd0000000000000 4337b53537b96da5
|
||||||
|
401fffffffffffff ffebff8000000000 801bff7fffffffff
|
||||||
|
c7eff77bf2b59c3c bfe0000000000001 47dff77bf2b59c3e
|
||||||
|
380c3f72cc3dec98 c3fffffffbffffff bc1c3f72c8b5fe3d
|
||||||
|
b8e0000003fbffff c503f4d44f4bf888 3df3f4d454443066
|
||||||
|
3f3ffffc001fffff c000000000000001 bf4ffffc00200000
|
||||||
|
c340002000004000 c0db3367e0423019 442b339e47125d6b
|
||||||
|
4f60000801ffffff 41c07fe000000000 51307fe841fffbff
|
||||||
|
c1ffffffbfefffff c340000000000001 454fffffbff00001
|
||||||
|
404fff7fffffff7f 48ab7e2aad4ec686 490b7dbcb4a410dd
|
||||||
|
7ffc000000000000 ffefffffffffffff 7ff8000000000000
|
||||||
|
41e189ea1a6fff97 7ffc000000000000 7ff8000000000000
|
||||||
|
3ff0ee9046c9330f 8479e1e79766e02b 847b63d14ff91acb
|
||||||
|
d2f805130a8c11df 43effffdfdfffffe d6f8051188ba9004
|
||||||
|
4f1fffbfffe00000 bcd02000000007ff cc001fdfbfefe7fe
|
||||||
|
be70000077ffffff c1efffffffffffff 4070000077ffffff
|
||||||
|
41e1ffffbffffffe 3caffffffffffffe 3ea1ffffbffffffd
|
||||||
|
3bbd976272fb1d2a c06ffff80007fffe bc3d975b0d29e641
|
||||||
|
434fff01ffffffff 403dfeffffffffff 439dfe11e7efffff
|
||||||
|
be6fff7fffffffff 3feffffffffffffe be6fff7ffffffffd
|
||||||
|
41d007ff80000000 41f0fffffffc0000 43d1087f77fbfe01
|
||||||
|
ffeef7a206029708 bdcfa4109a3a5b22 7dce9eaa2542875b
|
||||||
|
3b6ffffffeffffc0 3c7ffffe003ffffe 37fffffdff3fffce
|
||||||
|
c1d1ffffffbfffff bfcffffefffff800 41b1ffff6fbffb82
|
||||||
|
2030000000000090 c05e2e90015c47a1 a09e2e90015c48b0
|
||||||
|
bbf000000007efff 001fe0000007fffe fc1fe0000017d01c
|
||||||
|
41cae866712069f4 c02fffffffffffff c20ae866712069f3
|
||||||
|
bfce1e32ccf56348 3ca1f66d4c8eeef3 bc80e7fa025544da
|
||||||
|
ffedfffff0000000 ffeffff000000800 3fedfff0f0000f80
|
||||||
|
37effffc3ffffffe bca0fffffffffffd b4a0fffe01fffffb
|
||||||
|
bc950a021bf9dee1 3db0001fffdffffe ba550a2c2fd402cd
|
||||||
|
fd4fffffdfffffef 41cffffdffffffef ff2ffffde00001de
|
||||||
|
bfc00000004007ff bcafffffffffffff 3c800000004007ff
|
||||||
|
c009130b80fe8274 b811571307061a38 382b2cb1993b60f3
|
||||||
|
c0600000ffffffdf 7feda1b8c591f9c6 805da1ba9fad85e2
|
||||||
|
c1e4af3f8d45e031 3ca0020002000000 be94b1d577cd70de
|
||||||
|
3800008100000000 b810000020000080 b020008120010280
|
||||||
|
372ff00000003fff 7fe000fdfffffffe 771ff1fb02003fff
|
||||||
|
47d00021fffffffe c00fffffffffffff c7f00021fffffffd
|
||||||
|
bfbc9ea0c2b4884b 43f4a552574073d5 c3c277000b21a4e7
|
||||||
|
bf1fe0000000ffff c01ffffffffffffe 3f4fe0000000fffe
|
||||||
|
41ffffffff7ffffb 0027ffffffffeffe 0237ffffff9feffb
|
||||||
|
c7e040000fffffff ffe0000000000000 07d040000fffffff
|
||||||
|
7ffc000000000000 3fe0000ffffff7ff 7ff8000000000000
|
||||||
|
c1effc1fffffffff 7ffc000000000000 7ff8000000000000
|
||||||
|
c0d000000001ffbf c03ba46e644e4e9c 411ba46e6451c2ba
|
||||||
|
c4500000005fffff c03a20ab4de47fc9 449a20ab4e8143cc
|
||||||
|
400e00000000007e 001fffffffffffff 003e00000000007e
|
||||||
|
45a01fffff7fffff c3c0020200000000 c9702206037fefee
|
||||||
|
3e8ff800000000ff 3caffffffffffffe 3b4ff800000000fe
|
||||||
|
be004000000007fe 3fdffff7ff7fffff bdf03ffbefbf07fd
|
||||||
|
b11000007ffffe00 3fe0000000000000 b10000007ffffe00
|
||||||
|
b80cef50bd17db40 c05fffc00000000e 387cef16de76611d
|
||||||
|
3d4000ffffffffff 3d47f68d8eb6b9a4 3a97f80cf78fa50f
|
||||||
|
ffe3fffffffffffb c03dc3321aaa5380 003299ff50aa742c
|
||||||
|
3ca3fffffffffeff bf02ffafb4e9241d bbb7bf9ba2236bf3
|
||||||
|
53598c812c3c39dd 3f20000100fffffe 52898c82c69d14b1
|
||||||
|
c3dffffff8000001 3fe0020000003ffe c3d001fffbffbffe
|
||||||
|
7ba00800003fffff 3ff9a9a129c791b3 7ba9b675fac31bff
|
||||||
|
c3d0000fffffffef 7fe0000000000001 83c0000ffffffff0
|
||||||
|
c34f80001fffffff b7fffffe0007ffff 3b5f7ffe2807ddff
|
||||||
|
0010000000001ff8 4800020000010000 0820020000011ffc
|
||||||
|
2c4c0000003fffff 230ffffc00400000 0f6bfffc8077fff8
|
||||||
|
381fffffffbff7fe 8010000000000000 f83fffffffbff7fe
|
||||||
|
802d3018ea8c241d c007fdffffffffff 0045e23fae5a7253
|
||||||
|
43e047fffffffffe 4000003ffdfffffe 43f048411df6fffc
|
||||||
|
c000005fffffffff 403ffffffff00002 c050005ffff7ffd0
|
||||||
|
3fc8b60e46a80f6d bfdffffffffffffe bfb8b60e46a80f6b
|
||||||
|
bd5fdffdffffffff 5644b72ace1bbb6b d3b4a27257daf2cd
|
||||||
|
b80010001fffffff 40e01ffffff7fffe b8f030202037f7fc
|
||||||
|
407000003ffbfffe 38042862fe8e3368 388428634f2ab547
|
||||||
|
bf8ffbfff7ffffff c00fffffffffffff 3faffbfff7ffffff
|
||||||
|
bcafc000003fffff c010000000000001 3ccfc00000400001
|
||||||
|
47eddf042473ef08 b7e00000fe000000 bfdddf05fea850ca
|
||||||
|
3fbfffff7fffffef c340ffffffffffbf c310ffffbbffffb5
|
||||||
|
c02f8000000007ff ffe0000000000001 001f800000000801
|
||||||
|
002f37ebf6c8eaec c08be464f4c81c69 80cb36000706e168
|
||||||
|
c00e800000000000 7ffc000000000000 7ff8000000000000
|
||||||
|
0010000000000000 0000000000000000 0000000000000000
|
||||||
|
bfffc00000000003 391001ffffffffff b91fc3f800000001
|
||||||
|
c1db54446247aa52 bfcc001fffffffff 41b7e9d72a43174f
|
||||||
|
0010000000000000 c0392c59c8e48f37 80592c59c8e48f37
|
||||||
|
0010000000000000 c0000800000001ff 80200800000001ff
|
||||||
|
0010000000000000 c1d0000004000fff 81f0000004000fff
|
||||||
|
4030040000200000 0017055f48beeff5 00570b20a0bf2a70
|
||||||
|
bc7000000000ffee c1e0001100000000 3e6000110000fff0
|
||||||
|
c040000000007fff c3b2a6c91c557f56 4402a6c91c56148c
|
||||||
|
41ffffffff003fff c3b0000007ffffee c5c0000007801fed
|
||||||
|
21900001dfffffff bf20000017fffffe a0c00001f80002cc
|
||||||
|
0029954d0f0df5b3 41e00000000003ff 0219954d0f0dfc17
|
||||||
|
b810000020000001 47ffdfffffffff80 c01fe0003fbfff81
|
||||||
|
0010000000000000 ffeffff800007fff c00ffff800007fff
|
||||||
|
0010000000000000 4010000000000000 0030000000000000
|
||||||
|
bf700000000100ff 401fffffffffffff bfa00000000100fe
|
||||||
|
37feffffffffffff 47ef8000000fffff 3ffe8400000f7fff
|
||||||
|
b80f800001fffffe 44e00000ffff7fff bcff8001f9ff041c
|
||||||
|
0010000000000000 434ffffffffffffe 036ffffffffffffe
|
||||||
|
41ffffdfffff8000 7fe0000000000001 01efffdfffff8002
|
||||||
|
b80a16ad02c87cd3 380fffffffffe7fe b02a16ad02c86940
|
||||||
|
47f0fffffffffffb 7ffc000000000000 7ff8000000000000
|
||||||
|
0010000000000000 41ffffffffbfff7f 021fffffffbfff7f
|
||||||
|
0010000000000000 8000000000000000 0000000000000000
|
||||||
|
c3d00001000001ff b7f60cb3edb38762 3bd60cb54e7ec8fe
|
||||||
|
0010000000000000 8010000000000001 c030000000000001
|
||||||
|
43c0007fffdfffff 801ffffffffffffe 83f0007fffdffffd
|
||||||
|
c7efffffdffffbff bca0000000000001 449fffffdffffc01
|
||||||
|
0010000000000000 c11ff00000000003 813ff00000000003
|
||||||
|
0010000000000000 bfd0000000000000 ffefffffffffffff
|
||||||
|
c0ffffffffeffffe bfdfffffffffffff 40efffffffeffffe
|
||||||
|
6f7000000001fdff 1510010000000fff 4490010000020e1e
|
||||||
|
37f002000000000f b1effcfffffffffe a9f0007fd000000d
|
||||||
|
cc3050bc013d7cd7 bff0000000000000 4c3050bc013d7cd7
|
||||||
|
0010000000000000 87fff0000000fffe c81ff0000000fffe
|
||||||
|
0010000000000000 bffffffffffffffe 801ffffffffffffe
|
||||||
|
43effbfffffff7ff 7fefffffff801ffe 03effbffff8027fa
|
||||||
|
c015834380f2b995 3f9fff0000000400 bfc5829766d6b4af
|
||||||
|
0010000000000000 41dfffffc0001000 01ffffffc0001000
|
||||||
|
0010000000000000 c01fffffffffffff 803fffffffffffff
|
||||||
|
41e010000000001f c5b04000000fffff c7a050400010101e
|
||||||
|
3b40018000000000 3ea0400000000100 39f0418600000101
|
||||||
|
0010000000000000 4cdffeffff7fffff 0cfffeffff7fffff
|
||||||
|
16dff0001ffffffe 3fb500ae0796659d 16a4f62dc5934871
|
||||||
|
b7e003ffffffff7f deafffffeffffffd 56a003fff7fdff7e
|
||||||
|
406000001fffbfff 3f20020000080000 3f900200200bbff8
|
||||||
|
0010000000000000 7ffc000000000000 7ff8000000000000
|
||||||
|
439fbffffffbffff bf8454fd38ef0ba0 c3342c533e7aa2e8
|
||||||
|
c1c000000200007e bf000001ffffffbf 40d000020200007e
|
||||||
|
480000000008fffe 001637e790e69de2 082637e790f31d52
|
||||||
|
bffffffc000003fe 3ca0000000000001 bcaffffc000003ff
|
||||||
|
6b4848a9a8c0dcd5 480ffffffffbdfff 736848a9a8bdbb77
|
199
wally-pipelined/src/fpu/FMA/tbgen/output
Normal file
199
wally-pipelined/src/fpu/FMA/tbgen/output
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
c22000007fffffff 24700000ffffffef a6a00001800007ee
|
||||||
|
bfc00000000011fe 3fdfffffffffff03 bfb000000000117f
|
||||||
|
a83100000007fffe 41e0000effffffff aa21000ff0080004
|
||||||
|
0000000000000000 001ffffffffffffe 0000000000000000
|
||||||
|
400327ca64d70ec7 3ca0000000000001 3cb327ca64d70ec8
|
||||||
|
0000000000000000 43e207ffffffffff 0000000000000000
|
||||||
|
0000000000000000 3fd0000000000000 0000000000000000
|
||||||
|
0000000000000000 3fdfffffffffffff 0000000000000000
|
||||||
|
0000000000000000 3fe0000000000000 0000000000000000
|
||||||
|
c870200000010000 3fefffffffffffff c87020000000ffff
|
||||||
|
c00aaa4fd557ef13 c3b8917384eb32d0 43d478efdc9216d7
|
||||||
|
0000000000000000 7ffc000000000000 7ffc000000000000
|
||||||
|
0000000000000000 c18aca47203438e2 8000000000000000
|
||||||
|
0000000000000000 4000000000000001 0000000000000000
|
||||||
|
47efff0008000000 b1dcb0523546117f b9dcaf6cb9e07bdc
|
||||||
|
43f000ffffff7fff 22300000001fffdf 26300100001f81de
|
||||||
|
402ff000001fffff 40759558e27de226 40b58a8e3622388d
|
||||||
|
0000000000000000 40efdeffffffffff 0000000000000000
|
||||||
|
0000000000000000 434fffffffffffff 0000000000000000
|
||||||
|
7ffc000000000000 7fe0000000000000 7ffc000000000000
|
||||||
|
b35e061abc769f3a c078000003fffffe 33e684941119bac1
|
||||||
|
403a793cfb1e2471 bff0000100007fff c03a793ea2b2c7eb
|
||||||
|
3d1ffffbfe000000 216898822a24af3f 1e98987f158ae1d8
|
||||||
|
bfb00000001bffff 7ffc000000000000 7ffc000000000000
|
||||||
|
37f0000000efffff c3d00007fffffeff bbd0000800efff76
|
||||||
|
0000000000000000 ffefff8000080000 8000000000000000
|
||||||
|
3fb00200000000ff c0000000011fffff bfc00200012024fe
|
||||||
|
41c0000007ffffff 49103fffefffffff 4ae03ffff81ffff6
|
||||||
|
407effbfffffffff 3e00000040001fff 3e8effc07bff3dfd
|
||||||
|
c1f00013fffffffe 7ffc000000000000 7ffc000000000000
|
||||||
|
c3f00004000001ff c3d00bfffffffffe 47d00c04030001fe
|
||||||
|
403b5ab30b28be12 bfdfffffffffffff c02b5ab30b28be11
|
||||||
|
0000000000000000 c1cfffffff87ffff 8000000000000000
|
||||||
|
0000000000000000 bfe0000000000001 8000000000000000
|
||||||
|
801ffc000007ffff bfeffffffffffffe 001ffc000007fffd
|
||||||
|
0000000000000000 ffe0000005fffffe 8000000000000000
|
||||||
|
0000000000000000 bfffffffffffffff 8000000000000000
|
||||||
|
0000000000000000 c000000000000000 8000000000000000
|
||||||
|
c3d09308769f3f51 c00fffffffffffff 43f09308769f3f50
|
||||||
|
0000000000000000 402ffffdfefffffe 0000000000000000
|
||||||
|
0000000000000000 c010000000000001 8000000000000000
|
||||||
|
c01fffffffc00fff c01ffffffffffffe 404fffffffc00ffd
|
||||||
|
c025e14360f49046 412fff0000000003 c165e09456d988a4
|
||||||
|
0000000000000000 43ee59a2f1155c8b 0000000000000000
|
||||||
|
3fe0000000008fff 802ffffff7fffff6 801ffffff8011ff4
|
||||||
|
0000000000000000 ffefffffffffffff 8000000000000000
|
||||||
|
40401007fffffffe fff0000000000000 fff0000000000000
|
||||||
|
0000000000000000 c0045abb4860cbf3 8000000000000000
|
||||||
|
0000000000000000 7ffc000000000000 7ffc000000000000
|
||||||
|
bffffffec0000000 c000000000003eff 400ffffec0007dfe
|
||||||
|
48000000004001ff 41f331de979ac49e 4a0331de97e78e7d
|
||||||
|
3d0fffffbff7ffff 7ffc000000000000 7ffc000000000000
|
||||||
|
43d3ffffff000000 3caffffffffffffe 4093fffffeffffff
|
||||||
|
7ffc000000000000 43dfff8004000000 7ffc000000000000
|
||||||
|
bcaffe0000000008 3fd00008000000ff bc8ffe0fff000206
|
||||||
|
404ffbfffffffffc c34ffff8003fffff c3affbf8013ff7fb
|
||||||
|
43e0000000000082 3db000003ffffeff 41a000003fffff81
|
||||||
|
c1d004000ffffffe 4000000000000000 c1e004000ffffffe
|
||||||
|
c00fffffc000007e c02ffffdfffffbff 404ffffdc000007d
|
||||||
|
409dfffbffffffff 4010000000000001 40bdfffc00000001
|
||||||
|
c120000003ffffe0 c06000fffbffffff 4190010000003fde
|
||||||
|
3fd1f7ffffffffff c01000001dffffff bff1f80021b0fffe
|
||||||
|
2e0fefdfffffffff 4030000020000040 2e4fefe03fdfc07f
|
||||||
|
43c0000803ffffff 3fcfffffffffffff 43a0000803fffffe
|
||||||
|
c0afffffbffffdfe 3fc07ffdffffffff c0807ffddf0002f6
|
||||||
|
c0fffffffeffffee 55139bb9349e058c d6239bb9340127b7
|
||||||
|
41ffdbaf18ce06bd 8010000000000000 821fdbaf18ce06bd
|
||||||
|
c0e1000000080000 801ffffffffffffe 011100000007ffff
|
||||||
|
3fbffffff0000007 c807dfffffffffff c7d7dffff4100004
|
||||||
|
c357b53537b96da5 bfd0000000000000 4337b53537b96da5
|
||||||
|
401fffffffffffff ffebff8000000000 fff0000000000000
|
||||||
|
c7eff77bf2b59c3c bfe0000000000001 47dff77bf2b59c3e
|
||||||
|
380c3f72cc3dec98 c3fffffffbffffff bc1c3f72c8b5fe3e
|
||||||
|
b8e0000003fbffff c503f4d44f4bf888 3df3f4d454443065
|
||||||
|
3f3ffffc001fffff c000000000000001 bf4ffffc00200001
|
||||||
|
c340002000004000 c0db3367e0423019 442b339e47125d6b
|
||||||
|
4f60000801ffffff 41c07fe000000000 51307fe841fffbff
|
||||||
|
c1ffffffbfefffff c340000000000001 454fffffbff00001
|
||||||
|
404fff7fffffff7f 48ab7e2aad4ec686 490b7dbcb4a410dc
|
||||||
|
7ffc000000000000 ffefffffffffffff 7ffc000000000000
|
||||||
|
41e189ea1a6fff97 7ffc000000000000 7ffc000000000000
|
||||||
|
3ff0ee9046c9330f 8479e1e79766e02b 847b63d14ff91acb
|
||||||
|
d2f805130a8c11df 43effffdfdfffffe d6f8051188ba9004
|
||||||
|
4f1fffbfffe00000 bcd02000000007ff cc001fdfbfefe7ff
|
||||||
|
be70000077ffffff c1efffffffffffff 4070000077fffffe
|
||||||
|
41e1ffffbffffffe 3caffffffffffffe 3ea1ffffbffffffd
|
||||||
|
3bbd976272fb1d2a c06ffff80007fffe bc3d975b0d29e642
|
||||||
|
434fff01ffffffff 403dfeffffffffff 439dfe11e7effffe
|
||||||
|
be6fff7fffffffff 3feffffffffffffe be6fff7ffffffffd
|
||||||
|
41d007ff80000000 41f0fffffffc0000 43d1087f77fbfe00
|
||||||
|
ffeef7a206029708 bdcfa4109a3a5b22 7dce9eaa2542875b
|
||||||
|
3b6ffffffeffffc0 3c7ffffe003ffffe 37fffffdff3fffce
|
||||||
|
c1d1ffffffbfffff bfcffffefffff800 41b1ffff6fbffb81
|
||||||
|
2030000000000090 c05e2e90015c47a1 a09e2e90015c48b1
|
||||||
|
bbf000000007efff 001fe0000007fffe 8000000000000000
|
||||||
|
41cae866712069f4 c02fffffffffffff c20ae866712069f3
|
||||||
|
bfce1e32ccf56348 3ca1f66d4c8eeef3 bc80e7fa025544db
|
||||||
|
ffedfffff0000000 ffeffff000000800 7ff0000000000000
|
||||||
|
37effffc3ffffffe bca0fffffffffffd b4a0fffe01fffffc
|
||||||
|
bc950a021bf9dee1 3db0001fffdffffe ba550a2c2fd402ce
|
||||||
|
fd4fffffdfffffef 41cffffdffffffef ff2ffffde00001de
|
||||||
|
bfc00000004007ff bcafffffffffffff 3c800000004007fe
|
||||||
|
c009130b80fe8274 b811571307061a38 382b2cb1993b60f2
|
||||||
|
c0600000ffffffdf 7feda1b8c591f9c6 fff0000000000000
|
||||||
|
c1e4af3f8d45e031 3ca0020002000000 be94b1d577cd70df
|
||||||
|
3800008100000000 b810000020000080 b020008120010280
|
||||||
|
372ff00000003fff 7fe000fdfffffffe 771ff1fb02003fff
|
||||||
|
47d00021fffffffe c00fffffffffffff c7f00021fffffffd
|
||||||
|
bfbc9ea0c2b4884b 43f4a552574073d5 c3c277000b21a4e8
|
||||||
|
bf1fe0000000ffff c01ffffffffffffe 3f4fe0000000fffd
|
||||||
|
41ffffffff7ffffb 0027ffffffffeffe 0237ffffff9feffa
|
||||||
|
c7e040000fffffff ffe0000000000000 7ff0000000000000
|
||||||
|
7ffc000000000000 3fe0000ffffff7ff 7ffc000000000000
|
||||||
|
c1effc1fffffffff 7ffc000000000000 7ffc000000000000
|
||||||
|
c0d000000001ffbf c03ba46e644e4e9c 411ba46e6451c2ba
|
||||||
|
c4500000005fffff c03a20ab4de47fc9 449a20ab4e8143cb
|
||||||
|
400e00000000007e 001fffffffffffff 003e00000000007d
|
||||||
|
45a01fffff7fffff c3c0020200000000 c9702206037fefef
|
||||||
|
3e8ff800000000ff 3caffffffffffffe 3b4ff800000000fd
|
||||||
|
be004000000007fe 3fdffff7ff7fffff bdf03ffbefbf07fd
|
||||||
|
b11000007ffffe00 3fe0000000000000 b10000007ffffe00
|
||||||
|
b80cef50bd17db40 c05fffc00000000e 387cef16de76611d
|
||||||
|
3d4000ffffffffff 3d47f68d8eb6b9a4 3a97f80cf78fa50e
|
||||||
|
ffe3fffffffffffb c03dc3321aaa5380 7ff0000000000000
|
||||||
|
3ca3fffffffffeff bf02ffafb4e9241d bbb7bf9ba2236bf3
|
||||||
|
53598c812c3c39dd 3f20000100fffffe 52898c82c69d14b0
|
||||||
|
c3dffffff8000001 3fe0020000003ffe c3d001fffbffbfff
|
||||||
|
7ba00800003fffff 3ff9a9a129c791b3 7ba9b675fac31bff
|
||||||
|
c3d0000fffffffef 7fe0000000000001 fff0000000000000
|
||||||
|
c34f80001fffffff b7fffffe0007ffff 3b5f7ffe2807ddfe
|
||||||
|
0010000000001ff8 4800020000010000 0820020000011ffc
|
||||||
|
2c4c0000003fffff 230ffffc00400000 0f6bfffc8077fff7
|
||||||
|
381fffffffbff7fe 8010000000000000 8000000000000000
|
||||||
|
802d3018ea8c241d c007fdffffffffff 0045e23fae5a7253
|
||||||
|
43e047fffffffffe 4000003ffdfffffe 43f048411df6fffc
|
||||||
|
c000005fffffffff 403ffffffff00002 c050005ffff7ffd0
|
||||||
|
3fc8b60e46a80f6d bfdffffffffffffe bfb8b60e46a80f6b
|
||||||
|
bd5fdffdffffffff 5644b72ace1bbb6b d3b4a27257daf2cd
|
||||||
|
b80010001fffffff 40e01ffffff7fffe b8f030202037f7fd
|
||||||
|
407000003ffbfffe 38042862fe8e3368 388428634f2ab547
|
||||||
|
bf8ffbfff7ffffff c00fffffffffffff 3faffbfff7fffffe
|
||||||
|
bcafc000003fffff c010000000000001 3ccfc00000400001
|
||||||
|
47eddf042473ef08 b7e00000fe000000 bfdddf05fea850cb
|
||||||
|
3fbfffff7fffffef c340ffffffffffbf c310ffffbbffffb6
|
||||||
|
c02f8000000007ff ffe0000000000001 7ff0000000000000
|
||||||
|
002f37ebf6c8eaec c08be464f4c81c69 80cb36000706e169
|
||||||
|
c00e800000000000 7ffc000000000000 7ffc000000000000
|
||||||
|
0010000000000000 0000000000000000 0000000000000000
|
||||||
|
bfffc00000000003 391001ffffffffff b91fc3f800000001
|
||||||
|
c1db54446247aa52 bfcc001fffffffff 41b7e9d72a43174f
|
||||||
|
0010000000000000 c0392c59c8e48f37 80592c59c8e48f37
|
||||||
|
0010000000000000 c0000800000001ff 80200800000001ff
|
||||||
|
0010000000000000 c1d0000004000fff 81f0000004000fff
|
||||||
|
4030040000200000 0017055f48beeff5 00570b20a0bf2a70
|
||||||
|
bc7000000000ffee c1e0001100000000 3e6000110000ffef
|
||||||
|
c040000000007fff c3b2a6c91c557f56 4402a6c91c56148b
|
||||||
|
41ffffffff003fff c3b0000007ffffee c5c0000007801fed
|
||||||
|
21900001dfffffff bf20000017fffffe a0c00001f80002cd
|
||||||
|
0029954d0f0df5b3 41e00000000003ff 0219954d0f0dfc17
|
||||||
|
b810000020000001 47ffdfffffffff80 c01fe0003fbfff82
|
||||||
|
0010000000000000 ffeffff800007fff c00ffff800007fff
|
||||||
|
0010000000000000 4010000000000000 0030000000000000
|
||||||
|
bf700000000100ff 401fffffffffffff bfa00000000100fe
|
||||||
|
37feffffffffffff 47ef8000000fffff 3ffe8400000f7ffe
|
||||||
|
b80f800001fffffe 44e00000ffff7fff bcff8001f9ff041c
|
||||||
|
0010000000000000 434ffffffffffffe 036ffffffffffffe
|
||||||
|
41ffffdfffff8000 7fe0000000000001 7ff0000000000000
|
||||||
|
b80a16ad02c87cd3 380fffffffffe7fe b02a16ad02c86940
|
||||||
|
47f0fffffffffffb 7ffc000000000000 7ffc000000000000
|
||||||
|
0010000000000000 41ffffffffbfff7f 021fffffffbfff7f
|
||||||
|
0010000000000000 8000000000000000 8000000000000000
|
||||||
|
c3d00001000001ff b7f60cb3edb38762 3bd60cb54e7ec8fd
|
||||||
|
0010000000000000 8010000000000001 8000000000000000
|
||||||
|
43c0007fffdfffff 801ffffffffffffe 83f0007fffdffffe
|
||||||
|
c7efffffdffffbff bca0000000000001 449fffffdffffc01
|
||||||
|
0010000000000000 c11ff00000000003 813ff00000000003
|
||||||
|
0010000000000000 bfd0000000000000 8000000000000000
|
||||||
|
c0ffffffffeffffe bfdfffffffffffff 40efffffffeffffd
|
||||||
|
6f7000000001fdff 1510010000000fff 4490010000020e1e
|
||||||
|
37f002000000000f b1effcfffffffffe a9f0007fd000000e
|
||||||
|
cc3050bc013d7cd7 bff0000000000000 4c3050bc013d7cd7
|
||||||
|
0010000000000000 87fff0000000fffe 8000000000000000
|
||||||
|
0010000000000000 bffffffffffffffe 801ffffffffffffe
|
||||||
|
43effbfffffff7ff 7fefffffff801ffe 7ff0000000000000
|
||||||
|
c015834380f2b995 3f9fff0000000400 bfc5829766d6b4b0
|
||||||
|
0010000000000000 41dfffffc0001000 01ffffffc0001000
|
||||||
|
0010000000000000 c01fffffffffffff 803fffffffffffff
|
||||||
|
41e010000000001f c5b04000000fffff c7a050400010101e
|
||||||
|
3b40018000000000 3ea0400000000100 39f0418600000100
|
||||||
|
0010000000000000 4cdffeffff7fffff 0cfffeffff7fffff
|
||||||
|
16dff0001ffffffe 3fb500ae0796659d 16a4f62dc5934870
|
||||||
|
b7e003ffffffff7f deafffffeffffffd 56a003fff7fdff7d
|
||||||
|
406000001fffbfff 3f20020000080000 3f900200200bbff7
|
||||||
|
0010000000000000 7ffc000000000000 7ffc000000000000
|
||||||
|
439fbffffffbffff bf8454fd38ef0ba0 c3342c533e7aa2e8
|
||||||
|
c1c000000200007e bf000001ffffffbf 40d000020200007d
|
||||||
|
480000000008fffe 001637e790e69de2 082637e790f31d51
|
||||||
|
bffffffc000003fe 3ca0000000000001 bcaffffc00000400
|
||||||
|
6b4848a9a8c0dcd5 480ffffffffbdfff 736848a9a8bdbb76
|
1
wally-pipelined/src/fpu/FMA/tbgen/results.dat
Normal file
1
wally-pipelined/src/fpu/FMA/tbgen/results.dat
Normal file
@ -0,0 +1 @@
|
|||||||
|
0020000803ffffff bfcb4181a9468e24 000fffffffffffff 7fe2f9c2bca0f33c 00092f9c2bca0f33 Wrong zdenorm 18
|
BIN
wally-pipelined/src/fpu/FMA/tbgen/tb
Executable file
BIN
wally-pipelined/src/fpu/FMA/tbgen/tb
Executable file
Binary file not shown.
116
wally-pipelined/src/fpu/FMA/tbgen/tb.c
Normal file
116
wally-pipelined/src/fpu/FMA/tbgen/tb.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
FILE *fp, *fq, *fr;
|
||||||
|
int cnt=0;
|
||||||
|
char *ln;
|
||||||
|
size_t nbytes = 80;
|
||||||
|
|
||||||
|
ln = (char *)malloc(nbytes + 1);
|
||||||
|
|
||||||
|
// fp = fopen("tb.dat","r");
|
||||||
|
fp = fopen("testFloat","r");
|
||||||
|
fq = fopen("tb.v","a");
|
||||||
|
system("cp tbhead.v tb.v");
|
||||||
|
int k=0;
|
||||||
|
for(k=0; k<91 && !feof(fp); k++) {
|
||||||
|
//3FDBFFFFFFFFFF7F DE608000000001FF 43CFED83C17EDBD0 DE4CE000000002F9 01
|
||||||
|
// b68ffff8000000ff_3f9080000007ffff_b6307ffbe0080080_00001
|
||||||
|
char ch;
|
||||||
|
int i,j;
|
||||||
|
char *ln;
|
||||||
|
char xrf[17];
|
||||||
|
char y[17];
|
||||||
|
char zrf[17];
|
||||||
|
char ans[81];
|
||||||
|
char flags[3];
|
||||||
|
int rn,rz,rm,rp;
|
||||||
|
{
|
||||||
|
//my_string = (char *) malloc (nbytes + 1);
|
||||||
|
//bytes_read = getline (&my_string, &nbytes, stdin);
|
||||||
|
if(getline(&ln,&nbytes,fp) < 0) break;
|
||||||
|
//fprintf(stderr,"%s\n", ln);
|
||||||
|
|
||||||
|
strncpy(xrf, ln, 16); xrf[16]=0;
|
||||||
|
strncpy(y, &ln[17], 16); y[16]=0;
|
||||||
|
strncpy(zrf, &ln[34], 16); zrf[16]=0;
|
||||||
|
// fprintf(stdout,"[%s]\n[%s]\n", ln,zrf);
|
||||||
|
strncpy(ans, &ln[51], 16); ans[16]=0;
|
||||||
|
strncpy(flags,&ln[68],2); flags[2]=0;
|
||||||
|
|
||||||
|
// fprintf(stdout,"[%s]\n[%s]\n", ln,zrf);
|
||||||
|
fprintf(fq," xrf = 64'h%s;\n",xrf);
|
||||||
|
fprintf(fq," y = 64'h%s;\n",y);
|
||||||
|
fprintf(fq," zrf = 64'h%s;\n",zrf);
|
||||||
|
fprintf(fq," ans = 64'h%s;\n", ans);
|
||||||
|
// fprintf(fq," flags = 5'h%s;\n", flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//rn=1; rz=0; rm=0; rp=0;
|
||||||
|
fprintf(fq," rn = %d;\n",1);
|
||||||
|
fprintf(fq," rz = %d;\n", 0);
|
||||||
|
fprintf(fq," rm = %d;\n", 0);
|
||||||
|
fprintf(fq," rp = %d;\n", 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
fprintf(fq," earlyres = 64'b0;\n");
|
||||||
|
fprintf(fq," earlyressel = 0;\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
fprintf(fq," bypsel= 2'b0;\n"); //, bysel);
|
||||||
|
fprintf(fq," bypplus1 = 0;\n"); //, byp1);
|
||||||
|
fprintf(fq," byppostnorm = 0;\n"); //, bypnorm);
|
||||||
|
}
|
||||||
|
fprintf(fq,"#10\n");
|
||||||
|
// IEEE 754-2008 section 6.3 states "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
|
||||||
|
//fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h \",xrf,y,w, ans);\n");
|
||||||
|
fprintf(fq," // IEEE 754-2008 section 6.3 states: \"When ether an input or result is NaN, this\n");
|
||||||
|
fprintf(fq," // standard does not interpret the sign of a NaN.\"\n");
|
||||||
|
fprintf(fq," nan = (w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000) ||\n");
|
||||||
|
fprintf(fq," (w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) ||\n");
|
||||||
|
fprintf(fq," (w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) ||\n");
|
||||||
|
fprintf(fq," (w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff );\n");
|
||||||
|
// fprintf(fq," if(!(~(|xrf[62:52]) && |xrf[51:0] || ~(|y[62:52]) && |y[51:0])) begin\n");
|
||||||
|
// not looknig at negative zero results right now
|
||||||
|
//fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) && !(w == 64'h8000000000000000 && ans == 64'b0)) begin\n");
|
||||||
|
fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) ) begin\n");
|
||||||
|
fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h %%h Wrong \",xrf,y, zrf, w, ans);\n");
|
||||||
|
fprintf(fq," if(w == 64'h8000000000000000) $fwrite(fp, \"w=-zero \");\n");
|
||||||
|
fprintf(fq," if(~(|xrf[62:52]) && |xrf[51:0]) $fwrite(fp, \"xdenorm \");\n");
|
||||||
|
fprintf(fq," if(~(|y[62:52]) && |y[51:0]) $fwrite(fp, \"ydenorm \");\n");
|
||||||
|
fprintf(fq," if(~(|zrf[62:52]) && |zrf[51:0]) $fwrite(fp, \"zdenorm \");\n");
|
||||||
|
fprintf(fq," if(invalid != 0) $fwrite(fp, \"invld \");\n");
|
||||||
|
fprintf(fq," if(overflow != 0) $fwrite(fp, \"ovrflw \");\n");
|
||||||
|
fprintf(fq," if(underflow != 0) $fwrite(fp, \"unflw \");\n");
|
||||||
|
fprintf(fq," if(w == 64'hFFF0000000000000) $fwrite(fp, \"w=-inf \");\n");
|
||||||
|
fprintf(fq," if(w == 64'h7FF0000000000000) $fwrite(fp, \"w=+inf \");\n");
|
||||||
|
fprintf(fq," if(w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
|
||||||
|
fprintf(fq," if(w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
|
||||||
|
fprintf(fq," if(w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
|
||||||
|
fprintf(fq," if(w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
|
||||||
|
|
||||||
|
fprintf(fq," if(ans == 64'hFFF0000000000000) $fwrite(fp, \"ans=-inf \");\n");
|
||||||
|
fprintf(fq," if(ans == 64'h7FF0000000000000) $fwrite(fp, \"ans=+inf \");\n");
|
||||||
|
fprintf(fq," if(ans > 64'h7FF0000000000000 && ans < 64'h7FF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
|
||||||
|
fprintf(fq," if(ans > 64'hFFF8000000000000 && ans < 64'hFFF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
|
||||||
|
fprintf(fq," if(ans >= 64'h7FF8000000000000 && ans <= 64'h7FFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
|
||||||
|
fprintf(fq," if(ans >= 64'hFFF8000000000000 && ans <= 64'hFFFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
|
||||||
|
fprintf(fq," $fwrite(fp,\"%d\\n\");\n",cnt);
|
||||||
|
if(cnt == 358)fprintf(fq," $stop;\n");
|
||||||
|
// fprintf(fq," end\n");
|
||||||
|
fprintf(fq," end\n");
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
//if(cnt > 100) break;
|
||||||
|
fflush(fq);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fq, "\t$stop;\n\tend\nendmodule");
|
||||||
|
fclose(fq);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
3952
wally-pipelined/src/fpu/FMA/tbgen/tb.v
Normal file
3952
wally-pipelined/src/fpu/FMA/tbgen/tb.v
Normal file
File diff suppressed because it is too large
Load Diff
BIN
wally-pipelined/src/fpu/FMA/tbgen/tbgen
Executable file
BIN
wally-pipelined/src/fpu/FMA/tbgen/tbgen
Executable file
Binary file not shown.
36
wally-pipelined/src/fpu/FMA/tbgen/tbhead.v
Normal file
36
wally-pipelined/src/fpu/FMA/tbgen/tbhead.v
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
`timescale 1 ns/10 ps
|
||||||
|
module tb;
|
||||||
|
|
||||||
|
|
||||||
|
reg [63:0] xrf;
|
||||||
|
reg [63:0] y;
|
||||||
|
reg [63:0] zrf;
|
||||||
|
reg [63:0] ans;
|
||||||
|
reg rn;
|
||||||
|
reg rz;
|
||||||
|
reg rm;
|
||||||
|
reg rp;
|
||||||
|
reg [63:0] earlyres;
|
||||||
|
reg earlyressel;
|
||||||
|
reg [1:0] bypsel;
|
||||||
|
reg bypplus1;
|
||||||
|
reg byppostnorm;
|
||||||
|
wire [63:0] w;
|
||||||
|
wire [63:0] wbypass;
|
||||||
|
wire invalid;
|
||||||
|
wire overflow;
|
||||||
|
wire underflow;
|
||||||
|
wire inexact;
|
||||||
|
|
||||||
|
integer fp;
|
||||||
|
reg nan;
|
||||||
|
|
||||||
|
localparam period = 20;
|
||||||
|
fmac UUT(.xrf(xrf), .y(y), .zrf(zrf), .rn(rn), .rz(rz), .rp(rp), .rm(rm),
|
||||||
|
.earlyres(earlyres), .earlyressel(earlyressel), .bypsel(bypsel), .bypplus1(bypplus1), .byppostnorm(byppostnorm),
|
||||||
|
.w(w), .wbypass(wbypass), .invalid(invalid), .overflow(overflow), .underflow(underflow), .inexact(inexact));
|
||||||
|
|
||||||
|
|
||||||
|
initial
|
||||||
|
begin
|
||||||
|
fp = $fopen("/home/kparry/code/FMAC/tbgen/results.dat","w");
|
1000
wally-pipelined/src/fpu/FMA/tbgen/testMini
Normal file
1000
wally-pipelined/src/fpu/FMA/tbgen/testMini
Normal file
File diff suppressed because it is too large
Load Diff
1
wally-pipelined/src/fpu/FMA/tbgen/test_gen.sh
Executable file
1
wally-pipelined/src/fpu/FMA/tbgen/test_gen.sh
Executable file
@ -0,0 +1 @@
|
|||||||
|
testfloat_gen f64_mulAdd -n 6133248 -rnear_even -seed 113355 -level 1 >> testFloat
|
1
wally-pipelined/src/fpu/FMA/tbgen/tstFlMult.awk
Executable file
1
wally-pipelined/src/fpu/FMA/tbgen/tstFlMult.awk
Executable file
@ -0,0 +1 @@
|
|||||||
|
awk 'BEGIN {FS = " "; OFS = "_"} {if ($3 == "0000000000000000") print $1, $2, $4;}' testFloat | head -n 1000 > testMini
|
@ -340,7 +340,7 @@ module freg3adr (
|
|||||||
generate
|
generate
|
||||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
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]));
|
floprc #(`XLEN) reg[i](.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||||
end
|
end
|
||||||
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
29
wally-pipelined/src/fpu/dev/fcsr.sv
Normal file
29
wally-pipelined/src/fpu/dev/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) fcsrreg(.clk(clk), .reset(reset), .clear(clear), .d(regInput), .q(regOutput));
|
||||||
|
|
||||||
|
assign readData = regOutput;
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
143
wally-pipelined/src/fpu/dev/fctrl.sv
Normal file
143
wally-pipelined/src/fpu/dev/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
|
59
wally-pipelined/src/fpu/dev/fputop.sv
Normal file
59
wally-pipelined/src/fpu/dev/fputop.sv
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
`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
|
||||||
|
//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
|
||||||
|
|
||||||
|
//result mux
|
||||||
|
*/
|
||||||
|
endmodule
|
513
wally-pipelined/src/fpu/dev/freg.sv
Normal file
513
wally-pipelined/src/fpu/dev/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) freg[i](.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) freg[i](.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) freg[i](.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
|
@ -47,6 +47,16 @@ module flopr #(parameter WIDTH = 8) (
|
|||||||
else q <= #1 d;
|
else q <= #1 d;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// flop with enable
|
||||||
|
module flopen #(parameter WIDTH = 8) (
|
||||||
|
input logic clk, en,
|
||||||
|
input logic [WIDTH-1:0] d,
|
||||||
|
output logic [WIDTH-1:0] q);
|
||||||
|
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
if (en) q <= #1 d;
|
||||||
|
endmodule
|
||||||
|
|
||||||
// flop with enable, asynchronous reset, synchronous clear
|
// flop with enable, asynchronous reset, synchronous clear
|
||||||
module flopenrc #(parameter WIDTH = 8) (
|
module flopenrc #(parameter WIDTH = 8) (
|
||||||
input logic clk, reset, clear, en,
|
input logic clk, reset, clear, en,
|
||||||
|
@ -27,19 +27,18 @@
|
|||||||
|
|
||||||
module hazard(
|
module hazard(
|
||||||
// Detect hazards
|
// Detect hazards
|
||||||
// input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
|
|
||||||
// input logic MemReadE,
|
|
||||||
// input logic RegWriteM, RegWriteW,
|
|
||||||
input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM,
|
input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM,
|
||||||
input logic LoadStallD, MulDivStallD,
|
input logic LoadStallD, MulDivStallD,
|
||||||
input logic InstrStall, DataStall,
|
input logic InstrStall, DataStall,
|
||||||
// Stall outputs
|
// Stall & flush outputs
|
||||||
output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW
|
output logic StallF, StallD, StallE, StallM, StallW,
|
||||||
|
output logic FlushD, FlushE, FlushM, FlushW
|
||||||
);
|
);
|
||||||
|
|
||||||
logic BranchFlushDE;
|
logic BranchFlushDE;
|
||||||
logic StallDCause, StallFCause, StallWCause;
|
logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause;
|
||||||
|
logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW;
|
||||||
|
|
||||||
// stalls and flushes
|
// stalls and flushes
|
||||||
// loads: stall for one cycle if the subsequent instruction depends on the load
|
// loads: stall for one cycle if the subsequent instruction depends on the load
|
||||||
// branches and jumps: flush the next two instructions if the branch is taken in EXE
|
// branches and jumps: flush the next two instructions if the branch is taken in EXE
|
||||||
@ -54,14 +53,27 @@ module hazard(
|
|||||||
|
|
||||||
assign BranchFlushDE = PCSrcE | RetM | TrapM;
|
assign BranchFlushDE = PCSrcE | RetM | TrapM;
|
||||||
|
|
||||||
assign StallDCause = LoadStallD | MulDivStallD;
|
assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE);
|
||||||
assign StallFCause = InstrStall | CSRWritePendingDEM;
|
assign StallDCause = LoadStallD | MulDivStallD; // stall in decode if instruction is a load/mul dependent on previous
|
||||||
assign StallWCause = DataStall; // *** not yet used
|
assign StallECause = 0;
|
||||||
|
assign StallMCause = 0;
|
||||||
|
assign StallWCause = DataStall | InstrStall;
|
||||||
|
|
||||||
assign StallD = StallDCause;
|
// Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
|
||||||
assign StallF = StallD | StallFCause;
|
assign StallF = StallD | StallFCause;
|
||||||
assign FlushD = BranchFlushDE | StallFCause; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
|
assign StallD = StallE | StallDCause;
|
||||||
assign FlushE = StallD | BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
|
assign StallE = StallM | StallECause;
|
||||||
assign FlushM = RetM | TrapM;
|
assign StallM = StallW | StallMCause;
|
||||||
assign FlushW = TrapM;
|
assign StallW = StallWCause;
|
||||||
|
|
||||||
|
assign FirstUnstalledD = (~StallD & StallF);
|
||||||
|
assign FirstUnstalledE = (~StallE & StallD);
|
||||||
|
assign FirstUnstalledM = (~StallM & StallE);
|
||||||
|
assign FirstUnstalledW = (~StallW & StallM);;
|
||||||
|
|
||||||
|
// Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush
|
||||||
|
assign FlushD = FirstUnstalledD || BranchFlushDE; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
|
||||||
|
assign FlushE = FirstUnstalledE || BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
|
||||||
|
assign FlushM = FirstUnstalledM || RetM || TrapM;
|
||||||
|
assign FlushW = FirstUnstalledW | TrapM;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -33,12 +33,11 @@ module controller(
|
|||||||
input logic [2:0] Funct3D,
|
input logic [2:0] Funct3D,
|
||||||
input logic [6:0] Funct7D,
|
input logic [6:0] Funct7D,
|
||||||
output logic [2:0] ImmSrcD,
|
output logic [2:0] ImmSrcD,
|
||||||
input logic StallD, FlushD,
|
|
||||||
input logic IllegalIEUInstrFaultD,
|
input logic IllegalIEUInstrFaultD,
|
||||||
output logic IllegalBaseInstrFaultD,
|
output logic IllegalBaseInstrFaultD,
|
||||||
// Execute stage control signals
|
// Execute stage control signals
|
||||||
input logic FlushE,
|
input logic StallE, FlushE,
|
||||||
input logic [2:0] FlagsE,
|
input logic [2:0] FlagsE,
|
||||||
output logic PCSrcE, // for datapath and Hazard Unit
|
output logic PCSrcE, // for datapath and Hazard Unit
|
||||||
output logic [4:0] ALUControlE,
|
output logic [4:0] ALUControlE,
|
||||||
output logic ALUSrcAE, ALUSrcBE,
|
output logic ALUSrcAE, ALUSrcBE,
|
||||||
@ -47,14 +46,13 @@ module controller(
|
|||||||
output logic [2:0] Funct3E,
|
output logic [2:0] Funct3E,
|
||||||
output logic MulDivE, W64E,
|
output logic MulDivE, W64E,
|
||||||
// Memory stage control signals
|
// Memory stage control signals
|
||||||
input logic FlushM,
|
input logic StallM, FlushM,
|
||||||
input logic DataMisalignedM,
|
|
||||||
output logic [1:0] MemRWM,
|
output logic [1:0] MemRWM,
|
||||||
output logic CSRWriteM, PrivilegedM,
|
output logic CSRWriteM, PrivilegedM,
|
||||||
output logic [2:0] Funct3M,
|
output logic [2:0] Funct3M,
|
||||||
output logic RegWriteM, // for Hazard Unit
|
output logic RegWriteM, // for Hazard Unit
|
||||||
// Writeback stage control signals
|
// Writeback stage control signals
|
||||||
input logic FlushW,
|
input logic StallW, FlushW,
|
||||||
output logic RegWriteW, // for datapath and Hazard Unit
|
output logic RegWriteW, // for datapath and Hazard Unit
|
||||||
output logic [2:0] ResultSrcW,
|
output logic [2:0] ResultSrcW,
|
||||||
output logic InstrValidW,
|
output logic InstrValidW,
|
||||||
@ -94,10 +92,14 @@ module controller(
|
|||||||
7'b0100011: ControlsD = 21'b0_001_01_01_000_0_00_0_0_0_0_0_0_0; // sw
|
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)
|
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
|
ControlsD = 21'b1_000_00_00_000_0_10_0_0_0_0_0_0_0; // R-type
|
||||||
|
else if (Funct7D == 7'b0000001 && `M_SUPPORTED)
|
||||||
|
ControlsD = 21'b1_000_00_00_100_0_00_0_0_0_0_0_1_0; // Multiply/Divide
|
||||||
else
|
else
|
||||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
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)
|
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
|
ControlsD = 21'b1_000_00_00_000_0_10_0_0_1_0_0_0_0; // R-type W instructions for RV64i
|
||||||
|
else if (Funct7D == 7'b0000001 && `M_SUPPORTED && `XLEN == 64)
|
||||||
|
ControlsD = 21'b1_000_00_00_100_0_00_0_0_1_0_0_1_0; // W-type Multiply/Divide
|
||||||
else
|
else
|
||||||
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
|
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'b1100011: ControlsD = 21'b0_010_00_00_000_1_01_0_0_0_0_0_0_0; // beq
|
||||||
@ -145,7 +147,7 @@ module controller(
|
|||||||
endcase
|
endcase
|
||||||
|
|
||||||
// Execute stage pipeline control register and logic
|
// Execute stage pipeline control register and logic
|
||||||
floprc #(24) controlregE(clk, reset, FlushE,
|
flopenrc #(24) controlregE(clk, reset, FlushE, ~StallE,
|
||||||
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, 1'b1},
|
{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});
|
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, InstrValidE});
|
||||||
|
|
||||||
@ -168,12 +170,12 @@ module controller(
|
|||||||
assign MemReadE = MemRWE[1];
|
assign MemReadE = MemRWE[1];
|
||||||
|
|
||||||
// Memory stage pipeline control register
|
// Memory stage pipeline control register
|
||||||
floprc #(12) controlregM(clk, reset, FlushM,
|
flopenrc #(12) controlregM(clk, reset, FlushM, ~StallM,
|
||||||
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE},
|
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE},
|
||||||
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM});
|
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM});
|
||||||
|
|
||||||
// Writeback stage pipeline control register
|
// Writeback stage pipeline control register
|
||||||
floprc #(5) controlregW(clk, reset, FlushW,
|
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,
|
||||||
{RegWriteM, ResultSrcM, InstrValidM},
|
{RegWriteM, ResultSrcM, InstrValidM},
|
||||||
{RegWriteW, ResultSrcW, InstrValidW});
|
{RegWriteW, ResultSrcW, InstrValidW});
|
||||||
|
|
||||||
|
@ -28,13 +28,11 @@
|
|||||||
module datapath (
|
module datapath (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
input logic StallD, FlushD,
|
|
||||||
input logic [2:0] ImmSrcD,
|
input logic [2:0] ImmSrcD,
|
||||||
input logic [31:0] InstrD,
|
input logic [31:0] InstrD,
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
input logic FlushE,
|
input logic StallE, FlushE,
|
||||||
input logic [1:0] ForwardAE, ForwardBE,
|
input logic [1:0] ForwardAE, ForwardBE,
|
||||||
input logic PCSrcE,
|
|
||||||
input logic [4:0] ALUControlE,
|
input logic [4:0] ALUControlE,
|
||||||
input logic ALUSrcAE, ALUSrcBE,
|
input logic ALUSrcAE, ALUSrcBE,
|
||||||
input logic TargetSrcE,
|
input logic TargetSrcE,
|
||||||
@ -43,13 +41,11 @@ module datapath (
|
|||||||
output logic [`XLEN-1:0] PCTargetE,
|
output logic [`XLEN-1:0] PCTargetE,
|
||||||
output logic [`XLEN-1:0] SrcAE, SrcBE,
|
output logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic FlushM,
|
input logic StallM, FlushM,
|
||||||
input logic [2:0] Funct3M,
|
|
||||||
input logic RetM, TrapM,
|
|
||||||
output logic [`XLEN-1:0] SrcAM,
|
output logic [`XLEN-1:0] SrcAM,
|
||||||
output logic [`XLEN-1:0] WriteDataM, MemAdrM,
|
output logic [`XLEN-1:0] WriteDataM, MemAdrM,
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic FlushW,
|
input logic StallW, FlushW,
|
||||||
input logic RegWriteW,
|
input logic RegWriteW,
|
||||||
input logic [2:0] ResultSrcW,
|
input logic [2:0] ResultSrcW,
|
||||||
input logic [`XLEN-1:0] PCLinkW,
|
input logic [`XLEN-1:0] PCLinkW,
|
||||||
@ -85,12 +81,12 @@ module datapath (
|
|||||||
extend ext(.InstrD(InstrD[31:7]), .*);
|
extend ext(.InstrD(InstrD[31:7]), .*);
|
||||||
|
|
||||||
// Execute stage pipeline register and logic
|
// Execute stage pipeline register and logic
|
||||||
floprc #(`XLEN) RD1EReg(clk, reset, FlushE, RD1D, RD1E);
|
flopenrc #(`XLEN) RD1EReg(clk, reset, FlushE, ~StallE, RD1D, RD1E);
|
||||||
floprc #(`XLEN) RD2EReg(clk, reset, FlushE, RD2D, RD2E);
|
flopenrc #(`XLEN) RD2EReg(clk, reset, FlushE, ~StallE, RD2D, RD2E);
|
||||||
floprc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ExtImmD, ExtImmE);
|
flopenrc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ~StallE, ExtImmD, ExtImmE);
|
||||||
floprc #(5) Rs1EReg(clk, reset, FlushE, Rs1D, Rs1E);
|
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||||
floprc #(5) Rs2EReg(clk, reset, FlushE, Rs2D, Rs2E);
|
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||||
floprc #(5) RdEReg(clk, reset, FlushE, RdD, RdE);
|
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||||
|
|
||||||
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
|
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
|
||||||
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
|
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
|
||||||
@ -101,15 +97,15 @@ module datapath (
|
|||||||
assign PCTargetE = ExtImmE + TargetBaseE;
|
assign PCTargetE = ExtImmE + TargetBaseE;
|
||||||
|
|
||||||
// Memory stage pipeline register
|
// Memory stage pipeline register
|
||||||
floprc #(`XLEN) SrcAMReg(clk, reset, FlushM, SrcAE, SrcAM);
|
flopenrc #(`XLEN) SrcAMReg(clk, reset, FlushM, ~StallM, SrcAE, SrcAM);
|
||||||
floprc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ALUResultE, ALUResultM);
|
flopenrc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ~StallM, ALUResultE, ALUResultM);
|
||||||
assign MemAdrM = ALUResultM;
|
assign MemAdrM = ALUResultM;
|
||||||
floprc #(`XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataM);
|
flopenrc #(`XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, WriteDataE, WriteDataM);
|
||||||
floprc #(5) RdMEg(clk, reset, FlushM, RdE, RdM);
|
flopenrc #(5) RdMEg(clk, reset, FlushM, ~StallM, RdE, RdM);
|
||||||
|
|
||||||
// Writeback stage pipeline register and logic
|
// Writeback stage pipeline register and logic
|
||||||
floprc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW);
|
flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
|
||||||
floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW);
|
flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW);
|
||||||
|
|
||||||
mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW);
|
mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW);
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -30,7 +30,7 @@ module forward(
|
|||||||
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
|
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
|
||||||
input logic MemReadE, MulDivE,
|
input logic MemReadE, MulDivE,
|
||||||
input logic RegWriteM, RegWriteW,
|
input logic RegWriteM, RegWriteW,
|
||||||
// Forwaring controls
|
// Forwarding controls
|
||||||
output logic [1:0] ForwardAE, ForwardBE,
|
output logic [1:0] ForwardAE, ForwardBE,
|
||||||
output logic LoadStallD, MulDivStallD
|
output logic LoadStallD, MulDivStallD
|
||||||
);
|
);
|
||||||
|
@ -49,8 +49,8 @@ module ieu (
|
|||||||
input logic [`XLEN-1:0] PCLinkW,
|
input logic [`XLEN-1:0] PCLinkW,
|
||||||
output logic InstrValidW,
|
output logic InstrValidW,
|
||||||
// hazards
|
// hazards
|
||||||
input logic StallD, FlushD, FlushE, FlushM, FlushW,
|
input logic StallE, StallM, StallW,
|
||||||
input logic RetM, TrapM,
|
input logic FlushE, FlushM, FlushW,
|
||||||
output logic LoadStallD, MulDivStallD,
|
output logic LoadStallD, MulDivStallD,
|
||||||
output logic PCSrcE,
|
output logic PCSrcE,
|
||||||
|
|
||||||
|
@ -28,13 +28,14 @@
|
|||||||
|
|
||||||
module ifu (
|
module ifu (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallF, StallD, FlushD, FlushE, FlushM, FlushW,
|
input logic StallF, StallD, StallE, StallM, StallW,
|
||||||
|
input logic FlushD, FlushE, FlushM, FlushW,
|
||||||
// Fetch
|
// Fetch
|
||||||
input logic [31:0] InstrF,
|
input logic [`XLEN-1:0] InstrInF,
|
||||||
output logic [`XLEN-1:0] PCF,
|
output logic [`XLEN-1:0] PCF,
|
||||||
output logic [`XLEN-1:0] InstrPAdrF,
|
output logic [`XLEN-1:0] InstrPAdrF,
|
||||||
|
output logic InstrReadF,
|
||||||
// Decode
|
// Decode
|
||||||
output logic InstrStall,
|
|
||||||
// Execute
|
// Execute
|
||||||
input logic PCSrcE,
|
input logic PCSrcE,
|
||||||
input logic [`XLEN-1:0] PCTargetE,
|
input logic [`XLEN-1:0] PCTargetE,
|
||||||
@ -50,29 +51,31 @@ module ifu (
|
|||||||
input logic IllegalBaseInstrFaultD,
|
input logic IllegalBaseInstrFaultD,
|
||||||
output logic IllegalIEUInstrFaultD,
|
output logic IllegalIEUInstrFaultD,
|
||||||
output logic InstrMisalignedFaultM,
|
output logic InstrMisalignedFaultM,
|
||||||
output logic [`XLEN-1:0] InstrMisalignedAdrM
|
output logic [`XLEN-1:0] InstrMisalignedAdrM,
|
||||||
|
// bogus
|
||||||
|
input logic [15:0] rd2
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
|
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
|
||||||
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
|
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
|
||||||
logic StallExceptResolveBranchesF, PrivilegedChangePCM;
|
logic PrivilegedChangePCM;
|
||||||
logic IllegalCompInstrD;
|
logic IllegalCompInstrD;
|
||||||
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM;
|
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM;
|
||||||
logic CompressedF;
|
logic CompressedF;
|
||||||
logic [31:0] InstrRawD, InstrE;
|
logic [31:0] InstrF, InstrRawD, InstrE, InstrW;
|
||||||
logic [31:0] nop = 32'h00000013; // instruction for NOP
|
logic [31:0] nop = 32'h00000013; // instruction for NOP
|
||||||
|
|
||||||
// *** put memory interface on here, InstrF becomes output
|
// *** put memory interface on here, InstrF becomes output
|
||||||
assign InstrStall = 0; // ***
|
|
||||||
assign InstrPAdrF = PCF; // *** no MMU
|
assign InstrPAdrF = PCF; // *** no MMU
|
||||||
|
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
|
||||||
|
assign InstrReadF = 1; // *** & ICacheMissF; add later
|
||||||
|
|
||||||
assign PrivilegedChangePCM = RetM | TrapM;
|
assign PrivilegedChangePCM = RetM | TrapM;
|
||||||
|
|
||||||
assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
|
|
||||||
|
|
||||||
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
|
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
|
||||||
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
|
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
|
||||||
flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF);
|
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
|
||||||
|
|
||||||
// pcadder
|
// pcadder
|
||||||
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
|
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
|
||||||
@ -86,6 +89,15 @@ module ifu (
|
|||||||
else PCPlus2or4F = {PCF[`XLEN-1:2], 2'b10};
|
else PCPlus2or4F = {PCF[`XLEN-1:2], 2'b10};
|
||||||
else PCPlus2or4F = {PCPlusUpperF, PCF[1:0]}; // add 4
|
else PCPlus2or4F = {PCPlusUpperF, PCF[1:0]}; // add 4
|
||||||
|
|
||||||
|
// harris 2/23/21 Add code to fetch instruction split across two words
|
||||||
|
generate
|
||||||
|
if (`XLEN==32) begin
|
||||||
|
assign InstrF = PCF[1] ? {rd2[15:0], InstrInF[31:16]} : InstrInF;
|
||||||
|
end else begin
|
||||||
|
assign InstrF = PCF[2] ? (PCF[1] ? {rd2[15:0], InstrInF[63:48]} : InstrInF[63:32])
|
||||||
|
: (PCF[1] ? InstrInF[47:16] : InstrInF[31:0]);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
// Decode stage pipeline register and logic
|
// Decode stage pipeline register and logic
|
||||||
flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrRawD);
|
flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrRawD);
|
||||||
@ -107,25 +119,26 @@ module ifu (
|
|||||||
|
|
||||||
// pipeline misaligned faults to M stage
|
// pipeline misaligned faults to M stage
|
||||||
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
|
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
|
||||||
flopr #(1) InstrMisalginedReg(clk, reset, BranchMisalignedFaultE, BranchMisalignedFaultM);
|
flopenr #(1) InstrMisalginedReg(clk, reset, ~StallM, BranchMisalignedFaultE, BranchMisalignedFaultM);
|
||||||
flopr #(`XLEN) InstrMisalignedAdrReg(clk, reset, PCNextF, InstrMisalignedAdrM);
|
flopenr #(`XLEN) InstrMisalignedAdrReg(clk, reset, ~StallM, PCNextF, InstrMisalignedAdrM);
|
||||||
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
|
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
|
||||||
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
|
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
|
||||||
|
|
||||||
flopr #(32) InstrEReg(clk, reset, FlushE ? nop : InstrD, InstrE);
|
flopenr #(32) InstrEReg(clk, reset, ~StallE, FlushE ? nop : InstrD, InstrE);
|
||||||
flopr #(32) InstrMReg(clk, reset, FlushM ? nop : InstrE, InstrM);
|
flopenr #(32) InstrMReg(clk, reset, ~StallM, FlushM ? nop : InstrE, InstrM);
|
||||||
flopr #(`XLEN) PCEReg(clk, reset, PCD, PCE);
|
flopenr #(32) InstrWReg(clk, reset, ~StallW, FlushW ? nop : InstrM, InstrW); // just for testbench, delete later
|
||||||
flopr #(`XLEN) PCMReg(clk, reset, PCE, PCM);
|
flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
||||||
flopr #(`XLEN) PCWReg(clk, reset, PCM, PCW); // *** probably not needed; delete later
|
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||||
|
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
|
||||||
|
|
||||||
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
|
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
|
||||||
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
|
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
|
||||||
// have dedicated adder in Mem stage based on PCM + 2 or 4
|
// have dedicated adder in Mem stage based on PCM + 2 or 4
|
||||||
// *** redo this
|
// *** redo this
|
||||||
flopr #(`XLEN) PCPDReg(clk, reset, PCPlus2or4F, PCLinkD);
|
flopenr #(`XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
||||||
flopr #(`XLEN) PCPEReg(clk, reset, PCLinkD, PCLinkE);
|
flopenr #(`XLEN) PCPEReg(clk, reset, ~StallE, PCLinkD, PCLinkE);
|
||||||
flopr #(`XLEN) PCPMReg(clk, reset, PCLinkE, PCLinkM);
|
flopenr #(`XLEN) PCPMReg(clk, reset, ~StallM, PCLinkE, PCLinkM);
|
||||||
flopr #(`XLEN) PCPWReg(clk, reset, PCLinkM, PCLinkW);
|
flopenr #(`XLEN) PCPWReg(clk, reset, ~StallW, PCLinkM, PCLinkW);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
77
wally-pipelined/src/muldiv/mul.sv
Normal file
77
wally-pipelined/src/muldiv/mul.sv
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// mul.sv
|
||||||
|
//
|
||||||
|
// Written: David_Harris@hmc.edu 16 February 2021
|
||||||
|
// Modified:
|
||||||
|
//
|
||||||
|
// Purpose: Multiply instructions
|
||||||
|
//
|
||||||
|
// 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 mul (
|
||||||
|
// Execute Stage interface
|
||||||
|
input logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||||
|
input logic [2:0] Funct3E,
|
||||||
|
output logic [`XLEN*2-1:0] ProdE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Number systems
|
||||||
|
// Let A' = sum(i=0, XLEN-2, A[i]*2^i)
|
||||||
|
// Unsigned: A = A' + A[XLEN-1]*2^(XLEN-1)
|
||||||
|
// Signed: A = A' - A[XLEN-1]*2^(XLEN-1)
|
||||||
|
|
||||||
|
// Multiplication: A*B
|
||||||
|
// Let P' = A' * B'
|
||||||
|
// PA = (A' * B[XLEN-1])
|
||||||
|
// PB = (B' * A[XLEN-1])
|
||||||
|
// PP = A[XLEN-1] * B[XLEN-1]
|
||||||
|
// Signed * Signed = P' + (-PA - PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
||||||
|
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
||||||
|
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
||||||
|
|
||||||
|
logic [`XLEN*2-1:0] PP1, PP2, PP3, PP4;
|
||||||
|
logic [`XLEN*2-1:0] Pprime;
|
||||||
|
logic [`XLEN-2:0] PA, PB;
|
||||||
|
logic PP;
|
||||||
|
logic MULH, MULHSU, MULHU;
|
||||||
|
|
||||||
|
// portions of product
|
||||||
|
assign Pprime = {1'b0, SrcAE[`XLEN-2:0]} * {1'b0, SrcBE[`XLEN-2:0]};
|
||||||
|
assign PA = {(`XLEN-1){SrcAE[`XLEN-1]}} & SrcBE[`XLEN-2:0];
|
||||||
|
assign PB = {(`XLEN-1){SrcBE[`XLEN-1]}} & SrcAE[`XLEN-2:0];
|
||||||
|
assign PP = SrcAE[`XLEN-1] & SrcBE[`XLEN-1];
|
||||||
|
|
||||||
|
// flavor of multiplication
|
||||||
|
assign MULH = (Funct3E == 2'b01);
|
||||||
|
assign MULHSU = (Funct3E == 2'b10);
|
||||||
|
// assign MULHU = (Funct3E == 2'b11); // signal unused
|
||||||
|
|
||||||
|
// Handle signs
|
||||||
|
assign PP1 = Pprime; // same for all flavors
|
||||||
|
assign PP2 = {2'b00, (MULH | MULHSU) ? ~PA : PA, {(`XLEN-1){1'b0}}};
|
||||||
|
assign PP3 = {2'b00, (MULH) ? ~PB : PB, {(`XLEN-1){1'b0}}};
|
||||||
|
always_comb
|
||||||
|
if (MULH) PP4 = {1'b1, PP, {(`XLEN-3){1'b0}}, 1'b1, {(`XLEN){1'b0}}};
|
||||||
|
else if (MULHSU) PP4 = {1'b1, ~PP, {(`XLEN-2){1'b0}}, 1'b1, {(`XLEN-1){1'b0}}};
|
||||||
|
else PP4 = {1'b0, PP, {(`XLEN*2-2){1'b0}}};
|
||||||
|
|
||||||
|
assign ProdE = PP1 + PP2 + PP3 + PP4; //SrcAE * SrcBE;
|
||||||
|
endmodule
|
||||||
|
|
@ -36,7 +36,7 @@ module muldiv (
|
|||||||
// Writeback stage
|
// Writeback stage
|
||||||
output logic [`XLEN-1:0] MulDivResultW,
|
output logic [`XLEN-1:0] MulDivResultW,
|
||||||
// hazards
|
// hazards
|
||||||
input logic FlushM, FlushW
|
input logic StallM, StallW, FlushM, FlushW
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
@ -46,6 +46,9 @@ module muldiv (
|
|||||||
logic [`XLEN-1:0] QuotE, RemE;
|
logic [`XLEN-1:0] QuotE, RemE;
|
||||||
logic [`XLEN*2-1:0] ProdE;
|
logic [`XLEN*2-1:0] ProdE;
|
||||||
|
|
||||||
|
// Multiplier
|
||||||
|
mul mul(.*);
|
||||||
|
|
||||||
// Select result
|
// Select result
|
||||||
always_comb
|
always_comb
|
||||||
case (Funct3E)
|
case (Funct3E)
|
||||||
@ -66,8 +69,8 @@ module muldiv (
|
|||||||
assign MulDivResultE = PrelimResultE;
|
assign MulDivResultE = PrelimResultE;
|
||||||
end
|
end
|
||||||
|
|
||||||
floprc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, MulDivResultE, MulDivResultM);
|
flopenrc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, ~StallM, MulDivResultE, MulDivResultM);
|
||||||
floprc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, MulDivResultM, MulDivResultW);
|
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
|
||||||
end else begin // no M instructions supported
|
end else begin // no M instructions supported
|
||||||
assign MulDivResultW = 0;
|
assign MulDivResultW = 0;
|
||||||
end
|
end
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
module csr (
|
module csr (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic FlushW,
|
input logic FlushW, StallW,
|
||||||
input logic [31:0] InstrM,
|
input logic [31:0] InstrM,
|
||||||
input logic [`XLEN-1:0] PCM, SrcAM,
|
input logic [`XLEN-1:0] PCM, SrcAM,
|
||||||
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
||||||
@ -102,7 +102,9 @@ module csr (
|
|||||||
|
|
||||||
// merge CSR Reads
|
// merge CSR Reads
|
||||||
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM;
|
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM;
|
||||||
floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW);
|
// *** add W stall 2/22/21 dh to try fixing memory stalls
|
||||||
|
// floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW);
|
||||||
|
flopenrc #(`XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
|
||||||
|
|
||||||
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
|
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
|
||||||
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) ||
|
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) ||
|
||||||
|
@ -60,15 +60,13 @@ module csrs #(parameter
|
|||||||
// Supervisor mode CSRs sometimes supported
|
// Supervisor mode CSRs sometimes supported
|
||||||
generate
|
generate
|
||||||
if (`S_SUPPORTED) begin
|
if (`S_SUPPORTED) begin
|
||||||
logic WriteSTVECM, WriteSEDELEGM, WriteSIDELEGM;
|
logic WriteSTVECM;
|
||||||
logic WriteSSCRATCHM, WriteSEPCM;
|
logic WriteSSCRATCHM, WriteSEPCM;
|
||||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||||
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW, SATP_REGW;
|
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW, SATP_REGW;
|
||||||
|
|
||||||
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS);
|
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS);
|
||||||
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC);
|
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC);
|
||||||
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
|
|
||||||
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
|
|
||||||
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH);
|
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH);
|
||||||
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC));
|
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC));
|
||||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE));
|
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE));
|
||||||
@ -85,6 +83,9 @@ module csrs #(parameter
|
|||||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
||||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
|
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
|
||||||
if (`N_SUPPORTED) begin
|
if (`N_SUPPORTED) begin
|
||||||
|
logic WriteSEDELEGM, WriteSIDELEGM;
|
||||||
|
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
|
||||||
|
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
|
||||||
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, zero, SEDELEG_REGW);
|
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, zero, SEDELEG_REGW);
|
||||||
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, zero, SIDELEG_REGW);
|
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, zero, SIDELEG_REGW);
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module csrsr (
|
module csrsr (
|
||||||
input logic clk, reset,
|
input logic clk, reset, StallW,
|
||||||
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
|
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
|
||||||
input logic TrapM, FloatRegWriteW,
|
input logic TrapM, FloatRegWriteW,
|
||||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||||
@ -116,9 +116,9 @@ module csrsr (
|
|||||||
STATUS_SPIE <= 0; //`S_SUPPORTED;
|
STATUS_SPIE <= 0; //`S_SUPPORTED;
|
||||||
STATUS_UPIE <= 0; // `U_SUPPORTED;
|
STATUS_UPIE <= 0; // `U_SUPPORTED;
|
||||||
STATUS_MIE <= 0; // Per Priv 3.3
|
STATUS_MIE <= 0; // Per Priv 3.3
|
||||||
STATUS_SIE <= 0; // `S_SUPPORTED;
|
STATUS_SIE <= `S_SUPPORTED;
|
||||||
STATUS_UIE <= 0; // `U_SUPPORTED;
|
STATUS_UIE <= `U_SUPPORTED;
|
||||||
end else begin
|
end else if (~StallW) begin
|
||||||
if (WriteMSTATUSM) begin
|
if (WriteMSTATUSM) begin
|
||||||
STATUS_SUM_INT <= CSRWriteValM[18];
|
STATUS_SUM_INT <= CSRWriteValM[18];
|
||||||
STATUS_MPRV_INT <= CSRWriteValM[17];
|
STATUS_MPRV_INT <= CSRWriteValM[17];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// exceptions.sv
|
// privileged.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 5 January 2021
|
// Written: David_Harris@hmc.edu 5 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
@ -45,7 +45,7 @@ module privileged (
|
|||||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
||||||
input logic [4:0] SetFflagsM,
|
input logic [4:0] SetFflagsM,
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
input logic FlushD, FlushE, FlushM, StallD
|
input logic FlushD, FlushE, FlushM, StallD, StallW
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
|
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
|
||||||
@ -81,8 +81,8 @@ module privileged (
|
|||||||
|
|
||||||
// PrivilegeMode FSM
|
// PrivilegeMode FSM
|
||||||
always_comb
|
always_comb
|
||||||
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode)
|
/* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
|
||||||
else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||||
else if (uretM) NextPrivilegeModeM = `U_MODE;
|
else if (uretM) NextPrivilegeModeM = `U_MODE;
|
||||||
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||||
@ -96,7 +96,7 @@ module privileged (
|
|||||||
else NextPrivilegeModeM = `M_MODE;
|
else NextPrivilegeModeM = `M_MODE;
|
||||||
end else NextPrivilegeModeM = PrivilegeModeW;
|
end else NextPrivilegeModeM = PrivilegeModeW;
|
||||||
|
|
||||||
flop #(2) privmodereg(clk, NextPrivilegeModeM, PrivilegeModeW);
|
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// decode privileged instructions
|
// decode privileged instructions
|
||||||
|
@ -44,7 +44,9 @@ module clint (
|
|||||||
assign memread = MemRWclint[1];
|
assign memread = MemRWclint[1];
|
||||||
assign memwrite = MemRWclint[0];
|
assign memwrite = MemRWclint[0];
|
||||||
assign HRESPCLINT = 0; // OK
|
assign HRESPCLINT = 0; // OK
|
||||||
assign HREADYCLINT = 1; // Respond immediately
|
// assign HREADYCLINT = 1; // Respond immediately
|
||||||
|
always_ff @(posedge HCLK) // delay response
|
||||||
|
HREADYCLINT <= memread | memwrite;
|
||||||
|
|
||||||
// word aligned reads
|
// word aligned reads
|
||||||
generate
|
generate
|
||||||
@ -54,16 +56,21 @@ module clint (
|
|||||||
assign #2 entry = {HADDR[15:2], 2'b00};
|
assign #2 entry = {HADDR[15:2], 2'b00};
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
||||||
|
// This will require synchronizing MTIME to the system clock
|
||||||
|
// before it is read or compared to MTIMECMP.
|
||||||
|
// It will also require synchronizing the write to MTIMECMP.
|
||||||
|
// Use req and ack signals synchronized across the clock domains.
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
generate
|
generate
|
||||||
if (`XLEN==64) begin
|
if (`XLEN==64) begin
|
||||||
always_comb begin
|
always @(posedge HCLK) begin
|
||||||
case(entry)
|
case(entry)
|
||||||
16'h0000: HREADCLINT = {63'b0, MSIP};
|
16'h0000: HREADCLINT <= {63'b0, MSIP};
|
||||||
16'h4000: HREADCLINT = MTIMECMP;
|
16'h4000: HREADCLINT <= MTIMECMP;
|
||||||
16'hBFF8: HREADCLINT = MTIME;
|
16'hBFF8: HREADCLINT <= MTIME;
|
||||||
default: HREADCLINT = 0;
|
default: HREADCLINT <= 0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
@ -80,14 +87,14 @@ module clint (
|
|||||||
else MTIME <= MTIME + 1;
|
else MTIME <= MTIME + 1;
|
||||||
end
|
end
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
always_comb begin
|
always @(posedge HCLK) begin
|
||||||
case(entry)
|
case(entry)
|
||||||
16'h0000: HREADCLINT = {31'b0, MSIP};
|
16'h0000: HREADCLINT <= {31'b0, MSIP};
|
||||||
16'h4000: HREADCLINT = MTIMECMP[31:0];
|
16'h4000: HREADCLINT <= MTIMECMP[31:0];
|
||||||
16'h4004: HREADCLINT = MTIMECMP[63:32];
|
16'h4004: HREADCLINT <= MTIMECMP[63:32];
|
||||||
16'hBFF8: HREADCLINT = MTIME[31:0];
|
16'hBFF8: HREADCLINT <= MTIME[31:0];
|
||||||
16'hBFFC: HREADCLINT = MTIME[63:32];
|
16'hBFFC: HREADCLINT <= MTIME[63:32];
|
||||||
default: HREADCLINT = 0;
|
default: HREADCLINT <= 0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
|
@ -36,6 +36,9 @@ module dtim (
|
|||||||
);
|
);
|
||||||
|
|
||||||
logic [`XLEN-1:0] RAM[0:65535];
|
logic [`XLEN-1:0] RAM[0:65535];
|
||||||
|
logic [18:0] HWADDR;
|
||||||
|
logic [`XLEN-1:0] HREADTim0;
|
||||||
|
|
||||||
// logic [`XLEN-1:0] write;
|
// logic [`XLEN-1:0] write;
|
||||||
logic [15:0] entry;
|
logic [15:0] entry;
|
||||||
logic memread, memwrite;
|
logic memread, memwrite;
|
||||||
@ -48,74 +51,56 @@ module dtim (
|
|||||||
end else begin
|
end else begin
|
||||||
if (HREADYTim & HSELTim) begin
|
if (HREADYTim & HSELTim) begin
|
||||||
busycount <= 0;
|
busycount <= 0;
|
||||||
HREADYTim <= 0;
|
HREADYTim <= #1 0;
|
||||||
end else if (~HREADYTim) begin
|
end else if (~HREADYTim) begin
|
||||||
if (busycount == 0) begin // TIM latency, for testing purposes
|
if (busycount == 2) begin // TIM latency, for testing purposes
|
||||||
HREADYTim <= 1;
|
HREADYTim <= #1 1;
|
||||||
end else
|
end else begin
|
||||||
busycount <= busycount + 1;
|
busycount <= busycount + 1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
|
if (~HRESETn) begin
|
||||||
|
HREADYTim <= 0;
|
||||||
|
end else begin
|
||||||
|
HREADYTim <= HSELTim; // always respond one cycle later
|
||||||
|
end */
|
||||||
|
|
||||||
|
|
||||||
assign memread = MemRWtim[1];
|
assign memread = MemRWtim[1];
|
||||||
assign memwrite = MemRWtim[0];
|
assign memwrite = MemRWtim[0];
|
||||||
|
// always_ff @(posedge HCLK)
|
||||||
|
// memwrite <= MemRWtim[0]; // delay memwrite to write phase
|
||||||
assign HRESPTim = 0; // OK
|
assign HRESPTim = 0; // OK
|
||||||
// assign HREADYTim = 1; // Respond immediately; *** extend this
|
// assign HREADYTim = 1; // Respond immediately; *** extend this
|
||||||
|
|
||||||
|
|
||||||
|
// Model memory read and write
|
||||||
|
|
||||||
// word aligned reads
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN==64)
|
if (`XLEN == 64) begin
|
||||||
assign #2 entry = HADDR[18:3];
|
// always_ff @(negedge HCLK)
|
||||||
else
|
// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
|
||||||
assign #2 entry = HADDR[17:2];
|
always_ff @(posedge HCLK) begin
|
||||||
endgenerate
|
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
||||||
assign HREADTim = RAM[entry];
|
HWADDR <= HADDR;
|
||||||
// assign HREADTim = HREADYTim ? RAM[entry] : ~RAM[entry]; // *** temproary mess up read value before ready
|
HREADTim0 <= RAM[HADDR[17:3]];
|
||||||
|
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
|
||||||
// write each byte based on the byte mask
|
end
|
||||||
// UInstantiate a byte-writable memory here if possible
|
end else begin
|
||||||
// and drop tihs masking logic. Otherwise, use the masking
|
// always_ff @(negedge HCLK)
|
||||||
// from dmem
|
// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
|
||||||
/*generate
|
always_ff @(posedge HCLK) begin
|
||||||
|
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
||||||
if (`XLEN==64) begin
|
HWADDR <= HADDR;
|
||||||
always_comb begin
|
HREADTim0 <= RAM[HADDR[17:2]];
|
||||||
write=HREADTim;
|
if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
|
||||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
end
|
||||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
|
||||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
|
||||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
|
||||||
if (ByteMaskM[4]) write[39:32] = HWDATA[39:32];
|
|
||||||
if (ByteMaskM[5]) write[47:40] = HWDATA[47:40];
|
|
||||||
if (ByteMaskM[6]) write[55:48] = HWDATA[55:48];
|
|
||||||
if (ByteMaskM[7]) write[63:56] = HWDATA[63:56];
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk)
|
|
||||||
if (memwrite) RAM[HADDR[18:3]] <= write;
|
|
||||||
end else begin // 32-bit
|
|
||||||
always_comb begin
|
|
||||||
write=HREADTim;
|
|
||||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
|
||||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
|
||||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
|
||||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk)
|
|
||||||
if (memwrite) RAM[HADDR[17:2]] <= write;
|
|
||||||
end
|
end
|
||||||
endgenerate */
|
|
||||||
generate
|
|
||||||
if (`XLEN == 64)
|
|
||||||
always_ff @(posedge HCLK) begin
|
|
||||||
if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
|
||||||
// HREADTim <= RAM[HADDR[17:3]];
|
|
||||||
end
|
|
||||||
else
|
|
||||||
always_ff @(posedge HCLK) begin
|
|
||||||
if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
|
||||||
// HREADTim <= RAM[HADDR[17:2]];
|
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
assign HREADTim = HREADYTim ? HREADTim0 : 'bz;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -45,7 +45,9 @@ module gpio (
|
|||||||
assign memread = MemRWgpio[1];
|
assign memread = MemRWgpio[1];
|
||||||
assign memwrite = MemRWgpio[0];
|
assign memwrite = MemRWgpio[0];
|
||||||
assign HRESPGPIO = 0; // OK
|
assign HRESPGPIO = 0; // OK
|
||||||
assign HREADYGPIO = 1; // Respond immediately
|
always_ff @(posedge HCLK) // delay response to data cycle
|
||||||
|
HREADYGPIO <= memread | memwrite;
|
||||||
|
// assign HREADYGPIO = 1; // Respond immediately
|
||||||
|
|
||||||
// word aligned reads
|
// word aligned reads
|
||||||
generate
|
generate
|
||||||
@ -67,12 +69,12 @@ module gpio (
|
|||||||
// register access
|
// register access
|
||||||
generate
|
generate
|
||||||
if (`XLEN==64) begin
|
if (`XLEN==64) begin
|
||||||
always_comb begin
|
always_ff @(posedge HCLK) begin
|
||||||
case(entry)
|
case(entry)
|
||||||
8'h00: HREADGPIO = {INPUT_EN, INPUT_VAL};
|
8'h00: HREADGPIO <= {INPUT_EN, INPUT_VAL};
|
||||||
8'h08: HREADGPIO = {OUTPUT_VAL, OUTPUT_EN};
|
8'h08: HREADGPIO <= {OUTPUT_VAL, OUTPUT_EN};
|
||||||
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0
|
8'h40: HREADGPIO <= 0; // OUT_XOR reads as 0
|
||||||
default: HREADGPIO = 0;
|
default: HREADGPIO <= 0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
@ -86,14 +88,14 @@ module gpio (
|
|||||||
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA[31:0]; // OUT_XOR
|
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA[31:0]; // OUT_XOR
|
||||||
end
|
end
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
always_comb begin
|
always_ff @(posedge HCLK) begin
|
||||||
case(entry)
|
case(entry)
|
||||||
8'h00: HREADGPIO = INPUT_VAL;
|
8'h00: HREADGPIO <= INPUT_VAL;
|
||||||
8'h04: HREADGPIO = INPUT_EN;
|
8'h04: HREADGPIO <= INPUT_EN;
|
||||||
8'h08: HREADGPIO = OUTPUT_EN;
|
8'h08: HREADGPIO <= OUTPUT_EN;
|
||||||
8'h0C: HREADGPIO = OUTPUT_VAL;
|
8'h0C: HREADGPIO <= OUTPUT_VAL;
|
||||||
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0
|
8'h40: HREADGPIO <= 0; // OUT_XOR reads as 0
|
||||||
default: HREADGPIO = 0;
|
default: HREADGPIO <= 0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
module imem (
|
module imem (
|
||||||
input logic [`XLEN-1:1] AdrF,
|
input logic [`XLEN-1:1] AdrF,
|
||||||
output logic [31:0] InstrF,
|
output logic [31:0] InstrF,
|
||||||
|
output logic [15:0] rd2, // bogus, delete when real multicycle fetch works
|
||||||
output logic InstrAccessFaultF);
|
output logic InstrAccessFaultF);
|
||||||
|
|
||||||
/* verilator lint_off UNDRIVEN */
|
/* verilator lint_off UNDRIVEN */
|
||||||
@ -35,7 +36,7 @@ module imem (
|
|||||||
/* verilator lint_on UNDRIVEN */
|
/* verilator lint_on UNDRIVEN */
|
||||||
logic [15:0] adrbits;
|
logic [15:0] adrbits;
|
||||||
logic [`XLEN-1:0] rd;
|
logic [`XLEN-1:0] rd;
|
||||||
logic [15:0] rd2;
|
// logic [15:0] rd2;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN==32) assign adrbits = AdrF[17:2];
|
if (`XLEN==32) assign adrbits = AdrF[17:2];
|
||||||
@ -52,11 +53,19 @@ module imem (
|
|||||||
generate
|
generate
|
||||||
if (`XLEN==32) begin
|
if (`XLEN==32) begin
|
||||||
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
|
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
|
||||||
assign InstrAccessFaultF = ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF
|
if(`TIMBASE==0) begin
|
||||||
|
assign InstrAccessFaultF = 0;
|
||||||
|
end else begin
|
||||||
|
assign InstrAccessFaultF = ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF
|
||||||
|
end
|
||||||
end else begin
|
end else begin
|
||||||
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
|
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
|
||||||
: (AdrF[1] ? rd[47:16] : rd[31:0]);
|
: (AdrF[1] ? rd[47:16] : rd[31:0]);
|
||||||
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32]) | ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF]
|
if(`TIMBASE==0) begin
|
||||||
|
assign InstrAccessFaultF = 0;
|
||||||
|
end else begin
|
||||||
|
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32]) | ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -27,37 +27,35 @@
|
|||||||
|
|
||||||
module subwordwrite (
|
module subwordwrite (
|
||||||
input logic [`XLEN-1:0] HRDATA,
|
input logic [`XLEN-1:0] HRDATA,
|
||||||
input logic [31:0] HADDR,
|
input logic [2:0] HADDRD,
|
||||||
input logic [2:0] HSIZE,
|
input logic [3:0] HSIZED,
|
||||||
input logic [`XLEN-1:0] HWDATAIN,
|
input logic [`XLEN-1:0] HWDATAIN,
|
||||||
output logic [`XLEN-1:0] HWDATA
|
output logic [`XLEN-1:0] HWDATA
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
|
|
||||||
logic [15:0] HalfwordM;
|
|
||||||
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
|
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
|
||||||
logic [7:0] ByteMaskM;
|
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 64) begin
|
if (`XLEN == 64) begin
|
||||||
|
logic [7:0] ByteMaskM;
|
||||||
// Compute write mask
|
// Compute write mask
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZE[1:0])
|
case(HSIZED[1:0])
|
||||||
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDR[2:0]] = 1; end // sb
|
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDRD[2:0]] = 1; end // sb
|
||||||
2'b01: case (HADDR[2:1])
|
2'b01: case (HADDRD[2:1])
|
||||||
2'b00: ByteMaskM = 8'b00000011;
|
2'b00: ByteMaskM = 8'b00000011;
|
||||||
2'b01: ByteMaskM = 8'b00001100;
|
2'b01: ByteMaskM = 8'b00001100;
|
||||||
2'b10: ByteMaskM = 8'b00110000;
|
2'b10: ByteMaskM = 8'b00110000;
|
||||||
2'b11: ByteMaskM = 8'b11000000;
|
2'b11: ByteMaskM = 8'b11000000;
|
||||||
endcase
|
endcase
|
||||||
2'b10: if (HADDR[2]) ByteMaskM = 8'b11110000;
|
2'b10: if (HADDRD[2]) ByteMaskM = 8'b11110000;
|
||||||
else ByteMaskM = 8'b00001111;
|
else ByteMaskM = 8'b00001111;
|
||||||
2'b11: ByteMaskM = 8'b11111111;
|
2'b11: ByteMaskM = 8'b11111111;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// Handle subword writes
|
// Handle subword writes
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZE[1:0])
|
case(HSIZED[1:0])
|
||||||
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
|
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
|
||||||
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
|
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
|
||||||
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
|
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
|
||||||
@ -77,19 +75,20 @@ module subwordwrite (
|
|||||||
end
|
end
|
||||||
|
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
|
logic [3:0] ByteMaskM;
|
||||||
// Compute write mask
|
// Compute write mask
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZE[1:0])
|
case(HSIZED[1:0])
|
||||||
2'b00: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, HADDR[1:0]}] = 1; end // sb
|
2'b00: begin ByteMaskM = 4'b0000; ByteMaskM[HADDRD[1:0]] = 1; end // sb
|
||||||
2'b01: if (HADDR[1]) ByteMaskM = 8'b1100;
|
2'b01: if (HADDRD[1]) ByteMaskM = 4'b1100;
|
||||||
else ByteMaskM = 8'b0011;
|
else ByteMaskM = 4'b0011;
|
||||||
2'b10: ByteMaskM = 8'b1111;
|
2'b10: ByteMaskM = 4'b1111;
|
||||||
default: ByteMaskM = 8'b111; // shouldn't happen
|
default: ByteMaskM = 4'b111; // shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// Handle subword writes
|
// Handle subword writes
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZE[1:0])
|
case(HSIZED[1:0])
|
||||||
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
|
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
|
||||||
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
|
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
|
||||||
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw
|
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw
|
||||||
|
@ -48,31 +48,33 @@ module uart (
|
|||||||
assign MEMWb = ~MemRWuart[0];
|
assign MEMWb = ~MemRWuart[0];
|
||||||
assign A = HADDR[2:0];
|
assign A = HADDR[2:0];
|
||||||
assign HRESPUART = 0; // OK
|
assign HRESPUART = 0; // OK
|
||||||
assign HREADYUART = 1; // Respond immediately
|
//assign HREADYUART = 1; // Respond immediately
|
||||||
|
always_ff @(posedge HCLK) // delay response to data cycle
|
||||||
|
HREADYUART <= ~MEMRb | ~MEMWb;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 64) begin
|
if (`XLEN == 64) begin
|
||||||
always_comb begin
|
always @(posedge HCLK) begin
|
||||||
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
|
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
|
||||||
case (HADDR)
|
case (HADDR)
|
||||||
3'b000: Din = HWDATA[7:0];
|
3'b000: Din <= HWDATA[7:0];
|
||||||
3'b001: Din = HWDATA[15:8];
|
3'b001: Din <= HWDATA[15:8];
|
||||||
3'b010: Din = HWDATA[23:16];
|
3'b010: Din <= HWDATA[23:16];
|
||||||
3'b011: Din = HWDATA[31:24];
|
3'b011: Din <= HWDATA[31:24];
|
||||||
3'b100: Din = HWDATA[39:32];
|
3'b100: Din <= HWDATA[39:32];
|
||||||
3'b101: Din = HWDATA[47:40];
|
3'b101: Din <= HWDATA[47:40];
|
||||||
3'b110: Din = HWDATA[55:48];
|
3'b110: Din <= HWDATA[55:48];
|
||||||
3'b111: Din = HWDATA[63:56];
|
3'b111: Din <= HWDATA[63:56];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
always_comb begin
|
always @(posedge HCLK) begin
|
||||||
HREADUART = {Dout, Dout, Dout, Dout};
|
HREADUART = {Dout, Dout, Dout, Dout};
|
||||||
case (HADDR[1:0])
|
case (HADDR[1:0])
|
||||||
2'b00: Din = HWDATA[7:0];
|
2'b00: Din <= HWDATA[7:0];
|
||||||
2'b01: Din = HWDATA[15:8];
|
2'b01: Din <= HWDATA[15:8];
|
||||||
2'b10: Din = HWDATA[23:16];
|
2'b10: Din <= HWDATA[23:16];
|
||||||
2'b11: Din = HWDATA[31:24];
|
2'b11: Din <= HWDATA[31:24];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
// Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs
|
// Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs
|
||||||
// Emulates interface of Texas Instruments PC16550D
|
// Emulates interface of Texas Instruments PC16550D
|
||||||
|
// https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/PC16550D.pdf
|
||||||
// Compatible with UART in Imperas Virtio model ***
|
// Compatible with UART in Imperas Virtio model ***
|
||||||
//
|
//
|
||||||
// Compatible with most of PC16550D with the following known exceptions:
|
// Compatible with most of PC16550D with the following known exceptions:
|
||||||
|
@ -43,6 +43,10 @@ module uncore (
|
|||||||
input logic HREADYEXT, HRESPEXT,
|
input logic HREADYEXT, HRESPEXT,
|
||||||
output logic [`AHBW-1:0] HRDATA,
|
output logic [`AHBW-1:0] HRDATA,
|
||||||
output logic HREADY, HRESP,
|
output logic HREADY, HRESP,
|
||||||
|
// delayed signals
|
||||||
|
input logic [2:0] HADDRD,
|
||||||
|
input logic [3:0] HSIZED,
|
||||||
|
input logic HWRITED,
|
||||||
// bus interface
|
// bus interface
|
||||||
output logic DataAccessFaultM,
|
output logic DataAccessFaultM,
|
||||||
// peripheral pins
|
// peripheral pins
|
||||||
@ -71,7 +75,7 @@ module uncore (
|
|||||||
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
|
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
|
||||||
|
|
||||||
// Enable read or write based on decoded address
|
// Enable read or write based on decoded address
|
||||||
assign MemRW = {~HWRITE, HWRITE};
|
assign MemRW = {~HWRITE, HWRITED};
|
||||||
assign MemRWtim = MemRW & {2{HSELTim}};
|
assign MemRWtim = MemRW & {2{HSELTim}};
|
||||||
assign MemRWclint = MemRW & {2{HSELCLINT}};
|
assign MemRWclint = MemRW & {2{HSELCLINT}};
|
||||||
assign MemRWgpio = MemRW & {2{HSELGPIO}};
|
assign MemRWgpio = MemRW & {2{HSELGPIO}};
|
||||||
|
@ -29,12 +29,13 @@
|
|||||||
module wallypipelinedhart (
|
module wallypipelinedhart (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
output logic [`XLEN-1:0] PCF,
|
output logic [`XLEN-1:0] PCF,
|
||||||
input logic [31:0] InstrF,
|
// input logic [31:0] InstrF,
|
||||||
// Privileged
|
// Privileged
|
||||||
input logic TimerIntM, ExtIntM, SwIntM,
|
input logic TimerIntM, ExtIntM, SwIntM,
|
||||||
input logic InstrAccessFaultF,
|
input logic InstrAccessFaultF,
|
||||||
input logic DataAccessFaultM,
|
input logic DataAccessFaultM,
|
||||||
// Bus Interface
|
// Bus Interface
|
||||||
|
input logic [15:0] rd2, // bogus, delete when real multicycle fetch works
|
||||||
input logic [`AHBW-1:0] HRDATA,
|
input logic [`AHBW-1:0] HRDATA,
|
||||||
input logic HREADY, HRESP,
|
input logic HREADY, HRESP,
|
||||||
output logic HCLK, HRESETn,
|
output logic HCLK, HRESETn,
|
||||||
@ -45,11 +46,16 @@ module wallypipelinedhart (
|
|||||||
output logic [2:0] HBURST,
|
output logic [2:0] HBURST,
|
||||||
output logic [3:0] HPROT,
|
output logic [3:0] HPROT,
|
||||||
output logic [1:0] HTRANS,
|
output logic [1:0] HTRANS,
|
||||||
output logic HMASTLOCK
|
output logic HMASTLOCK,
|
||||||
|
// Delayed signals for subword write
|
||||||
|
output logic [2:0] HADDRD,
|
||||||
|
output logic [3:0] HSIZED,
|
||||||
|
output logic HWRITED
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [1:0] ForwardAE, ForwardBE;
|
// logic [1:0] ForwardAE, ForwardBE;
|
||||||
logic StallF, StallD, FlushD, FlushE, FlushM, FlushW;
|
logic StallF, StallD, StallE, StallM, StallW;
|
||||||
|
logic FlushD, FlushE, FlushM, FlushW;
|
||||||
logic RetM, TrapM;
|
logic RetM, TrapM;
|
||||||
|
|
||||||
// new signals that must connect through DP
|
// new signals that must connect through DP
|
||||||
@ -72,7 +78,6 @@ module wallypipelinedhart (
|
|||||||
logic LoadMisalignedFaultM, LoadAccessFaultM;
|
logic LoadMisalignedFaultM, LoadAccessFaultM;
|
||||||
logic StoreMisalignedFaultM, StoreAccessFaultM;
|
logic StoreMisalignedFaultM, StoreAccessFaultM;
|
||||||
logic [`XLEN-1:0] InstrMisalignedAdrM;
|
logic [`XLEN-1:0] InstrMisalignedAdrM;
|
||||||
logic [`XLEN-1:0] zero = 0;
|
|
||||||
|
|
||||||
logic PCSrcE;
|
logic PCSrcE;
|
||||||
logic CSRWritePendingDEM;
|
logic CSRWritePendingDEM;
|
||||||
@ -82,26 +87,35 @@ module wallypipelinedhart (
|
|||||||
logic FloatRegWriteW;
|
logic FloatRegWriteW;
|
||||||
|
|
||||||
// bus interface to dmem
|
// bus interface to dmem
|
||||||
logic [1:0] MemRWAlignedM;
|
logic MemReadM, MemWriteM;
|
||||||
logic [2:0] Funct3M;
|
logic [2:0] Funct3M;
|
||||||
logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM;
|
logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM;
|
||||||
logic [`XLEN-1:0] ReadDataM, ReadDataW;
|
logic [`XLEN-1:0] ReadDataW;
|
||||||
logic [`XLEN-1:0] InstrPAdrF;
|
logic [`XLEN-1:0] InstrPAdrF;
|
||||||
|
logic [`XLEN-1:0] InstrRData;
|
||||||
|
logic InstrReadF;
|
||||||
logic DataStall, InstrStall;
|
logic DataStall, InstrStall;
|
||||||
logic InstrAckD, MemAckW;
|
logic InstrAckD, MemAckW;
|
||||||
|
|
||||||
ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache
|
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache
|
||||||
|
|
||||||
ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller
|
ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller
|
||||||
dmem dmem(/*.Funct3M(InstrM[14:12]),*/ .*); // data cache unit
|
dmem dmem(.*); // data cache unit
|
||||||
|
|
||||||
ahblite ebu( // *** make IRData InstrF
|
|
||||||
.IReadF(1'b1), .IRData(), //.IReady(),
|
ahblite ebu(
|
||||||
.DReadM(MemRWAlignedM[1]), .DWriteM(MemRWAlignedM[0]),
|
//.InstrReadF(1'b0),
|
||||||
.DSizeM(Funct3M[1:0]), .DRData(ReadDataM), //.DReady(),
|
//.InstrRData(InstrF), // hook up InstrF later
|
||||||
.UnsignedLoadM(Funct3M[2]),
|
.MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
|
||||||
.*);
|
.*);
|
||||||
//assign InstrF = ReadDataM[31:0];
|
|
||||||
|
// changing from this to the line above breaks the program. auipc at 104 fails; seems to be flushed.
|
||||||
|
// Would need to insertinstruction as InstrD, not InstrF
|
||||||
|
/*ahblite ebu(
|
||||||
|
.InstrReadF(1'b0),
|
||||||
|
.InstrRData(), // hook up InstrF later
|
||||||
|
.MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
|
||||||
|
.*); */
|
||||||
|
|
||||||
|
|
||||||
muldiv mdu(.*); // multiply and divide unit
|
muldiv mdu(.*); // multiply and divide unit
|
||||||
|
@ -56,7 +56,6 @@ module wallypipelinedsoc (
|
|||||||
|
|
||||||
// to instruction memory *** remove later
|
// to instruction memory *** remove later
|
||||||
logic [`XLEN-1:0] PCF;
|
logic [`XLEN-1:0] PCF;
|
||||||
logic [31:0] InstrF;
|
|
||||||
|
|
||||||
// Uncore signals
|
// Uncore signals
|
||||||
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
|
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
|
||||||
@ -64,6 +63,11 @@ module wallypipelinedsoc (
|
|||||||
logic InstrAccessFaultF, DataAccessFaultM;
|
logic InstrAccessFaultF, DataAccessFaultM;
|
||||||
logic TimerIntM, SwIntM; // from CLINT
|
logic TimerIntM, SwIntM; // from CLINT
|
||||||
logic ExtIntM = 0; // not yet connected
|
logic ExtIntM = 0; // not yet connected
|
||||||
|
logic [2:0] HADDRD;
|
||||||
|
logic [3:0] HSIZED;
|
||||||
|
logic HWRITED;
|
||||||
|
logic [15:0] rd2; // bogus, delete when real multicycle fetch works
|
||||||
|
logic [31:0] InstrF;
|
||||||
|
|
||||||
// instantiate processor and memories
|
// instantiate processor and memories
|
||||||
wallypipelinedhart hart(.*);
|
wallypipelinedhart hart(.*);
|
||||||
|
@ -1,11 +1,40 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// testbench-imperas.sv
|
||||||
|
//
|
||||||
|
// Written: David_Harris@hmc.edu 9 January 2021
|
||||||
|
// Modified:
|
||||||
|
//
|
||||||
|
// Purpose: Wally Testbench and helper modules
|
||||||
|
// Applies test programs from the Imperas suite
|
||||||
|
//
|
||||||
|
// 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"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module testbench();
|
module testbench();
|
||||||
logic clk;
|
logic clk;
|
||||||
logic reset;
|
logic reset;
|
||||||
|
int test, i, errors, totalerrors;
|
||||||
string memfilename;
|
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[];
|
||||||
logic [`AHBW-1:0] HRDATAEXT;
|
logic [`AHBW-1:0] HRDATAEXT;
|
||||||
logic HREADYEXT, HRESPEXT;
|
logic HREADYEXT, HRESPEXT;
|
||||||
logic [31:0] HADDR;
|
logic [31:0] HADDR;
|
||||||
@ -17,31 +46,167 @@ module testbench();
|
|||||||
logic [1:0] HTRANS;
|
logic [1:0] HTRANS;
|
||||||
logic HMASTLOCK;
|
logic HMASTLOCK;
|
||||||
logic HCLK, HRESETn;
|
logic HCLK, HRESETn;
|
||||||
|
|
||||||
|
// pick tests based on modes supported
|
||||||
|
initial
|
||||||
|
tests = {"../../imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/coremark.RV64I.bare.elf.memfile", "1000"};
|
||||||
|
string signame, memfilename;
|
||||||
logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
|
logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
|
||||||
logic UARTSin, UARTSout;
|
logic UARTSin, UARTSout;
|
||||||
|
|
||||||
// instantiate device to be tested
|
// instantiate device to be tested
|
||||||
assign GPIOPinsIn = 0;
|
assign GPIOPinsIn = 0;
|
||||||
assign UARTSin = 1;
|
assign UARTSin = 1;
|
||||||
assign HREADYEXT = 1;
|
assign HREADYEXT = 1;
|
||||||
assign HRESPEXT = 0;
|
assign HRESPEXT = 0;
|
||||||
assign HRDATAEXT = 0;
|
assign HRDATAEXT = 0;
|
||||||
|
wallypipelinedsoc dut(.*);
|
||||||
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
|
// initialize tests
|
||||||
initial
|
initial
|
||||||
begin
|
begin
|
||||||
memfilename = "../../imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/coremark.RV64I.bare.elf.memfile";
|
totalerrors = 0;
|
||||||
|
// read test vectors into memory
|
||||||
|
memfilename = tests[0];
|
||||||
$readmemh(memfilename, dut.imem.RAM);
|
$readmemh(memfilename, dut.imem.RAM);
|
||||||
$readmemh(memfilename, dut.uncore.dtim.RAM);
|
$readmemh(memfilename, dut.uncore.dtim.RAM);
|
||||||
reset = 1; # 22; reset = 0;
|
reset = 1; # 22; reset = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// generate clock to sequence tests
|
// generate clock to sequence tests
|
||||||
always
|
always
|
||||||
begin
|
begin
|
||||||
clk = 1; # 5; clk = 0; # 5;
|
clk = 1; # 5; clk = 0; # 5;
|
||||||
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 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_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";
|
||||||
|
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 = "MULHU";
|
||||||
|
else name = "ILLEGAL";
|
||||||
|
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
|
||||||
|
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";
|
||||||
|
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
|
endmodule
|
||||||
|
@ -35,7 +35,7 @@ module testbench();
|
|||||||
logic [`XLEN-1:0] signature[0:10000];
|
logic [`XLEN-1:0] signature[0:10000];
|
||||||
logic [`XLEN-1:0] testadr;
|
logic [`XLEN-1:0] testadr;
|
||||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||||
logic [31:0] InstrW;
|
//logic [31:0] InstrW;
|
||||||
logic [`XLEN-1:0] meminit;
|
logic [`XLEN-1:0] meminit;
|
||||||
string tests64m[] = '{
|
string tests64m[] = '{
|
||||||
"rv64m/I-MUL-01", "3000",
|
"rv64m/I-MUL-01", "3000",
|
||||||
@ -90,7 +90,6 @@ string tests64iNOc[] = {
|
|||||||
"rv64i/I-MISALIGN_JMP-01","2000"
|
"rv64i/I-MISALIGN_JMP-01","2000"
|
||||||
};
|
};
|
||||||
string tests64i[] = '{
|
string tests64i[] = '{
|
||||||
"rv64i/I-LW-01", "4110",
|
|
||||||
"rv64i/I-ADD-01", "3000",
|
"rv64i/I-ADD-01", "3000",
|
||||||
"rv64i/I-ADDI-01", "3000",
|
"rv64i/I-ADDI-01", "3000",
|
||||||
"rv64i/I-ADDIW-01", "3000",
|
"rv64i/I-ADDIW-01", "3000",
|
||||||
@ -198,7 +197,6 @@ string tests64iNOc[] = {
|
|||||||
// "rv32m/I-REMU-01", "2000"
|
// "rv32m/I-REMU-01", "2000"
|
||||||
};
|
};
|
||||||
string tests32ic[] = '{
|
string tests32ic[] = '{
|
||||||
// "rv32ic/WALLY-C-ADHOC-01", "2000",
|
|
||||||
"rv32ic/I-C-ADD-01", "2000",
|
"rv32ic/I-C-ADD-01", "2000",
|
||||||
"rv32ic/I-C-ADDI-01", "2000",
|
"rv32ic/I-C-ADDI-01", "2000",
|
||||||
"rv32ic/I-C-AND-01", "2000",
|
"rv32ic/I-C-AND-01", "2000",
|
||||||
@ -347,9 +345,9 @@ string tests32i[] = {
|
|||||||
|
|
||||||
// Track names of instructions
|
// Track names of instructions
|
||||||
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
|
||||||
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
|
dut.hart.ifu.InstrF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
|
||||||
dut.hart.ifu.InstrM, InstrW,
|
dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
|
||||||
InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// initialize tests
|
// initialize tests
|
||||||
initial
|
initial
|
||||||
@ -452,14 +450,16 @@ endmodule
|
|||||||
|
|
||||||
module instrTrackerTB(
|
module instrTrackerTB(
|
||||||
input logic clk, reset, FlushE,
|
input logic clk, reset, FlushE,
|
||||||
input logic [31:0] InstrD,
|
input logic [31:0] InstrF, InstrD,
|
||||||
input logic [31:0] InstrE, InstrM,
|
input logic [31:0] InstrE, InstrM,
|
||||||
output logic [31:0] InstrW,
|
input logic [31:0] InstrW,
|
||||||
output string InstrDName, InstrEName, InstrMName, InstrWName);
|
// output logic [31:0] InstrW,
|
||||||
|
output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// stage Instr to Writeback for visualization
|
// stage Instr to Writeback for visualization
|
||||||
flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
|
// flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
|
||||||
|
|
||||||
|
instrNameDecTB fdec(InstrF, InstrFName);
|
||||||
instrNameDecTB ddec(InstrD, InstrDName);
|
instrNameDecTB ddec(InstrD, InstrDName);
|
||||||
instrNameDecTB edec(InstrE, InstrEName);
|
instrNameDecTB edec(InstrE, InstrEName);
|
||||||
instrNameDecTB mdec(InstrM, InstrMName);
|
instrNameDecTB mdec(InstrM, InstrMName);
|
||||||
|
Loading…
Reference in New Issue
Block a user