mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
7e4988c2de
3
.gitignore
vendored
3
.gitignore
vendored
@ -32,6 +32,9 @@ testsBP/*/*/*.elf*
|
||||
testsBP/*/OBJ/*
|
||||
testsBP/*/*.a
|
||||
tests/wally-riscv-arch-test/riscv-test-suite/*/I/*/*
|
||||
tests/riscof/riscof_work*/*
|
||||
tests/riscof/config32.ini
|
||||
tests/riscof/config64.ini
|
||||
tests/linux-testgen/linux-testvectors/*
|
||||
!tests/linux-testgen/linux-testvectors/tvCopier.py
|
||||
!tests/linux-testgen/linux-testvectors/tvLinker.sh
|
||||
|
@ -81,7 +81,7 @@
|
||||
|
||||
// Floating point constants needed for FPU paramerterization
|
||||
`define FPSIZES ((32)'(`Q_SUPPORTED)+(32)'(`D_SUPPORTED)+(32)'(`F_SUPPORTED)+(32)'(`ZFH_SUPPORTED))
|
||||
`define FMTBITS ((`FPSIZES>=3)+1)
|
||||
`define FMTBITS ((32)'(`FPSIZES>=3)+1)
|
||||
`define LEN1 ((`D_SUPPORTED & (`FLEN != `D_LEN)) ? `D_LEN : (`F_SUPPORTED & (`FLEN != `S_LEN)) ? `S_LEN : `H_LEN)
|
||||
`define NE1 ((`D_SUPPORTED & (`FLEN != `D_LEN)) ? `D_NE : (`F_SUPPORTED & (`FLEN != `S_LEN)) ? `S_NE : `H_NE)
|
||||
`define NF1 ((`D_SUPPORTED & (`FLEN != `D_LEN)) ? `D_NF : (`F_SUPPORTED & (`FLEN != `S_LEN)) ? `S_NF : `H_NF)
|
||||
|
@ -52,7 +52,7 @@ module fcmp (
|
||||
3'b010: CmpNVE = EitherSNaN;//equal
|
||||
3'b001: CmpNVE = EitherNaN;//less than
|
||||
3'b011: CmpNVE = EitherNaN;//less than or equal
|
||||
default: CmpNVE = 1'b0;
|
||||
default: CmpNVE = 1'bx;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -91,7 +91,7 @@ module fcmp (
|
||||
`FMT2:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`LEN2{1'b1}}, XSgnE, {`NE2{1'b1}}, 1'b1, XManE[`NF-2:`NF-`NF2]};
|
||||
else NaNRes = {{`FLEN-`LEN2{1'b1}}, 1'b0, {`NE2{1'b1}}, 1'b1, (`NF2-1)'(0)};
|
||||
default: NaNRes = (`FLEN)'(0);
|
||||
default: NaNRes = {`FLEN{1'bx}};
|
||||
endcase
|
||||
|
||||
else if (`FPSIZES == 4)
|
||||
|
@ -24,18 +24,18 @@ module fctrl (
|
||||
// FPU Instruction Decoder
|
||||
always_comb
|
||||
if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled
|
||||
ControlsD = `FCTRLW'b0_0_00_00_000_0_1;
|
||||
ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1;
|
||||
else case(OpD)
|
||||
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr
|
||||
7'b0000111: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_10_00_000_0_0; // flw
|
||||
3'b011: ControlsD = `FCTRLW'b1_0_10_00_000_0_0; // fld
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0; // flw
|
||||
3'b011: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0; // fld
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
7'b0100111: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b0_0_00_00_000_0_0; // fsw
|
||||
3'b011: ControlsD = `FCTRLW'b0_0_00_00_000_0_0; // fsd
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
3'b010: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_0; // fsw
|
||||
3'b011: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_0; // fsd
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0; // fmadd
|
||||
7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0; // fmsub
|
||||
@ -45,29 +45,29 @@ module fctrl (
|
||||
7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0; // fadd
|
||||
7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0; // fsub
|
||||
7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0; // fmul
|
||||
7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_000_1_0; // fdiv
|
||||
7'b01011??: ControlsD = `FCTRLW'b1_0_01_01_001_1_0; // fsqrt
|
||||
7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0; // fdiv
|
||||
7'b01011??: ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0; // fsqrt
|
||||
7'b00100??: case(Funct3D)
|
||||
3'b000: ControlsD = `FCTRLW'b1_0_00_00_000_0_0; // fsgnj
|
||||
3'b001: ControlsD = `FCTRLW'b1_0_00_00_001_0_0; // fsgnjn
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_00_00_010_0_0; // fsgnjx
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0; // fsgnj
|
||||
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0; // fsgnjn
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0; // fsgnjx
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
7'b00101??: case(Funct3D)
|
||||
3'b000: ControlsD = `FCTRLW'b1_0_00_00_110_0_0; // fmin
|
||||
3'b001: ControlsD = `FCTRLW'b1_0_00_00_101_0_0; // fmax
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0; // fmin
|
||||
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0; // fmax
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
7'b10100??: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b0_1_00_00_010_0_0; // feq
|
||||
3'b001: ControlsD = `FCTRLW'b0_1_00_00_001_0_0; // flt
|
||||
3'b000: ControlsD = `FCTRLW'b0_1_00_00_011_0_0; // fle
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000__0_1; // non-implemented instruction
|
||||
3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0; // feq
|
||||
3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0; // flt
|
||||
3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0; // fle
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx__0_1; // non-implemented instruction
|
||||
endcase
|
||||
7'b11100??: if (Funct3D == 3'b001) ControlsD = `FCTRLW'b0_1_10_00_000_0_0; // fclass
|
||||
else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_00_000_0_0; // fmv.x.w to int reg
|
||||
else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_00_000_0_0; // fmv.x.d to int reg
|
||||
else ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
7'b11100??: if (Funct3D == 3'b001) ControlsD = `FCTRLW'b0_1_10_xx_000_0_0; // fclass
|
||||
else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0; // fmv.x.w to int reg
|
||||
else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0; // fmv.x.d to int reg
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
7'b1101000: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0; // fcvt.s.w w->s
|
||||
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0; // fcvt.s.wu wu->s
|
||||
@ -80,7 +80,7 @@ module fctrl (
|
||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0; // fcvt.l.s s->l
|
||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0; // fcvt.lu.s s->lu
|
||||
endcase
|
||||
7'b1111000: ControlsD = `FCTRLW'b1_0_00_00_011_0_0; // fmv.w.x to fp reg
|
||||
7'b1111000: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0; // fmv.w.x to fp reg
|
||||
7'b0100000: ControlsD = `FCTRLW'b1_0_01_00_000_0_0; // fcvt.s.d
|
||||
7'b1101001: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0; // fcvt.d.w w->d
|
||||
@ -94,11 +94,11 @@ module fctrl (
|
||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0; // fcvt.l.d d->l
|
||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0; // fcvt.lu.d d->lu
|
||||
endcase
|
||||
7'b1111001: ControlsD = `FCTRLW'b1_0_00_00_011_0_0; // fmv.d.x to fp reg
|
||||
7'b1111001: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0; // fmv.d.x to fp reg
|
||||
7'b0100001: ControlsD = `FCTRLW'b1_0_01_00_001_0_0; // fcvt.d.s
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
default: ControlsD = `FCTRLW'b0_0_00_00_000_0_1; // non-implemented instruction
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1; // non-implemented instruction
|
||||
endcase
|
||||
|
||||
// unswizzle control bits
|
||||
|
@ -133,7 +133,7 @@ module fcvt (
|
||||
`FMT: NewBiasToFp = (`NE-1)'(`BIAS);
|
||||
`FMT1: NewBiasToFp = (`NE-1)'(`BIAS1);
|
||||
`FMT2: NewBiasToFp = (`NE-1)'(`BIAS2);
|
||||
default: NewBiasToFp = 1'bx;
|
||||
default: NewBiasToFp = {`NE-1{1'bx}};
|
||||
endcase
|
||||
assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp;
|
||||
|
||||
|
@ -34,7 +34,8 @@ module flags(
|
||||
logic FmaInvalid; // integer invalid flag
|
||||
logic DivInvalid; // integer invalid flag
|
||||
logic DivByZero;
|
||||
logic [`NE-1:0] MaxExp; // the maximum exponent before overflow
|
||||
logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent
|
||||
logic ShiftGtIntSz; // is the shift greater than the the integer size (use ResExp to account for possible roundning "shift")
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Flags
|
||||
@ -43,56 +44,51 @@ module flags(
|
||||
|
||||
|
||||
if (`FPSIZES == 1) begin
|
||||
assign MaxExp = ToInt&CvtOp ? Int64 ? (`NE)'(65) : (`NE)'(33) : {`NE{1'b1}};
|
||||
assign ResExpGteMax = &FullResExp[`NE-1:0] | FullResExp[`NE];
|
||||
assign ShiftGtIntSz = (|FullResExp[`NE:7]|(FullResExp[6]&~Int64)) | ((|FullResExp[4:0]|(FullResExp[5]&Int64))&((FullResExp[5]&~Int64) | FullResExp[6]&Int64));
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign MaxExp = ToInt&CvtOp ? Int64 ? (`NE)'($unsigned(65)) : (`NE)'($unsigned(33)) :
|
||||
OutFmt ? {`NE{1'b1}} : {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}};
|
||||
assign ResExpGteMax = OutFmt ? &FullResExp[`NE-1:0] | FullResExp[`NE] : &FullResExp[`NE1-1:0] | (|FullResExp[`NE:`NE1]);
|
||||
|
||||
assign ShiftGtIntSz = (|FullResExp[`NE:7]|(FullResExp[6]&~Int64)) | ((|FullResExp[4:0]|(FullResExp[5]&Int64))&((FullResExp[5]&~Int64) | FullResExp[6]&Int64));
|
||||
end else if (`FPSIZES == 3) begin
|
||||
logic [`NE-1:0] MaxExpFp;
|
||||
always_comb
|
||||
case (OutFmt)
|
||||
`FMT: begin
|
||||
MaxExpFp = {`NE{1'b1}};
|
||||
end
|
||||
`FMT1: begin
|
||||
MaxExpFp = {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}};
|
||||
end
|
||||
`FMT2: begin
|
||||
MaxExpFp = {{`NE-`NE2{1'b0}}, {`NE2{1'b1}}};
|
||||
end
|
||||
default: begin
|
||||
MaxExpFp = 1'bx;
|
||||
end
|
||||
`FMT: ResExpGteMax = &FullResExp[`NE-1:0] | FullResExp[`NE];
|
||||
`FMT1: ResExpGteMax = &FullResExp[`NE1-1:0] | (|FullResExp[`NE:`NE1]);
|
||||
`FMT2: ResExpGteMax = &FullResExp[`NE2-1:0] | (|FullResExp[`NE:`NE2]);
|
||||
default: ResExpGteMax = 1'bx;
|
||||
endcase
|
||||
assign MaxExp = ToInt&CvtOp ? Int64 ? (`NE)'(65) : (`NE)'(33) : MaxExpFp;
|
||||
assign ShiftGtIntSz = (|FullResExp[`NE:7]|(FullResExp[6]&~Int64)) | ((|FullResExp[4:0]|(FullResExp[5]&Int64))&((FullResExp[5]&~Int64) | FullResExp[6]&Int64));
|
||||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
logic [`NE-1:0] MaxExpFp;
|
||||
always_comb
|
||||
case (OutFmt)
|
||||
2'h3: begin
|
||||
MaxExpFp = {`Q_NE{1'b1}};
|
||||
end
|
||||
2'h1: begin
|
||||
MaxExpFp = {{`Q_NE-`D_NE{1'b0}}, {`D_NE{1'b1}}};
|
||||
end
|
||||
2'h0: begin
|
||||
MaxExpFp = {{`Q_NE-`S_NE{1'b0}}, {`S_NE{1'b1}}};
|
||||
end
|
||||
2'h2: begin
|
||||
MaxExpFp = {{`Q_NE-`H_NE{1'b0}}, {`H_NE{1'b1}}};
|
||||
end
|
||||
`Q_FMT: ResExpGteMax = &FullResExp[`Q_NE-1:0] | FullResExp[`Q_NE];
|
||||
`D_FMT: ResExpGteMax = &FullResExp[`D_NE-1:0] | (|FullResExp[`Q_NE:`D_NE]);
|
||||
`S_FMT: ResExpGteMax = &FullResExp[`S_NE-1:0] | (|FullResExp[`Q_NE:`S_NE]);
|
||||
`H_FMT: ResExpGteMax = &FullResExp[`H_NE-1:0] | (|FullResExp[`Q_NE:`H_NE]);
|
||||
endcase
|
||||
assign MaxExp = ToInt&CvtOp ? Int64 ? (`NE)'(65) : (`NE)'(33) : MaxExpFp;
|
||||
// a left shift of intlen+1 is still in range but any more than that is an overflow
|
||||
// inital: | 64 0's | XLEN |
|
||||
// | 64 0's | XLEN | << 64
|
||||
// | XLEN | 00000... |
|
||||
// 65 = ...0 0 0 0 0 1 0 0 0 0 0 1
|
||||
// | or | | or |
|
||||
// 33 = ...0 0 0 0 0 0 1 0 0 0 0 1
|
||||
// | or | | or |
|
||||
// larger or equal if:
|
||||
// - any of the bits after the most significan 1 is one
|
||||
// - the most signifcant in 65 or 33 is still a one in the number and
|
||||
// one of the later bits is one
|
||||
assign ShiftGtIntSz = (|FullResExp[`Q_NE:7]|(FullResExp[6]&~Int64)) | ((|FullResExp[4:0]|(FullResExp[5]&Int64))&((FullResExp[5]&~Int64) | FullResExp[6]&Int64));
|
||||
end
|
||||
|
||||
// if the result is greater than or equal to the max exponent
|
||||
// | and the exponent isn't negitive
|
||||
// | | if the input isnt infinity or NaN
|
||||
// | | |
|
||||
assign Overflow = (FullResExp>={2'b0, MaxExp}) & ~FullResExp[`NE+1]&~(InfIn|NaNIn);
|
||||
// if the result is greater than or equal to the max exponent(not taking into account sign)
|
||||
// | and the exponent isn't negitive
|
||||
// | | if the input isnt infinity or NaN
|
||||
// | | |
|
||||
assign Overflow = ResExpGteMax & ~FullResExp[`NE+1]&~(InfIn|NaNIn);
|
||||
|
||||
// detecting tininess after rounding
|
||||
// the exponent is negitive
|
||||
@ -123,12 +119,12 @@ module flags(
|
||||
|
||||
// if the input is NaN or infinity
|
||||
// | if the integer res overflows (out of range)
|
||||
// | | if the input was negitive but ouputing to a unsigned number
|
||||
// | | | the res doesn't round to zero
|
||||
// | | | | or the res rounds up out of bounds
|
||||
// | | | | and the res didn't underflow
|
||||
// | | | | |
|
||||
assign IntInvalid = XNaNM|XInfM|Overflow|((XSgnM&~Signed)&(~((CvtCalcExpM[`NE]|(~|CvtCalcExpM))&~Plus1)))|(NegResMSBS[1]^NegResMSBS[0]);
|
||||
// | | if the input was negitive but ouputing to a unsigned number
|
||||
// | | | the res doesn't round to zero
|
||||
// | | | | or the res rounds up out of bounds
|
||||
// | | | | and the res didn't underflow
|
||||
// | | | | |
|
||||
assign IntInvalid = XNaNM|XInfM|(ShiftGtIntSz&~FullResExp[`NE+1])|((XSgnM&~Signed)&(~((CvtCalcExpM[`NE]|(~|CvtCalcExpM))&~Plus1)))|(NegResMSBS[1]^NegResMSBS[0]);
|
||||
// |
|
||||
// or when the positive res rounds up out of range
|
||||
assign SigNaN = (XSNaNM&~(IntToFp&CvtOp)) | (YSNaNM&~CvtOp) | (ZSNaNM&FmaOp);
|
||||
|
@ -25,7 +25,7 @@ module fmashiftcalc(
|
||||
assign SumZero = ~(|SumM);
|
||||
|
||||
// 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));
|
||||
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
|
||||
if (`FPSIZES == 1) begin
|
||||
@ -40,7 +40,7 @@ module fmashiftcalc(
|
||||
`FMT: ConvNormSumExp = NormSumExp;
|
||||
`FMT1: ConvNormSumExp = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`BIAS1))&{`NE+2{|NormSumExp}};
|
||||
`FMT2: ConvNormSumExp = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`BIAS2))&{`NE+2{|NormSumExp}};
|
||||
default: ConvNormSumExp = `NE+2'bx;
|
||||
default: ConvNormSumExp = {`NE+2{1'bx}};
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -46,7 +46,7 @@ module fsgninj (
|
||||
//
|
||||
|
||||
// calculate the result's sign
|
||||
assign ResSgn = SgnOpCodeE[1] ? (XSgnE ^ YSgnE) : (YSgnE ^ SgnOpCodeE[0]);
|
||||
assign ResSgn = (SgnOpCodeE[1] ? XSgnE : SgnOpCodeE[0]) ^ YSgnE;
|
||||
|
||||
// format final result based on precision
|
||||
// - uses NaN-blocking format
|
||||
@ -56,25 +56,30 @@ module fsgninj (
|
||||
assign SgnResE = {ResSgn, FSrcXE[`FLEN-2:0]};
|
||||
|
||||
else if (`FPSIZES == 2)
|
||||
assign SgnResE = FmtE ? {ResSgn, FSrcXE[`FLEN-2:0]} : {{`FLEN-`LEN1{1'b1}}, ResSgn, FSrcXE[`LEN1-2:0]};
|
||||
assign SgnResE = {~FmtE|ResSgn, FSrcXE[`FLEN-2:`LEN1], FmtE ? FSrcXE[`LEN1-1] : ResSgn, FSrcXE[`LEN1-2:0]};
|
||||
|
||||
else if (`FPSIZES == 3)
|
||||
else if (`FPSIZES == 3) begin
|
||||
logic [2:0] SgnBits;
|
||||
always_comb
|
||||
case (FmtE)
|
||||
`FMT: SgnResE = {ResSgn, FSrcXE[`FLEN-2:0]};
|
||||
`FMT1: SgnResE = {{`FLEN-`LEN1{1'b1}}, ResSgn, FSrcXE[`LEN1-2:0]};
|
||||
`FMT2: SgnResE = {{`FLEN-`LEN2{1'b1}}, ResSgn, FSrcXE[`LEN2-2:0]};
|
||||
default: SgnResE = 0;
|
||||
`FMT: SgnBits = {ResSgn, FSrcXE[`LEN1-1], FSrcXE[`LEN2-1]};
|
||||
`FMT1: SgnBits = {1'b1, ResSgn, FSrcXE[`LEN2-1]};
|
||||
`FMT2: SgnBits = {2'b11, ResSgn};
|
||||
default: SgnBits = {3{1'bx}};
|
||||
endcase
|
||||
assign SgnResE = {SgnBits[2], FSrcXE[`FLEN-2:`LEN1], SgnBits[1], FSrcXE[`LEN1-2:`LEN2], SgnBits[0], FSrcXE[`LEN2-2:0]};
|
||||
|
||||
|
||||
else if (`FPSIZES == 4)
|
||||
end else if (`FPSIZES == 4) begin
|
||||
logic [3:0] SgnBits;
|
||||
always_comb
|
||||
case (FmtE)
|
||||
2'h3: SgnResE = {ResSgn, FSrcXE[`Q_LEN-2:0]};
|
||||
2'h1: SgnResE = {{`Q_LEN-`D_LEN{1'b1}}, ResSgn, FSrcXE[`D_LEN-2:0]};
|
||||
2'h0: SgnResE = {{`Q_LEN-`S_LEN{1'b1}}, ResSgn, FSrcXE[`S_LEN-2:0]};
|
||||
2'h2: SgnResE = {{`Q_LEN-`H_LEN{1'b1}}, ResSgn, FSrcXE[`H_LEN-2:0]};
|
||||
`Q_FMT: SgnBits = {ResSgn, FSrcXE[`D_LEN-1], FSrcXE[`S_LEN-1], FSrcXE[`H_LEN-1]};
|
||||
`D_FMT: SgnBits = {1'b1, ResSgn, FSrcXE[`S_LEN-1], FSrcXE[`H_LEN-1]};
|
||||
`S_FMT: SgnBits = {2'b11, ResSgn, FSrcXE[`H_LEN-1]};
|
||||
`H_FMT: SgnBits = {3'b111, ResSgn};
|
||||
endcase
|
||||
|
||||
assign SgnResE = {SgnBits[3], FSrcXE[`Q_LEN-2:`D_LEN], SgnBits[2], FSrcXE[`D_LEN-2:`S_LEN], SgnBits[1], FSrcXE[`S_LEN-2:`H_LEN], SgnBits[0], FSrcXE[`H_LEN-2:0]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -82,7 +82,7 @@ module postprocess(
|
||||
logic PreResultDenorm; // is the result denormalized - calculated before LZA corection
|
||||
logic [$clog2(3*`NF+7)-1:0] FmaShiftAmt; // normalization shift count
|
||||
logic [$clog2(`NORMSHIFTSZ)-1:0] ShiftAmt; // normalization shift count
|
||||
logic [3*`NF+8:0] ShiftIn; // is the sum zero
|
||||
logic [`NORMSHIFTSZ-1:0] ShiftIn; // is the sum zero
|
||||
logic [`NORMSHIFTSZ-1:0] Shifted; // the shifted result
|
||||
logic Plus1; // add one to the final result?
|
||||
logic IntInvalid, Overflow, Underflow, Invalid; // flags
|
||||
@ -98,6 +98,7 @@ module postprocess(
|
||||
logic DivOp;
|
||||
logic InfIn;
|
||||
logic ResSgn;
|
||||
logic RoundSgn;
|
||||
logic NaNIn;
|
||||
logic UfLSBRes;
|
||||
logic Sqrt;
|
||||
@ -150,8 +151,8 @@ module postprocess(
|
||||
ShiftIn = 0;//{{`NORMSHIFTSZ-(3*`NF+8){1'b0}}, DivShiftIn};
|
||||
end
|
||||
default: begin
|
||||
ShiftAmt = 0;
|
||||
ShiftIn = 0;
|
||||
ShiftAmt = {$clog2(`NORMSHIFTSZ){1'bx}};
|
||||
ShiftIn = {`NORMSHIFTSZ{1'bx}};
|
||||
end
|
||||
endcase
|
||||
|
||||
@ -171,15 +172,16 @@ module postprocess(
|
||||
// round to nearest max magnitude
|
||||
|
||||
round round(.OutFmt, .FrmM, .Sticky, .AddendStickyM, .ZZeroM, .Plus1, .PostProcSelM, .CvtCalcExpM,
|
||||
.InvZM, .ResSgn, .SumExp, .FmaOp, .CvtOp, .CvtResDenormUfM, .CorrShifted, .ToInt, .CvtResUf,
|
||||
.InvZM, .RoundSgn, .SumExp, .FmaOp, .CvtOp, .CvtResDenormUfM, .CorrShifted, .ToInt, .CvtResUf,
|
||||
.UfPlus1, .FullResExp, .ResFrac, .ResExp, .Round, .RoundAdd, .UfLSBRes, .RoundExp);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Sign calculation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
resultsign resultsign(.FrmM, .PSgnM, .PostProcSelM, .ZSgnEffM, .InvZM, .SumExp, .Round, .Sticky,
|
||||
.ZInfM, .InfIn, .NegSumM, .SumZero, .Mult, .CvtResSgnM, .ResSgn);
|
||||
resultsign resultsign(.FrmM, .PSgnM, .ZSgnEffM, .InvZM, .SumExp, .Round, .Sticky,
|
||||
.FmaOp, .DivOp, .CvtOp, .ZInfM, .InfIn, .NegSumM, .SumZero, .Mult,
|
||||
.CvtResSgnM, .RoundSgn, .ResSgn);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Flags
|
||||
|
@ -7,13 +7,16 @@ module resultsign(
|
||||
input logic ZInfM,
|
||||
input logic InfIn,
|
||||
input logic NegSumM,
|
||||
input logic [1:0] PostProcSelM,
|
||||
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,
|
||||
output logic ResSgn
|
||||
);
|
||||
|
||||
@ -40,11 +43,9 @@ module resultsign(
|
||||
assign InfSgn = ZInfM ? ZSgnEffM : PSgnM;
|
||||
assign FmaResSgn = InfIn ? InfSgn : SumZero ? ZeroSgn : FmaResSgnTmp;
|
||||
|
||||
always_comb
|
||||
case(PostProcSelM)
|
||||
2'b10: ResSgn = FmaResSgn; // fma
|
||||
2'b00: ResSgn = CvtResSgnM; // cvt
|
||||
2'b01: ResSgn = 0; // divide
|
||||
default: ResSgn = 1'bx;
|
||||
endcase
|
||||
// Sign for rounding calulation
|
||||
assign RoundSgn = (FmaResSgnTmp&FmaOp) | (CvtResSgnM&CvtOp) | (1'b0&DivOp);
|
||||
|
||||
assign ResSgn = (FmaResSgn&FmaOp) | (CvtResSgnM&CvtOp) | (1'b0&DivOp);
|
||||
|
||||
endmodule
|
@ -21,7 +21,7 @@ module round(
|
||||
input logic ZZeroM, // is Z zero
|
||||
input logic InvZM, // invert Z
|
||||
input logic [`NE+1:0] SumExp, // exponent of the normalized sum
|
||||
input logic ResSgn, // the result's sign
|
||||
input logic RoundSgn, // the result's sign
|
||||
input logic [`NE:0] CvtCalcExpM, // the calculated expoent
|
||||
output logic UfPlus1, // do you add or subtract on from the result
|
||||
output logic [`NE+1:0] FullResExp, // ResExp with bits to determine sign and overflow
|
||||
@ -230,8 +230,8 @@ module round(
|
||||
case (FrmM)
|
||||
3'b000: CalcPlus1 = Round & ((Sticky| LSBRes)&~SubBySmallNum);//round to nearest even
|
||||
3'b001: CalcPlus1 = 0;//round to zero
|
||||
3'b010: CalcPlus1 = ResSgn & ~(SubBySmallNum & ~Round);//round down
|
||||
3'b011: CalcPlus1 = ~ResSgn & ~(SubBySmallNum & ~Round);//round up
|
||||
3'b010: CalcPlus1 = RoundSgn & ~(SubBySmallNum & ~Round);//round down
|
||||
3'b011: CalcPlus1 = ~RoundSgn & ~(SubBySmallNum & ~Round);//round up
|
||||
3'b100: CalcPlus1 = Round & ~SubBySmallNum;//round to nearest max magnitude
|
||||
default: CalcPlus1 = 1'bx;
|
||||
endcase
|
||||
@ -239,8 +239,8 @@ module round(
|
||||
case (FrmM)
|
||||
3'b000: UfCalcPlus1 = UfRound & ((UfSticky| UfLSBRes)&~UfSubBySmallNum);//round to nearest even
|
||||
3'b001: UfCalcPlus1 = 0;//round to zero
|
||||
3'b010: UfCalcPlus1 = ResSgn & ~(UfSubBySmallNum & ~UfRound);//round down
|
||||
3'b011: UfCalcPlus1 = ~ResSgn & ~(UfSubBySmallNum & ~UfRound);//round up
|
||||
3'b010: UfCalcPlus1 = RoundSgn & ~(UfSubBySmallNum & ~UfRound);//round down
|
||||
3'b011: UfCalcPlus1 = ~RoundSgn & ~(UfSubBySmallNum & ~UfRound);//round up
|
||||
3'b100: UfCalcPlus1 = UfRound & ~UfSubBySmallNum;//round to nearest max magnitude
|
||||
default: UfCalcPlus1 = 1'bx;
|
||||
endcase
|
||||
@ -248,8 +248,8 @@ module round(
|
||||
case (FrmM)
|
||||
3'b000: CalcMinus1 = 0;//round to nearest even
|
||||
3'b001: CalcMinus1 = SubBySmallNum & ~Round;//round to zero
|
||||
3'b010: CalcMinus1 = ~ResSgn & ~Round & SubBySmallNum;//round down
|
||||
3'b011: CalcMinus1 = ResSgn & ~Round & SubBySmallNum;//round up
|
||||
3'b010: CalcMinus1 = ~RoundSgn & ~Round & SubBySmallNum;//round down
|
||||
3'b011: CalcMinus1 = RoundSgn & ~Round & SubBySmallNum;//round up
|
||||
3'b100: CalcMinus1 = 0;//round to nearest max magnitude
|
||||
default: CalcMinus1 = 1'bx;
|
||||
endcase
|
||||
|
@ -98,7 +98,7 @@ module unpackinput (
|
||||
`FMT: BadNaNBox = 0;
|
||||
`FMT1: BadNaNBox = ~&In[`FLEN-1:`LEN1];
|
||||
`FMT2: BadNaNBox = ~&In[`FLEN-1:`LEN2];
|
||||
default: BadNaNBox = 0;
|
||||
default: BadNaNBox = 1'bx;
|
||||
endcase
|
||||
|
||||
// extract the sign bit
|
||||
@ -107,7 +107,7 @@ module unpackinput (
|
||||
`FMT: Sgn = In[`FLEN-1];
|
||||
`FMT1: Sgn = In[`LEN1-1];
|
||||
`FMT2: Sgn = In[`LEN2-1];
|
||||
default: Sgn = 0;
|
||||
default: Sgn = 1'bx;
|
||||
endcase
|
||||
|
||||
// extract the fraction
|
||||
@ -116,7 +116,7 @@ module unpackinput (
|
||||
`FMT: Frac = In[`NF-1:0];
|
||||
`FMT1: Frac = {In[`NF1-1:0], (`NF-`NF1)'(0)};
|
||||
`FMT2: Frac = {In[`NF2-1:0], (`NF-`NF2)'(0)};
|
||||
default: Frac = 0;
|
||||
default: Frac = {`NF{1'bx}};
|
||||
endcase
|
||||
|
||||
// is the exponent non-zero
|
||||
@ -125,7 +125,7 @@ module unpackinput (
|
||||
`FMT: ExpNonZero = |In[`FLEN-2:`NF]; // if input is largest precision (`FLEN - ie quad or double)
|
||||
`FMT1: ExpNonZero = |In[`LEN1-2:`NF1]; // if input is larger precsion (`LEN1 - double or single)
|
||||
`FMT2: ExpNonZero = |In[`LEN2-2:`NF2]; // if input is smallest precsion (`LEN2 - single or half)
|
||||
default: ExpNonZero = 0;
|
||||
default: ExpNonZero = 1'bx;
|
||||
endcase
|
||||
|
||||
// example double to single conversion:
|
||||
@ -142,7 +142,7 @@ module unpackinput (
|
||||
`FMT: Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero};
|
||||
`FMT1: Exp = {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero};
|
||||
`FMT2: Exp = {In[`LEN2-2], {`NE-`NE2{~In[`LEN2-2]}}, In[`LEN2-3:`NF2+1], In[`NF2]|~ExpNonZero};
|
||||
default: Exp = 0;
|
||||
default: Exp = {`NE{1'bx}};
|
||||
endcase
|
||||
|
||||
// is the exponent all 1's
|
||||
@ -151,7 +151,7 @@ module unpackinput (
|
||||
`FMT: ExpMax = &In[`FLEN-2:`NF];
|
||||
`FMT1: ExpMax = &In[`LEN1-2:`NF1];
|
||||
`FMT2: ExpMax = &In[`LEN2-2:`NF2];
|
||||
default: ExpMax = 0;
|
||||
default: ExpMax = 1'bx;
|
||||
endcase
|
||||
|
||||
end else if (`FPSIZES == 4) begin // if all precsisons are supported - quad, double, single, and half
|
||||
|
@ -549,6 +549,30 @@ module ppa_mux8d_1 #(parameter WIDTH = 1) (
|
||||
assign y = s[2] ? (s[1] ? (s[0] ? d5 : d4) : (s[0] ? d6 : d7)) : (s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0));
|
||||
endmodule
|
||||
|
||||
module ppa_mux2_1 #(parameter WIDTH = 1) (
|
||||
input logic [WIDTH-1:0] d0, d1,
|
||||
input logic s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s ? d1 : d0;
|
||||
endmodule
|
||||
|
||||
module ppa_mux4_1 #(parameter WIDTH = 1) (
|
||||
input logic [WIDTH-1:0] d0, d1, d2, d3,
|
||||
input logic [1:0] s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0);
|
||||
endmodule
|
||||
|
||||
module ppa_mux8_1 #(parameter WIDTH = 1) (
|
||||
input logic [WIDTH-1:0] d0, d1, d2, d3, d4, d5, d6, d7,
|
||||
input logic [2:0] s,
|
||||
output logic [WIDTH-1:0] y);
|
||||
|
||||
assign y = s[2] ? (s[1] ? (s[0] ? d5 : d4) : (s[0] ? d6 : d7)) : (s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0));
|
||||
endmodule
|
||||
|
||||
module ppa_mux2_8 #(parameter WIDTH = 8) (
|
||||
input logic [WIDTH-1:0] d0, d1,
|
||||
input logic s,
|
||||
|
18
pipelined/srt/stine/Makefile
Normal file
18
pipelined/srt/stine/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -lm
|
||||
LIBS =
|
||||
OBJS = disp.o srt4div.o
|
||||
|
||||
srt4div: $(OBJS)
|
||||
$(CC) -g -O3 -o srt4div $(OBJS) $(CFLAGS)
|
||||
|
||||
disp.o: disp.h disp.c
|
||||
$(CC) -g -c -o disp.o disp.c $(CFLAGS)
|
||||
|
||||
srt4div.o: srt4div.c
|
||||
$(CC) -g -c -o srt4div.o srt4div.c $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f core
|
60
pipelined/srt/stine/disp.c
Executable file
60
pipelined/srt/stine/disp.c
Executable file
@ -0,0 +1,60 @@
|
||||
#include "disp.h"
|
||||
|
||||
double rnd_zero(double x, double bits) {
|
||||
if (x < 0)
|
||||
return ceiling(x, bits);
|
||||
else
|
||||
return flr(x, bits);
|
||||
}
|
||||
|
||||
double rne(double x, double precision) {
|
||||
double scale, x_round;
|
||||
scale = pow(2.0, precision);
|
||||
x_round = rint(x * scale) / scale;
|
||||
return x_round;
|
||||
}
|
||||
|
||||
double flr(double x, double precision) {
|
||||
double scale, x_round;
|
||||
scale = pow(2.0, precision);
|
||||
x_round = floor(x * scale) / scale;
|
||||
return x_round;
|
||||
}
|
||||
|
||||
double ceiling(double x, double precision) {
|
||||
double scale, x_round;
|
||||
scale = pow(2.0, precision);
|
||||
x_round = ceil(x * scale) / scale;
|
||||
return x_round;
|
||||
}
|
||||
|
||||
void disp_bin(double x, int bits_to_left, int bits_to_right, FILE *out_file) {
|
||||
|
||||
double diff;
|
||||
int i;
|
||||
if (fabs(x) < pow(2.0, -bits_to_right)) {
|
||||
for (i = -bits_to_left + 1; i <= bits_to_right; i++) {
|
||||
fprintf(out_file,"0");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (x < 0.0) {
|
||||
// fprintf(out_file, "-");
|
||||
// x = - x;
|
||||
x = pow(2.0, ((double) bits_to_left)) + x;
|
||||
}
|
||||
for (i = -bits_to_left + 1; i <= bits_to_right; i++) {
|
||||
diff = pow(2.0, -i);
|
||||
if (x < diff) {
|
||||
fprintf(out_file, "0");
|
||||
}
|
||||
else {
|
||||
fprintf(out_file, "1");
|
||||
x -= diff;
|
||||
}
|
||||
if (i == 0) {
|
||||
fprintf(out_file, ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
pipelined/srt/stine/disp.h
Executable file
18
pipelined/srt/stine/disp.h
Executable file
@ -0,0 +1,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef DISP
|
||||
#define DISP
|
||||
|
||||
double rnd_zero(double x, double bits);
|
||||
|
||||
double rne(double x, double precision);
|
||||
|
||||
double flr(double x, double precision);
|
||||
|
||||
double ceiling(double x, double precision);
|
||||
|
||||
void disp_bin(double x, int bits_to_left, int bits_to_right, FILE *out_file);
|
||||
|
||||
#endif
|
@ -195,7 +195,7 @@ module divide4 #(parameter WIDTH=64)
|
||||
logic [WIDTH:0] Qstar;
|
||||
logic [WIDTH:0] QMstar;
|
||||
logic [WIDTH:0] QM2star;
|
||||
logic [6:0] qtotal;
|
||||
logic [7:0] qtotal;
|
||||
logic [WIDTH+3:0] SumN, CarryN, SumN2, CarryN2;
|
||||
logic [WIDTH+3:0] divi1, divi2, divi1c, divi2c, dive1;
|
||||
logic [WIDTH+3:0] mdivi_temp, mdivi;
|
||||
@ -219,9 +219,9 @@ module divide4 #(parameter WIDTH=64)
|
||||
mux2 #(WIDTH+4) mx2 ({CarryN2[WIDTH+1:0], 2'h0}, {WIDTH+4{1'b0}}, state0, CarryN);
|
||||
mux2 #(WIDTH+4) mx3 ({SumN2[WIDTH+1:0], 2'h0}, dive1, state0, SumN);
|
||||
// Simplify QST
|
||||
adder #(7) cpa1 (SumN[WIDTH+3:WIDTH-3], CarryN[WIDTH+3:WIDTH-3], qtotal);
|
||||
adder #(8) cpa1 (SumN[WIDTH+3:WIDTH-4], CarryN[WIDTH+3:WIDTH-4], qtotal);
|
||||
// q = {+2, +1, -1, -2} else q = 0
|
||||
qst4 pd1 (qtotal[6:0], divi1[WIDTH-1:WIDTH-3], quotient);
|
||||
qst4 pd1 (qtotal[7:1], divi1[WIDTH-1:WIDTH-3], quotient);
|
||||
assign ulp = quotient[2]|quotient[3];
|
||||
assign zero = ~(quotient[3]|quotient[2]|quotient[1]|quotient[0]);
|
||||
// Map to binary encoding
|
||||
|
BIN
pipelined/srt/stine/srt4div
Executable file
BIN
pipelined/srt/stine/srt4div
Executable file
Binary file not shown.
325
pipelined/srt/stine/srt4div.c
Executable file
325
pipelined/srt/stine/srt4div.c
Executable file
@ -0,0 +1,325 @@
|
||||
#include "disp.h"
|
||||
#include <math.h>
|
||||
|
||||
int qslc (double prem, double d) {
|
||||
|
||||
int q;
|
||||
|
||||
printf("d --> %lg\n", d);
|
||||
printf("rw --> %lg\n", prem);
|
||||
if ((d>=0.0)&&(d<1.0)) {
|
||||
if (prem>=1.0)
|
||||
q = 2;
|
||||
else if (prem>=0.25)
|
||||
q = 1;
|
||||
else if (prem>=-0.25)
|
||||
q = 0;
|
||||
else if (prem >= -1)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=1.0)&&(d<2.0)) {
|
||||
if (prem>=2.0)
|
||||
q = 2;
|
||||
else if (prem>=0.66667)
|
||||
q = 1;
|
||||
else if (prem>=-0.6667)
|
||||
q = 0;
|
||||
else if (prem >= -2)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=2.0)&&(d<3.0)) {
|
||||
if (prem>=4.0)
|
||||
q = 2;
|
||||
else if (prem>=1.25)
|
||||
q = 1;
|
||||
else if (prem>=-1.25)
|
||||
q = 0;
|
||||
else if (prem >= -4)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=3.0)&&(d<4.0)) {
|
||||
if (prem>=5.0)
|
||||
q = 2;
|
||||
else if (prem>=2.0)
|
||||
q = 1;
|
||||
else if (prem>=-2.0)
|
||||
q = 0;
|
||||
else if (prem >= -5)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=4.0)&&(d<5.0)) {
|
||||
if (prem>=6.66667)
|
||||
q = 2;
|
||||
else if (prem>=2.0)
|
||||
q = 1;
|
||||
else if (prem>=-2.0)
|
||||
q = 0;
|
||||
else if (prem >= -6.66667)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=5.0)&&(d<6.0)) {
|
||||
if (prem>=8.0)
|
||||
q = 2;
|
||||
else if (prem>=2.0)
|
||||
q = 1;
|
||||
else if (prem>=-2.0)
|
||||
q = 0;
|
||||
else if (prem >= -8.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=6.0)&&(d<7.0)) {
|
||||
if (prem>=10.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -10.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=7.0)&&(d<8.0)) {
|
||||
if (prem>=11.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -11.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=8.0)&&(d<9.0)) {
|
||||
if (prem>=12.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -12.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=9.0)&&(d<10.0)) {
|
||||
if (prem>=15.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -15.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=10.0)&&(d<11.0)) {
|
||||
if (prem>=15.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -15.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=11.0)&&(d<12.0)) {
|
||||
if (prem>=16.0)
|
||||
q = 2;
|
||||
else if (prem>=4.0)
|
||||
q = 1;
|
||||
else if (prem>=-4.0)
|
||||
q = 0;
|
||||
else if (prem >= -16.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=12.0)&&(d<13.0)) {
|
||||
if (prem>=20.0)
|
||||
q = 2;
|
||||
else if (prem>=8.0)
|
||||
q = 1;
|
||||
else if (prem>=-8.0)
|
||||
q = 0;
|
||||
else if (prem >= -20.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=13.0)&&(d<14.0)) {
|
||||
if (prem>=20.0)
|
||||
q = 2;
|
||||
else if (prem>=8.0)
|
||||
q = 1;
|
||||
else if (prem>=-8.0)
|
||||
q = 0;
|
||||
else if (prem >= -20.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=14.0)&&(d<15.0)) {
|
||||
if (prem>=20.0)
|
||||
q = 2;
|
||||
else if (prem>=8.0)
|
||||
q = 1;
|
||||
else if (prem>=-8.0)
|
||||
q = 0;
|
||||
else if (prem >= -20.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
if ((d>=15.0)&&(d<16.0)) {
|
||||
if (prem>=24.0)
|
||||
q = 2;
|
||||
else if (prem>=8.0)
|
||||
q = 1;
|
||||
else if (prem>=-8.0)
|
||||
q = 0;
|
||||
else if (prem >= -24.0)
|
||||
q = -1;
|
||||
else
|
||||
q = -2;
|
||||
return q;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This routine performs a radix-4 SRT division
|
||||
algorithm. The user inputs the numerator, the denominator,
|
||||
and the number of iterations. It assumes that 0.5 <= D < 1.
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
double P, N, D, Q, RQ, RD, RREM, scale;
|
||||
int q;
|
||||
int num_iter, i;
|
||||
int prec;
|
||||
if (argc < 5) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s numerator denominator num_iterations prec\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
sscanf(argv[1],"%lg", &N);
|
||||
sscanf(argv[2],"%lg", &D);
|
||||
sscanf(argv[3],"%d", &num_iter);
|
||||
sscanf(argv[4],"%d", &prec);
|
||||
// Round to precision
|
||||
N = rne(N, prec);
|
||||
D = rne(D, prec);
|
||||
printf("N = ");
|
||||
disp_bin(N, 3, prec, stdout);
|
||||
printf("\n");
|
||||
printf("D = ");
|
||||
disp_bin(D, 3, prec, stdout);
|
||||
printf("\n");
|
||||
|
||||
Q = 0;
|
||||
P = N*0.25;
|
||||
printf("N = %lg, D = %lg, N/D = %lg, num_iter = %d \n\n",
|
||||
N, D, N/D, num_iter);
|
||||
for (scale = 1, i = 0; i < num_iter; i++) {
|
||||
// Shift by r
|
||||
scale = scale*0.25;
|
||||
q = qslc(flr((4*P)*16,3), D*16);
|
||||
//q = -q;
|
||||
printf("4*W[n] = ");
|
||||
disp_bin(4*P,3,prec,stdout);
|
||||
printf("\n");
|
||||
printf("q*D = ");
|
||||
disp_bin(q*D,3,prec,stdout);
|
||||
printf("\n");
|
||||
printf("W[n+1] = ");
|
||||
disp_bin(P ,3,prec,stdout);
|
||||
printf("\n");
|
||||
// Recurrence
|
||||
P = 4*P - q*D;
|
||||
// OTFC
|
||||
Q = Q + q*scale;
|
||||
printf("i = %d, q = %d, Q = %1.18lf, W = %1.18lf\n", i, q, Q, P);
|
||||
printf("i = %d, q = %d", i, q);
|
||||
printf(", Q = ");
|
||||
disp_bin(Q, 3, prec, stdout);
|
||||
printf(", W = ");
|
||||
disp_bin(P, 3, prec, stdout);
|
||||
printf("\n\n");
|
||||
}
|
||||
if (P < 0) {
|
||||
Q = Q - scale;
|
||||
P = P + D;
|
||||
printf("\nCorrecting Negative Remainder\n");
|
||||
printf("Q = %1.18lf, W = %1.18lf\n", Q, P);
|
||||
printf("Q = ");
|
||||
disp_bin(Q, 3, prec, stdout);
|
||||
printf(", W = ");
|
||||
disp_bin(P, 3, prec, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
RQ = flr(N/D, (double) prec);
|
||||
RD = Q*4;
|
||||
printf("true = %1.18lf, computed = %1.18lf, \n", RQ, RD);
|
||||
printf("true = ");
|
||||
disp_bin(RQ, 3, prec, stdout);
|
||||
printf(", computed = ");
|
||||
disp_bin(RD, 3, prec, stdout);
|
||||
printf("\n\n");
|
||||
printf("REM = %1.18lf \n", P);
|
||||
printf("REM = ");
|
||||
disp_bin(P, 3, prec, stdout);
|
||||
printf("\n\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,101 +1,101 @@
|
||||
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,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,5049,0.21904002158843336,237.160005,57.793,84.98752837631214
|
||||
mux2,sky90,64,4087,0.2460982481037436,482.160008,124.422,156.51848579398091
|
||||
mux2,sky90,128,3920,0.25878504081632653,955.500018,279.611,313.9062545102041
|
||||
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,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,3092,0.33231726520051746,1062.320021,325.058,219.99402956274258
|
||||
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
|
||||
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,8,27000,0.04027303703703704,10.332,86.166,4.244778103703704
|
||||
mux2,tsmc28,16,19440,0.052470329218107,15.372,84.373,5.1473392962962965
|
||||
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,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,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
|
||||
priorityencoder,sky90,8,7683,0.12508649056358195,50.960001,24.761,1.0685929975270078e-05
|
||||
priorityencoder,sky90,16,5773,0.16977016282695304,136.220003,77.243,2.1773774467348e-05
|
||||
priorityencoder,sky90,32,4500,0.2218912222222222,372.400007,189.626,4.371111111111111e-05
|
||||
priorityencoder,sky90,64,4098,0.2439914738897023,797.720015,382.205,7.393850658857981e-05
|
||||
priorityencoder,sky90,128,3409,0.2933331557641537,1602.300031,610.009,0.0001261366969785861
|
||||
add,sky90,8,3658,0.27337042810278844,253.820005,154.438,0.00010825587752870422
|
||||
add,sky90,16,2942,0.3393218266485384,722.260013,485.109,0.00032460910944935416
|
||||
add,sky90,32,2468,0.40496338573743923,1440.600027,714.057,0.0006580226904376014
|
||||
add,sky90,64,2139,0.4674681813931744,2781.240054,1050.0,0.0009392239364188873
|
||||
add,sky90,128,1885,0.5304949787798409,6186.740118,2230.0,0.0021480106100795755
|
||||
csa,sky90,8,5758,0.16536141368530738,266.560005,154.202,0.00013650573115665162
|
||||
csa,sky90,16,5931,0.1654056314280897,533.12001,308.404,0.00027263530601922105
|
||||
csa,sky90,32,5758,0.16536141368530738,1066.240021,616.808,0.0005448072247308093
|
||||
csa,sky90,64,5931,0.1654056314280897,2132.480042,1230.0,0.0010905412240768842
|
||||
csa,sky90,128,5931,0.1654056314280897,4264.960083,2470.0,0.002178553363682347
|
||||
shiftleft,sky90,8,4327,0.23025600254217704,259.700005,196.451,7.534088282874971e-05
|
||||
shiftleft,sky90,16,3355,0.29803959314456036,666.400006,558.433,0.00019552906110283157
|
||||
shiftleft,sky90,32,2503,0.39951757530962845,1475.880027,768.262,0.0003807431082700759
|
||||
shiftleft,sky90,64,2203,0.45385946391284615,3914.120062,2680.0,0.001144802541988198
|
||||
shiftleft,sky90,128,1907,0.5242938489774515,9192.400136,6080.0,0.0029008914525432616
|
||||
comparator,sky90,8,4839,0.20629126741062204,200.900004,136.6,5.001033271337053e-05
|
||||
comparator,sky90,16,4018,0.24806303982080635,358.680007,189.253,6.321553011448482e-05
|
||||
comparator,sky90,32,3602,0.276293542476402,690.900013,315.709,0.00010771793448084398
|
||||
comparator,sky90,64,3129,0.31954192361776923,1372.980026,508.393,0.0002048577820389901
|
||||
comparator,sky90,128,2791,0.35824651809387315,2744.980052,796.047,0.0003439627373701182
|
||||
flop,sky90,8,10,0.1143419999999935,133.279999,64.8145,0.000193835
|
||||
flop,sky90,16,10,0.1143419999999935,266.5599975,129.629,0.00038715000000000006
|
||||
flop,sky90,32,10,0.1143419999999935,533.119995,259.258,0.0007723000000000001
|
||||
flop,sky90,64,10,0.1143419999999935,1066.23999,520.0,0.00154955
|
||||
flop,sky90,128,10,0.1143419999999935,2132.4799805,1035.0,0.003094
|
||||
mux2,sky90,8,5299,0.1883518518588413,63.700001,21.541,1.932440083034535e-05
|
||||
mux2,sky90,16,4850,0.20207356701030926,119.560002,32.354,3.884536082474227e-05
|
||||
mux2,sky90,32,5003,0.19908807195682593,375.340008,259.372,0.00013671796921846892
|
||||
mux2,sky90,64,3989,0.24961239583855604,479.220007,148.175,0.00016570569064928555
|
||||
mux2,sky90,128,4004,0.24974824975024976,1302.420025,767.078,0.0004665334665334665
|
||||
mux4,sky90,8,4661,0.21448923471358078,164.640002,88.494,4.31452478009011e-05
|
||||
mux4,sky90,16,4392,0.22421770309653916,359.659999,419.855,0.0001006375227686703
|
||||
mux4,sky90,32,4118,0.24283532831471588,594.860011,331.197,0.00013161728994657602
|
||||
mux4,sky90,64,3710,0.26931477897574124,899.640016,344.331,0.00028625336927223723
|
||||
mux4,sky90,128,3167,0.31575023618566467,2016.840039,722.109,0.0005917271866119355
|
||||
mux8,sky90,8,3585,0.2789170278940028,287.140006,116.648,6.089260808926081e-05
|
||||
mux8,sky90,16,3362,0.295237998810232,582.120003,282.366,0.00014455681142177274
|
||||
mux8,sky90,32,3178,0.3140553102580239,1319.079995,670.683,0.0003577721837633732
|
||||
mux8,sky90,64,2906,0.3440756228492774,2132.48004,808.482,0.0004428768066070199
|
||||
mux8,sky90,128,2667,0.3749401308586427,4575.620089,1830.0,0.0009786276715410573
|
||||
mult,sky90,8,1310,0.7631557786259543,2194.220041,1440.0,0.0014213740458015268
|
||||
mult,sky90,16,997,1.0029260270812437,7519.540137,4940.0,0.0063761283851554666
|
||||
mult,sky90,32,763,1.3106129895150722,25200.700446,14900.0,0.024931847968545216
|
||||
mult,sky90,64,632,1.5822664810126583,86011.661365,42600.0,0.08884651898734176
|
||||
mult,sky90,128,524,1.9083759465648855,296198.144128,114000.0,0.2733148854961832
|
||||
priorityencoder,tsmc28,8,31335,0.031912196106590074,8.316,34.836,1.716929950534546e-06
|
||||
priorityencoder,tsmc28,16,21253,0.04703118086858326,21.672,78.026,4.008845810003294e-06
|
||||
priorityencoder,tsmc28,32,16464,0.06071258114674442,61.614,207.499,9.323372206025267e-06
|
||||
priorityencoder,tsmc28,64,13804,0.07239877021153289,137.466,425.592,1.847290640394089e-05
|
||||
priorityencoder,tsmc28,128,11440,0.0874065874125874,317.646,973.649,4.117132867132867e-05
|
||||
add,tsmc28,8,13838,0.07207477814713109,34.272,187.089,1.3311172134701546e-05
|
||||
add,tsmc28,16,11521,0.08678002100512108,90.972001,475.207,3.367763214998698e-05
|
||||
add,tsmc28,32,9812,0.1018860211985324,209.286002,1060.0,8.153281695882594e-05
|
||||
add,tsmc28,64,8206,0.12185605215695831,388.836003,1770.0,0.0001409943943456008
|
||||
add,tsmc28,128,7354,0.13597341881968997,907.452008,4360.0,0.00034511830296437315
|
||||
csa,tsmc28,8,24524,0.040663382319360626,52.416,482.462,2.173381177621921e-05
|
||||
csa,tsmc28,16,24524,0.040663382319360626,104.832,964.99,4.346762355243842e-05
|
||||
csa,tsmc28,32,24524,0.040663382319360626,209.664,1930.0,8.677214157559942e-05
|
||||
csa,tsmc28,64,24524,0.040663382319360626,419.327999,3860.0,0.00017342195400424075
|
||||
csa,tsmc28,128,24524,0.040663382319360626,838.655998,7720.0,0.00034717011906703634
|
||||
shiftleft,tsmc28,8,15202,0.0656078183133798,50.652,367.074,1.6991185370346006e-05
|
||||
shiftleft,tsmc28,16,11804,0.08465604506946797,127.511999,602.29,3.388681802778719e-05
|
||||
shiftleft,tsmc28,32,9587,0.10430391697089808,384.803997,1940.0,0.00010180452696359654
|
||||
shiftleft,tsmc28,64,8272,0.12086674854932303,1041.263998,5460.0,0.0002895309477756286
|
||||
shiftleft,tsmc28,128,7023,0.14238329232521713,1836.953994,8670.0,0.000566566994162039
|
||||
comparator,tsmc28,8,17422,0.05733769130983814,35.784,170.595,9.488003673516243e-06
|
||||
comparator,tsmc28,16,13736,0.07273839778683751,54.558,250.167,1.4349155503785673e-05
|
||||
comparator,tsmc28,32,12139,0.08236710865804432,145.782,622.975,3.567015404893319e-05
|
||||
comparator,tsmc28,64,11080,0.09024670758122744,294.21,1250.0,6.84115523465704e-05
|
||||
comparator,tsmc28,128,9371,0.10671119720414043,558.432,2400.0,0.00012794792444776438
|
||||
flop,tsmc28,8,10,0.048889000000002625,15.12,78.6345,2.7246000000000003e-05
|
||||
flop,tsmc28,16,10,0.048889000000002625,30.24,157.29,5.4290000000000004e-05
|
||||
flop,tsmc28,32,10,0.048889000000002625,60.4799995,314.5805,0.00010908
|
||||
flop,tsmc28,64,10,0.048889000000002625,120.959999,630.0,0.00021765500000000003
|
||||
flop,tsmc28,128,10,0.048889000000002625,241.919998,1260.0,0.00043579999999999997
|
||||
mux2,tsmc28,8,29614,0.03374481252110488,16.758,114.564,5.436617815897886e-06
|
||||
mux2,tsmc28,16,18767,0.053046021580433735,15.75,88.025,5.142004582511856e-06
|
||||
mux2,tsmc28,32,17903,0.05585556035301346,32.130001,171.146,9.897782494553986e-06
|
||||
mux2,tsmc28,64,18568,0.05371109651012495,91.35,523.884,2.757432141318397e-05
|
||||
mux2,tsmc28,128,16637,0.05991099044298852,176.525999,941.106,5.012923002945243e-05
|
||||
mux4,tsmc28,8,18151,0.055092383284667513,27.971999,133.963,8.032615282904523e-06
|
||||
mux4,tsmc28,16,16486,0.06057952759917506,39.438,186.231,1.2556108213029237e-05
|
||||
mux4,tsmc28,32,15196,0.06580579126085812,69.174,324.969,2.3229797315082915e-05
|
||||
mux4,tsmc28,64,13926,0.07180612868016659,137.465999,648.086,4.5741777969266124e-05
|
||||
mux4,tsmc28,128,13090,0.07636619404125286,294.335997,1420.0,9.358288770053477e-05
|
||||
mux8,tsmc28,8,12902,0.07750336319950395,44.604,214.286,1.17501162610448e-05
|
||||
mux8,tsmc28,16,12264,0.08147446510110894,128.771998,548.714,2.666340508806262e-05
|
||||
mux8,tsmc28,32,11713,0.08517122410996329,172.115999,823.633,4.695637326047981e-05
|
||||
mux8,tsmc28,64,11014,0.09067453550027238,304.163999,1460.0,8.498274922825495e-05
|
||||
mux8,tsmc28,128,10474,0.09542350830628223,683.045996,2820.0,0.00015705556616383426
|
||||
mult,tsmc28,8,5200,0.1922996923076923,577.206,4340.0,0.00037769230769230767
|
||||
mult,tsmc28,16,3819,0.26184265147944485,1634.472002,11800.0,0.0014553548049227546
|
||||
mult,tsmc28,32,3033,0.3295775611605671,6343.721998,47200.0,0.0063033300362677225
|
||||
mult,tsmc28,64,2390,0.4184090418410042,16045.092071,109000.0,0.01854602510460251
|
||||
mult,tsmc28,128,1868,0.5353279057815846,44272.49428,262000.0,0.05001177730192719
|
||||
|
|
113
synthDC/oldBestSynths.csv
Normal file
113
synthDC/oldBestSynths.csv
Normal file
@ -0,0 +1,113 @@
|
||||
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
|
|
2006
synthDC/oldPpaData.csv
Normal file
2006
synthDC/oldPpaData.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,7 +60,7 @@ def synthsintocsv():
|
||||
delay = 1000/int(freq) - metrics[0]
|
||||
area = metrics[1]
|
||||
lpower = metrics[4]
|
||||
denergy = (metrics[2] + metrics[3])*delay*1000 # (switching + internal powers)*delay, more practical units for regression coefs
|
||||
denergy = (metrics[2] + metrics[3])/int(freq) # (switching + internal powers)*delay, more practical units for regression coefs
|
||||
|
||||
if ('flop' in module): # since two flops in each module
|
||||
[area, lpower, denergy] = [n/2 for n in [area, lpower, denergy]]
|
||||
@ -85,22 +85,26 @@ def cleanup():
|
||||
output = subprocess.check_output(['bash','-c', bashCommand])
|
||||
allSynths = output.decode("utf-8").split('\n')[:-1]
|
||||
for oneSynth in allSynths:
|
||||
for phrase in [['Path Length', 'qor'], ['Design Area', 'qor'], ['100', 'power']]:
|
||||
for phrase in [['Path Length', 'qor']]: #, ['Design Area', 'qor'], ['100', 'power']]:
|
||||
bashCommand = 'grep "{}" '+ oneSynth[2:]+'/reports/*{}*'
|
||||
bashCommand = bashCommand.format(*phrase)
|
||||
try: output = subprocess.check_output(['bash','-c', bashCommand])
|
||||
except:
|
||||
bc = 'rm -r '+ oneSynth[2:]
|
||||
try: output = subprocess.check_output(['bash','-c', bc])
|
||||
except: pass
|
||||
output = subprocess.check_output(['bash','-c', bc])
|
||||
print("All cleaned up!")
|
||||
|
||||
def getVals(tech, module, var, freq=None):
|
||||
def getVals(tech, module, var, freq=None, width=None):
|
||||
''' for a specified tech, module, and variable/metric
|
||||
returns a list of values for that metric in ascending width order
|
||||
works at a specified target frequency or if none is given, uses the synthesis with the best achievable delay for each width
|
||||
'''
|
||||
|
||||
if width != None:
|
||||
widthsToGet = width
|
||||
else:
|
||||
widthsToGet = widths
|
||||
|
||||
metric = []
|
||||
widthL = []
|
||||
|
||||
@ -112,7 +116,7 @@ def getVals(tech, module, var, freq=None):
|
||||
metric += [osdict[var]]
|
||||
metric = [x for _, x in sorted(zip(widthL, metric))] # ordering
|
||||
else:
|
||||
for w in widths:
|
||||
for w in widthsToGet:
|
||||
for oneSynth in bestSynths:
|
||||
if (oneSynth.width == w) & (oneSynth.tech == tech) & (oneSynth.module == module):
|
||||
osdict = oneSynth._asdict()
|
||||
@ -120,30 +124,59 @@ def getVals(tech, module, var, freq=None):
|
||||
metric += [met]
|
||||
return metric
|
||||
|
||||
def csvOfBest():
|
||||
def csvOfBest(filename):
|
||||
bestSynths = []
|
||||
for tech in [x.tech for x in techSpecs]:
|
||||
for mod in modules:
|
||||
for w in widths:
|
||||
m = np.Inf # large number to start
|
||||
best = None
|
||||
if [mod, tech, w] in leftblue:
|
||||
for oneSynth in allSynths:
|
||||
if ([mod, tech, w] in leftblue):
|
||||
for oneSynth in allSynths: # leftmost blue
|
||||
if (oneSynth.width == w) & (oneSynth.tech == tech) & (oneSynth.module == mod):
|
||||
if (oneSynth.freq < m) & (1000/oneSynth.delay < oneSynth.freq):
|
||||
if ([mod, tech, w] != ['mux2', 'sky90', 128]) or (oneSynth.area < 1100):
|
||||
m = oneSynth.freq
|
||||
best = oneSynth
|
||||
# if ([mod, tech, w] != ['mux2', 'sky90', 128]) or (oneSynth.area < 1100):
|
||||
m = oneSynth.freq
|
||||
best = oneSynth
|
||||
else:
|
||||
for oneSynth in allSynths:
|
||||
for oneSynth in allSynths: # best achievable, rightmost green
|
||||
if (oneSynth.width == w) & (oneSynth.tech == tech) & (oneSynth.module == mod):
|
||||
if (oneSynth.delay < m) & (1000/oneSynth.delay > oneSynth.freq):
|
||||
m = oneSynth.delay
|
||||
best = oneSynth
|
||||
# contenders = []
|
||||
# delays = []
|
||||
# for oneSynth in allSynths: # choose synth w minimal delay
|
||||
# if (oneSynth.width == w) & (oneSynth.tech == tech) & (oneSynth.module == mod):
|
||||
# contenders += [oneSynth]
|
||||
# delays += [oneSynth.delay]
|
||||
# if oneSynth.delay < m:
|
||||
# m = oneSynth.delay
|
||||
# best = oneSynth
|
||||
|
||||
# for oneSynth in contenders: # if m is min delay, choose best area within s as percent of m
|
||||
# s = oneSynth.delay/m - 1
|
||||
# if s < 0.1:
|
||||
# if oneSynth.area < best.area:
|
||||
# best = oneSynth
|
||||
|
||||
# bestval = 1.9 # score algorithm
|
||||
# for oneSynth in contenders:
|
||||
# delaydif = abs(1 - oneSynth.delay/best.delay)
|
||||
# areadif = 1 - oneSynth.area/best.area
|
||||
# try: val = areadif/delaydif
|
||||
# except: val = 1
|
||||
# # if (oneSynth.width == 64) & (oneSynth.tech == 'sky90') & (oneSynth.module == 'comparator'):
|
||||
# # print(oneSynth.freq, ' ', delaydif, ' ', areadif, ' ', val)
|
||||
# if val > bestval:
|
||||
# bestval = val
|
||||
# best = oneSynth
|
||||
|
||||
if (best != None) & (best not in bestSynths):
|
||||
bestSynths += [best]
|
||||
|
||||
file = open("bestSynths.csv", "w")
|
||||
|
||||
file = open(filename, "w")
|
||||
writer = csv.writer(file)
|
||||
writer.writerow(['Module', 'Tech', 'Width', 'Target Freq', 'Delay', 'Area', 'L Power (nW)', 'D energy (fJ)'])
|
||||
for synth in bestSynths:
|
||||
@ -234,20 +267,18 @@ def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn', norm=True, colo
|
||||
else:
|
||||
ylabeldic = {"lpower": "Leakage Power (nW)", "denergy": "Dynamic Energy (fJ)", "area": "Area (sq microns)", "delay": "Delay (ns)"}
|
||||
|
||||
# fullLeg += genLegend(fits, coefs, r2, combined, ale=ale)
|
||||
# legLoc = 'upper left' if ale else 'center right'
|
||||
# ax.add_artist(ax.legend(handles=fullLeg, loc=legLoc))
|
||||
|
||||
ax.set_xticks(widths)
|
||||
ax.set_xlabel("Width (bits)")
|
||||
ax.set_ylabel(ylabeldic[var])
|
||||
ax.set_xticks(widths)
|
||||
|
||||
if (module in ['flop', 'csa']) & (var == 'delay'):
|
||||
ax.set_ylim(ymin=0)
|
||||
ytop = ax.get_ylim()[1]
|
||||
ax.set_ylim(ymax=1.1*ytop)
|
||||
if singlePlot or (var == 'lpower') or (var == 'denergy'):
|
||||
ax.set_xlabel("Width (bits)")
|
||||
if not singlePlot and ((var == 'delay') or (var == 'area')):
|
||||
ax.tick_params(labelbottom=False)
|
||||
|
||||
if singlePlot:
|
||||
fullLeg += genLegend(fits, coefs, r2, combined, ale=ale)
|
||||
legLoc = 'upper left' if ale else 'center right'
|
||||
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')
|
||||
@ -260,7 +291,7 @@ def regress(widths, var, fits='clsgn', ale=False):
|
||||
'''
|
||||
|
||||
funcArr = genFuncs(fits)
|
||||
xp = np.linspace(4, 140, 200)
|
||||
xp = np.linspace(min(widths)/2, max(widths)*1.1, 200)
|
||||
xpToCalc = xp
|
||||
|
||||
if ale:
|
||||
@ -413,7 +444,7 @@ def freqPlot(tech, mod, width):
|
||||
median = np.median(list(flatten(freqsL)))
|
||||
|
||||
f, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
|
||||
for ax in (ax1, ax2): #, ax3, ax4):
|
||||
for ax in (ax1, ax2):
|
||||
ax.ticklabel_format(useOffset=False, style='plain')
|
||||
|
||||
for ind in [0,1]:
|
||||
@ -421,15 +452,11 @@ def freqPlot(tech, mod, width):
|
||||
delays = delaysL[ind]
|
||||
freqs = freqsL[ind]
|
||||
|
||||
# freqs, delays, areas = noOutliers(median, freqs, delays, areas) # comment out to see all syntheses
|
||||
freqs, delays, areas = noOutliers(median, freqs, delays, areas) # comment out to see all syntheses
|
||||
|
||||
c = 'blue' if ind else 'green'
|
||||
# adprod = adprodpow(areas, delays, 1)
|
||||
# adpow = adprodpow(areas, delays, 2)
|
||||
ax1.scatter(freqs, delays, color=c)
|
||||
ax2.scatter(freqs, areas, color=c)
|
||||
# ax3.scatter(freqs, adprod, color=c)
|
||||
# ax4.scatter(freqs, adpow, color=c)
|
||||
|
||||
legend_elements = [lines.Line2D([0], [0], color='green', ls='', marker='o', label='timing achieved'),
|
||||
lines.Line2D([0], [0], color='blue', ls='', marker='o', label='slack violated')]
|
||||
@ -440,8 +467,6 @@ def freqPlot(tech, mod, width):
|
||||
ax2.set_xlabel("Target Freq (MHz)")
|
||||
ax1.set_ylabel('Delay (ns)')
|
||||
ax2.set_ylabel('Area (sq microns)')
|
||||
# ax3.set_ylabel('Area * Delay')
|
||||
# ax4.set_ylabel('Area * $Delay^2$')
|
||||
ax1.set_title(mod + '_' + width)
|
||||
if ('mux' in mod) & ('d' in mod):
|
||||
width = mod
|
||||
@ -524,22 +549,13 @@ def squarify(fig):
|
||||
l = (1.-axs/h)/2
|
||||
fig.subplots_adjust(bottom=l, top=1-l)
|
||||
|
||||
def adprodpow(areas, delays, pow):
|
||||
''' for each value in [areas] returns area*delay^pow
|
||||
helper function for freqPlot'''
|
||||
result = []
|
||||
|
||||
for i in range(len(areas)):
|
||||
result += [(areas[i])*(delays[i])**pow]
|
||||
|
||||
return result
|
||||
|
||||
def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
||||
''' for the module specified, plots width vs delay, area, leakage power, and dynamic energy with fits
|
||||
if no freq specified, uses the synthesis with best achievable delay for each width
|
||||
overlays data from both techs
|
||||
'''
|
||||
plt.rcParams["figure.figsize"] = (10,7)
|
||||
plt.rcParams["figure.figsize"] = (7,3.6)
|
||||
fig, axs = plt.subplots(2, 2)
|
||||
|
||||
arr = [['delay', 'area'], ['lpower', 'denergy']]
|
||||
@ -557,14 +573,17 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
||||
r2 = oneMetricPlot(mod, arr[i][j], ax=axs[i, j], freq=f, norm=norm)
|
||||
ls = '--' if f else '-'
|
||||
leg += [lines.Line2D([0], [0], color='red', label='$R^2$='+str(round(r2, 4)), linestyle=ls)]
|
||||
axs[i, j].legend(handles=leg)
|
||||
|
||||
if (mod in ['flop', 'csa']) & (arr[i][j] == 'delay'):
|
||||
axs[i, j].set_ylim(ymin=0)
|
||||
ytop = axs[i, j].get_ylim()[1]
|
||||
axs[i, j].set_ylim(ymax=1.1*ytop)
|
||||
else:
|
||||
axs[i, j].legend(handles=leg, handlelength=1.5)
|
||||
|
||||
titleStr = " (target " + str(freq)+ "MHz)" if freq != None else ""
|
||||
plt.suptitle(mod + titleStr)
|
||||
|
||||
fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')]
|
||||
fullLeg += [lines.Line2D([0], [0], color='black', label='smallest', linestyle='--')]
|
||||
fig.legend(handles=fullLeg, ncol=3, loc='center', bbox_to_anchor=(0.3, 0.82, 0.4, 0.2))
|
||||
plt.tight_layout(pad=0.05, w_pad=1, h_pad=0.5, rect=(0,0,1,0.97))
|
||||
|
||||
if freq != 10:
|
||||
n = 'normalized' if norm else 'unnormalized'
|
||||
@ -574,32 +593,103 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
||||
|
||||
def plotBestAreas(mod):
|
||||
fig, axs = plt.subplots(1, 1)
|
||||
### all areas on one
|
||||
# mods = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop']
|
||||
# colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple']
|
||||
# legend_elements = []
|
||||
# for i in range(len(mods)):
|
||||
# oneMetricPlot(mods[i], 'area', ax=axs, freq=10, norm=False, color=colors[i])
|
||||
# legend_elements += [lines.Line2D([0], [0], color=colors[i], ls='', marker='o', label=mods[i])]
|
||||
# plt.suptitle('Optimized Areas (target freq 10MHz)')
|
||||
# plt.legend(handles=legend_elements)
|
||||
# plt.savefig('./plots/bestareas.png')
|
||||
# plt.show()
|
||||
|
||||
oneMetricPlot(mod, 'area', freq=10)
|
||||
plt.title(mod + ' Optimized Areas (target freq 10MHz)')
|
||||
plt.savefig('./plots/bestAreas/' + mod + '.png')
|
||||
|
||||
def makeDaLegend():
|
||||
plt.rcParams["figure.figsize"] = (5.5,0.3)
|
||||
fig = plt.figure()
|
||||
fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')]
|
||||
fullLeg += [lines.Line2D([0], [0], color='black', label='smallest', linestyle='--')]
|
||||
fullLeg += [lines.Line2D([0], [0], color='blue', label='tsmc28', marker='^')]
|
||||
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'
|
||||
plt.savefig(saveStr)
|
||||
|
||||
def calcAvgRsq():
|
||||
with open('ppaFitting.csv', newline='') as csvfile:
|
||||
csvreader = csv.reader(csvfile)
|
||||
allSynths = list(csvreader)[1:]
|
||||
csvfile.close()
|
||||
|
||||
others = []
|
||||
muxes = []
|
||||
|
||||
for synth in allSynths:
|
||||
if ('easy' not in synth) or ('delay' not in synth):
|
||||
if 'mux' in synth[0]:
|
||||
muxes += [float(synth[8])]
|
||||
elif '0.0' != synth[8]:
|
||||
others += [float(synth[8])]
|
||||
|
||||
print('Others: ', np.mean(others))
|
||||
print('Muxes: ', np.mean(muxes))
|
||||
|
||||
def muxPlot(fits='clsgn', norm=True):
|
||||
''' module: string module name
|
||||
freq: int freq (MHz)
|
||||
var: string delay, area, lpower, or denergy
|
||||
fits: constant, linear, square, log2, Nlog2
|
||||
plots given variable vs width for all matching syntheses with regression
|
||||
'''
|
||||
ax = plt.gca()
|
||||
|
||||
inputs = [2, 4, 8]
|
||||
allInputs = inputs*2
|
||||
fullLeg = []
|
||||
|
||||
for crit in ['data', 'control']:
|
||||
allMetrics = []
|
||||
muxes = ['mux2', 'mux4', 'mux8']
|
||||
|
||||
if crit == 'data':
|
||||
ls = '--'
|
||||
muxes = [m + 'd' for m in muxes]
|
||||
elif crit == 'control':
|
||||
ls = '-'
|
||||
|
||||
for spec in techSpecs:
|
||||
metric = []
|
||||
for module in muxes:
|
||||
metric += getVals(spec.tech, module, 'delay', width=[1])
|
||||
|
||||
if norm:
|
||||
techdict = spec._asdict()
|
||||
norm = techdict['delay']
|
||||
metric = [m/norm for m in metric]
|
||||
|
||||
if len(metric) == 3: # don't include the spec if we don't have points for all
|
||||
xp, pred, coefs, r2 = regress(inputs, metric, fits, ale=False)
|
||||
ax.scatter(inputs, metric, color=spec.color, marker=spec.shape)
|
||||
ax.plot(xp, pred, color=spec.color, linestyle=ls)
|
||||
allMetrics += metric
|
||||
|
||||
xp, pred, coefs, r2 = regress(allInputs, allMetrics, fits)
|
||||
ax.plot(xp, pred, color='red', linestyle=ls)
|
||||
fullLeg += [lines.Line2D([0], [0], color='red', label=crit, linestyle=ls)]
|
||||
|
||||
ax.set_ylabel('Delay (FO4)')
|
||||
ax.set_xticks(inputs)
|
||||
ax.set_xlabel("Number of inputs")
|
||||
ax.set_title('mux timing')
|
||||
|
||||
ax.legend(handles = fullLeg)
|
||||
plt.savefig('./plots/PPA/mux.png')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
##############################
|
||||
# set up stuff, global variables
|
||||
widths = [8, 16, 32, 64, 128]
|
||||
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult'] #, 'mux2d', 'mux4d', 'mux8d',]
|
||||
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult'] # 'mux2d', 'mux4d', 'mux8d']
|
||||
normAddWidth = 32 # divisor to use with N since normalizing to add_32
|
||||
|
||||
fitDict = {'add': ['cg', 'l', 'l'], 'mult': ['cg', 'ls', 'ls'], 'comparator': ['cg', 'l', 'l'], 'csa': ['c', 'l', 'l'], 'shiftleft': ['cg', 'l', 'ln'], 'flop': ['c', 'l', 'l'], 'priorityencoder': ['cg', 'l', 'l']}
|
||||
fitDict.update(dict.fromkeys(['mux2', 'mux4', 'mux8'], ['cg', 'l', 'l']))
|
||||
leftblue = [['mux2', 'sky90', 32], ['mux2', 'sky90', 64], ['mux2', 'sky90', 128], ['mux8', 'sky90', 32], ['mux2', 'tsmc28', 8], ['mux2', 'tsmc28', 64]]
|
||||
leftblue = [] #[['mux2', 'tsmc28', 8], ['mux4', 'sky90', 16]]
|
||||
|
||||
TechSpec = namedtuple("TechSpec", "tech color shape delay area lpower denergy")
|
||||
techSpecs = [['sky90', 'green', 'o', 43.2e-3, 1330.84, 582.81, 520.66], ['tsmc28', 'blue', '^', 12.2e-3, 209.29, 1060, 81.43]]
|
||||
@ -612,20 +702,23 @@ if __name__ == '__main__':
|
||||
# synthsintocsv() # slow, run only when new synth runs to add to csv
|
||||
|
||||
allSynths = synthsfromcsv('ppaData.csv') # your csv here!
|
||||
bestSynths = csvOfBest()
|
||||
bestSynths = csvOfBest('bestSynths.csv')
|
||||
|
||||
# ### plotting examples
|
||||
# squareAreaDelay('sky90', 'add', 32)
|
||||
# oneMetricPlot('add', 'delay')
|
||||
# oneMetricPlot('add', 'area')
|
||||
# freqPlot('sky90', 'mux4', 16)
|
||||
# plotBestAreas('add')
|
||||
# makeCoefTable()
|
||||
# calcAvgRsq()
|
||||
# makeEqTable()
|
||||
|
||||
for mod in modules:
|
||||
plotPPA(mod, norm=False)
|
||||
plotPPA(mod, aleOpt=True)
|
||||
for w in [8, 16, 32, 64, 128]:
|
||||
freqPlot('sky90', mod, w)
|
||||
freqPlot('tsmc28', mod, w)
|
||||
plt.close('all')
|
||||
# makeDaLegend()
|
||||
# muxPlot()
|
||||
|
||||
# for mod in modules:
|
||||
# # plotPPA(mod, norm=False)
|
||||
# # plotPPA(mod, aleOpt=True)
|
||||
# for w in widths:
|
||||
# freqPlot('sky90', mod, w)
|
||||
# freqPlot('tsmc28', mod, w)
|
||||
# plt.close('all')
|
2961
synthDC/ppaData.csv
2961
synthDC/ppaData.csv
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
34
tests/riscof/Makefile
Normal file
34
tests/riscof/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
arch_dir = ../../addins/riscv-arch-test
|
||||
work_dir = "./riscof_work"
|
||||
current_dir = $(shell pwd)
|
||||
|
||||
all: clone memfile
|
||||
|
||||
clone:
|
||||
mkdir -p $(work_dir)
|
||||
mkdir -p work
|
||||
sed 's,{0},$(current_dir),g;s,{1},32imc,g' config.ini > config32.ini
|
||||
sed 's,{0},$(current_dir),g;s,{1},64gc,g' config.ini > config64.ini
|
||||
riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env
|
||||
cp -r $(work_dir)/rv64i_m work/
|
||||
riscof run --work-dir=$(work_dir) --config=config32.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env
|
||||
cp -r $(work_dir)/rv32i_m work/
|
||||
# sed >> config64.ini
|
||||
# (cd $(arch_dir) && riscof validateyaml --config=config.ini)
|
||||
# (cd $(arch_dir) && riscof --verbose info arch-test --clone)
|
||||
# (cd $(arch_dir) && riscof testlist --config=config.ini --suite=riscv-arch-test/riscv-test-suite/ --env=riscv-arch-test/riscv-test-suite/env)
|
||||
# sed -i 's/riscv{.}-unknown-/riscv64-unknown-/g' $(arch_dir)/spike/riscof_spike.py
|
||||
# sed -i 's/riscv{.}-unknown-/riscv64-unknown-/g' $(arch_dir)/sail_cSim/riscof_sail_cSim.py
|
||||
|
||||
memfile:
|
||||
sleep 1
|
||||
find work/rv*/*/ -type f -name "*ref.elf" | while read f; do riscv64-unknown-elf-objdump -S -D "$$f" > "$$f.objdump"; done
|
||||
find work/rv32*/*/ -type f -name "*ref.elf" | while read f; do riscv64-unknown-elf-elf2hex --bit-width 32 --input "$$f" --output "$$f.memfile"; done
|
||||
find work/rv64*/*/ -type f -name "*ref.elf" | while read f; do riscv64-unknown-elf-elf2hex --bit-width 64 --input "$$f" --output "$$f.memfile"; done
|
||||
find work/rv*/*/ -type f -name "*.objdump" | while read f; do extractFunctionRadix.sh $$f; done
|
||||
|
||||
clean:
|
||||
rm -f config64.ini
|
||||
rm -f config32.ini
|
||||
rm -rf $(work_dir)
|
||||
rm -rf work
|
14
tests/riscof/config.ini
Normal file
14
tests/riscof/config.ini
Normal file
@ -0,0 +1,14 @@
|
||||
[RISCOF]
|
||||
ReferencePlugin=sail_cSim
|
||||
ReferencePluginPath={0}/sail_cSim
|
||||
DUTPlugin=spike
|
||||
DUTPluginPath={0}/spike
|
||||
|
||||
[spike]
|
||||
pluginpath={0}/spike
|
||||
ispec={0}/spike/spike_rv{1}_isa.yaml
|
||||
pspec={0}/spike/spike_platform.yaml
|
||||
target_run=1
|
||||
|
||||
[sail_cSim]
|
||||
pluginpath={0}/sail_cSim
|
2
tests/riscof/sail_cSim/__init__.py
Normal file
2
tests/riscof/sail_cSim/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
18
tests/riscof/sail_cSim/env/link.ld
vendored
Normal file
18
tests/riscof/sail_cSim/env/link.ld
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(rvtest_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80000000;
|
||||
.text.init : { *(.text.init) }
|
||||
. = ALIGN(0x1000);
|
||||
.tohost : { *(.tohost) }
|
||||
. = ALIGN(0x1000);
|
||||
.text : { *(.text) }
|
||||
. = ALIGN(0x1000);
|
||||
.data : { *(.data) }
|
||||
.data.string : { *(.data.string)}
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
|
55
tests/riscof/sail_cSim/env/model_test.h
vendored
Normal file
55
tests/riscof/sail_cSim/env/model_test.h
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef _COMPLIANCE_MODEL_H
|
||||
#define _COMPLIANCE_MODEL_H
|
||||
|
||||
#define RVMODEL_DATA_SECTION \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.align 8; .global tohost; tohost: .dword 0; \
|
||||
.align 8; .global fromhost; fromhost: .dword 0; \
|
||||
.popsection; \
|
||||
.align 8; .global begin_regstate; begin_regstate: \
|
||||
.word 128; \
|
||||
.align 8; .global end_regstate; end_regstate: \
|
||||
.word 4;
|
||||
|
||||
//RV_COMPLIANCE_HALT
|
||||
#define RVMODEL_HALT \
|
||||
li x1, 1; \
|
||||
write_tohost: \
|
||||
sw x1, tohost, t5; \
|
||||
j write_tohost;
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
|
||||
//RV_COMPLIANCE_DATA_BEGIN
|
||||
#define RVMODEL_DATA_BEGIN \
|
||||
RVMODEL_DATA_SECTION \
|
||||
.align 4;\
|
||||
.global begin_signature; begin_signature:
|
||||
|
||||
//RV_COMPLIANCE_DATA_END
|
||||
#define RVMODEL_DATA_END \
|
||||
.align 4; .global end_signature; end_signature:
|
||||
|
||||
//RVTEST_IO_INIT
|
||||
#define RVMODEL_IO_INIT
|
||||
//RVTEST_IO_WRITE_STR
|
||||
#define RVMODEL_IO_WRITE_STR(_R, _STR)
|
||||
//RVTEST_IO_CHECK
|
||||
#define RVMODEL_IO_CHECK()
|
||||
//RVTEST_IO_ASSERT_GPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)
|
||||
//RVTEST_IO_ASSERT_SFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
|
||||
//RVTEST_IO_ASSERT_DFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
|
||||
|
||||
#define RVMODEL_SET_MSW_INT
|
||||
|
||||
#define RVMODEL_CLEAR_MSW_INT
|
||||
|
||||
#define RVMODEL_CLEAR_MTIMER_INT
|
||||
|
||||
#define RVMODEL_CLEAR_MEXT_INT
|
||||
|
||||
|
||||
#endif // _COMPLIANCE_MODEL_H
|
124
tests/riscof/sail_cSim/riscof_sail_cSim.py
Normal file
124
tests/riscof/sail_cSim/riscof_sail_cSim.py
Normal file
@ -0,0 +1,124 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import shlex
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
from string import Template
|
||||
|
||||
import riscof.utils as utils
|
||||
from riscof.pluginTemplate import pluginTemplate
|
||||
import riscof.constants as constants
|
||||
from riscv_isac.isac import isac
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class sail_cSim(pluginTemplate):
|
||||
__model__ = "sail_c_simulator"
|
||||
__version__ = "0.5.0"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
sclass = super().__init__(*args, **kwargs)
|
||||
|
||||
config = kwargs.get('config')
|
||||
if config is None:
|
||||
logger.error("Config node for sail_cSim missing.")
|
||||
raise SystemExit(1)
|
||||
self.num_jobs = str(config['jobs'] if 'jobs' in config else 1)
|
||||
self.pluginpath = os.path.abspath(config['pluginpath'])
|
||||
self.sail_exe = { '32' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV32"),
|
||||
'64' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV64")}
|
||||
self.isa_spec = os.path.abspath(config['ispec']) if 'ispec' in config else ''
|
||||
self.platform_spec = os.path.abspath(config['pspec']) if 'ispec' in config else ''
|
||||
self.make = config['make'] if 'make' in config else 'make'
|
||||
logger.debug("SAIL CSim plugin initialised using the following configuration.")
|
||||
for entry in config:
|
||||
logger.debug(entry+' : '+config[entry])
|
||||
return sclass
|
||||
|
||||
def initialise(self, suite, work_dir, archtest_env):
|
||||
self.suite = suite
|
||||
self.work_dir = work_dir
|
||||
self.objdump_cmd = 'riscv64-unknown-elf-objdump -D {0} > {2};'
|
||||
self.compile_cmd = 'riscv64-unknown-elf-gcc -march={0} \
|
||||
-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles\
|
||||
-T '+self.pluginpath+'/env/link.ld\
|
||||
-I '+self.pluginpath+'/env/\
|
||||
-I ' + archtest_env
|
||||
|
||||
def build(self, isa_yaml, platform_yaml):
|
||||
ispec = utils.load_yaml(isa_yaml)['hart0']
|
||||
self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32')
|
||||
self.isa = 'rv' + self.xlen
|
||||
self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ')
|
||||
if "I" in ispec["ISA"]:
|
||||
self.isa += 'i'
|
||||
if "M" in ispec["ISA"]:
|
||||
self.isa += 'm'
|
||||
if "C" in ispec["ISA"]:
|
||||
self.isa += 'c'
|
||||
if "F" in ispec["ISA"]:
|
||||
self.isa += 'f'
|
||||
if "D" in ispec["ISA"]:
|
||||
self.isa += 'd'
|
||||
objdump = "riscv64-unknown-elf-objdump".format(self.xlen)
|
||||
if shutil.which(objdump) is None:
|
||||
logger.error(objdump+": executable not found. Please check environment setup.")
|
||||
raise SystemExit(1)
|
||||
compiler = "riscv64-unknown-elf-gcc".format(self.xlen)
|
||||
if shutil.which(compiler) is None:
|
||||
logger.error(compiler+": executable not found. Please check environment setup.")
|
||||
raise SystemExit(1)
|
||||
if shutil.which(self.sail_exe[self.xlen]) is None:
|
||||
logger.error(self.sail_exe[self.xlen]+ ": executable not found. Please check environment setup.")
|
||||
raise SystemExit(1)
|
||||
if shutil.which(self.make) is None:
|
||||
logger.error(self.make+": executable not found. Please check environment setup.")
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def runTests(self, testList, cgf_file=None):
|
||||
if os.path.exists(self.work_dir+ "/Makefile." + self.name[:-1]):
|
||||
os.remove(self.work_dir+ "/Makefile." + self.name[:-1])
|
||||
make = utils.makeUtil(makefilePath=os.path.join(self.work_dir, "Makefile." + self.name[:-1]))
|
||||
make.makeCommand = self.make + ' -j' + self.num_jobs
|
||||
for file in testList:
|
||||
testentry = testList[file]
|
||||
test = testentry['test_path']
|
||||
test_dir = testentry['work_dir']
|
||||
test_name = test.rsplit('/',1)[1][:-2]
|
||||
|
||||
elf = 'ref.elf'
|
||||
|
||||
execute = "@cd "+testentry['work_dir']+";"
|
||||
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen) + ' ' + test + ' -o ' + elf
|
||||
compile_cmd = cmd + ' -D' + " -D".join(testentry['macros'])
|
||||
execute+=compile_cmd+";"
|
||||
|
||||
execute += self.objdump_cmd.format(elf, self.xlen, 'ref.disass')
|
||||
sig_file = os.path.join(test_dir, self.name[:-1] + ".signature")
|
||||
|
||||
execute += self.sail_exe[self.xlen] + ' --test-signature={0} {1} > {2}.log 2>&1;'.format(sig_file, elf, test_name)
|
||||
|
||||
cov_str = ' '
|
||||
for label in testentry['coverage_labels']:
|
||||
cov_str+=' -l '+label
|
||||
|
||||
if cgf_file is not None:
|
||||
coverage_cmd = 'riscv_isac --verbose info coverage -d \
|
||||
-t {0}.log --parser-name c_sail -o coverage.rpt \
|
||||
--sig-label begin_signature end_signature \
|
||||
--test-label rvtest_code_begin rvtest_code_end \
|
||||
-e ref.elf -c {1} -x{2} {3};'.format(\
|
||||
test_name, ' -c '.join(cgf_file), self.xlen, cov_str)
|
||||
else:
|
||||
coverage_cmd = ''
|
||||
|
||||
|
||||
execute+=coverage_cmd
|
||||
|
||||
make.add_target(execute)
|
||||
make.execute_all(self.work_dir)
|
18
tests/riscof/spike/env/link.ld
vendored
Normal file
18
tests/riscof/spike/env/link.ld
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(rvtest_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80000000;
|
||||
.text.init : { *(.text.init) }
|
||||
. = ALIGN(0x1000);
|
||||
.tohost : { *(.tohost) }
|
||||
. = ALIGN(0x1000);
|
||||
.text : { *(.text) }
|
||||
. = ALIGN(0x1000);
|
||||
.data : { *(.data) }
|
||||
.data.string : { *(.data.string)}
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
|
60
tests/riscof/spike/env/model_test.h
vendored
Normal file
60
tests/riscof/spike/env/model_test.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef _COMPLIANCE_MODEL_H
|
||||
#define _COMPLIANCE_MODEL_H
|
||||
#define RVMODEL_DATA_SECTION \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.align 8; .global tohost; tohost: .dword 0; \
|
||||
.align 8; .global fromhost; fromhost: .dword 0; \
|
||||
.popsection; \
|
||||
.align 8; .global begin_regstate; begin_regstate: \
|
||||
.word 128; \
|
||||
.align 8; .global end_regstate; end_regstate: \
|
||||
.word 4;
|
||||
|
||||
//RV_COMPLIANCE_HALT
|
||||
#define RVMODEL_HALT \
|
||||
li x1, 1; \
|
||||
write_tohost: \
|
||||
sw x1, tohost, t5; \
|
||||
j write_tohost;
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
|
||||
//RV_COMPLIANCE_DATA_BEGIN
|
||||
#define RVMODEL_DATA_BEGIN \
|
||||
RVMODEL_DATA_SECTION \
|
||||
.align 4;\
|
||||
.global begin_signature; begin_signature:
|
||||
|
||||
//RV_COMPLIANCE_DATA_END
|
||||
#define RVMODEL_DATA_END \
|
||||
.align 4;\
|
||||
.global end_signature; end_signature:
|
||||
|
||||
//RVTEST_IO_INIT
|
||||
#define RVMODEL_IO_INIT
|
||||
//RVTEST_IO_WRITE_STR
|
||||
#define RVMODEL_IO_WRITE_STR(_R, _STR)
|
||||
//RVTEST_IO_CHECK
|
||||
#define RVMODEL_IO_CHECK()
|
||||
//RVTEST_IO_ASSERT_GPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)
|
||||
//RVTEST_IO_ASSERT_SFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
|
||||
//RVTEST_IO_ASSERT_DFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
|
||||
|
||||
#define RVMODEL_SET_MSW_INT \
|
||||
li t1, 1; \
|
||||
li t2, 0x2000000; \
|
||||
sw t1, 0(t2);
|
||||
|
||||
#define RVMODEL_CLEAR_MSW_INT \
|
||||
li t2, 0x2000000; \
|
||||
sw x0, 0(t2);
|
||||
|
||||
#define RVMODEL_CLEAR_MTIMER_INT
|
||||
|
||||
#define RVMODEL_CLEAR_MEXT_INT
|
||||
|
||||
|
||||
#endif // _COMPLIANCE_MODEL_H
|
253
tests/riscof/spike/riscof_spike.py
Normal file
253
tests/riscof/spike/riscof_spike.py
Normal file
@ -0,0 +1,253 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import shlex
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
from string import Template
|
||||
import sys
|
||||
|
||||
import riscof.utils as utils
|
||||
import riscof.constants as constants
|
||||
from riscof.pluginTemplate import pluginTemplate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class spike(pluginTemplate):
|
||||
__model__ = "spike"
|
||||
|
||||
#TODO: please update the below to indicate family, version, etc of your DUT.
|
||||
__version__ = "XXX"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
sclass = super().__init__(*args, **kwargs)
|
||||
|
||||
config = kwargs.get('config')
|
||||
|
||||
# If the config node for this DUT is missing or empty. Raise an error. At minimum we need
|
||||
# the paths to the ispec and pspec files
|
||||
if config is None:
|
||||
print("Please enter input file paths in configuration.")
|
||||
raise SystemExit(1)
|
||||
|
||||
# In case of an RTL based DUT, this would be point to the final binary executable of your
|
||||
# test-bench produced by a simulator (like verilator, vcs, incisive, etc). In case of an iss or
|
||||
# emulator, this variable could point to where the iss binary is located. If 'PATH variable
|
||||
# is missing in the config.ini we can hardcode the alternate here.
|
||||
self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else "","spike")
|
||||
|
||||
# Number of parallel jobs that can be spawned off by RISCOF
|
||||
# for various actions performed in later functions, specifically to run the tests in
|
||||
# parallel on the DUT executable. Can also be used in the build function if required.
|
||||
self.num_jobs = str(config['jobs'] if 'jobs' in config else 1)
|
||||
|
||||
# Path to the directory where this python file is located. Collect it from the config.ini
|
||||
self.pluginpath=os.path.abspath(config['pluginpath'])
|
||||
|
||||
# Collect the paths to the riscv-config absed ISA and platform yaml files. One can choose
|
||||
# to hardcode these here itself instead of picking it from the config.ini file.
|
||||
self.isa_spec = os.path.abspath(config['ispec'])
|
||||
self.platform_spec = os.path.abspath(config['pspec'])
|
||||
|
||||
#We capture if the user would like the run the tests on the target or
|
||||
#not. If you are interested in just compiling the tests and not running
|
||||
#them on the target, then following variable should be set to False
|
||||
if 'target_run' in config and config['target_run']=='0':
|
||||
self.target_run = False
|
||||
else:
|
||||
self.target_run = True
|
||||
|
||||
# Return the parameters set above back to RISCOF for further processing.
|
||||
return sclass
|
||||
|
||||
def initialise(self, suite, work_dir, archtest_env):
|
||||
|
||||
# capture the working directory. Any artifacts that the DUT creates should be placed in this
|
||||
# directory. Other artifacts from the framework and the Reference plugin will also be placed
|
||||
# here itself.
|
||||
self.work_dir = work_dir
|
||||
|
||||
# capture the architectural test-suite directory.
|
||||
self.suite_dir = suite
|
||||
|
||||
# Note the march is not hardwired here, because it will change for each
|
||||
# test. Similarly the output elf name and compile macros will be assigned later in the
|
||||
# runTests function
|
||||
self.compile_cmd = 'riscv64-unknown-elf-gcc -march={0} \
|
||||
-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\
|
||||
-T '+self.pluginpath+'/env/link.ld\
|
||||
-I '+self.pluginpath+'/env/\
|
||||
-I ' + archtest_env + ' {2} -o {3} {4}'
|
||||
|
||||
# add more utility snippets here
|
||||
|
||||
def build(self, isa_yaml, platform_yaml):
|
||||
|
||||
# load the isa yaml as a dictionary in python.
|
||||
ispec = utils.load_yaml(isa_yaml)['hart0']
|
||||
|
||||
# capture the XLEN value by picking the max value in 'supported_xlen' field of isa yaml. This
|
||||
# will be useful in setting integer value in the compiler string (if not already hardcoded);
|
||||
self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32')
|
||||
|
||||
# for spike start building the '--isa' argument. the self.isa is dutnmae specific and may not be
|
||||
# useful for all DUTs
|
||||
self.isa = 'rv' + self.xlen
|
||||
if "I" in ispec["ISA"]:
|
||||
self.isa += 'i'
|
||||
if "M" in ispec["ISA"]:
|
||||
self.isa += 'm'
|
||||
if "F" in ispec["ISA"]:
|
||||
self.isa += 'f'
|
||||
if "D" in ispec["ISA"]:
|
||||
self.isa += 'd'
|
||||
if "C" in ispec["ISA"]:
|
||||
self.isa += 'c'
|
||||
|
||||
#TODO: The following assumes you are using the riscv-gcc toolchain. If
|
||||
# not please change appropriately
|
||||
self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ')
|
||||
|
||||
def runTests(self, testList):
|
||||
|
||||
# Delete Makefile if it already exists.
|
||||
if os.path.exists(self.work_dir+ "/Makefile." + self.name[:-1]):
|
||||
os.remove(self.work_dir+ "/Makefile." + self.name[:-1])
|
||||
# create an instance the makeUtil class that we will use to create targets.
|
||||
make = utils.makeUtil(makefilePath=os.path.join(self.work_dir, "Makefile." + self.name[:-1]))
|
||||
|
||||
# set the make command that will be used. The num_jobs parameter was set in the __init__
|
||||
# function earlier
|
||||
make.makeCommand = 'make -j' + self.num_jobs
|
||||
|
||||
# we will iterate over each entry in the testList. Each entry node will be refered to by the
|
||||
# variable testname.
|
||||
for testname in testList:
|
||||
|
||||
# for each testname we get all its fields (as described by the testList format)
|
||||
testentry = testList[testname]
|
||||
|
||||
# we capture the path to the assembly file of this test
|
||||
test = testentry['test_path']
|
||||
|
||||
# capture the directory where the artifacts of this test will be dumped/created. RISCOF is
|
||||
# going to look into this directory for the signature files
|
||||
test_dir = testentry['work_dir']
|
||||
|
||||
# name of the elf file after compilation of the test
|
||||
elf = 'my.elf'
|
||||
|
||||
# name of the signature file as per requirement of RISCOF. RISCOF expects the signature to
|
||||
# be named as DUT-<dut-name>.signature. The below variable creates an absolute path of
|
||||
# signature file.
|
||||
sig_file = os.path.join(test_dir, self.name[:-1] + ".signature")
|
||||
|
||||
# for each test there are specific compile macros that need to be enabled. The macros in
|
||||
# the testList node only contain the macros/values. For the gcc toolchain we need to
|
||||
# prefix with "-D". The following does precisely that.
|
||||
compile_macros= ' -D' + " -D".join(testentry['macros'])
|
||||
|
||||
# substitute all variables in the compile command that we created in the initialize
|
||||
# function
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen, test, elf, compile_macros)
|
||||
|
||||
# if the user wants to disable running the tests and only compile the tests, then
|
||||
# the "else" clause is executed below assigning the sim command to simple no action
|
||||
# echo statement.
|
||||
if self.target_run:
|
||||
# set up the simulation command. Template is for spike. Please change.
|
||||
simcmd = self.dut_exe + ' --isa={0} +signature={1} +signature-granularity=4 {2}'.format(self.isa, sig_file, elf)
|
||||
else:
|
||||
simcmd = 'echo "NO RUN"'
|
||||
|
||||
# concatenate all commands that need to be executed within a make-target.
|
||||
execute = '@cd {0}; {1}; {2};'.format(testentry['work_dir'], cmd, simcmd)
|
||||
|
||||
# create a target. The makeutil will create a target with the name "TARGET<num>" where num
|
||||
# starts from 0 and increments automatically for each new target that is added
|
||||
make.add_target(execute)
|
||||
|
||||
# if you would like to exit the framework once the makefile generation is complete uncomment the
|
||||
# following line. Note this will prevent any signature checking or report generation.
|
||||
#raise SystemExit
|
||||
|
||||
# once the make-targets are done and the makefile has been created, run all the targets in
|
||||
# parallel using the make command set above.
|
||||
make.execute_all(self.work_dir)
|
||||
|
||||
# if target runs are not required then we simply exit as this point after running all
|
||||
# the makefile targets.
|
||||
if not self.target_run:
|
||||
raise SystemExit(0)
|
||||
|
||||
#The following is an alternate template that can be used instead of the above.
|
||||
#The following template only uses shell commands to compile and run the tests.
|
||||
|
||||
# def runTests(self, testList):
|
||||
#
|
||||
# # we will iterate over each entry in the testList. Each entry node will be referred to by the
|
||||
# # variable testname.
|
||||
# for testname in testList:
|
||||
#
|
||||
# logger.debug('Running Test: {0} on DUT'.format(testname))
|
||||
# # for each testname we get all its fields (as described by the testList format)
|
||||
# testentry = testList[testname]
|
||||
#
|
||||
# # we capture the path to the assembly file of this test
|
||||
# test = testentry['test_path']
|
||||
#
|
||||
# # capture the directory where the artifacts of this test will be dumped/created.
|
||||
# test_dir = testentry['work_dir']
|
||||
#
|
||||
# # name of the elf file after compilation of the test
|
||||
# elf = 'my.elf'
|
||||
#
|
||||
# # name of the signature file as per requirement of RISCOF. RISCOF expects the signature to
|
||||
# # be named as DUT-<dut-name>.signature. The below variable creates an absolute path of
|
||||
# # signature file.
|
||||
# sig_file = os.path.join(test_dir, self.name[:-1] + ".signature")
|
||||
#
|
||||
# # for each test there are specific compile macros that need to be enabled. The macros in
|
||||
# # the testList node only contain the macros/values. For the gcc toolchain we need to
|
||||
# # prefix with "-D". The following does precisely that.
|
||||
# compile_macros= ' -D' + " -D".join(testentry['macros'])
|
||||
#
|
||||
# # collect the march string required for the compiler
|
||||
# marchstr = testentry['isa'].lower()
|
||||
#
|
||||
# # substitute all variables in the compile command that we created in the initialize
|
||||
# # function
|
||||
# cmd = self.compile_cmd.format(marchstr, self.xlen, test, elf, compile_macros)
|
||||
#
|
||||
# # just a simple logger statement that shows up on the terminal
|
||||
# logger.debug('Compiling test: ' + test)
|
||||
#
|
||||
# # the following command spawns a process to run the compile command. Note here, we are
|
||||
# # changing the directory for this command to that pointed by test_dir. If you would like
|
||||
# # the artifacts to be dumped else where change the test_dir variable to the path of your
|
||||
# # choice.
|
||||
# utils.shellCommand(cmd).run(cwd=test_dir)
|
||||
#
|
||||
# # for debug purposes if you would like stop the DUT plugin after compilation, you can
|
||||
# # comment out the lines below and raise a SystemExit
|
||||
#
|
||||
# if self.target_run:
|
||||
# # build the command for running the elf on the DUT. In this case we use spike and indicate
|
||||
# # the isa arg that we parsed in the build stage, elf filename and signature filename.
|
||||
# # Template is for spike. Please change for your DUT
|
||||
# execute = self.dut_exe + ' --isa={0} +signature={1} +signature-granularity=4 {2}'.format(self.isa, sig_file, elf)
|
||||
# logger.debug('Executing on Spike ' + execute)
|
||||
#
|
||||
# # launch the execute command. Change the test_dir if required.
|
||||
# utils.shellCommand(execute).run(cwd=test_dir)
|
||||
#
|
||||
# # post-processing steps can be added here in the template below
|
||||
# #postprocess = 'mv {0} temp.sig'.format(sig_file)'
|
||||
# #utils.shellCommand(postprocess).run(cwd=test_dir)
|
||||
#
|
||||
# # if target runs are not required then we simply exit as this point after running all
|
||||
# # the makefile targets.
|
||||
# if not self.target_run:
|
||||
# raise SystemExit
|
10
tests/riscof/spike/spike_platform.yaml
Normal file
10
tests/riscof/spike/spike_platform.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
mtime:
|
||||
implemented: true
|
||||
address: 0xbff8
|
||||
mtimecmp:
|
||||
implemented: true
|
||||
address: 0x4000
|
||||
nmi:
|
||||
label: nmi_vector
|
||||
reset:
|
||||
label: reset_vector
|
29
tests/riscof/spike/spike_rv32imc_isa.yaml
Normal file
29
tests/riscof/spike/spike_rv32imc_isa.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
hart_ids: [0]
|
||||
hart0:
|
||||
ISA: RV32IMCZicsr_Zifencei
|
||||
physical_addr_sz: 32
|
||||
User_Spec_Version: '2.3'
|
||||
supported_xlen: [32]
|
||||
misa:
|
||||
reset-val: 0x40001104
|
||||
rv32:
|
||||
accessible: true
|
||||
mxl:
|
||||
implemented: true
|
||||
type:
|
||||
warl:
|
||||
dependency_fields: []
|
||||
legal:
|
||||
- mxl[1:0] in [0x1]
|
||||
wr_illegal:
|
||||
- Unchanged
|
||||
extensions:
|
||||
implemented: true
|
||||
type:
|
||||
warl:
|
||||
dependency_fields: []
|
||||
legal:
|
||||
- extensions[25:0] bitmask [0x0001104, 0x0000000]
|
||||
wr_illegal:
|
||||
- Unchanged
|
||||
|
31
tests/riscof/spike/spike_rv64gc_isa.yaml
Normal file
31
tests/riscof/spike/spike_rv64gc_isa.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
hart_ids: [0]
|
||||
hart0:
|
||||
ISA: RV64IMAFDCSUZicsr_Zifencei
|
||||
physical_addr_sz: 56
|
||||
User_Spec_Version: '2.3'
|
||||
supported_xlen: [64]
|
||||
misa:
|
||||
reset-val: 0x800000000014112D
|
||||
rv32:
|
||||
accessible: false
|
||||
rv64:
|
||||
accessible: true
|
||||
mxl:
|
||||
implemented: true
|
||||
type:
|
||||
warl:
|
||||
dependency_fields: []
|
||||
legal:
|
||||
- mxl[1:0] in [0x2]
|
||||
wr_illegal:
|
||||
- Unchanged
|
||||
extensions:
|
||||
implemented: true
|
||||
type:
|
||||
warl:
|
||||
dependency_fields: []
|
||||
legal:
|
||||
- extensions[25:0] bitmask [0x014112D, 0x0000000]
|
||||
wr_illegal:
|
||||
- Unchanged
|
||||
|
Loading…
Reference in New Issue
Block a user