From 482afd36506dfe468ef864c9517dad7f9c5b1665 Mon Sep 17 00:00:00 2001 From: Ivan Ribeiro Date: Tue, 28 Jan 2020 06:54:38 +0000 Subject: [PATCH 1/6] Update Blarney Wrapper generator to fix bug Fixes a bug in the Blarney Wrapper generator where if a function input had an underscore in its identifier, only the last word in the identifier would be recognized. --- CHERICapWrapBlarney.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) 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)) From 58341115245eefa8f5942000cb2a9b0dd4258597 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Tue, 11 Feb 2020 22:46:07 +0000 Subject: [PATCH 2/6] Avoid shift amount overflow in maskAddr --- CHERICC_Fat.bsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 26658e6..d732329 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -1021,8 +1021,9 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); 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; + UInt#(TAdd#(ExpW,1)) expExt = zeroExtend(cap.bounds.exp); //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? + cap.addrBits = (({40'b0,cap.address})[expExt+fromInteger(valueOf(TSub#(MW,1))):expExt]); //TODO avoid shift? return cap; endfunction From 1a8f20bad3acd06bcca0c27aa72259ccc37489df Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 12 Feb 2020 22:36:38 +0000 Subject: [PATCH 3/6] Cleanup maskAddr to use setCapPointer --- CHERICC_Fat.bsv | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index d732329..2d179fa 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 @@ -1020,11 +1020,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; - UInt#(TAdd#(ExpW,1)) expExt = zeroExtend(cap.bounds.exp); - //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})[expExt+fromInteger(valueOf(TSub#(MW,1))):expExt]); //TODO avoid shift? - return cap; + return setCapPointer(cap, cap.address & {~0,mask}); endfunction function Bit#(2) getBaseAlignment (CapReg cap); @@ -1113,7 +1109,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); let result = setCapPointer(cap.capFat, zeroExtend(address)); cap.capFat = result; From ba95fc9a01eaa81d417f284b3064e20f6500cf30 Mon Sep 17 00:00:00 2001 From: Alexandre Joannou Date: Thu, 27 Feb 2020 13:52:07 +0000 Subject: [PATCH 4/6] Typo "inOffset" -> "incOffset" --- CHERICapWrap.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 *) From 42cdd2e3da76c6c3b373a422a9e3ea54c8eb982c Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Fri, 28 Feb 2020 12:17:19 +0000 Subject: [PATCH 5/6] Update to new SetBounds which is precise. This one isn't quite fast enough on CHERI-MIPS, so good luck with that RISC-V! --- CHERICC_Fat.bsv | 90 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 2d179fa..27b0ed0 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -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); + Bool lengthCarryIn = (~lmaskLor & topLo) != 0; + Bool lengthRoundUp = (lmaskLor & topLo) != 0; + 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; + LCapAddress baseMask = ~lmaskLor; + if(lengthOverflow && intExp) begin + e = e+1; + ret.bounds.topBits = (lostSignificantTopHigher) ? (newTopBitsHigher+'b1000):newTopBitsHigher; + ret.bounds.baseBits = truncateLSB(newBaseBits); + exact = !(lostSignificantBaseHigher || lostSignificantTopHigher); + baseMask = ~lmaskLo; 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,18 @@ 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 + // 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; @@ -994,8 +1022,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); @@ -1033,9 +1061,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 From ebac2cdf6de643715a41300bae05d1c3b4cbb7fa Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Mon, 2 Mar 2020 16:10:33 +0000 Subject: [PATCH 6/6] An apparently faster iteration of CSetBounds. --- CHERICC_Fat.bsv | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 27b0ed0..2e4f12b 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -478,8 +478,10 @@ function SetBoundsReturn setBoundsFat(CapFat cap, Address lengthFull); // 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); - Bool lengthCarryIn = (~lmaskLor & topLo) != 0; - Bool lengthRoundUp = (lmaskLor & topLo) != 0; + 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); @@ -488,13 +490,11 @@ function SetBoundsReturn setBoundsFat(CapFat cap, Address lengthFull); if (lengthIsMaxLessOne && lengthCarryIn && lengthRoundUp) lengthOverflow = True; Bool exact = True; - LCapAddress baseMask = ~lmaskLor; if(lengthOverflow && intExp) begin e = e+1; ret.bounds.topBits = (lostSignificantTopHigher) ? (newTopBitsHigher+'b1000):newTopBitsHigher; ret.bounds.baseBits = truncateLSB(newBaseBits); exact = !(lostSignificantBaseHigher || lostSignificantTopHigher); - baseMask = ~lmaskLo; end else begin ret.bounds.topBits = (lostSignificantTop) ? truncate(newTopBits+'b1000):truncate(newTopBits); ret.bounds.baseBits = truncate(newBaseBits); @@ -524,6 +524,7 @@ function SetBoundsReturn setBoundsFat(CapFat cap, Address lengthFull); newLengthRounded = (newLengthRounded & (~lmaskLor)); if (lostSignificantLen) newLength = newLengthRounded; end + LCapAddress baseMask = ~lmaskLor; // Return derived capability return SetBoundsReturn{cap: ret, exact: exact, length: truncate(newLength), mask: truncate(baseMask)};