forked from Github_Repos/cvw
Resolved conflicts between different gpio files
This commit is contained in:
commit
f8059e9e40
3
.gitignore
vendored
3
.gitignore
vendored
@ -76,7 +76,8 @@ synthDC/*.log
|
||||
synthDC/*.svf
|
||||
synthDC/runs/
|
||||
synthDC/newRuns
|
||||
synthDC/PPAruns
|
||||
synthDC/ppa/PPAruns
|
||||
synthDC/ppa/plots
|
||||
synthDC/plots/
|
||||
synthDC/runArchive
|
||||
synthDC/hdl
|
||||
|
@ -157,7 +157,7 @@ void softfloatInit(void) {
|
||||
// RM: softfloat_round_min
|
||||
softfloat_roundingMode = softfloat_round_near_even;
|
||||
softfloat_exceptionFlags = 0; // clear exceptions
|
||||
softfloat_detectTininess = softfloat_tininess_beforeRounding; // RISC-V behavior for tininess
|
||||
softfloat_detectTininess = softfloat_tininess_afterRounding; // RISC-V behavior for tininess
|
||||
}
|
||||
|
||||
uint64_t parseNum(char *num) {
|
||||
|
@ -37,7 +37,7 @@ void softfloatInit(void) {
|
||||
// RM: softfloat_round_min
|
||||
softfloat_roundingMode = softfloat_round_near_even;
|
||||
softfloat_exceptionFlags = 0; // clear exceptions
|
||||
softfloat_detectTininess = softfloat_tininess_beforeRounding; // RISC-V behavior for tininess
|
||||
softfloat_detectTininess = softfloat_tininess_afterRounding; // RISC-V behavior for tininess
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -32,7 +32,7 @@
|
||||
`define DESIGN_COMPILER 0
|
||||
|
||||
// RV32 or RV64: XLEN = 32 or 64
|
||||
`define XLEN 32
|
||||
`define XLEN 64
|
||||
|
||||
// IEEE 754 compliance
|
||||
`define IEEE754 0
|
||||
|
@ -36,7 +36,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||
# start and run simulation
|
||||
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -o testbenchopt
|
||||
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084
|
||||
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084 -fatal 7
|
||||
|
||||
run -all
|
||||
run -all
|
||||
@ -46,7 +46,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
# start and run simulation
|
||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
||||
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt
|
||||
vsim -lib wkdir/work_${1}_${2} testbenchopt
|
||||
vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7
|
||||
# Adding coverage increases runtime from 2:00 to 4:29. Can't run it all the time
|
||||
#vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf
|
||||
#vsim -coverage -lib work_$2 workopt_$2
|
||||
|
@ -35,7 +35,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||
# start and run simulation
|
||||
vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -G NO_SPOOFING=0 -o testbenchopt
|
||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829
|
||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829 -fatal 7
|
||||
|
||||
#-- Run the Simulation
|
||||
run -all
|
||||
@ -49,7 +49,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||
# start and run simulation
|
||||
vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=0 -G INSTR_WAVEON=0 -G CHECKPOINT=0 -G NO_SPOOFING=1 -o testbenchopt
|
||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829
|
||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829 -fatal 7
|
||||
|
||||
#-- Run the Simulation
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
@ -69,7 +69,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063
|
||||
vopt +acc work.testbench -G TEST=$2 -G DEBUG=1 -o workopt
|
||||
|
||||
vsim workopt +nowarn3829
|
||||
vsim workopt +nowarn3829 -fatal 7
|
||||
|
||||
view wave
|
||||
#-- display input and output signals as hexidecimal values
|
||||
@ -78,12 +78,12 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
do wave.do
|
||||
|
||||
# power add generates the logging necessary for saif generation.
|
||||
power add -r /dut/core/*
|
||||
#power add -r /dut/core/*
|
||||
#-- Run the Simulation
|
||||
|
||||
run -all
|
||||
power off -r /dut/core/*
|
||||
power report -all -bsaif power.saif
|
||||
#power off -r /dut/core/*
|
||||
#power report -all -bsaif power.saif
|
||||
noview ../testbench/testbench.sv
|
||||
view wave
|
||||
}
|
||||
|
6
pipelined/src/cache/cache.sv
vendored
6
pipelined/src/cache/cache.sv
vendored
@ -168,9 +168,9 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGWPL, WORDLEN, MUXINTER
|
||||
else
|
||||
mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteData}}),
|
||||
.d1(CacheBusWriteData), .s(SetValid), .y(CacheWriteData));
|
||||
mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
|
||||
.d1({VictimTag, PAdr[SETTOP-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
|
||||
.d2({VictimTag, FlushAdr, {{OFFSETLEN}{1'b0}}}),
|
||||
mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
|
||||
.d1({VictimTag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
|
||||
.d2({VictimTag, FlushAdr, {OFFSETLEN{1'b0}}}),
|
||||
.s({SelFlush, SelEvict}), .y(CacheBusAdr));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -49,6 +49,8 @@ module ahblite (
|
||||
input logic [2:0] IFUBurstType,
|
||||
input logic [1:0] IFUTransType,
|
||||
input logic IFUTransComplete,
|
||||
input logic [(`XLEN-1)/8:0] ByteMaskM,
|
||||
|
||||
// Signals from Data Cache
|
||||
input logic [`PA_BITS-1:0] LSUBusAdr,
|
||||
input logic LSUBusRead,
|
||||
@ -67,6 +69,7 @@ module ahblite (
|
||||
(* mark_debug = "true" *) output logic HCLK, HRESETn,
|
||||
(* mark_debug = "true" *) output logic [31:0] HADDR, // *** one day switch to a different bus that supports the full physical address
|
||||
(* mark_debug = "true" *) output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
(* mark_debug = "true" *) output logic HWRITE,
|
||||
(* mark_debug = "true" *) output logic [2:0] HSIZE,
|
||||
(* mark_debug = "true" *) output logic [2:0] HBURST,
|
||||
@ -131,8 +134,8 @@ module ahblite (
|
||||
|
||||
// bus outputs
|
||||
assign #1 GrantData = (NextBusState == MEMREAD) | (NextBusState == MEMWRITE);
|
||||
assign #1 AccessAddress = (GrantData) ? LSUBusAdr[31:0] : IFUBusAdr[31:0];
|
||||
assign #1 HADDR = AccessAddress;
|
||||
assign AccessAddress = (GrantData) ? LSUBusAdr[31:0] : IFUBusAdr[31:0];
|
||||
assign HADDR = AccessAddress;
|
||||
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
|
||||
assign HSIZE = (GrantData) ? {1'b0, LSUBusSize[1:0]} : ISize;
|
||||
assign HBURST = (GrantData) ? LSUBurstType : IFUBurstType; // If doing memory accesses, use LSUburst, else use Instruction burst.
|
||||
@ -154,6 +157,7 @@ module ahblite (
|
||||
assign HTRANS = (GrantData) ? LSUTransType : IFUTransType; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
|
||||
assign HMASTLOCK = 0; // no locking supported
|
||||
assign HWRITE = (NextBusState == MEMWRITE);
|
||||
assign HWSTRB = ByteMaskM;
|
||||
// delay write data by one cycle for
|
||||
flopen #(`XLEN) wdreg(HCLK, (LSUBusAck | LSUBusInit), LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
||||
// delay signals for subword writes
|
||||
@ -163,13 +167,10 @@ module ahblite (
|
||||
|
||||
// Route signals to Instruction and Data Caches
|
||||
// *** assumes AHBW = XLEN
|
||||
|
||||
|
||||
assign IFUBusHRDATA = HRDATA;
|
||||
assign LSUBusHRDATA = HRDATA;
|
||||
assign IFUBusInit = (BusState != INSTRREAD) & (NextBusState == INSTRREAD);
|
||||
assign LSUBusInit = (((BusState != MEMREAD) & (NextBusState == MEMREAD)) | (BusState != MEMWRITE) & (NextBusState == MEMWRITE));
|
||||
assign IFUBusAck = HREADY & (BusState == INSTRREAD);
|
||||
assign LSUBusAck = HREADY & ((BusState == MEMREAD) | (BusState == MEMWRITE));
|
||||
|
||||
endmodule
|
||||
|
@ -31,6 +31,7 @@ module cvtshiftcalc(
|
||||
// | `NF-1 zeros | Mantissa | 0's if nessisary |
|
||||
// - otherwise:
|
||||
// | LzcInM | 0's if nessisary |
|
||||
// change to int shift to the left one
|
||||
assign CvtShiftIn = ToInt ? {{`XLEN{1'b0}}, XManM[`NF]&~CvtCalcExpM[`NE], XManM[`NF-1]|(CvtCalcExpM[`NE]&XManM[`NF]), XManM[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}} :
|
||||
CvtResDenormUfM ? {{`NF-1{1'b0}}, XManM, {`CVTLEN-`NF+1{1'b0}}} :
|
||||
{CvtLzcInM, {`NF+1{1'b0}}};
|
||||
|
@ -11,7 +11,7 @@ module divshiftcalc(
|
||||
output logic [`NE+1:0] DivDenormShift
|
||||
);
|
||||
logic [`NE+1:0] NormShift;
|
||||
logic [`NE+1:0] Nf, NfPlus1;
|
||||
logic [`NE+1:0] Nf;
|
||||
|
||||
// is the result denromalized
|
||||
// if the exponent is 1 then the result needs to be normalized then the result is denormalizes
|
||||
@ -19,51 +19,25 @@ module divshiftcalc(
|
||||
// select the proper fraction lengnth
|
||||
if (`FPSIZES == 1) begin
|
||||
assign Nf = (`NE+2)'(`NF);
|
||||
assign NfPlus1 = (`NE+2)'(`NF+1);
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign Nf = FmtM ? (`NE+2)'(`NF) : (`NE+2)'(`NF1);
|
||||
assign NfPlus1 = FmtM ? (`NE+2)'(`NF+1) : (`NE+2)'(`NF1+1);
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
always_comb
|
||||
case (FmtM)
|
||||
`FMT: begin
|
||||
Nf = (`NE+2)'(`NF);
|
||||
NfPlus1 = (`NE+2)'(`NF+1);
|
||||
end
|
||||
`FMT1: begin
|
||||
Nf = (`NE+2)'(`NF1);
|
||||
NfPlus1 = (`NE+2)'(`NF1+1);
|
||||
end
|
||||
`FMT2: begin
|
||||
Nf = (`NE+2)'(`NF2);
|
||||
NfPlus1 = (`NE+2)'(`NF2+1);
|
||||
end
|
||||
default: begin
|
||||
Nf = 1'bx;
|
||||
NfPlus1 = 1'bx;
|
||||
end
|
||||
`FMT: Nf = (`NE+2)'(`NF);
|
||||
`FMT1: Nf = (`NE+2)'(`NF1);
|
||||
`FMT2: Nf = (`NE+2)'(`NF2);
|
||||
default: Nf = 1'bx;
|
||||
endcase
|
||||
end else if (`FPSIZES == 4) begin
|
||||
always_comb
|
||||
case (FmtM)
|
||||
2'h3: begin
|
||||
Nf = (`NE+2)'(`Q_NF);
|
||||
NfPlus1 = (`NE+2)'(`Q_NF+1);
|
||||
end
|
||||
2'h1: begin
|
||||
Nf = (`NE+2)'(`D_NF);
|
||||
NfPlus1 = (`NE+2)'(`D_NF+1);
|
||||
end
|
||||
2'h0: begin
|
||||
Nf = (`NE+2)'(`S_NF);
|
||||
NfPlus1 = (`NE+2)'(`S_NF+1);
|
||||
end
|
||||
2'h2: begin
|
||||
Nf = (`NE+2)'(`H_NF);
|
||||
NfPlus1 = (`NE+2)'(`H_NF+1);
|
||||
end
|
||||
2'h3: Nf = (`NE+2)'(`Q_NF);
|
||||
2'h1: Nf = (`NE+2)'(`D_NF);
|
||||
2'h0: Nf = (`NE+2)'(`S_NF);
|
||||
2'h2: Nf = (`NE+2)'(`H_NF);
|
||||
endcase
|
||||
end
|
||||
// if the result is denormalized
|
||||
|
@ -179,7 +179,7 @@ module fcvt (
|
||||
// - shifted right by XLEN (XLEN)
|
||||
// - shift left to normilize (-1-ZeroCnt)
|
||||
// - newBias to make the biased exponent
|
||||
//
|
||||
// oldexp - biasold +newbias - (ZeroCnt+1)&(XDenormE|IntToFp)
|
||||
assign CvtCalcExpE = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE{1'b0}}, XDenormE|IntToFp} - {{`NE-`LOGCVTLEN+1{1'b0}}, (ZeroCnt&{`LOGCVTLEN{XDenormE|IntToFp}})};
|
||||
// find if the result is dnormal or underflows
|
||||
// - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0)
|
||||
|
@ -30,27 +30,27 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module fma(
|
||||
input logic XSgnE, YSgnE, ZSgnE, // input's signs
|
||||
input logic [`NE-1:0] XExpE, YExpE, ZExpE, // biased exponents in B(NE.0) format
|
||||
input logic [`NF:0] XManE, YManE, ZManE, // fractions in U(0.NF) format
|
||||
input logic Xs, Ys, Zs, // input's signs
|
||||
input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format
|
||||
input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format
|
||||
input logic XZeroE, YZeroE, ZZeroE, // is the input zero
|
||||
input logic [2:0] FOpCtrlE, // 000 = fmadd (X*Y)+Z, 001 = fmsub (X*Y)-Z, 010 = fnmsub -(X*Y)+Z, 011 = fnmadd -(X*Y)-Z, 100 = fmul (X*Y)
|
||||
input logic [`FMTBITS-1:0] FmtE, // precision 1 = double 0 = single
|
||||
output logic [`NE+1:0] ProdExpE, // X exponent + Y exponent - bias in B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign
|
||||
output logic [`NE+1:0] Pe, // the product's exponent B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign
|
||||
output logic AddendStickyE, // sticky bit that is calculated during alignment
|
||||
output logic KillProdE, // set the product to zero before addition if the product is too small to matter
|
||||
output logic [3*`NF+5:0] SumE, // the positive sum
|
||||
output logic [3*`NF+5:0] Sm, // the positive sum
|
||||
output logic NegSumE, // was the sum negitive
|
||||
output logic InvZE, // intert Z
|
||||
output logic InvA, // intert Z
|
||||
output logic ZSgnEffE, // the modified Z sign
|
||||
output logic PSgnE, // the product's sign
|
||||
output logic Ps, // the product's sign
|
||||
output logic [$clog2(3*`NF+7)-1:0] FmaNormCntE // normalization shift cnt
|
||||
);
|
||||
|
||||
logic [2*`NF+1:0] ProdManE; // 1.X frac * 1.Y frac in U(2.2Nf) format
|
||||
logic [3*`NF+5:0] AlignedAddendE; // Z aligned for addition in U(NF+5.2NF+1)
|
||||
logic [3*`NF+6:0] AlignedAddendInv; // aligned addend possibly inverted
|
||||
logic [2*`NF+1:0] ProdManKilled; // the product's mantissa possibly killed
|
||||
logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format
|
||||
logic [3*`NF+5:0] Am; // Z aligned for addition in U(NF+5.2NF+1)
|
||||
logic [3*`NF+6:0] AmInv; // aligned addend possibly inverted
|
||||
logic [2*`NF+1:0] PmKilled; // the product's mantissa possibly killed
|
||||
logic [3*`NF+6:0] PreSum, NegPreSum; // positive and negitve versions of the sum
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Calculate the product
|
||||
@ -62,46 +62,40 @@ module fma(
|
||||
|
||||
|
||||
// calculate the product's exponent
|
||||
expadd expadd(.FmtE, .XExpE, .YExpE, .XZeroE, .YZeroE,
|
||||
.ProdExpE);
|
||||
expadd expadd(.FmtE, .Xe, .Ye, .XZeroE, .YZeroE, .Pe);
|
||||
|
||||
// multiplication of the mantissa's
|
||||
mult mult(.XManE, .YManE, .ProdManE);
|
||||
mult mult(.Xm, .Ym, .Pm);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Alignment shifter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
align align(.ZExpE, .ZManE, .XZeroE, .YZeroE, .ZZeroE, .ProdExpE, .XExpE, .YExpE,
|
||||
.AlignedAddendE, .AddendStickyE, .KillProdE);
|
||||
align align(.Ze, .Zm, .XZeroE, .YZeroE, .ZZeroE, .Xe, .Ye,
|
||||
.Am, .AddendStickyE, .KillProdE);
|
||||
|
||||
// calculate the signs and take the opperation into account
|
||||
sign sign(.FOpCtrlE, .XSgnE, .YSgnE, .ZSgnE, .PSgnE, .ZSgnEffE);
|
||||
sign sign(.FOpCtrlE, .Xs, .Ys, .Zs, .Ps, .ZSgnEffE);
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////////////
|
||||
// // Addition/LZA
|
||||
// ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
add add(.AlignedAddendE, .ProdManE, .PSgnE, .ZSgnEffE, .KillProdE, .AlignedAddendInv, .ProdManKilled, .NegSumE, .PreSum, .NegPreSum, .InvZE, .XZeroE, .YZeroE);
|
||||
add add(.Am, .Pm, .Ps, .ZSgnEffE, .KillProdE, .AmInv, .PmKilled, .NegSumE, .PreSum, .NegPreSum, .InvA, .XZeroE, .YZeroE, .Sm);
|
||||
|
||||
loa loa(.A(AlignedAddendInv+{(3*`NF+6)'(0),InvZE}), .P(ProdManKilled), .FmaNormCntE);
|
||||
|
||||
// Choose the positive sum and accompanying LZA result.
|
||||
assign SumE = NegSumE ? NegPreSum[3*`NF+5:0] : PreSum[3*`NF+5:0];
|
||||
|
||||
|
||||
loa loa(.A(AmInv+{(3*`NF+6)'(0),InvA}), .P(PmKilled), .FmaNormCntE);
|
||||
endmodule
|
||||
|
||||
|
||||
module expadd(
|
||||
input logic [`FMTBITS-1:0] FmtE, // precision
|
||||
input logic [`NE-1:0] XExpE, YExpE, // input exponents
|
||||
input logic [`NE-1:0] Xe, Ye, // input exponents
|
||||
input logic XZeroE, YZeroE, // are the inputs zero
|
||||
output logic [`NE+1:0] ProdExpE // product's exponent B^(1023)NE+2
|
||||
output logic [`NE+1:0] Pe // product's exponent B^(1023)NE+2
|
||||
);
|
||||
|
||||
// kill the exponent if the product is zero - either X or Y is 0
|
||||
assign ProdExpE = ({2'b0, XExpE} + {2'b0, YExpE} - {2'b0, (`NE)'(`BIAS)})&{`NE+2{~(XZeroE|YZeroE)}};
|
||||
assign Pe = ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)})&{`NE+2{~(XZeroE|YZeroE)}};
|
||||
|
||||
endmodule
|
||||
|
||||
@ -110,10 +104,10 @@ endmodule
|
||||
|
||||
|
||||
module mult(
|
||||
input logic [`NF:0] XManE, YManE,
|
||||
output logic [2*`NF+1:0] ProdManE
|
||||
input logic [`NF:0] Xm, Ym,
|
||||
output logic [2*`NF+1:0] Pm
|
||||
);
|
||||
assign ProdManE = XManE * YManE;
|
||||
assign Pm = Xm * Ym;
|
||||
endmodule
|
||||
|
||||
|
||||
@ -125,8 +119,8 @@ endmodule
|
||||
|
||||
module sign(
|
||||
input logic [2:0] FOpCtrlE, // precision
|
||||
input logic XSgnE, YSgnE, ZSgnE, // are the inputs denormalized
|
||||
output logic PSgnE, // the product's sign - takes opperation into account
|
||||
input logic Xs, Ys, Zs, // are the inputs denormalized
|
||||
output logic Ps, // the product's sign - takes opperation into account
|
||||
output logic ZSgnEffE // Z sign used in fma - takes opperation into account
|
||||
);
|
||||
|
||||
@ -134,9 +128,9 @@ module sign(
|
||||
// Negate product's sign if FNMADD or FNMSUB
|
||||
|
||||
// flip is negation opperation
|
||||
assign PSgnE = XSgnE ^ YSgnE ^ (FOpCtrlE[1]&~FOpCtrlE[2]);
|
||||
assign Ps = Xs ^ Ys ^ (FOpCtrlE[1]&~FOpCtrlE[2]);
|
||||
// flip if subtraction
|
||||
assign ZSgnEffE = ZSgnE^FOpCtrlE[0];
|
||||
assign ZSgnEffE = Zs^FOpCtrlE[0];
|
||||
|
||||
endmodule
|
||||
|
||||
@ -148,11 +142,10 @@ endmodule
|
||||
|
||||
|
||||
module align(
|
||||
input logic [`NE-1:0] XExpE, YExpE, ZExpE, // biased exponents in B(NE.0) format
|
||||
input logic [`NF:0] ZManE, // fractions in U(0.NF) format]
|
||||
input logic [`NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
|
||||
input logic [`NF:0] Zm, // fractions in U(0.NF) format]
|
||||
input logic XZeroE, YZeroE, ZZeroE, // is the input zero
|
||||
input logic [`NE+1:0] ProdExpE, // the product's exponent
|
||||
output logic [3*`NF+5:0] AlignedAddendE, // Z aligned for addition in U(NF+5.2NF+1)
|
||||
output logic [3*`NF+5:0] Am, // Z aligned for addition in U(NF+5.2NF+1)
|
||||
output logic AddendStickyE, // Sticky bit calculated from the aliged addend
|
||||
output logic KillProdE // should the product be set to zero
|
||||
);
|
||||
@ -160,6 +153,7 @@ module align(
|
||||
logic [`NE+1:0] AlignCnt; // how far to shift the addend to align with the product in Q(NE+2.0) format
|
||||
logic [4*`NF+5:0] ZManShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1)
|
||||
logic [4*`NF+5:0] ZManPreShifted; // input to the alignment shifter U(NF+5.3NF+1)
|
||||
logic KillZ;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Alignment shifter
|
||||
@ -168,16 +162,19 @@ module align(
|
||||
// determine the shift count for alignment
|
||||
// - negitive means Z is larger, so shift Z left
|
||||
// - positive means the product is larger, so shift Z right
|
||||
// *** can we use ProdExpE instead of XExp/YExp to save an adder? DH 5/12/22
|
||||
// KP- yes we used ProdExpE originally but we did this for timing
|
||||
assign AlignCnt = XZeroE|YZeroE ? -(`NE+2)'($unsigned(1)) : {2'b0, XExpE} + {2'b0, YExpE} - {2'b0, (`NE)'(`BIAS)} + (`NE+2)'(`NF)+3 - {2'b0, ZExpE};
|
||||
// This could have been done using Pe, but AlignCnt is on the critical path so we replicate logic for speed
|
||||
assign AlignCnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)} + (`NE+2)'(`NF+3) - {2'b0, Ze};
|
||||
|
||||
// Defualt Addition without shifting
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
|
||||
// the 1'b0 before the added is because the product's mantissa has two bits before the binary point (xx.xxxxxxxxxx...)
|
||||
assign ZManPreShifted = {ZManE,(3*`NF+5)'(0)};
|
||||
assign ZManPreShifted = {Zm,(3*`NF+5)'(0)};
|
||||
|
||||
assign KillProdE = AlignCnt[`NE+1]|XZeroE|YZeroE;
|
||||
assign KillZ = $signed(AlignCnt)>$signed((`NE+2)'(3)*(`NE+2)'(`NF)+(`NE+2)'(5));
|
||||
|
||||
always_comb
|
||||
begin
|
||||
|
||||
@ -185,34 +182,31 @@ module align(
|
||||
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
if ($signed(AlignCnt) < $signed((`NE+2)'(0))) begin
|
||||
KillProdE = 1;
|
||||
if (KillProdE) begin
|
||||
ZManShifted = ZManPreShifted;
|
||||
AddendStickyE = ~(XZeroE|YZeroE);
|
||||
|
||||
// If the Addend is shifted right
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
end else if ($signed(AlignCnt)<=$signed((`NE+2)'(3)*(`NE+2)'(`NF)+(`NE+2)'(5))) begin
|
||||
KillProdE = 0;
|
||||
ZManShifted = ZManPreShifted >> AlignCnt;
|
||||
AddendStickyE = |(ZManShifted[`NF-1:0]);
|
||||
|
||||
// If the addend is too small to effect the addition
|
||||
// - The addend has to shift two past the end of the addend to be considered too small
|
||||
// - The 2 extra bits are needed for rounding
|
||||
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
end else begin
|
||||
KillProdE = 0;
|
||||
end else if (KillZ) begin
|
||||
ZManShifted = 0;
|
||||
AddendStickyE = ~ZZeroE;
|
||||
|
||||
// If the Addend is shifted right
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
end else begin
|
||||
ZManShifted = ZManPreShifted >> AlignCnt;
|
||||
AddendStickyE = |(ZManShifted[`NF-1:0]);
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
assign AlignedAddendE = ZManShifted[4*`NF+5:`NF];
|
||||
assign Am = ZManShifted[4*`NF+5:`NF];
|
||||
|
||||
endmodule
|
||||
|
||||
@ -223,15 +217,16 @@ endmodule
|
||||
|
||||
|
||||
module add(
|
||||
input logic [3*`NF+5:0] AlignedAddendE, // Z aligned for addition in U(NF+5.2NF+1)
|
||||
input logic [2*`NF+1:0] ProdManE, // the product's mantissa
|
||||
input logic PSgnE, ZSgnEffE,// the product and modified Z signs
|
||||
input logic [3*`NF+5:0] Am, // Z aligned for addition in U(NF+5.2NF+1)
|
||||
input logic [2*`NF+1:0] Pm, // the product's mantissa
|
||||
input logic Ps, ZSgnEffE,// the product and modified Z signs
|
||||
input logic KillProdE, // should the product be set to 0
|
||||
input logic XZeroE, YZeroE, // is the input zero
|
||||
output logic [3*`NF+6:0] AlignedAddendInv, // aligned addend possibly inverted
|
||||
output logic [2*`NF+1:0] ProdManKilled, // the product's mantissa possibly killed
|
||||
output logic [3*`NF+6:0] AmInv, // aligned addend possibly inverted
|
||||
output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed
|
||||
output logic NegSumE, // was the sum negitive
|
||||
output logic InvZE, // do you invert Z
|
||||
output logic InvA, // do you invert Z
|
||||
output logic [3*`NF+5:0] Sm, // the positive sum
|
||||
output logic [3*`NF+6:0] PreSum, NegPreSum// possibly negitive sum
|
||||
);
|
||||
|
||||
@ -242,27 +237,29 @@ module add(
|
||||
// Negate Z when doing one of the following opperations:
|
||||
// -prod + Z
|
||||
// prod - Z
|
||||
assign InvZE = ZSgnEffE ^ PSgnE;
|
||||
assign InvA = ZSgnEffE ^ Ps;
|
||||
|
||||
// Choose an inverted or non-inverted addend - the one has to be added now for the LZA
|
||||
assign AlignedAddendInv = InvZE ? {1'b1, ~AlignedAddendE} : {1'b0, AlignedAddendE};
|
||||
assign AmInv = InvA ? {1'b1, ~Am} : {1'b0, Am};
|
||||
// Kill the product if the product is too small to effect the addition (determined in fma1.sv)
|
||||
assign ProdManKilled = ProdManE&{2*`NF+2{~KillProdE}};
|
||||
assign PmKilled = Pm&{2*`NF+2{~KillProdE}};
|
||||
|
||||
|
||||
|
||||
// Do the addition
|
||||
// - calculate a positive and negitive sum in parallel
|
||||
assign PreSum = AlignedAddendInv + {{`NF+3{1'b0}}, ProdManKilled, 2'b0} + {{3*`NF+6{1'b0}}, InvZE};
|
||||
assign NegPreSum = XZeroE|YZeroE|KillProdE ? {1'b0, AlignedAddendE} : {1'b0, AlignedAddendE} + {{`NF+3{1'b1}}, ~ProdManKilled, 2'b0} + {(3*`NF+7)'(4)};
|
||||
assign PreSum = {{`NF+3{1'b0}}, PmKilled, 2'b0} + AmInv + {{3*`NF+6{1'b0}}, InvA};
|
||||
assign NegPreSum = {1'b0, Am} + {{`NF+3{1'b1}}, ~PmKilled, 2'b0} + {(3*`NF+7)'(4)};
|
||||
|
||||
// Is the sum negitive
|
||||
assign NegSumE = PreSum[3*`NF+6];
|
||||
|
||||
// Choose the positive sum and accompanying LZA result.
|
||||
assign Sm = NegSumE ? NegPreSum[3*`NF+5:0] : PreSum[3*`NF+5:0];
|
||||
endmodule
|
||||
|
||||
|
||||
module loa( //https://ieeexplore.ieee.org/abstract/document/930098
|
||||
module loa( // [Schmookler & Nowka, Leading zero anticipation and detection, IEEE Sym. Computer Arithmetic, 2001]
|
||||
input logic [3*`NF+6:0] A, // addend
|
||||
input logic [2*`NF+1:0] P, // product
|
||||
output logic [$clog2(3*`NF+7)-1:0] FmaNormCntE // normalization shift count for the positive result
|
||||
|
@ -27,7 +27,7 @@ module fmashiftcalc(
|
||||
// calculate the sum's exponent
|
||||
assign NormSumExp = KillProdM ? {2'b0, ZExpM[`NE-1:1], ZExpM[0]&~ZDenormM} : ProdExpM + -{{`NE+2-$unsigned($clog2(3*`NF+7)){1'b0}}, FmaNormCntM} - 1 + (`NE+2)'(`NF+4);
|
||||
|
||||
//convert the sum's exponent into the propper percision
|
||||
//convert the sum's exponent into the proper percision
|
||||
if (`FPSIZES == 1) begin
|
||||
assign ConvNormSumExp = NormSumExp;
|
||||
|
||||
@ -105,7 +105,7 @@ module fmashiftcalc(
|
||||
2'h1: PreResultDenorm = Sum1LEZ & Sum1GEFL & ~SumZero;
|
||||
2'h0: PreResultDenorm = Sum2LEZ & Sum2GEFL & ~SumZero;
|
||||
2'h2: PreResultDenorm = Sum3LEZ & Sum3GEFL & ~SumZero;
|
||||
endcase
|
||||
endcase // *** remove checking to see if it's underflowed and only check for less than zero for denorm checking
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -110,7 +110,7 @@ module fpu (
|
||||
logic [`NE+1:0] ProdExpE, ProdExpM;
|
||||
logic AddendStickyE, AddendStickyM;
|
||||
logic KillProdE, KillProdM;
|
||||
logic InvZE, InvZM;
|
||||
logic InvAE, InvAM;
|
||||
logic NegSumE, NegSumM;
|
||||
logic ZSgnEffE, ZSgnEffM;
|
||||
logic PSgnE, PSgnM;
|
||||
@ -249,10 +249,10 @@ module fpu (
|
||||
.XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE);
|
||||
|
||||
// fma - does multiply, add, and multiply-add instructions
|
||||
fma fma (.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE,
|
||||
.XManE, .YManE, .ZManE, .XZeroE, .YZeroE, .ZZeroE,
|
||||
.FOpCtrlE, .FmtE, .SumE, .NegSumE, .InvZE, .FmaNormCntE,
|
||||
.ZSgnEffE, .PSgnE, .ProdExpE, .AddendStickyE, .KillProdE);
|
||||
fma fma (.Xs(XSgnE), .Ys(YSgnE), .Zs(ZSgnE), .Xe(XExpE), .Ye(YExpE), .Ze(ZExpE),
|
||||
.Xm(XManE), .Ym(YManE), .Zm(ZManE), .XZeroE, .YZeroE, .ZZeroE,
|
||||
.FOpCtrlE, .FmtE, .Sm(SumE), .NegSumE, .InvA(InvAE), .FmaNormCntE,
|
||||
.ZSgnEffE, .Ps(PSgnE), .Pe(ProdExpE), .AddendStickyE, .KillProdE);
|
||||
|
||||
// fpdivsqrt using Goldschmidt's iteration
|
||||
if(`FLEN == 64) begin
|
||||
@ -351,8 +351,8 @@ module fpu (
|
||||
flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SumE, SumM);
|
||||
flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, ProdExpE, ProdExpM);
|
||||
flopenrc #($clog2(3*`NF+7)+6) EMRegFma4(clk, reset, FlushM, ~StallM,
|
||||
{AddendStickyE, KillProdE, InvZE, FmaNormCntE, NegSumE, ZSgnEffE, PSgnE},
|
||||
{AddendStickyM, KillProdM, InvZM, FmaNormCntM, NegSumM, ZSgnEffM, PSgnM});
|
||||
{AddendStickyE, KillProdE, InvAE, FmaNormCntE, NegSumE, ZSgnEffE, PSgnE},
|
||||
{AddendStickyM, KillProdM, InvAM, FmaNormCntM, NegSumM, ZSgnEffM, PSgnM});
|
||||
flopenrc #(`NE+`LOGCVTLEN+`CVTLEN+4) EMRegCvt(clk, reset, FlushM, ~StallM,
|
||||
{CvtCalcExpE, CvtShiftAmtE, CvtResDenormUfE, CvtResSgnE, IntZeroE, CvtLzcInE},
|
||||
{CvtCalcExpM, CvtShiftAmtM, CvtResDenormUfM, CvtResSgnM, IntZeroM, CvtLzcInM});
|
||||
@ -374,7 +374,7 @@ module fpu (
|
||||
postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, .EarlyTermShiftDiv2M,
|
||||
.AddendStickyM, .KillProdM, .XZeroM, .YZeroM, .ZZeroM, .XInfM, .YInfM, .Quot,
|
||||
.ZInfM, .XNaNM, .YNaNM, .ZNaNM, .XSNaNM, .YSNaNM, .ZSNaNM, .SumM, .DivCalcExpM,
|
||||
.NegSumM, .InvZM, .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, .DivNegStickyM,
|
||||
.NegSumM, .InvZM(InvAM), .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, .DivNegStickyM,
|
||||
.CvtCalcExpM, .CvtResDenormUfM,.CvtShiftAmtM, .CvtResSgnM, .FWriteIntM, .DivStickyM,
|
||||
.CvtLzcInM, .IntZeroM, .PostProcSelM, .PostProcResM, .PostProcFlgM, .FCvtIntResM);
|
||||
|
||||
|
20
pipelined/src/fpu/negateintres.sv
Normal file
20
pipelined/src/fpu/negateintres.sv
Normal file
@ -0,0 +1,20 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module negateintres(
|
||||
input logic XSgnM,
|
||||
input logic [`NORMSHIFTSZ-1:0] Shifted,
|
||||
input logic Signed,
|
||||
input logic Int64,
|
||||
input logic Plus1,
|
||||
output logic [1:0] NegResMSBS,
|
||||
output logic [`XLEN+1:0] NegRes
|
||||
);
|
||||
|
||||
|
||||
// round and negate the positive res if needed
|
||||
assign NegRes = XSgnM ? -({2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1};
|
||||
|
||||
assign NegResMSBS = Signed ? Int64 ? NegRes[`XLEN:`XLEN-1] : NegRes[32:31] :
|
||||
Int64 ? NegRes[`XLEN+1:`XLEN] : NegRes[33:32];
|
||||
|
||||
endmodule
|
@ -109,6 +109,7 @@ module postprocess(
|
||||
// conversion signals
|
||||
logic [`CVTLEN+`NF:0] CvtShiftIn; // number to be shifted
|
||||
logic [1:0] NegResMSBS;
|
||||
logic [`XLEN+1:0] NegRes;
|
||||
logic CvtResUf;
|
||||
// readability signals
|
||||
logic Mult; // multiply opperation
|
||||
@ -166,7 +167,7 @@ module postprocess(
|
||||
ShiftAmt = {{$clog2(`NORMSHIFTSZ)-$clog2(`CVTLEN+1){1'b0}}, CvtShiftAmtM};
|
||||
ShiftIn = {CvtShiftIn, {`NORMSHIFTSZ-`CVTLEN-`NF-1{1'b0}}};
|
||||
end
|
||||
2'b01: begin //div ***prob can take out
|
||||
2'b01: begin //div
|
||||
ShiftAmt = DivShiftAmt;
|
||||
ShiftIn = DivShiftIn;
|
||||
end
|
||||
@ -201,9 +202,11 @@ module postprocess(
|
||||
// Sign calculation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
resultsign resultsign(.FrmM, .PSgnM, .ZSgnEffM, .InvZM, .SumExp, .Round, .Sticky,
|
||||
.FmaOp, .DivOp, .CvtOp, .ZInfM, .InfIn, .NegSumM, .SumZero, .Mult,
|
||||
.XSgnM, .YSgnM, .CvtResSgnM, .RoundSgn, .ResSgn);
|
||||
resultsign resultsign(.FrmM, .PSgnM, .ZSgnEffM, .SumExp, .Round, .Sticky,
|
||||
.FmaOp, .ZInfM, .InfIn, .SumZero, .Mult, .RoundSgn, .ResSgn);
|
||||
|
||||
roundsign roundsign(.PSgnM, .ZSgnEffM, .InvZM, .FmaOp, .DivOp, .CvtOp, .NegSumM,
|
||||
.XSgnM, .YSgnM, .CvtResSgnM, .RoundSgn);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Flags
|
||||
@ -219,10 +222,11 @@ module postprocess(
|
||||
// Select the result
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
resultselect resultselect(.XSgnM, .ZExpM, .XManM, .YManM, .ZManM, .ZDenormM, .ZZeroM, .XZeroM, .IntInvalid,
|
||||
.IntZeroM, .FrmM, .OutFmt, .AddendStickyM, .KillProdM, .XNaNM, .YNaNM, .ZNaNM, .RoundAdd, .CvtResUf,
|
||||
.NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .NegResMSBS,
|
||||
negateintres negateintres(.XSgnM, .Shifted, .Signed, .Int64, .Plus1, .NegResMSBS, .NegRes);
|
||||
resultselect resultselect(.XSgnM, .XManM, .YManM, .ZManM, .XZeroM, .IntInvalid,
|
||||
.IntZeroM, .FrmM, .OutFmt, .XNaNM, .YNaNM, .ZNaNM, .CvtResUf,
|
||||
.NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .NegRes,
|
||||
.XInfM, .YInfM, .DivOp,
|
||||
.DivByZero, .FullResExp, .Shifted, .CvtCalcExpM, .ResSgn, .ResExp, .ResFrac, .PostProcResM, .FCvtIntResM);
|
||||
.DivByZero, .FullResExp, .CvtCalcExpM, .ResSgn, .ResExp, .ResFrac, .PostProcResM, .FCvtIntResM);
|
||||
|
||||
endmodule
|
||||
|
@ -1,45 +1,38 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module resultselect(
|
||||
input logic XSgnM, // input signs
|
||||
input logic [`NE-1:0] ZExpM, // input exponents
|
||||
input logic [`NF:0] XManM, YManM, ZManM, // input mantissas
|
||||
input logic XNaNM, YNaNM, ZNaNM, // inputs are NaN
|
||||
input logic [2:0] FrmM, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
|
||||
input logic [`FMTBITS-1:0] OutFmt, // output format
|
||||
input logic InfIn,
|
||||
input logic XInfM, YInfM,
|
||||
input logic XZeroM, ZZeroM,
|
||||
input logic IntZeroM,
|
||||
input logic NaNIn,
|
||||
input logic IntToFp,
|
||||
input logic Int64,
|
||||
input logic Signed,
|
||||
input logic CvtOp,
|
||||
input logic DivOp,
|
||||
input logic FmaOp,
|
||||
input logic [`NORMSHIFTSZ-1:0] Shifted, // is the sum zero
|
||||
input logic Plus1,
|
||||
input logic DivByZero,
|
||||
input logic [`NE:0] CvtCalcExpM, // the calculated expoent
|
||||
input logic AddendStickyM, // sticky bit that is calculated during alignment
|
||||
input logic KillProdM, // set the product to zero before addition if the product is too small to matter
|
||||
input logic ZDenormM, // is the original precision denormalized
|
||||
input logic ResSgn, // the res's sign
|
||||
input logic [`FLEN:0] RoundAdd, // how much to add to the res
|
||||
input logic IntInvalid, Invalid, Overflow, // flags
|
||||
input logic CvtResUf,
|
||||
input logic [`NE-1:0] ResExp, // Res exponent
|
||||
input logic [`NE+1:0] FullResExp, // Res exponent
|
||||
input logic [`NF-1:0] ResFrac, // Res fraction
|
||||
output logic [`FLEN-1:0] PostProcResM, // final res
|
||||
output logic [1:0] NegResMSBS,
|
||||
output logic [`XLEN-1:0] FCvtIntResM // final res
|
||||
input logic XSgnM, // input signs
|
||||
input logic [`NF:0] XManM, YManM, ZManM, // input mantissas
|
||||
input logic XNaNM, YNaNM, ZNaNM, // inputs are NaN
|
||||
input logic [2:0] FrmM, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
|
||||
input logic [`FMTBITS-1:0] OutFmt, // output format
|
||||
input logic InfIn,
|
||||
input logic XInfM, YInfM,
|
||||
input logic XZeroM,
|
||||
input logic IntZeroM,
|
||||
input logic NaNIn,
|
||||
input logic IntToFp,
|
||||
input logic Int64,
|
||||
input logic Signed,
|
||||
input logic CvtOp,
|
||||
input logic DivOp,
|
||||
input logic FmaOp,
|
||||
input logic Plus1,
|
||||
input logic DivByZero,
|
||||
input logic [`NE:0] CvtCalcExpM, // the calculated expoent
|
||||
input logic ResSgn, // the res's sign
|
||||
input logic IntInvalid, Invalid, Overflow, // flags
|
||||
input logic CvtResUf,
|
||||
input logic [`NE-1:0] ResExp, // Res exponent
|
||||
input logic [`NE+1:0] FullResExp, // Res exponent
|
||||
input logic [`NF-1:0] ResFrac, // Res fraction
|
||||
input logic [`XLEN+1:0] NegRes, // the negation of the result
|
||||
output logic [`FLEN-1:0] PostProcResM, // final res
|
||||
output logic [`XLEN-1:0] FCvtIntResM // final res
|
||||
);
|
||||
logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, UfRes, NormRes; // possible results
|
||||
logic OfResMax;
|
||||
logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output
|
||||
logic [`XLEN+1:0] NegRes; // the negation of the result
|
||||
logic KillRes;
|
||||
logic SelOfRes;
|
||||
|
||||
@ -244,7 +237,7 @@ module resultselect(
|
||||
// signed | -2^31 | -2^63 |
|
||||
// unsigned | 0 | 0 |
|
||||
//
|
||||
// - positive infinity and out of range negitive input and NaNs
|
||||
// - positive infinity and out of range positive input and NaNs
|
||||
// | int | long |
|
||||
// signed | 2^31-1 | 2^63-1 |
|
||||
// unsigned | 2^32-1 | 2^64-1 |
|
||||
@ -254,13 +247,7 @@ module resultselect(
|
||||
Int64 ? {1'b0, {`XLEN-1{1'b1}}} : {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}} : // signed positive
|
||||
XSgnM&~XNaNM ? {`XLEN{1'b0}} : // unsigned negitive
|
||||
{`XLEN{1'b1}};// unsigned positive
|
||||
|
||||
// round and negate the positive res if needed
|
||||
assign NegRes = XSgnM ? -({2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1};
|
||||
|
||||
//*** false critical path probably
|
||||
assign NegResMSBS = Signed ? Int64 ? NegRes[`XLEN:`XLEN-1] : NegRes[32:31] :
|
||||
Int64 ? NegRes[`XLEN+1:`XLEN] : NegRes[33:32];
|
||||
|
||||
|
||||
// select the integer output
|
||||
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
|
||||
|
@ -3,31 +3,21 @@
|
||||
module resultsign(
|
||||
input logic [2:0] FrmM,
|
||||
input logic PSgnM, ZSgnEffM,
|
||||
input logic InvZM,
|
||||
input logic XSgnM,
|
||||
input logic YSgnM,
|
||||
input logic ZInfM,
|
||||
input logic InfIn,
|
||||
input logic NegSumM,
|
||||
input logic FmaOp,
|
||||
input logic DivOp,
|
||||
input logic CvtOp,
|
||||
input logic [`NE+1:0] SumExp,
|
||||
input logic SumZero,
|
||||
input logic Mult,
|
||||
input logic Round,
|
||||
input logic Sticky,
|
||||
input logic CvtResSgnM,
|
||||
output logic RoundSgn,
|
||||
input logic RoundSgn,
|
||||
output logic ResSgn
|
||||
);
|
||||
|
||||
logic ZeroSgn;
|
||||
logic InfSgn;
|
||||
logic FmaResSgn;
|
||||
logic FmaResSgnTmp;
|
||||
logic Underflow;
|
||||
logic DivSgn;
|
||||
// logic ResultSgnTmp;
|
||||
|
||||
// Determine the sign if the sum is zero
|
||||
@ -42,14 +32,7 @@ module resultsign(
|
||||
// if p - z is the Sum negitive
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
assign FmaResSgnTmp = InvZM&(ZSgnEffM)&NegSumM | InvZM&PSgnM&~NegSumM | (ZSgnEffM&PSgnM);
|
||||
assign InfSgn = ZInfM ? ZSgnEffM : PSgnM;
|
||||
assign FmaResSgn = InfIn ? InfSgn : SumZero ? ZeroSgn : FmaResSgnTmp;
|
||||
|
||||
assign DivSgn = XSgnM^YSgnM;
|
||||
|
||||
// Sign for rounding calulation
|
||||
assign RoundSgn = (FmaResSgnTmp&FmaOp) | (CvtResSgnM&CvtOp) | (DivSgn&DivOp);
|
||||
assign ResSgn = (FmaResSgn&FmaOp) | (CvtResSgnM&CvtOp) | (DivSgn&DivOp);
|
||||
assign ResSgn = InfIn&FmaOp ? InfSgn : SumZero&FmaOp ? ZeroSgn : RoundSgn;
|
||||
|
||||
endmodule
|
32
pipelined/src/fpu/roundsign.sv
Normal file
32
pipelined/src/fpu/roundsign.sv
Normal file
@ -0,0 +1,32 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module roundsign(
|
||||
input logic PSgnM, ZSgnEffM,
|
||||
input logic InvZM,
|
||||
input logic XSgnM,
|
||||
input logic YSgnM,
|
||||
input logic NegSumM,
|
||||
input logic FmaOp,
|
||||
input logic DivOp,
|
||||
input logic CvtOp,
|
||||
input logic CvtResSgnM,
|
||||
output logic RoundSgn
|
||||
);
|
||||
|
||||
logic FmaResSgnTmp;
|
||||
logic DivSgn;
|
||||
|
||||
// is the result negitive
|
||||
// if p - z is the Sum negitive
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
assign FmaResSgnTmp = NegSumM^PSgnM; //*** move to execute stage
|
||||
|
||||
// assign FmaResSgnTmp = InvZM&(ZSgnEffM)&NegSumM | InvZM&PSgnM&~NegSumM | (ZSgnEffM&PSgnM);
|
||||
|
||||
assign DivSgn = XSgnM^YSgnM;
|
||||
|
||||
// Sign for rounding calulation
|
||||
assign RoundSgn = (FmaResSgnTmp&FmaOp) | (CvtResSgnM&CvtOp) | (DivSgn&DivOp);
|
||||
|
||||
endmodule
|
@ -4,12 +4,14 @@ module lzc #(parameter WIDTH = 1) (
|
||||
output logic [$clog2(WIDTH+1)-1:0] ZeroCnt
|
||||
);
|
||||
/* verilator lint_off CMPCONST */
|
||||
/* verilator lint_off WIDTH */
|
||||
|
||||
logic [$clog2(WIDTH+1)-1:0] i;
|
||||
int i;
|
||||
always_comb begin
|
||||
i = 0;
|
||||
while (~num[WIDTH-1-(32)'(i)] & $unsigned(i) <= $unsigned(($clog2(WIDTH+1))'(WIDTH-1))) i = i+1; // search for leading one
|
||||
while (~num[WIDTH-1-i] & (i < WIDTH)) i = i+1; // search for leading one
|
||||
ZeroCnt = i;
|
||||
end
|
||||
/* verilator lint_on WIDTH */
|
||||
/* verilator lint_on CMPCONST */
|
||||
endmodule
|
||||
|
@ -39,9 +39,11 @@ module priorityonehot #(parameter N = 8) (
|
||||
input logic [N-1:0] a,
|
||||
output logic [N-1:0] y
|
||||
);
|
||||
logic [N-1:0] nolower;
|
||||
|
||||
// create thermometer code mask
|
||||
prioritythermometer #(N) maskgen(.a({a[N-2:0], 1'b0}), .y(nolower));
|
||||
assign y = a & nolower;
|
||||
genvar i;
|
||||
assign y[0] = a[0];
|
||||
for (i=1; i<N; i++) begin:poh
|
||||
assign y[i] = a[i] & ~|a[i-1:0];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -77,6 +77,8 @@ module lsu (
|
||||
(* mark_debug = "true" *) output logic [2:0] LSUBurstType,
|
||||
(* mark_debug = "true" *) output logic [1:0] LSUTransType,
|
||||
(* mark_debug = "true" *) output logic LSUTransComplete,
|
||||
output logic [(`XLEN-1)/8:0] ByteMaskM,
|
||||
|
||||
// page table walker
|
||||
input logic [`XLEN-1:0] SATP_REGW, // from csr
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
@ -112,7 +114,6 @@ module lsu (
|
||||
logic LSUBusWriteCrit;
|
||||
logic DataDAPageFaultM;
|
||||
logic [`XLEN-1:0] LSUWriteDataM;
|
||||
logic [(`XLEN-1)/8:0] ByteMaskM;
|
||||
logic [`XLEN-1:0] WriteDataM;
|
||||
logic [`LLEN-1:0] ReadDataM;
|
||||
|
||||
@ -268,10 +269,10 @@ module lsu (
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Subword Accesses
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
subwordwrite subwordwrite(.LSUPAdrM(LSUPAdrM[2:0]),
|
||||
.LSUFunct3M, .AMOWriteDataM, .LittleEndianWriteDataM, .ByteMaskM);
|
||||
subwordread subwordread(.ReadDataWordMuxM, .LSUPAdrM(LSUPAdrM[2:0]),
|
||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||
subwordwrite subwordwrite(.LSUPAdrM(LSUPAdrM[2:0]),
|
||||
.LSUFunct3M, .AMOWriteDataM, .LittleEndianWriteDataM, .ByteMaskM);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MW Pipeline Register
|
||||
|
@ -39,7 +39,6 @@ module pmpadrdec (
|
||||
input logic [7:0] PMPCfg,
|
||||
input logic [`XLEN-1:0] PMPAdr,
|
||||
input logic PAgePMPAdrIn,
|
||||
input logic FirstMatch,
|
||||
output logic PAgePMPAdrOut,
|
||||
output logic Match, Active,
|
||||
output logic L, X, W, R
|
||||
@ -83,10 +82,10 @@ module pmpadrdec (
|
||||
(AdrMode == NA4 | AdrMode == NAPOT) ? NAMatch :
|
||||
0;
|
||||
|
||||
assign L = PMPCfg[7] & FirstMatch;
|
||||
assign X = PMPCfg[2] & FirstMatch;
|
||||
assign W = PMPCfg[1] & FirstMatch;
|
||||
assign R = PMPCfg[0] & FirstMatch;
|
||||
assign L = PMPCfg[7];
|
||||
assign X = PMPCfg[2];
|
||||
assign W = PMPCfg[1];
|
||||
assign R = PMPCfg[0];
|
||||
assign Active = |PMPCfg[4:3];
|
||||
endmodule
|
||||
|
||||
|
@ -67,16 +67,16 @@ module pmpchecker (
|
||||
.PMPAdr(PMPADDR_ARRAY_REGW),
|
||||
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
||||
.PAgePMPAdrOut(PAgePMPAdr),
|
||||
.FirstMatch, .Match, .Active, .L, .X, .W, .R);
|
||||
.Match, .Active, .L, .X, .W, .R);
|
||||
|
||||
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
||||
|
||||
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
|
||||
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
|
||||
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |(L & FirstMatch) : |Active;
|
||||
|
||||
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
|
||||
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
|
||||
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
|
||||
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ;
|
||||
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|(W & FirstMatch) ;
|
||||
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|(R & FirstMatch) ;
|
||||
end else begin: pmpchecker // no checker
|
||||
assign PMPInstrAccessFaultF = 0;
|
||||
assign PMPLoadAccessFaultM = 0;
|
||||
|
@ -34,9 +34,11 @@ module ahbapbbridge #(PERIPHS = 2) (
|
||||
input logic [PERIPHS-1:0] HSEL,
|
||||
input logic [31:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HREADY,
|
||||
// input logic [3:0] HPROT, // not used
|
||||
output logic [`XLEN-1:0] HRDATA,
|
||||
output logic HRESP, HREADYOUT,
|
||||
output logic PCLK, PRESETn,
|
||||
@ -45,30 +47,37 @@ module ahbapbbridge #(PERIPHS = 2) (
|
||||
output logic PENABLE,
|
||||
output logic [31:0] PADDR,
|
||||
output logic [`XLEN-1:0] PWDATA,
|
||||
// output logic [2:0] PPROT, // not used
|
||||
output logic [`XLEN/8-1:0] PSTRB,
|
||||
// output logic PWAKEUP // not used
|
||||
input logic [PERIPHS-1:0] PREADY,
|
||||
input var [`XLEN-1:0][PERIPHS-1:0] PRDATA
|
||||
input var [PERIPHS-1:0][`XLEN-1:0] PRDATA
|
||||
);
|
||||
|
||||
logic activeTrans;
|
||||
|
||||
logic initTrans, initTransSel, initTransSelD;
|
||||
logic nextPENABLE;
|
||||
logic PREADYOUT;
|
||||
|
||||
// convert AHB to APB signals
|
||||
assign PCLK = HCLK;
|
||||
assign PRESETn = HRESETn;
|
||||
|
||||
// identify start of a transaction
|
||||
assign activeTrans = (HTRANS == 2'b10); // only accept nonsequential transactions
|
||||
assign initTrans = activeTrans & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
||||
assign initTrans = HTRANS[1] & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
||||
assign initTransSel = initTrans & |HSEL; // capture data and address if any of the peripherals are selected
|
||||
|
||||
// delay AHB Address phase signals to align with AHB Data phase because APB expects them at the same time
|
||||
flopenr #(32) addrreg(HCLK, ~HRESETn, initTransSel, HADDR, PADDR);
|
||||
flopenr #(1) writereg(HCLK, ~HRESETn, initTransSel, HWRITE, PWRITE);
|
||||
// enable selreg with iniTrans rather than initTransSel so PSEL can turn off
|
||||
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, initTrans, HSEL & {PERIPHS{activeTrans}}, PSEL);
|
||||
// AHB Data phase signal doesn't need delay. Note that HWDATA is guaranteed to remain stable until READY is asserted
|
||||
flopen #(32) addrreg(HCLK, HREADY, HADDR, PADDR);
|
||||
flopenr #(1) writereg(HCLK, ~HRESETn, HREADY, HWRITE, PWRITE);
|
||||
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
||||
// PPROT[2:0] = {Data/InstrB, Secure, Privileged};
|
||||
// assign PPROT = {~HPROT[0], 1'b0, HPROT[1]}; // protection not presently used
|
||||
// assign PWAKEUP = 1'b1; // not used
|
||||
|
||||
// AHB Data phase signal doesn't need delay. Note that they are guaranteed to remain stable until READY is asserted
|
||||
assign PWDATA = HWDATA;
|
||||
assign PSTRB = HWSTRB;
|
||||
|
||||
// enable logic: goes high a cycle after initTrans, then back low on cycle after desired PREADY is asserted
|
||||
// cycle1: AHB puts HADDR, HWRITE, HSEL on bus. initTrans is 1, and these are captured
|
||||
@ -81,16 +90,19 @@ module ahbapbbridge #(PERIPHS = 2) (
|
||||
|
||||
// result and ready multiplexer
|
||||
int i;
|
||||
always_comb
|
||||
always_comb begin
|
||||
// default: no peripheral selected: read 0, indicate ready during access phase so bus doesn't hang
|
||||
// *** also could assert ready right away
|
||||
HRDATA = 0;
|
||||
PREADYOUT = 1'b1;
|
||||
for (i=0; i<PERIPHS; i++) begin
|
||||
// no peripheral selected: read 0, indicate ready
|
||||
HRDATA = 0;
|
||||
HREADYOUT = 1;
|
||||
if (PSEL[i]) begin // highest numbered peripheral has priority, but multiple PSEL should never be asserted
|
||||
HRDATA = PRDATA[i];
|
||||
HREADYOUT = PREADY[i];
|
||||
PREADYOUT = PREADY[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
assign HREADYOUT = PREADYOUT & ~initTransSelD; // don't raise HREADYOUT before access phase
|
||||
|
||||
// resp logic
|
||||
assign HRESP = 0; // bridge never indicates errors
|
||||
|
@ -28,7 +28,7 @@
|
||||
// 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 clint (
|
||||
@ -258,3 +258,4 @@ module graytobinary #(parameter N = `XLEN) (
|
||||
assign b[i] = g[i] ^ b[i+1];
|
||||
end
|
||||
endmodule
|
||||
*/
|
252
pipelined/src/uncore/clint_apb.sv
Normal file
252
pipelined/src/uncore/clint_apb.sv
Normal file
@ -0,0 +1,252 @@
|
||||
///////////////////////////////////////////
|
||||
// clint_apb.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 14 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Core-Local Interruptor
|
||||
// See FE310-G002-Manual-v19p05 for specifications
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 clint_apb (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [15:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
(* mark_debug = "true" *) output logic [63:0] MTIME,
|
||||
output logic MTimerInt, MSwInt);
|
||||
|
||||
logic MSIP;
|
||||
|
||||
logic [15:0] entry;
|
||||
logic memwrite;
|
||||
(* mark_debug = "true" *) logic [63:0] MTIMECMP;
|
||||
integer i, j;
|
||||
|
||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||
assign PREADY = 1'b1; // GPIO never takes >1 cycle to respond
|
||||
|
||||
// word aligned reads
|
||||
if (`XLEN==64) assign #2 entry = {PADDR[15:3], 3'b000};
|
||||
else assign #2 entry = {PADDR[15:2], 2'b00};
|
||||
|
||||
//swbytemask swbytemask(.Size(HSIZED[1:0]), .Adr(entry[2:0]), .ByteMask(PSTRB));
|
||||
|
||||
// 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
|
||||
if (`XLEN==64) begin:clint // 64-bit
|
||||
always @(posedge PCLK) begin
|
||||
case(entry)
|
||||
16'h0000: PRDATA <= {63'b0, MSIP};
|
||||
16'h4000: PRDATA <= MTIMECMP;
|
||||
16'hBFF8: PRDATA <= MTIME;
|
||||
default: PRDATA <= 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge PCLK or negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
MSIP <= 0;
|
||||
MTIMECMP <= 64'hFFFFFFFFFFFFFFFF; // Spec says MTIMECMP is not reset, but we reset to maximum value to prevent spurious timer interrupts
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= PWDATA[0];
|
||||
if (entry == 16'h4000) begin
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIMECMP[i*8 +: 8] <= PWDATA[i*8 +: 8]; // ***dh: this notation isn't in book yet - maybe from Ross
|
||||
end
|
||||
end
|
||||
|
||||
// eventually replace MTIME logic below with timereg
|
||||
// timereg tr(PCLK, PRESETn, TIMECLK, memwrite & (entry==16'hBFF8), 1'b0, PWDATA, MTIME, done);
|
||||
|
||||
always_ff @(posedge PCLK or negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
MTIME <= 0;
|
||||
end else if (memwrite & entry == 16'hBFF8) begin
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIME[j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
end else MTIME <= MTIME + 1;
|
||||
end else begin:clint // 32-bit
|
||||
always @(posedge PCLK) begin
|
||||
case(entry)
|
||||
16'h0000: PRDATA <= {31'b0, MSIP};
|
||||
16'h4000: PRDATA <= MTIMECMP[31:0];
|
||||
16'h4004: PRDATA <= MTIMECMP[63:32];
|
||||
16'hBFF8: PRDATA <= MTIME[31:0];
|
||||
16'hBFFC: PRDATA <= MTIME[63:32];
|
||||
default: PRDATA <= 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge PCLK or negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
MSIP <= 0;
|
||||
MTIMECMP <= 0;
|
||||
// MTIMECMP is not reset ***?
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= PWDATA[0];
|
||||
if (entry == 16'h4000)
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIMECMP[j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
if (entry == 16'h4004)
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIMECMP[32 + j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
end
|
||||
|
||||
// eventually replace MTIME logic below with timereg
|
||||
// timereg tr(PCLK, PRESETn, TIMECLK, memwrite & (entry==16'hBFF8), memwrite & (entry == 16'hBFFC), PWDATA, MTIME, done);
|
||||
always_ff @(posedge PCLK or negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
MTIME <= 0;
|
||||
// MTIMECMP is not reset
|
||||
end else if (memwrite & (entry == 16'hBFF8)) begin
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIME[i*8 +: 8] <= PWDATA[i*8 +: 8];
|
||||
end else if (memwrite & (entry == 16'hBFFC)) begin
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIME[32 + i*8 +: 8]<= PWDATA[i*8 +: 8];
|
||||
end else MTIME <= MTIME + 1;
|
||||
end
|
||||
|
||||
// Software interrupt when MSIP is set
|
||||
assign MSwInt = MSIP;
|
||||
// Timer interrupt when MTIME >= MTIMECMP
|
||||
assign MTimerInt = ({1'b0, MTIME} >= {1'b0, MTIMECMP}); // unsigned comparison
|
||||
|
||||
endmodule
|
||||
|
||||
module timeregsync(
|
||||
input logic clk, resetn,
|
||||
input logic we0, we1,
|
||||
input logic [`XLEN-1:0] wd,
|
||||
output logic [63:0] q);
|
||||
|
||||
if (`XLEN==64)
|
||||
always_ff @(posedge clk or negedge resetn)
|
||||
if (~resetn) q <= 0;
|
||||
else if (we0) q <= wd;
|
||||
else q <= q + 1;
|
||||
else
|
||||
always_ff @(posedge clk or negedge resetn)
|
||||
if (~resetn) q <= 0;
|
||||
else if (we0) q[31:0] <= wd;
|
||||
else if (we1) q[63:32] <= wd;
|
||||
else q <= q + 1;
|
||||
endmodule
|
||||
|
||||
module timereg(
|
||||
input logic PCLK, PRESETn, TIMECLK,
|
||||
input logic we0, we1,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
output logic [63:0] MTIME,
|
||||
output logic done);
|
||||
|
||||
// if (`TIMEBASE_SYNC) begin:timereg // use PCLK for MTIME
|
||||
if (1) begin:timereg // use PCLK for MTIME
|
||||
timregsync timeregsync(.clk(PCLK), .resetn(PRESETn), .we0, .we1, .wd(PWDATA), .q(MTIME));
|
||||
assign done = 1; // immediately completes
|
||||
end else begin // use asynchronous TIMECLK
|
||||
// TIME counter runs on TIMECLK but bus interface runs on PCLK
|
||||
// Need to synchronize reads and writes
|
||||
// This is subtle because synchronizing a binary counter on a per-bit basis could give a mix of old and new bits
|
||||
// Instead, we use a Gray coded counter that only changes one bit per cycle
|
||||
// Synchronizing this for a read is safe because we are guaranteed to get either the old or the new value.
|
||||
// Writing to the counter requires a request/acknowledge handshake to ensure the write value is held long enough.
|
||||
// The handshake signals are synchronized in each direction across the interface
|
||||
// There is no back pressure on instructions, so if multiple counter writes occur ***
|
||||
|
||||
logic req, req_sync, ack, we0_stored, we1_stored, ack_stored, resetn_sync;
|
||||
logic [`XLEN-1:0] wd_stored;
|
||||
logic [63:0] time_int, time_int_gc, time_gc, MTIME_GC;
|
||||
|
||||
// When a write enable is asserted for a cycle, sample the enables and data and raise a request until it is acknowledged
|
||||
// When the acknowledge falls, the transaction is done and the system is ready for another write.
|
||||
// ***look at redoing this assuming write enable and data are held rather than pulsed.
|
||||
always_ff @(posedge PCLK or negedge PRESETn)
|
||||
if (~PRESETn)
|
||||
req <= 0; // don't bother resetting wd
|
||||
else begin
|
||||
req <= we0 | we1 | req & ~ack;
|
||||
we0_stored <= we0;
|
||||
we1_stored <= we1;
|
||||
wd_stored <= PWDATA;
|
||||
ack_stored <= ack;
|
||||
done <= ack_stored & ~ack;
|
||||
end
|
||||
|
||||
// synchronize the reset and reqest into the TIMECLK domain
|
||||
sync resetsync(TIMECLK, PRESETn, resetn_sync);
|
||||
sync rsync(TIMECLK, req, req_sync);
|
||||
// synchronize the acknowledge back to the PCLK domain to indicate the request was handled and can be lowered
|
||||
sync async(PCLK, req_sync, ack);
|
||||
|
||||
timeregsync timeregsync(.clk(TIMECLK), .resetn(resetn_sync), .we0(we0_stored), .we1(we1_stored), .wd(wd_stored), .q(time_int));
|
||||
binarytogray b2g(time_int, time_int_gc);
|
||||
flop gcreg(TIMECLK, time_int_gc, time_gc);
|
||||
|
||||
sync timesync[63:0](PCLK, time_gc, MTIME_GC);
|
||||
graytobinary g2b(MTIME_GC, MTIME);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module binarytogray #(parameter N = `XLEN) (
|
||||
input logic [N-1:0] b,
|
||||
output logic [N-1:0] g);
|
||||
|
||||
// G[N-1] = B[N-1]; G[i] = B[i] ^ B[i+1] for 0 <= i < N-1
|
||||
// requires single layer of N-1 XOR gates
|
||||
assign g = b ^ {1'b0, b[N-1:1]};
|
||||
endmodule
|
||||
|
||||
module graytobinary #(parameter N = `XLEN) (
|
||||
input logic [N-1:0] g,
|
||||
output logic [N-1:0] b);
|
||||
|
||||
// B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1
|
||||
// requires rippling through N-1 XOR gates
|
||||
genvar i;
|
||||
assign b[N-1] = g[N-1];
|
||||
for (i=N-2; i >= 0; i--) begin:g2b
|
||||
assign b[i] = g[i] ^ b[i+1];
|
||||
end
|
||||
endmodule
|
@ -37,10 +37,12 @@ module gpio_apb (
|
||||
input logic PSEL,
|
||||
input logic [7:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic [31:0] iof0, iof1,
|
||||
input logic [31:0] GPIOPinsIn,
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn,
|
||||
output logic GPIOIntr);
|
||||
@ -48,6 +50,7 @@ module gpio_apb (
|
||||
logic [31:0] input0d, input1d, input2d, input3d;
|
||||
logic [31:0] input_val, input_en, output_en, output_val;
|
||||
logic [31:0] rise_ie, rise_ip, fall_ie, fall_ip, high_ie, high_ip, low_ie, low_ip;
|
||||
logic [31:0] out_xor, iof_en, iof_sel, iof_out, gpio_out;
|
||||
|
||||
logic [7:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
@ -55,8 +58,8 @@ module gpio_apb (
|
||||
|
||||
// APB I/O
|
||||
assign entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||
assign memwrite = PWRITE & PENABLE; // only write in access phase
|
||||
assign PREADY = PENABLE; // GPIO never takes >1 cycle to respond
|
||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||
assign PREADY = 1'b1; // GPIO never takes >1 cycle to respond
|
||||
|
||||
// account for subword read/write circuitry
|
||||
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
||||
@ -84,6 +87,9 @@ module gpio_apb (
|
||||
high_ip <= #1 0;
|
||||
low_ie <= #1 0;
|
||||
low_ip <= #1 0;
|
||||
iof_en <= #1 0;
|
||||
iof_sel <= #1 0;
|
||||
out_xor <= #1 0;
|
||||
end else begin // writes
|
||||
// According to FE310 spec: Once the interrupt is pending, it will remain set until a 1 is written to the *_ip register at that bit.
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
@ -96,7 +102,9 @@ module gpio_apb (
|
||||
8'h20: fall_ie <= #1 Din;
|
||||
8'h28: high_ie <= #1 Din;
|
||||
8'h30: low_ie <= #1 Din;
|
||||
8'h40: output_val <= #1 output_val ^ Din; // OUT_XOR
|
||||
8'h38: iof_en <= #1 Din;
|
||||
8'h3C: iof_sel <= #1 Din;
|
||||
8'h40: out_xor <= #1 Din;
|
||||
endcase
|
||||
/* verilator lint_on CASEINCOMPLETE */
|
||||
|
||||
@ -123,7 +131,9 @@ module gpio_apb (
|
||||
8'h2C: Dout <= #1 high_ip;
|
||||
8'h30: Dout <= #1 low_ie;
|
||||
8'h34: Dout <= #1 low_ip;
|
||||
8'h40: Dout <= #1 0; // OUT_XOR reads as 0
|
||||
8'h38: Dout <= #1 iof_en;
|
||||
8'h3C: Dout <= #1 iof_sel;
|
||||
8'h40: Dout <= #1 out_xor;
|
||||
default: Dout <= #1 0;
|
||||
endcase
|
||||
end
|
||||
@ -138,7 +148,9 @@ module gpio_apb (
|
||||
flop #(32) sync2(PCLK,input1d,input2d);
|
||||
flop #(32) sync3(PCLK,input2d,input3d);
|
||||
assign input_val = input3d;
|
||||
assign GPIOPinsOut = output_val;
|
||||
assign iof_out = iof_sel & iof1 | ~iof_sel & iof0; // per-bit mux between iof1 and iof0
|
||||
assign gpio_out = iof_en & iof_out | ~iof_en & output_val; // per-bit mux between IOF and output_val
|
||||
assign GPIOPinsOut = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||
assign GPIOPinsEn = output_en;
|
||||
|
||||
assign GPIOIntr = |{(rise_ip & rise_ie),(fall_ip & fall_ie),(high_ip & high_ie),(low_ip & low_ie)};
|
||||
|
@ -176,8 +176,8 @@ module plic (
|
||||
end
|
||||
|
||||
// pending interrupt requests
|
||||
//assign nextIntPending = (intPending | requests) & ~intInProgress;
|
||||
assign nextIntPending = requests;
|
||||
//assign nextIntPending = (intPending | requests) & ~intInProgress; //
|
||||
assign nextIntPending = requests; // DH: RT made this change May 2022, but it seems to be a bug to not consider intInProgress; see May 23, 2022 slack discussion
|
||||
flopr #(`N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending);
|
||||
|
||||
// context-dependent signals
|
||||
|
@ -39,6 +39,7 @@ module uncore (
|
||||
input logic TIMECLK,
|
||||
input logic [31:0] HADDR,
|
||||
input logic [`AHBW-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
@ -81,6 +82,22 @@ module uncore (
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic SDCIntM;
|
||||
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
// logic PSEL, PREADY;
|
||||
logic [1:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [`XLEN-1:0] PWDATA;
|
||||
logic [`XLEN/8-1:0] PSTRB;
|
||||
logic [1:0][`XLEN-1:0] PRDATA;
|
||||
// logic [`XLEN-1:0][8:0] PRDATA;
|
||||
logic [`XLEN-1:0] HREADBRIDGE;
|
||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||
|
||||
// *** to do:
|
||||
// hook up HWSTRB and remove subword write decoders
|
||||
// add other peripherals on AHB
|
||||
// HTRANS encoding
|
||||
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
// Use a trimmed down portion of the PMA checker - only the address decoders
|
||||
// Set access types to all 1 as don't cares because the MMU has already done access checking
|
||||
@ -89,130 +106,149 @@ module uncore (
|
||||
// unswizzle HSEL signals
|
||||
assign {HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELSDC} = HSELRegions[7:0];
|
||||
|
||||
// generate
|
||||
// on-chip RAM
|
||||
if (`RAM_SUPPORTED) begin : ram
|
||||
ram #(
|
||||
.BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram (
|
||||
.HCLK, .HRESETn,
|
||||
.HSELRam, .HADDR,
|
||||
.HWRITE, .HREADY, .HSIZED,
|
||||
.HTRANS, .HWDATA, .HREADRam,
|
||||
.HRESPRam, .HREADYRam);
|
||||
end
|
||||
// AHB -> APB bridge
|
||||
ahbapbbridge #(2) ahbapbbridge
|
||||
(.HCLK, .HRESETn, .HSEL({HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
||||
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
|
||||
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
|
||||
assign HSELBRIDGE = HSELGPIO | HSELCLINT; // if any of the bridge signals are selected
|
||||
|
||||
// on-chip RAM
|
||||
if (`RAM_SUPPORTED) begin : ram
|
||||
ram #(
|
||||
.BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram (
|
||||
.HCLK, .HRESETn,
|
||||
.HSELRam, .HADDR,
|
||||
.HWRITE, .HREADY, .HSIZED,
|
||||
.HTRANS, .HWDATA, .HREADRam,
|
||||
.HRESPRam, .HREADYRam);
|
||||
end
|
||||
|
||||
if (`BOOTROM_SUPPORTED) begin : bootrom
|
||||
ram_orig #(.BASE(`BOOTROM_BASE), .RANGE(`BOOTROM_RANGE))
|
||||
bootrom(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELRam(HSELBootRom), .HADDR,
|
||||
.HWRITE, .HREADY, .HTRANS, .HSIZED,
|
||||
.HWDATA,
|
||||
.HREADRam(HREADBootRom), .HRESPRam(HRESPBootRom), .HREADYRam(HREADYBootRom));
|
||||
end
|
||||
if (`BOOTROM_SUPPORTED) begin : bootrom
|
||||
ram_orig #(.BASE(`BOOTROM_BASE), .RANGE(`BOOTROM_RANGE))
|
||||
bootrom(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELRam(HSELBootRom), .HADDR,
|
||||
.HWRITE, .HREADY, .HTRANS, .HSIZED,
|
||||
.HWDATA,
|
||||
.HREADRam(HREADBootRom), .HRESPRam(HRESPBootRom), .HREADYRam(HREADYBootRom));
|
||||
end
|
||||
|
||||
// memory-mapped I/O peripherals
|
||||
if (`CLINT_SUPPORTED == 1) begin : clint
|
||||
clint clint(
|
||||
.HCLK, .HRESETn, .TIMECLK,
|
||||
.HSELCLINT, .HADDR(HADDR[15:0]), .HWRITE,
|
||||
.HWDATA, .HREADY, .HTRANS, .HSIZED,
|
||||
.HREADCLINT,
|
||||
.HRESPCLINT, .HREADYCLINT,
|
||||
.MTIME(MTIME_CLINT),
|
||||
.MTimerInt, .MSwInt);
|
||||
// memory-mapped I/O peripherals
|
||||
if (`CLINT_SUPPORTED == 1) begin : clint
|
||||
/* clint clint(
|
||||
.HCLK, .HRESETn, .TIMECLK,
|
||||
.HSELCLINT, .HADDR(HADDR[15:0]), .HWRITE,
|
||||
.HWDATA, .HREADY, .HTRANS, .HSIZED,
|
||||
.HREADCLINT,
|
||||
.HRESPCLINT, .HREADYCLINT,
|
||||
.MTIME(MTIME_CLINT),
|
||||
.MTimerInt, .MSwInt);*/
|
||||
clint_apb clint(
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[1]), .PADDR(PADDR[15:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[1]), .PREADY(PREADY[1]),
|
||||
.MTIME(MTIME_CLINT),
|
||||
.MTimerInt, .MSwInt);
|
||||
|
||||
end else begin : clint
|
||||
assign MTIME_CLINT = 0;
|
||||
assign MTimerInt = 0; assign MSwInt = 0;
|
||||
end
|
||||
if (`PLIC_SUPPORTED == 1) begin : plic
|
||||
plic plic(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELPLIC, .HADDR(HADDR[27:0]),
|
||||
.HWRITE, .HREADY, .HTRANS, .HWDATA,
|
||||
.UARTIntr, .GPIOIntr,
|
||||
.HREADPLIC, .HRESPPLIC, .HREADYPLIC,
|
||||
.MExtInt, .SExtInt);
|
||||
end else begin : plic
|
||||
assign MExtInt = 0;
|
||||
assign SExtInt = 0;
|
||||
end
|
||||
if (`GPIO_SUPPORTED == 1) begin : gpio
|
||||
gpio gpio(
|
||||
.HCLK, .HRESETn, .HSELGPIO,
|
||||
.HADDR(HADDR[7:0]),
|
||||
.HWDATA,
|
||||
.HWRITE, .HREADY,
|
||||
.HTRANS,
|
||||
.HREADGPIO,
|
||||
.HRESPGPIO, .HREADYGPIO,
|
||||
.GPIOPinsIn,
|
||||
.GPIOPinsOut, .GPIOPinsEn,
|
||||
.GPIOIntr);
|
||||
|
||||
end else begin : gpio
|
||||
assign GPIOPinsOut = 0; assign GPIOPinsEn = 0; assign GPIOIntr = 0;
|
||||
end
|
||||
if (`UART_SUPPORTED == 1) begin : uart
|
||||
uart uart(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELUART,
|
||||
.HADDR(HADDR[2:0]),
|
||||
.HWRITE, .HWDATA,
|
||||
.HREADUART, .HRESPUART, .HREADYUART,
|
||||
.SIN(UARTSin), .DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1), // from E1A driver from RS232 interface
|
||||
.SOUT(UARTSout), .RTSb(), .DTRb(), // to E1A driver to RS232 interface
|
||||
.OUT1b(), .OUT2b(), .INTR(UARTIntr), .TXRDYb(), .RXRDYb()); // to CPU
|
||||
end else begin : uart
|
||||
assign UARTSout = 0; assign UARTIntr = 0;
|
||||
end
|
||||
if (`SDC_SUPPORTED == 1) begin : sdc
|
||||
SDC SDC(.HCLK, .HRESETn, .HSELSDC, .HADDR(HADDR[4:0]), .HWRITE, .HREADY, .HTRANS,
|
||||
.HWDATA, .HREADSDC, .HRESPSDC, .HREADYSDC,
|
||||
// sdc interface
|
||||
.SDCCmdOut, .SDCCmdIn, .SDCCmdOE, .SDCDatIn, .SDCCLK,
|
||||
// interrupt to PLIC
|
||||
.SDCIntM
|
||||
);
|
||||
end else begin : sdc
|
||||
assign SDCCLK = 0;
|
||||
assign SDCCmdOut = 0;
|
||||
assign SDCCmdOE = 0;
|
||||
end
|
||||
// endgenerate
|
||||
end else begin : clint
|
||||
assign MTIME_CLINT = 0;
|
||||
assign MTimerInt = 0; assign MSwInt = 0;
|
||||
end
|
||||
if (`PLIC_SUPPORTED == 1) begin : plic
|
||||
plic plic(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELPLIC, .HADDR(HADDR[27:0]),
|
||||
.HWRITE, .HREADY, .HTRANS, .HWDATA,
|
||||
.UARTIntr, .GPIOIntr,
|
||||
.HREADPLIC, .HRESPPLIC, .HREADYPLIC,
|
||||
.MExtInt, .SExtInt);
|
||||
end else begin : plic
|
||||
assign MExtInt = 0;
|
||||
assign SExtInt = 0;
|
||||
end
|
||||
if (`GPIO_SUPPORTED == 1) begin : gpio
|
||||
/* gpio gpio(
|
||||
.HCLK, .HRESETn, .HSELGPIO,
|
||||
.HADDR(HADDR[7:0]),
|
||||
.HWDATA,
|
||||
.HWRITE, .HREADY,
|
||||
.HTRANS,
|
||||
.HREADGPIO,
|
||||
.HRESPGPIO, .HREADYGPIO,
|
||||
.GPIOPinsIn,
|
||||
.GPIOPinsOut, .GPIOPinsEn,
|
||||
.GPIOIntr); */
|
||||
gpio_apb gpio(
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[0]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[0]), .PREADY(PREADY[0]),
|
||||
.iof0(), .iof1(), .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .GPIOIntr);
|
||||
end else begin : gpio
|
||||
assign GPIOPinsOut = 0; assign GPIOPinsEn = 0; assign GPIOIntr = 0;
|
||||
end
|
||||
if (`UART_SUPPORTED == 1) begin : uart
|
||||
uart uart(
|
||||
.HCLK, .HRESETn,
|
||||
.HSELUART,
|
||||
.HADDR(HADDR[2:0]),
|
||||
.HWRITE, .HWDATA,
|
||||
.HREADUART, .HRESPUART, .HREADYUART,
|
||||
.SIN(UARTSin), .DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1), // from E1A driver from RS232 interface
|
||||
.SOUT(UARTSout), .RTSb(), .DTRb(), // to E1A driver to RS232 interface
|
||||
.OUT1b(), .OUT2b(), .INTR(UARTIntr), .TXRDYb(), .RXRDYb()); // to CPU
|
||||
end else begin : uart
|
||||
assign UARTSout = 0; assign UARTIntr = 0;
|
||||
end
|
||||
if (`SDC_SUPPORTED == 1) begin : sdc
|
||||
SDC SDC(.HCLK, .HRESETn, .HSELSDC, .HADDR(HADDR[4:0]), .HWRITE, .HREADY, .HTRANS,
|
||||
.HWDATA, .HREADSDC, .HRESPSDC, .HREADYSDC,
|
||||
// sdc interface
|
||||
.SDCCmdOut, .SDCCmdIn, .SDCCmdOE, .SDCDatIn, .SDCCLK,
|
||||
// interrupt to PLIC
|
||||
.SDCIntM
|
||||
);
|
||||
end else begin : sdc
|
||||
assign SDCCLK = 0;
|
||||
assign SDCCmdOut = 0;
|
||||
assign SDCCmdOE = 0;
|
||||
end
|
||||
|
||||
// mux could also include external memory
|
||||
// AHB Read Multiplexer
|
||||
assign HRDATA = ({`XLEN{HSELRamD}} & HREADRam) |
|
||||
({`XLEN{HSELEXTD}} & HRDATAEXT) |
|
||||
({`XLEN{HSELCLINTD}} & HREADCLINT) |
|
||||
// ({`XLEN{HSELCLINTD}} & HREADCLINT) |
|
||||
({`XLEN{HSELPLICD}} & HREADPLIC) |
|
||||
({`XLEN{HSELGPIOD}} & HREADGPIO) |
|
||||
// ({`XLEN{HSELGPIOD}} & HREADGPIO) |
|
||||
({`XLEN{HSELBRIDGED}} & HREADBRIDGE) |
|
||||
({`XLEN{HSELBootRomD}} & HREADBootRom) |
|
||||
({`XLEN{HSELUARTD}} & HREADUART) |
|
||||
({`XLEN{HSELSDCD}} & HREADSDC);
|
||||
|
||||
assign HRESP = HSELRamD & HRESPRam |
|
||||
HSELEXTD & HRESPEXT |
|
||||
HSELCLINTD & HRESPCLINT |
|
||||
// HSELCLINTD & HRESPCLINT |
|
||||
HSELPLICD & HRESPPLIC |
|
||||
HSELGPIOD & HRESPGPIO |
|
||||
// HSELGPIOD & HRESPGPIO |
|
||||
HSELBRIDGE & HRESPBRIDGE |
|
||||
HSELBootRomD & HRESPBootRom |
|
||||
HSELUARTD & HRESPUART |
|
||||
HSELSDC & HRESPSDC;
|
||||
|
||||
assign HREADY = HSELRamD & HREADYRam |
|
||||
HSELEXTD & HREADYEXT |
|
||||
HSELCLINTD & HREADYCLINT |
|
||||
// HSELCLINTD & HREADYCLINT |
|
||||
HSELPLICD & HREADYPLIC |
|
||||
HSELGPIOD & HREADYGPIO |
|
||||
// HSELGPIOD & HREADYGPIO |
|
||||
HSELBRIDGED & HREADYBRIDGE |
|
||||
HSELBootRomD & HREADYBootRom |
|
||||
HSELUARTD & HREADYUART |
|
||||
HSELSDCD & HREADYSDC |
|
||||
HSELNoneD; // don't lock up the bus if no region is being accessed
|
||||
|
||||
// *** remove HREADYGPIO, others
|
||||
|
||||
// Address Decoder Delay (figure 4-2 in spec)
|
||||
flopr #(9) hseldelayreg(HCLK, ~HRESETn, HSELRegions, {HSELNoneD, HSELEXTD, HSELBootRomD, HSELRamD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELSDCD});
|
||||
flopr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HSELBRIDGE, HSELBRIDGED);
|
||||
endmodule
|
||||
|
||||
|
@ -42,6 +42,7 @@ module wallypipelinedcore (
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [31:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
@ -115,6 +116,8 @@ module wallypipelinedcore (
|
||||
logic [1:0] PageType;
|
||||
logic sfencevmaM, wfiM, IntPendingM;
|
||||
logic SelHPTW;
|
||||
logic [`XLEN/8-1:0] ByteMaskM;
|
||||
|
||||
|
||||
// PMA checker signals
|
||||
var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0];
|
||||
@ -263,6 +266,7 @@ module wallypipelinedcore (
|
||||
// connected to ahb (all stay the same)
|
||||
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck, .LSUBusInit,
|
||||
.LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize, .LSUBurstType, .LSUTransType, .LSUTransComplete,
|
||||
.ByteMaskM,
|
||||
|
||||
// connect to csr or privilege and stay the same.
|
||||
.PrivilegeModeW, .BigEndianM, // connects to csr
|
||||
@ -309,9 +313,10 @@ module wallypipelinedcore (
|
||||
.LSUTransComplete,
|
||||
.LSUBusAck,
|
||||
.LSUBusInit,
|
||||
.ByteMaskM,
|
||||
|
||||
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn,
|
||||
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST,
|
||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST,
|
||||
.HPROT, .HTRANS, .HMASTLOCK, .HADDRD, .HSIZED,
|
||||
.HWRITED);
|
||||
|
||||
|
@ -48,6 +48,7 @@ module wallypipelinedsoc (
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [31:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
@ -79,6 +80,7 @@ module wallypipelinedsoc (
|
||||
logic [3:0] HSIZED;
|
||||
logic HWRITED;
|
||||
|
||||
|
||||
// synchronize reset to SOC clock domain
|
||||
synchronizer resetsync(.clk, .d(reset_ext), .q(reset));
|
||||
|
||||
@ -86,13 +88,13 @@ module wallypipelinedsoc (
|
||||
wallypipelinedcore core(.clk, .reset,
|
||||
.MTimerInt, .MExtInt, .SExtInt, .MSwInt,
|
||||
.MTIME_CLINT,
|
||||
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA,
|
||||
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
|
||||
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
|
||||
.HADDRD, .HSIZED, .HWRITED
|
||||
);
|
||||
|
||||
uncore uncore(.HCLK, .HRESETn, .TIMECLK,
|
||||
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HADDRD, .HSIZED, .HWRITED,
|
||||
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .UARTSin, .UARTSout, .MTIME_CLINT,
|
||||
.HSELEXT,
|
||||
|
BIN
pipelined/srt/inttestgen
Executable file
BIN
pipelined/srt/inttestgen
Executable file
Binary file not shown.
83
pipelined/srt/inttestgen.c
Normal file
83
pipelined/srt/inttestgen.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* testgen.c */
|
||||
|
||||
/* Written 10/31/96 by David Harris
|
||||
|
||||
This program creates test vectors for mantissa component
|
||||
of an IEEE floating point divider.
|
||||
*/
|
||||
|
||||
/* #includes */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define ENTRIES 10
|
||||
#define RANDOM_VECS 500
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long r, long rem);
|
||||
void printhex(FILE *fptr, long x);
|
||||
double random_input(void);
|
||||
|
||||
/* Main */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
long a, b, r, rem;
|
||||
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
|
||||
int i, j;
|
||||
|
||||
if ((fptr = fopen("inttestvectors","w")) == NULL) {
|
||||
fprintf(stderr, "Couldn't write testvectors file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i=0; i<ENTRIES; i++) {
|
||||
b = list[i];
|
||||
for (j=0; j<ENTRIES; j++) {
|
||||
a = list[j];
|
||||
r = a/b;
|
||||
rem = a%b;
|
||||
output(fptr, a, b, r, rem);
|
||||
}
|
||||
}
|
||||
|
||||
// for (i = 0; i< RANDOM_VECS; i++) {
|
||||
// a = random_input();
|
||||
// b = random_input();
|
||||
// r = a/b;
|
||||
// output(fptr, a, b, r);
|
||||
// }
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* Functions */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long r, long rem)
|
||||
{
|
||||
printhex(fptr, a);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, b);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, r);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, rem);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
void printhex(FILE *fptr, long m)
|
||||
{
|
||||
fprintf(fptr, "%016llx", m);
|
||||
}
|
||||
|
||||
double random_input(void)
|
||||
{
|
||||
return 1.0 + rand()/32767.0;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
add wave -noupdate /testbench/*
|
||||
add wave -noupdate /testbench/srt/*
|
||||
add wave -noupdate /testbench/srt/otfc2/*
|
||||
add wave -noupdate /testbench/srt/preproc/*
|
||||
add wave -noupdate /testbench/srt/divcounter/*
|
||||
|
@ -48,8 +48,8 @@ module srt (
|
||||
input logic Signed, // Interpret integers as signed 2's complement
|
||||
input logic Int, // Choose integer inputs
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
output logic rsign,
|
||||
output logic [`DIVLEN-1:0] Quot, Rem, QuotOTFC, // *** later handle integers
|
||||
output logic rsign, done,
|
||||
output logic [`DIVLEN-1:0] Rem, Quot, // *** later handle integers
|
||||
output logic [`NE-1:0] rExp,
|
||||
output logic [3:0] Flags
|
||||
);
|
||||
@ -59,11 +59,10 @@ module srt (
|
||||
logic calcSign;
|
||||
logic [`DIVLEN-1:0] X, Dpreproc;
|
||||
logic [`DIVLEN+3:0] WS, WSA, WSN, WC, WCA, WCN, D, Db, Dsel;
|
||||
logic [`DIVLEN+2:0] rp, rm;
|
||||
logic [$clog2(`XLEN+1)-1:0] intExp;
|
||||
logic [$clog2(`XLEN+1)-1:0] intExp, dur, calcDur;
|
||||
logic intSign;
|
||||
|
||||
srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, intSign);
|
||||
srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, calcDur, intSign);
|
||||
|
||||
// Top Muxes and Registers
|
||||
// When start is asserted, the inputs are loaded into the divider.
|
||||
@ -78,25 +77,25 @@ module srt (
|
||||
// Quotient Selection logic
|
||||
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
|
||||
qsel2 qsel2(WS[`DIVLEN+3:`DIVLEN], WC[`DIVLEN+3:`DIVLEN], qp, qz, qm);
|
||||
// Accumulate quotient digits in a shift register (now done in OTFC)
|
||||
qacc #(`DIVLEN+3) qacc(clk, Start, qp, qz, qm, rp, rm);
|
||||
|
||||
flopen #(`NE) expflop(clk, Start, calcExp, rExp);
|
||||
flopen #(1) signflop(clk, Start, calcSign, rsign);
|
||||
flopen #(7) durflop(clk, Start, calcDur, dur);
|
||||
|
||||
counter divcounter(clk, Start, dur, done);
|
||||
|
||||
// Divisor Selection logic
|
||||
inv dinv(D, Db);
|
||||
assign Db = ~D;
|
||||
mux3onehot #(`DIVLEN) divisorsel(Db, {(`DIVLEN+4){1'b0}}, D, qp, qz, qm, Dsel);
|
||||
|
||||
// Partial Product Generation
|
||||
csa #(`DIVLEN+4) csa(WS, WC, Dsel, qp, WSA, WCA);
|
||||
|
||||
otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qm, QuotOTFC);
|
||||
otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qm, Quot);
|
||||
|
||||
expcalc expcalc(.XExp, .YExp, .calcExp);
|
||||
|
||||
signcalc signcalc(.XSign, .YSign, .calcSign);
|
||||
|
||||
srtpostproc postproc(rp, rm, Quot);
|
||||
endmodule
|
||||
|
||||
////////////////
|
||||
@ -115,7 +114,7 @@ module srtpreproc (
|
||||
input logic Int, // Choose integer inputs
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
output logic [`DIVLEN-1:0] X, D,
|
||||
output logic [$clog2(`XLEN+1)-1:0] intExp, // Quotient integer exponent
|
||||
output logic [$clog2(`XLEN+1)-1:0] intExp, dur, // Quotient integer exponent
|
||||
output logic intSign // Quotient integer sign
|
||||
);
|
||||
|
||||
@ -132,8 +131,8 @@ module srtpreproc (
|
||||
assign ExtraA = {PosA, {`EXTRAINTBITS{1'b0}}};
|
||||
assign ExtraB = {PosB, {`EXTRAINTBITS{1'b0}}};
|
||||
|
||||
assign PreprocA = ExtraA << zeroCntA;
|
||||
assign PreprocB = ExtraB << zeroCntB;
|
||||
assign PreprocA = ExtraA << (zeroCntA + 1);
|
||||
assign PreprocB = ExtraB << (zeroCntB + 1);
|
||||
assign PreprocX = {SrcXFrac, {`EXTRAFRACBITS{1'b0}}};
|
||||
assign PreprocY = {SrcYFrac, {`EXTRAFRACBITS{1'b0}}};
|
||||
|
||||
@ -142,6 +141,8 @@ module srtpreproc (
|
||||
assign D = Int ? PreprocB : PreprocY;
|
||||
assign intExp = zeroCntB - zeroCntA + 1;
|
||||
assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
|
||||
|
||||
assign dur = Int ? (intExp & {7{~intExp[6]}}) : (`DIVLEN + 2);
|
||||
endmodule
|
||||
|
||||
/////////////////////////////////
|
||||
@ -179,38 +180,10 @@ module qsel2 ( // *** eventually just change to 4 bits
|
||||
assign #1 qm = magnitude & sign;
|
||||
endmodule
|
||||
|
||||
//////////
|
||||
// qacc //
|
||||
//////////
|
||||
// To be replaced by OTFC
|
||||
module qacc #(parameter N=68) (
|
||||
input logic clk,
|
||||
input logic req,
|
||||
input logic qp, qz, qm,
|
||||
output logic [N-1:0] rp, rm
|
||||
);
|
||||
|
||||
flopr #(N) rmreg(clk, req, {rm[N-2:0], qm}, rm);
|
||||
flopr #(N) rpreg(clk, req, {rp[N-2:0], qp}, rp);
|
||||
/* always @(posedge clk)
|
||||
begin
|
||||
if (req)
|
||||
begin
|
||||
rp <= #1 0;
|
||||
rm <= #1 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
rm <= #1 {rm[54:0], qm};
|
||||
rp <= #1 {rp[54:0], qp};
|
||||
end
|
||||
end */
|
||||
endmodule
|
||||
|
||||
///////////////////////////////////
|
||||
// On-The-Fly Converter, Radix 2 //
|
||||
///////////////////////////////////
|
||||
module otfc2 #(parameter N=65) (
|
||||
module otfc2 #(parameter N=64) (
|
||||
input logic clk,
|
||||
input logic Start,
|
||||
input logic qp, qz, qm,
|
||||
@ -254,13 +227,29 @@ module otfc2 #(parameter N=65) (
|
||||
|
||||
endmodule
|
||||
|
||||
/////////
|
||||
// inv //
|
||||
/////////
|
||||
module inv(input logic [`DIVLEN+3:0] in,
|
||||
output logic [`DIVLEN+3:0] out);
|
||||
/////////////
|
||||
// counter //
|
||||
/////////////
|
||||
module counter(input logic clk,
|
||||
input logic req,
|
||||
input logic [$clog2(`XLEN+1)-1:0] dur,
|
||||
output logic done);
|
||||
|
||||
logic [$clog2(`XLEN+1)-1:0] count;
|
||||
|
||||
assign #1 out = ~in;
|
||||
// This block of control logic sequences the divider
|
||||
// through its iterations. You may modify it if you
|
||||
// build a divider which completes in fewer iterations.
|
||||
// You are not responsible for the (trivial) circuit
|
||||
// design of the block.
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (count == dur) done <= #1 1;
|
||||
else if (done | req) done <= #1 0;
|
||||
if (req) count <= #1 0;
|
||||
else count <= #1 count+1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
//////////
|
||||
@ -323,43 +312,4 @@ module signcalc(
|
||||
|
||||
assign calcSign = XSign ^ YSign;
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////
|
||||
// Postprocessing //
|
||||
////////////////////
|
||||
module srtpostproc (
|
||||
input [`DIVLEN+2:0] rp, rm,
|
||||
output [`DIVLEN-1:0] Quot
|
||||
);
|
||||
|
||||
//assign Quot = rp - rm;
|
||||
finaladd #(`DIVLEN+3) finaladd(rp, rm, Quot);
|
||||
endmodule
|
||||
|
||||
//////////////
|
||||
// finaladd //
|
||||
//////////////
|
||||
module finaladd #(parameter N=68) (
|
||||
input logic [N-1:0] rp, rm,
|
||||
output logic [N-4:0] r
|
||||
);
|
||||
|
||||
logic [N-1:0] diff;
|
||||
|
||||
// this magic block performs the final addition for you
|
||||
// to convert the positive and negative quotient digits
|
||||
// into a normalized mantissa. It returns the 52 bit
|
||||
// mantissa after shifting to guarantee a leading 1.
|
||||
// You can assume this block operates in one cycle
|
||||
// and do not need to budget it in your area and power
|
||||
// calculations.
|
||||
|
||||
// Since no rounding is performed, the result may be too
|
||||
// small by one unit in the least significant place (ulp).
|
||||
// The checker ignores such an error.
|
||||
|
||||
assign #1 diff = rp - rm;
|
||||
assign #1 r = diff[N-1] ? diff[N-2:2] : diff[N-3:1];
|
||||
endmodule
|
||||
|
||||
endmodule
|
@ -3,26 +3,26 @@
|
||||
/////////////
|
||||
// counter //
|
||||
/////////////
|
||||
module counter(input logic clk,
|
||||
input logic req,
|
||||
output logic done);
|
||||
// module counter(input logic clk,
|
||||
// input logic req,
|
||||
// output logic done);
|
||||
|
||||
logic [7:0] count;
|
||||
// logic [7:0] count;
|
||||
|
||||
// This block of control logic sequences the divider
|
||||
// through its iterations. You may modify it if you
|
||||
// build a divider which completes in fewer iterations.
|
||||
// You are not responsible for the (trivial) circuit
|
||||
// design of the block.
|
||||
// // This block of control logic sequences the divider
|
||||
// // through its iterations. You may modify it if you
|
||||
// // build a divider which completes in fewer iterations.
|
||||
// // You are not responsible for the (trivial) circuit
|
||||
// // design of the block.
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (count == `DIVLEN + 2) done <= #1 1;
|
||||
else if (done | req) done <= #1 0;
|
||||
if (req) count <= #1 0;
|
||||
else count <= #1 count+1;
|
||||
end
|
||||
endmodule
|
||||
// always @(posedge clk)
|
||||
// begin
|
||||
// if (count == `DIVLEN + 2) done <= #1 1;
|
||||
// else if (done | req) done <= #1 0;
|
||||
// if (req) count <= #1 0;
|
||||
// else count <= #1 count+1;
|
||||
// end
|
||||
// endmodule
|
||||
|
||||
///////////
|
||||
// clock //
|
||||
@ -42,21 +42,23 @@ module testbench;
|
||||
logic clk;
|
||||
logic req;
|
||||
logic done;
|
||||
logic Int;
|
||||
logic [63:0] a, b;
|
||||
logic [51:0] afrac, bfrac;
|
||||
logic [10:0] aExp, bExp;
|
||||
logic asign, bsign;
|
||||
logic [51:0] r, rOTFC;
|
||||
logic [`DIVLEN-1:0] Quot, QuotOTFC;
|
||||
logic [54:0] rp, rm; // positive quotient digits
|
||||
logic [51:0] r;
|
||||
logic [63:0] rInt;
|
||||
logic [`DIVLEN-1:0] Quot;
|
||||
|
||||
// Test parameters
|
||||
parameter MEM_SIZE = 40000;
|
||||
parameter MEM_WIDTH = 64+64+64;
|
||||
parameter MEM_WIDTH = 64+64+64+64;
|
||||
|
||||
`define memr 63:0
|
||||
`define memb 127:64
|
||||
`define mema 191:128
|
||||
`define memrem 63:0
|
||||
`define memr 127:64
|
||||
`define memb 191:128
|
||||
`define mema 255:192
|
||||
|
||||
// Test logicisters
|
||||
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
|
||||
@ -67,18 +69,20 @@ module testbench;
|
||||
logic rsign;
|
||||
integer testnum, errors;
|
||||
|
||||
assign Int = 1'b1;
|
||||
|
||||
// Divider
|
||||
srt srt(.clk, .Start(req),
|
||||
.Stall(1'b0), .Flush(1'b0),
|
||||
.XExp(aExp), .YExp(bExp), .rExp,
|
||||
.XSign(asign), .YSign(bsign), .rsign,
|
||||
.SrcXFrac(afrac), .SrcYFrac(bfrac),
|
||||
.SrcA('0), .SrcB('0), .Fmt(2'b00),
|
||||
.W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0),
|
||||
.Quot, .QuotOTFC, .Rem(), .Flags());
|
||||
.SrcA(a), .SrcB(b), .Fmt(2'b00),
|
||||
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt(1'b0),
|
||||
.Quot, .Rem(), .Flags(), .done);
|
||||
|
||||
// Counter
|
||||
counter counter(clk, req, done);
|
||||
// counter counter(clk, req, done);
|
||||
|
||||
|
||||
initial
|
||||
@ -94,7 +98,7 @@ module testbench;
|
||||
begin
|
||||
testnum = 0;
|
||||
errors = 0;
|
||||
$readmemh ("testvectors", Tests);
|
||||
$readmemh ("inttestvectors", Tests);
|
||||
Vec = Tests[testnum];
|
||||
a = Vec[`mema];
|
||||
{asign, aExp, afrac} = a;
|
||||
@ -102,7 +106,7 @@ module testbench;
|
||||
{bsign, bExp, bfrac} = b;
|
||||
nextr = Vec[`memr];
|
||||
r = Quot[(`DIVLEN - 1):(`DIVLEN - 52)];
|
||||
rOTFC = QuotOTFC[(`DIVLEN - 1):(`DIVLEN - 52)];
|
||||
rInt = Quot;
|
||||
req <= #5 1;
|
||||
end
|
||||
|
||||
@ -111,45 +115,54 @@ module testbench;
|
||||
always @(posedge clk)
|
||||
begin
|
||||
r = Quot[(`DIVLEN - 1):(`DIVLEN - 52)];
|
||||
rOTFC = QuotOTFC[(`DIVLEN - 1):(`DIVLEN - 52)];
|
||||
if (done)
|
||||
begin
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
if ((rsign !== correctr[63]) | (rExp !== correctr[62:52]) | ($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
begin
|
||||
errors = errors+1;
|
||||
$display("result was %h_%h, should be %h %h %h\n", rExp, r, correctr, diffn, diffp);
|
||||
$display("failed\n");
|
||||
$stop;
|
||||
end
|
||||
if (r !== rOTFC) // Check if OTFC works
|
||||
begin
|
||||
errors = errors+1;
|
||||
$display("OTFC is %h, should be %h\n", rOTFC, r);
|
||||
$display("failed\n");
|
||||
// $stop;
|
||||
rInt = Quot;
|
||||
if (done) begin
|
||||
if (~Int) begin
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
if ((rsign !== correctr[63]) | (rExp !== correctr[62:52]) | ($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
begin
|
||||
errors = errors+1;
|
||||
$display("result was %h_%h, should be %h %h %h\n", rExp, r, correctr, diffn, diffp);
|
||||
$display("failed\n");
|
||||
$stop;
|
||||
end
|
||||
if (afrac === 52'hxxxxxxxxxxxxx)
|
||||
begin
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
req <= #5 1;
|
||||
diffp = correctr[63:0] - rInt;
|
||||
diffn = rInt - correctr[63:0];
|
||||
if (($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
begin
|
||||
errors = errors+1;
|
||||
$display("result was %h, should be %h %h %h\n", rInt, correctr, diffn, diffp);
|
||||
$display("failed\n");
|
||||
$stop;
|
||||
end
|
||||
if (afrac === 52'hxxxxxxxxxxxxx)
|
||||
begin
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
end
|
||||
if (afrac === 52'hxxxxxxxxxxxxx)
|
||||
begin
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
if (req)
|
||||
begin
|
||||
req <= #5 0;
|
||||
correctr = nextr;
|
||||
testnum = testnum+1;
|
||||
Vec = Tests[testnum];
|
||||
$display("a = %h b = %h",a,b);
|
||||
a = Vec[`mema];
|
||||
{asign, aExp, afrac} = a;
|
||||
b = Vec[`memb];
|
||||
{bsign, bExp, bfrac} = b;
|
||||
nextr = Vec[`memr];
|
||||
end
|
||||
if (req) begin
|
||||
req <= #5 0;
|
||||
correctr = nextr;
|
||||
testnum = testnum+1;
|
||||
Vec = Tests[testnum];
|
||||
$display("a = %h b = %h",a,b);
|
||||
a = Vec[`mema];
|
||||
{asign, aExp, afrac} = a;
|
||||
b = Vec[`memb];
|
||||
{bsign, bExp, bfrac} = b;
|
||||
nextr = Vec[`memr];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -61,15 +61,15 @@ module testbenchfp;
|
||||
|
||||
// in-between FMA signals
|
||||
logic Mult;
|
||||
logic [`NE+1:0] ProdExpE;
|
||||
logic [`NE+1:0] Pe;
|
||||
logic AddendStickyE;
|
||||
logic KillProdE;
|
||||
logic [$clog2(3*`NF+7)-1:0] FmaNormCntE;
|
||||
logic [3*`NF+5:0] SumE;
|
||||
logic [3*`NF+5:0] Sm;
|
||||
logic InvZE;
|
||||
logic NegSumE;
|
||||
logic ZSgnEffE;
|
||||
logic PSgnE;
|
||||
logic Ps;
|
||||
logic DivSticky;
|
||||
logic DivNegSticky;
|
||||
logic [`NE+1:0] DivCalcExp;
|
||||
@ -637,12 +637,12 @@ module testbenchfp;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// instantiate devices under test
|
||||
fma fma(.XSgnE(XSgn), .YSgnE(YSgn), .ZSgnE(ZSgn),
|
||||
.XExpE(XExp), .YExpE(YExp), .ZExpE(ZExp),
|
||||
.XManE(XMan), .YManE(YMan), .ZManE(ZMan),
|
||||
fma fma(.Xs(XSgn), .Ys(YSgn), .Zs(ZSgn),
|
||||
.Xe(XExp), .Ye(YExp), .Ze(ZExp),
|
||||
.Xm(XMan), .Ym(YMan), .Zm(ZMan),
|
||||
.XZeroE(XZero), .YZeroE(YZero), .ZZeroE(ZZero),
|
||||
.FOpCtrlE(OpCtrlVal), .FmtE(ModFmt), .SumE, .NegSumE, .InvZE, .FmaNormCntE, .ZSgnEffE, .PSgnE,
|
||||
.ProdExpE, .AddendStickyE, .KillProdE);
|
||||
.FOpCtrlE(OpCtrlVal), .FmtE(ModFmt), .Sm, .NegSumE, .InvA(InvZE), .FmaNormCntE, .ZSgnEffE, .Ps,
|
||||
.Pe, .AddendStickyE, .KillProdE);
|
||||
|
||||
postprocess postprocess(.XSgnM(XSgn), .YSgnM(YSgn), .PostProcSelM(UnitVal[1:0]),
|
||||
.ZExpM(ZExp), .ZDenormM(ZDenorm), .FOpCtrlM(OpCtrlVal), .Quot, .DivCalcExpM(DivCalcExp),
|
||||
@ -651,8 +651,8 @@ module testbenchfp;
|
||||
.XZeroM(XZero), .YZeroM(YZero), .ZZeroM(ZZero), .CvtShiftAmtM(CvtShiftAmtE),
|
||||
.XInfM(XInf), .YInfM(YInf), .ZInfM(ZInf), .CvtResSgnM(CvtResSgnE), .FWriteIntM(WriteIntVal),
|
||||
.XSNaNM(XSNaN), .YSNaNM(YSNaN), .ZSNaNM(ZSNaN), .CvtLzcInM(CvtLzcInE), .IntZeroM(IntZeroE),
|
||||
.KillProdM(KillProdE), .AddendStickyM(AddendStickyE), .ProdExpM(ProdExpE),
|
||||
.SumM(SumE), .NegSumM(NegSumE), .InvZM(InvZE), .FmaNormCntM(FmaNormCntE), .EarlyTermShiftDiv2M(EarlyTermShiftDiv2), .ZSgnEffM(ZSgnEffE), .PSgnM(PSgnE), .FmtM(ModFmt), .FrmM(FrmVal),
|
||||
.KillProdM(KillProdE), .AddendStickyM(AddendStickyE), .ProdExpM(Pe),
|
||||
.SumM(Sm), .NegSumM(NegSumE), .InvZM(InvZE), .FmaNormCntM(FmaNormCntE), .EarlyTermShiftDiv2M(EarlyTermShiftDiv2), .ZSgnEffM(ZSgnEffE), .PSgnM(Ps), .FmtM(ModFmt), .FrmM(FrmVal),
|
||||
.PostProcFlgM(Flg), .PostProcResM(FpRes), .FCvtIntResM(IntRes));
|
||||
|
||||
fcvt fcvt (.XSgnE(XSgn), .XExpE(XExp), .XManE(XMan), .ForwardedSrcAE(SrcA), .FWriteIntE(WriteIntVal),
|
||||
@ -818,7 +818,15 @@ end
|
||||
|
||||
// check if result is correct
|
||||
// - wait till the division result is done or one extra cylcle for early termination (to simulate the EM pipline stage)
|
||||
if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&((~DivStart&DivDone)^~(UnitVal == `DIVUNIT))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||
if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&((UnitVal !== `DIVUNIT))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||
errors += 1;
|
||||
$display("There is an error in %s", Tests[TestNum]);
|
||||
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Ans: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
|
||||
$stop;
|
||||
end
|
||||
|
||||
// division
|
||||
else if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&(~DivStart&DivDone)&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||
errors += 1;
|
||||
$display("There is an error in %s", Tests[TestNum]);
|
||||
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Ans: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
|
||||
|
@ -290,7 +290,6 @@ logic [3:0] dummy;
|
||||
// if (signature[i+4] !== 'bx | (signature[i] !== 32'hFFFFFFFF & signature[i] !== 32'h00000000)) begin
|
||||
// report errors unless they are garbage at the end of the sim
|
||||
// kind of hacky test for garbage right now
|
||||
$display("sig4 = %h ne %b", signature[i+4], signature[i+4] !== 'bx);
|
||||
errors = errors+1;
|
||||
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DMEM) = %h, signature = %h",
|
||||
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]);
|
||||
|
@ -5,8 +5,8 @@ NAME := synth
|
||||
|
||||
# defaults
|
||||
export DESIGN ?= wallypipelinedcore
|
||||
export FREQ ?= 3402
|
||||
export CONFIG ?= rv32e
|
||||
export FREQ ?= 3000
|
||||
export CONFIG ?= rv32gc
|
||||
# sky130 and sky90 presently supported
|
||||
export TECH ?= tsmc28
|
||||
# MAXCORES allows parallel compilation, which is faster but less CPU-efficient
|
||||
@ -14,7 +14,7 @@ export TECH ?= tsmc28
|
||||
export MAXCORES ?= 4
|
||||
# MAXOPT turns on flattening, boundary optimization, and retiming
|
||||
# The output netlist is hard to interpret, but significantly better PPA
|
||||
export MAXOPT ?= 0
|
||||
export MAXOPT ?= 1
|
||||
export DRIVE ?= FLOP
|
||||
|
||||
time := $(shell date +%F-%H-%M)
|
||||
|
@ -1,113 +0,0 @@
|
||||
Module,Tech,Width,Target Freq,Delay,Area,L Power (nW),D energy (fJ)
|
||||
priorityencoder,sky90,8,7994,0.12495882036527395,60.760001,44.346,13.42057730723042
|
||||
priorityencoder,sky90,16,5761,0.16976997552508244,136.220003,77.243,21.28915493084534
|
||||
priorityencoder,sky90,32,4776,0.20887023450586265,379.260006,246.78,50.06619521105528
|
||||
priorityencoder,sky90,64,4096,0.244021625,794.780014,364.853,72.71844425000002
|
||||
priorityencoder,sky90,128,3409,0.2933331557641537,1602.300031,610.009,126.1332569785861
|
||||
add,sky90,8,3652,0.2733695629791895,245.000005,139.276,101.6934774282585
|
||||
add,sky90,16,2931,0.33991248447628797,623.280012,352.919,268.5308627362675
|
||||
add,sky90,32,2420,0.4132191404958678,1330.840024,582.809,520.6561170247934
|
||||
add,sky90,64,2139,0.4674681813931744,2781.240054,1050.0,939.1435764188874
|
||||
add,sky90,128,1885,0.5304949787798409,6186.740118,2230.0,2147.9741690795754
|
||||
csa,sky90,8,5740,0.16671402787456446,290.080006,207.654,143.04063591637635
|
||||
csa,sky90,16,5984,0.16522529946524064,588.000011,322.135,321.19798216042784
|
||||
csa,sky90,32,5740,0.16671402787456446,1160.320023,826.559,570.4954033867597
|
||||
csa,sky90,64,5984,0.16522529946524064,2469.600048,1440.0,1354.3517797165773
|
||||
csa,sky90,128,5984,0.16522529946524064,4897.060095,2990.0,2649.0572263262034
|
||||
shiftleft,sky90,8,4321,0.23108991020597083,250.880004,181.951,70.25133270261513
|
||||
shiftleft,sky90,16,3355,0.29803959314456036,666.400006,558.433,195.51397310283156
|
||||
shiftleft,sky90,32,2500,0.39945200000000003,1400.420023,738.137,368.29474400000004
|
||||
shiftleft,sky90,64,2203,0.45385946391284615,3914.120062,2680.0,1144.633567988198
|
||||
shiftleft,sky90,128,1907,0.5242938489774515,9192.400136,6080.0,2900.3935725432616
|
||||
comparator,sky90,8,4829,0.2066692116380203,198.940004,136.459,48.56726473493477
|
||||
comparator,sky90,16,4014,0.24886605181863478,355.740006,188.666,62.714245058295965
|
||||
comparator,sky90,32,3596,0.27763876307007784,697.760013,316.793,109.38967264961067
|
||||
comparator,sky90,64,3129,0.31954192361776923,1372.980026,508.393,204.82637303899006
|
||||
comparator,sky90,128,2682,0.37267507755406415,2836.120055,772.571,463.6077964772558
|
||||
flop,sky90,8,10,0.1143419999999935,133.279999,64.8145,0.22163481569998741
|
||||
flop,sky90,16,10,0.1143419999999935,266.5599975,129.629,0.4426750529999749
|
||||
flop,sky90,32,10,0.1143419999999935,533.119995,259.258,0.88306326599995
|
||||
flop,sky90,64,10,0.1143419999999935,1066.23999,520.0,1.7717864609998994
|
||||
flop,sky90,128,10,0.1143419999999935,2132.4799805,1035.0,3.537741479999799
|
||||
mux2,sky90,1,11806,0.08300869354565475,13.72,12.3,3.8183999031001186
|
||||
mux2,sky90,8,5280,0.1887229393939394,63.700001,23.506,19.476207345454547
|
||||
mux2,sky90,16,4815,0.20207331983385254,119.560002,32.354,37.76750347694705
|
||||
mux2,sky90,32,5000,0.19989700000000002,374.360008,259.372,136.72954800000002
|
||||
mux2,sky90,64,4060,0.24566741871921183,514.50001,165.954,163.6145008669951
|
||||
mux2,sky90,128,4004,0.24974824975024976,1302.420025,767.078,466.52973053346653
|
||||
mux4,sky90,1,7687,0.12838276193573567,28.420001,22.994,6.3164318872381955
|
||||
mux4,sky90,8,4655,0.21455177121374866,159.740002,86.462,42.03069198077337
|
||||
mux4,sky90,16,4452,0.22313914914645103,392.0,398.313,103.09028690566036
|
||||
mux4,sky90,32,3802,0.2622634634402946,465.500009,150.568,139.26189908679646
|
||||
mux4,sky90,64,3699,0.2695173360367667,877.100017,304.149,274.9076827575021
|
||||
mux4,sky90,128,3166,0.3157249696778269,1984.500039,725.267,569.5678452987997
|
||||
mux8,sky90,1,5763,0.17009673572791947,70.560001,49.874,12.31500366670137
|
||||
mux8,sky90,8,3577,0.2789168803466592,287.140006,116.648,60.83177160360637
|
||||
mux8,sky90,16,3419,0.2915101822170225,588.000006,280.193,150.71076420620065
|
||||
mux8,sky90,32,3155,0.3146512107765452,1237.740008,639.983,323.14679346751194
|
||||
mux8,sky90,64,3020,0.33032882781456957,2207.940042,730.503,445.61358872185434
|
||||
mux8,sky90,128,2666,0.37501377344336084,3761.240072,1460.0,854.281375903976
|
||||
mult,sky90,8,1310,0.7631557786259543,2194.220041,1440.0,1420.996059801527
|
||||
mult,sky90,16,997,1.0029260270812437,7519.540137,4940.0,6375.600754155466
|
||||
mult,sky90,32,763,1.3106129895150722,25200.700446,14900.0,24931.79089954522
|
||||
mult,sky90,64,632,1.5822664810126583,86011.661365,42600.0,88845.84517534176
|
||||
mult,sky90,128,524,1.9083759465648855,296198.144128,114000.0,273311.87793918326
|
||||
mux2d,sky90,1,13217,0.07565913467503972,19.6,18.562,6.03759894706817
|
||||
mux4d,sky90,1,9701,0.10307715647871353,51.940001,49.18,13.626800086485927
|
||||
mux8d,sky90,1,7099,0.1341249105507818,85.260001,40.078,14.405015393153965
|
||||
priorityencoder,tsmc28,8,31306,0.03191275857663067,8.316,34.836,1.713715135565067
|
||||
priorityencoder,tsmc28,16,21202,0.04705136175832468,21.294,73.912,3.815865438600132
|
||||
priorityencoder,tsmc28,32,16453,0.060740189205615996,62.118,205.801,9.439025402552724
|
||||
priorityencoder,tsmc28,64,13786,0.07244435673872045,137.088001,428.365,18.328422254896275
|
||||
priorityencoder,tsmc28,128,11439,0.0874122290410001,315.252,980.365,40.908923191188045
|
||||
add,tsmc28,8,13787,0.07226709545223761,33.012,176.194,12.328766484151734
|
||||
add,tsmc28,16,11520,0.08680155555555555,90.972001,475.452,33.67900355555555
|
||||
add,tsmc28,32,9810,0.1019177991845056,209.286002,1060.0,81.43232154841998
|
||||
add,tsmc28,64,8203,0.12186861952944045,392.616003,1800.0,142.34254761038645
|
||||
add,tsmc28,128,7210,0.13869425520110956,868.140006,4090.0,331.3405756754508
|
||||
csa,tsmc28,8,23865,0.04077636748376283,49.392,473.393,20.91827651917033
|
||||
csa,tsmc28,16,23865,0.04077636748376283,98.783999,946.879,41.75500030337314
|
||||
csa,tsmc28,32,23865,0.04077636748376283,197.567999,1890.0,83.30611876932745
|
||||
csa,tsmc28,64,23865,0.04077636748376283,395.135998,3790.0,166.5306848036874
|
||||
csa,tsmc28,128,23865,0.04077636748376283,790.271996,7570.0,333.1021459748586
|
||||
shiftleft,tsmc28,8,15183,0.06578013640255549,48.384,333.876,15.51753417736284
|
||||
shiftleft,tsmc28,16,11800,0.0847177627118644,130.788,613.549,33.71766955932203
|
||||
shiftleft,tsmc28,32,9587,0.10430391697089808,384.803997,1940.0,101.80062296359652
|
||||
shiftleft,tsmc28,64,8269,0.12088260744951022,967.427998,4980.0,272.83204501354453
|
||||
shiftleft,tsmc28,128,7023,0.14238329232521713,1836.953994,8670.0,566.543120162039
|
||||
comparator,tsmc28,8,17054,0.05854826984871585,32.256,160.477,8.752966342383019
|
||||
comparator,tsmc28,16,13709,0.07280278080093369,48.132,204.944,11.852292714392004
|
||||
comparator,tsmc28,32,12136,0.08238147264337507,146.16,623.674,35.50641470929466
|
||||
comparator,tsmc28,64,10862,0.09205807659731172,291.312,1240.0,69.41178975437303
|
||||
comparator,tsmc28,128,9371,0.10671119720414043,558.432,2400.0,127.9467254477644
|
||||
flop,tsmc28,8,10,0.048889000000002625,15.12,78.6345,0.013320296940000717
|
||||
flop,tsmc28,16,10,0.048889000000002625,30.24,157.29,0.026541838100001425
|
||||
flop,tsmc28,32,10,0.048889000000002625,60.4799995,314.5805,0.05332812120000287
|
||||
flop,tsmc28,64,10,0.048889000000002625,120.959999,630.0,0.10640935295000573
|
||||
flop,tsmc28,128,10,0.048889000000002625,241.919998,1260.0,0.21305826200001143
|
||||
mux2,tsmc28,1,50000,0.019658000000000002,2.142,15.112,0.5917058000000001
|
||||
mux2,tsmc28,8,29041,0.033768075961571574,16.884,113.726,5.335356001928308
|
||||
mux2,tsmc28,16,19059,0.05221864998163597,15.75,88.448,5.133093293194816
|
||||
mux2,tsmc28,32,17903,0.05585556035301346,32.130001,171.146,9.897605294553983
|
||||
mux2,tsmc28,64,18546,0.05385698274560552,90.846,517.414,27.359347234767604
|
||||
mux2,tsmc28,128,16594,0.0601057455706882,184.968,1150.0,58.603101931421
|
||||
mux4,tsmc28,1,26255,0.03808798324128737,5.292,41.928,1.7101504475338032
|
||||
mux4,tsmc28,8,18130,0.05509219801434087,27.971999,133.963,8.021424030888031
|
||||
mux4,tsmc28,16,16440,0.06065625060827251,39.438,185.149,12.373875124087593
|
||||
mux4,tsmc28,32,15168,0.0658052700421941,69.174,324.969,23.229260324894515
|
||||
mux4,tsmc28,64,13915,0.07180589399928135,137.465999,648.086,45.59674268954365
|
||||
mux4,tsmc28,128,13089,0.07639603056001222,296.603997,1440.0,94.50188980273512
|
||||
mux8,tsmc28,1,16320,0.05991150980392156,7.182,38.342,1.8428780415686272
|
||||
mux8,tsmc28,8,12885,0.07750962359332557,44.856,215.13,11.90547818393481
|
||||
mux8,tsmc28,16,12256,0.08154268929503918,121.841998,521.624,25.93057519582246
|
||||
mux8,tsmc28,32,11695,0.08537362676357418,168.21,815.694,46.35787933262078
|
||||
mux8,tsmc28,64,11000,0.0907930909090909,304.037999,1490.0,81.89536799999999
|
||||
mux8,tsmc28,128,10464,0.09547474923547401,664.775992,2850.0,153.04602302446486
|
||||
mult,tsmc28,8,5000,0.19998100000000002,444.150001,3260.0,306.970835
|
||||
mult,tsmc28,16,3819,0.26184265147944485,1634.472002,11800.0,1455.3214569227544
|
||||
mult,tsmc28,32,2973,0.3363555785401951,5141.430011,36900.0,5416.333881232761
|
||||
mult,tsmc28,64,2390,0.4184090418410042,16045.092071,109000.0,18545.980779602512
|
||||
mult,tsmc28,128,1868,0.5353279057815846,44272.49428,262000.0,50011.4036139272
|
||||
mux2d,tsmc28,1,51887,0.018931650182126544,3.276,26.574,0.9106123737602868
|
||||
mux4d,tsmc28,1,32558,0.03008041734750292,4.158,30.464,1.2543534033908719
|
||||
mux8d,tsmc28,1,21936,0.045586162654996355,20.664,171.151,6.614552201239972
|
|
File diff suppressed because it is too large
Load Diff
@ -245,7 +245,7 @@ def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn', norm=True, colo
|
||||
ax.add_artist(ax.legend(handles=fullLeg, loc=legLoc))
|
||||
titleStr = " (target " + str(freq)+ "MHz)" if freq != None else " (best achievable delay)"
|
||||
ax.set_title(module + titleStr)
|
||||
plt.savefig('./plots/PPA/'+ module + '_' + var + '.png')
|
||||
plt.savefig('.plots/'+ module + '_' + var + '.png')
|
||||
# plt.show()
|
||||
return r2
|
||||
|
||||
@ -550,7 +550,7 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
||||
|
||||
if freq != 10:
|
||||
n = 'normalized' if norm else 'unnormalized'
|
||||
saveStr = './plots/PPA/'+ n + '/' + mod + '.png'
|
||||
saveStr = './plots/'+ n + '/' + mod + '.png'
|
||||
plt.savefig(saveStr)
|
||||
# plt.show()
|
||||
|
||||
@ -563,7 +563,7 @@ def makeLineLegend():
|
||||
fullLeg += [lines.Line2D([0], [0], color='green', label='sky90', marker='o')]
|
||||
fullLeg += [lines.Line2D([0], [0], color='red', label='combined', marker='_')]
|
||||
fig.legend(handles=fullLeg, ncol=5, handlelength=1.4, loc='center')
|
||||
saveStr = './plots/PPA/legend.png'
|
||||
saveStr = './plots/legend.png'
|
||||
plt.savefig(saveStr)
|
||||
|
||||
def muxPlot(fits='clsgn', norm=True):
|
||||
@ -616,7 +616,7 @@ def muxPlot(fits='clsgn', norm=True):
|
||||
ax.set_title('mux timing')
|
||||
|
||||
ax.legend(handles = fullLeg)
|
||||
plt.savefig('./plots/PPA/mux.png')
|
||||
plt.savefig('./plots/mux.png')
|
||||
|
||||
def stdDevError():
|
||||
for var in ['delay', 'area', 'lpower', 'denergy']:
|
@ -102,7 +102,8 @@ set_critical_range [expr $my_period*0.05] $current_design
|
||||
|
||||
# Partitioning - flatten or hierarchically synthesize
|
||||
if { $maxopt == 1 } {
|
||||
ungroup -all -flatten -simple_names
|
||||
ungroup -all -simple_names
|
||||
# -flatten
|
||||
}
|
||||
|
||||
# Set input pins except clock
|
||||
|
@ -857,6 +857,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
|
||||
addi a6, a6, 8
|
||||
.endm
|
||||
|
||||
// Place this macro in peripheral tests to setup all the PLIC registers to generate external interrupts
|
||||
.macro SETUP_PLIC
|
||||
# Setup PLIC with a series of register writes
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user