Merge branch 'master' into timing

This commit is contained in:
Peter Rugg
2020-03-03 18:31:45 +00:00
3 changed files with 83 additions and 46 deletions

View File

@@ -369,11 +369,11 @@ function CapFat pccJumpUpdate(CapFat pcc, LCapAddress fullBot);
pcc.addrBits = pcc.bounds.baseBits;
return pcc;
endfunction
function CapFat setCapPointer(CapFat cap, CapAddress pointer);
function CapFat setCapPointer(CapFat cap, LCapAddress pointer);
// Function to "cheat" and just set the pointer when we know that
// it will be in representable bounds by some other means.
CapFat ret = cap;
ret.address = zeroExtend(pointer);
ret.address = pointer;
ret.addrBits = truncate(ret.address >> ret.bounds.exp);
return ret;
endfunction
@@ -392,7 +392,15 @@ function Bit#(n) smearMSBRight(Bit#(n) x);
return res;
endfunction
function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
typedef struct
{
CapFat cap;
Bool exact;
CapAddress length;
CapAddress mask;
} SetBoundsReturn deriving (Bits, Eq, FShow);
function SetBoundsReturn setBoundsFat(CapFat cap, Address lengthFull);
CapFat ret = cap;
// Find new exponent by finding the index of the most significant bit of the
// length, or counting leading zeros in the high bits of the length, and
@@ -426,7 +434,6 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
// Create a mask with all bits set below the MSB of length and then masking all bits
// below the mantissa bits.
LCapAddress lmask = smearMSBRight(len);
LCapAddress lengthMsb = lmask ^ (lmask>>1);
// The shift amount required to put the most significant set bit of the
// len just above the bottom HalfExpW bits that are taken by the exp.
Integer shiftAmount = valueOf(TSub#(TSub#(MW,2),HalfExpW));
@@ -438,17 +445,16 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
// shifted out bits or in the HalfExpW bits stolen for the exponent
// Shift by MW-1 to move MSB of mask just below the mantissa, then up HalfExpW
// more to take in the bits that will be lost for the exponent when it is non-zero.
LCapAddress lmaskLo = lmask>>fromInteger(shiftAmount+1);
LCapAddress lmaskLor = lmask>>fromInteger(shiftAmount+1);
LCapAddress lmaskLo = lmask>>fromInteger(shiftAmount);
// For the len, we're not actually losing significance since we're not storing it,
// we just want to know if any low bits are non-zero so that we will know if it will
// cause the total length to round up.
Bool lostSignificantLen = (len&lmaskLo)!=0 && intExp;
Bool lostSignificantTop = (top&lmaskLo)!=0 && intExp;
Bool lostSignificantLen = (len&lmaskLor)!=0 && intExp;
Bool lostSignificantTop = (top&lmaskLor)!=0 && intExp;
// Check if non-zero bits were lost in the low bits of base, either in the 'e'
// shifted out bits or in the HalfExpW bits stolen for the exponent
Bool lostSignificantBase = (base&lmaskLo)!=0 && intExp;
// If either base or top lost significant bits and we wanted an exact setBounds,
// void the return capability
Bool lostSignificantBase = (base&lmaskLor)!=0 && intExp;
// Calculate all values associated with E=e+1 (e rounding up due to msb of L increasing by 1)
// This value is just to avoid adding later.
@@ -457,7 +463,6 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
// shifted out bits or in the HalfExpW bits stolen for the exponent
// Shift by MW-1 to move MSB of mask just below the mantissa, then up HalfExpW
// more to take in the bits that will be lost for the exponent when it is non-zero.
lmaskLo = lmask>>fromInteger(shiftAmount);
Bool lostSignificantTopHigher = (top&lmaskLo)!=0 && intExp;
// Check if non-zero bits were lost in the low bits of base, either in the 'e'
// shifted out bits or in the HalfExpW bits stolen for the exponent
@@ -465,24 +470,37 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
// If either base or top lost significant bits and we wanted an exact setBounds,
// void the return capability
// We need to round up Exp if the msb of length will increase.
// We can check how much the length will increase without looking at the result of adding the
// length to the base. We do this by adding the lower bits of the length to the base and then
// comparing both halves (above and below the mask) to zero. Either side that is non-zero indicates
// an extra "1" that will be added to the "mantissa" bits of the length, potentially causing overflow.
// Finally check how close the requested length is to overflow, and test in relation to how much the
// length will increase.
LCapAddress topLo = (lmaskLor & len) + (lmaskLor & base);
LCapAddress mwLsbMask = lmaskLor ^ lmaskLo;
// If the first bit of the mantissa of the top is not the sum of the corrosponding bits of base and length, there was a carry in.
Bool lengthCarryIn = (mwLsbMask & top) != ((mwLsbMask & base)^(mwLsbMask & len));
Bool lengthRoundUp = lostSignificantTop;
Bool lengthIsMax = (len & (~lmaskLor)) == (lmask ^ lmaskLor);
Bool lengthIsMaxLessOne = (len & (~lmaskLor)) == (lmask ^ lmaskLo);
// We need to round up Exp if the length is within 1 of the maximum and if it will increase.
// The lomask for checking for potential overflow should mask all but the bottom bit of the mantissa.
lmaskLo = lmask>>fromInteger(shiftAmount);
Bool lengthMax = (len&(~lmaskLo))==(lmask&(~lmaskLo));
Bool resultExact = True;
if(lengthMax && intExp && (lostSignificantLen || lostSignificantBase)) begin
e = e+1;
ret.bounds.topBits = (lostSignificantTopHigher) ? (newTopBitsHigher+'b1000):newTopBitsHigher;
ret.bounds.baseBits = truncateLSB(newBaseBits);
if (lostSignificantBaseHigher || lostSignificantTopHigher) resultExact = False;
Bool lengthOverflow = False;
if (lengthIsMax && (lengthCarryIn || lengthRoundUp)) lengthOverflow = True;
if (lengthIsMaxLessOne && lengthCarryIn && lengthRoundUp) lengthOverflow = True;
Bool exact = True;
if(lengthOverflow && intExp) begin
e = e+1;
ret.bounds.topBits = (lostSignificantTopHigher) ? (newTopBitsHigher+'b1000):newTopBitsHigher;
ret.bounds.baseBits = truncateLSB(newBaseBits);
exact = !(lostSignificantBaseHigher || lostSignificantTopHigher);
end else begin
ret.bounds.topBits = (lostSignificantTop) ? truncate(newTopBits+'b1000):truncate(newTopBits);
ret.bounds.baseBits = truncate(newBaseBits);
if (lostSignificantBase || lostSignificantTop) resultExact = False;
ret.bounds.topBits = (lostSignificantTop) ? truncate(newTopBits+'b1000):truncate(newTopBits);
ret.bounds.baseBits = truncate(newBaseBits);
exact = !(lostSignificantBase || lostSignificantTop);
end
ret.bounds.exp = e;
// Update the addrBits fields
ret.addrBits = ret.bounds.baseBits;
@@ -497,8 +515,19 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
ret.bounds.topBits = {truncateLSB(ret.bounds.topBits), botZeroes};
end
// Begin calculate newLength in case this is a request just for a representable length:
LCapAddress newLength = zeroExtend(length);
if (intExp) begin
LCapAddress oneInLsb = (lmask ^ (lmask>>1)) >> shiftAmount;
LCapAddress newLengthRounded = newLength + oneInLsb;
newLength = (newLength & (~lmaskLor));
newLengthRounded = (newLengthRounded & (~lmaskLor));
if (lostSignificantLen) newLength = newLengthRounded;
end
LCapAddress baseMask = ~lmaskLor;
// Return derived capability
return tuple2(ret, resultExact);
return SetBoundsReturn{cap: ret, exact: exact, length: truncate(newLength), mask: truncate(baseMask)};
endfunction
function CapFat seal(CapFat cap, TempFields tf, CType otype);
CapFat ret = cap;
@@ -997,8 +1026,8 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function isInBounds = error("feature not implemented for this cap type");
function Exact#(CapReg) setBounds (CapReg cap, Bit#(CapAddressW) length);
match {.result, .exact} = setBoundsFat(cap, length);
return Exact {exact: exact, value: result};
SetBoundsReturn sr = setBoundsFat(cap, length);
return Exact {exact: sr.exact, value: sr.cap};
endfunction
function CapReg nullWithAddr (Bit#(CapAddressW) addr);
@@ -1023,10 +1052,7 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function toMem (x) = unpack(cast(x));
function CapReg maskAddr (CapReg cap, Bit#(TSub#(MW, 3)) mask);
cap.address[valueOf(TSub#(MW, 4)):0] = cap.address[valueOf(TSub#(MW, 4)):0] & mask;
//Update addrBits. Since exp can be up to 64, extend to 64 + 8 bits so bit-select is always in range
cap.addrBits = (({40'b0,cap.address})[cap.bounds.exp+fromInteger(valueOf(TSub#(MW,1))):cap.bounds.exp]); //TODO avoid shift?
return cap;
return setCapPointer(cap, cap.address & {~0,mask});
endfunction
function Bit#(2) getBaseAlignment (CapReg cap);
@@ -1039,9 +1065,13 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
endfunction
function Bit#(CapAddressW) getRepresentableAlignmentMask (CapReg dummy, Bit#(CapAddressW) length_request);
let setBoundsCap = nullWithAddr((~0) - length_request);
Exact#(CapFat) result = setBounds(setBoundsCap, length_request);
return (~0) << (result.value.bounds.exp == 0 ? 0 : result.value.bounds.exp + fromInteger(valueOf(HalfExpW)));
SetBoundsReturn sr = setBoundsFat(nullCap, length_request);
return sr.mask;
endfunction
function Bit#(CapAddressW) getRepresentableLength (CapReg dummy, Bit#(CapAddressW) length_request);
SetBoundsReturn sr = setBoundsFat(nullCap, length_request);
return sr.length;
endfunction
endinstance
@@ -1115,7 +1145,7 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
cap.tempFields = getTempFields(cap.capFat);
return Exact {exact: result.v, value: cap};
endfunction
function CapPipe setAddrUnsafe (CapPipe cap, Bit#(CapAddressW) address);
cap.capFat = setAddrUnsafe(cap.capFat, address);
cap.tempFields = getTempFields(cap.capFat);

View File

@@ -81,7 +81,7 @@ function Exact#(`CAPTYPE) `W(modifyOffset) (`CAPTYPE cap, Bit#(CapAddressW) offs
(* noinline *)
function Exact#(`CAPTYPE) `W(setOffset) (`CAPTYPE cap, Bit#(CapAddressW) offset) = setOffset (cap, offset);
(* noinline *)
function Exact#(`CAPTYPE) `W(inOffset) (`CAPTYPE cap, Bit#(CapAddressW) inc) = incOffset (cap, inc);
function Exact#(`CAPTYPE) `W(incOffset) (`CAPTYPE cap, Bit#(CapAddressW) inc) = incOffset (cap, inc);
(* noinline *)
function Bit#(CapAddressW) `W(getBase) (`CAPTYPE cap) = getBase(cap);
(* noinline *)

View File

@@ -45,30 +45,37 @@ class BlarneyWrapper:
return "{:s}\n{:s}".format(str_type, str_decl)
def main():
# define regexps
# define module regexp
modDecl = re.compile("^module\s+module_wrap(\d+)_(\w+)\(")
inDecl = re.compile("^\s*input(\s+\[(\d+)\s+:\s+0\])?\s+wrap(\d+)_(\w+)_(\w+);")
outDecl = re.compile("^\s*output(\s+\[(\d+)\s+:\s+0\])?\s+wrap(\d+)_(\w+);")
# TODO handle size 1
#
wrappers = []
for fname in args.verilog_files:
size = 0
name = ""
name = None
ins = []
out = ("",0)
with open(fname, "r") as f:
for ln in f:
modM = modDecl.match(ln)
inM = inDecl.match(ln)
outM = outDecl.match(ln)
if modM:
size = int(modM.group(1))
name = modM.group(2)
elif inM:
ins.append((inM.group(5), (int(inM.group(2)) + 1) if inM.group(1) else 1))
break
if not name:
print("Couldn't find a valid Verilog module definition")
exit(-1)
# define input/output regexp
inDecl = re.compile("^\s*input(\s+\[(\d+)\s+:\s+0\])?\s+wrap(\d+)_"+name+"_(\w+);")
outDecl = re.compile("^\s*output(\s+\[(\d+)\s+:\s+0\])?\s+wrap(\d+)_"+name+";")
for ln in f:
inM = inDecl.match(ln)
outM = outDecl.match(ln)
if inM:
ins.append((inM.group(4), (int(inM.group(2)) + 1) if inM.group(1) else 1))
elif outM:
out = (outM.group(4), (int(outM.group(2)) + 1) if outM.group(1) else 1)
out = (name, (int(outM.group(2)) + 1) if outM.group(1) else 1)
#else:
# print("===>> no match for line: {:s}".format(ln))
wrappers.append(BlarneyWrapper(size, name, ins, out))