diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 827e319..6343d09 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -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); diff --git a/CHERICapWrap.bsv b/CHERICapWrap.bsv index fe78901..62a9658 100644 --- a/CHERICapWrap.bsv +++ b/CHERICapWrap.bsv @@ -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 *) diff --git a/CHERICapWrapBlarney.py b/CHERICapWrapBlarney.py index ef4af46..5e44b3c 100755 --- a/CHERICapWrapBlarney.py +++ b/CHERICapWrapBlarney.py @@ -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))