Turn the address field in CapFat to a Bit#(CapAdressW) (with pdr32 and jdw57)

This commit is contained in:
Alexandre Joannou
2021-01-20 00:41:06 +00:00
parent 508da818ba
commit e8868e7d79

View File

@@ -45,7 +45,6 @@ export OTypeW;
export FlagsW;
export Perms;
export ResW;
export LCapAddress;
export Format;
export TempFields;
export Bounds;
@@ -92,7 +91,14 @@ typedef struct {
typedef 64 CapAddressW;
typedef 128 CapW;
`endif
typedef Bit#(CapAddressW) Address;
// The Address type is used to represent the full sized address returned to the
// consuming pipeline. In cases where fewer than CapAddressW bits are stored to
// represent a memory address (and remaining bits are usable for storing extra
// metadata), returning a value of type Address is currently expected to sign
// extend the address.
// SizeOf#(Address) should be greater or equal to CapAddressW
typedef CapAddressW AddressW;
typedef Bit#(AddressW) Address;
typedef TDiv#(ExpW,2) HalfExpW;
typedef TSub#(MW,HalfExpW) UpperMW;
@@ -138,7 +144,6 @@ typedef struct {
typedef Bit#(TAdd#(CapW,1)) Capability;
// not including the tag bit
typedef Bit#(CapW) CapBits;
typedef Bit#(128) ShortCap;
/* TODO
staticAssert(valueOf(SizeOf#(CapabilityInMemory))==valueOf(SizeOf#(Capability)),
"The CapabilityInMemory type has incorrect size of " + integerToString(valueOf(SizeOf#(CapabilityInMemory))) + " (CapW = " + integerToString(valueOf(CapW)) + ")"
@@ -162,15 +167,15 @@ Bit#(OTypeW) otype_res1 = -4;
// unpacked capability format
typedef struct {
Bool isCapability;
LCapAddress address;
Bit#(MW) addrBits;
Perms perms;
Bit#(FlagsW) flags;
Bit#(ResW) reserved;
Bit#(OTypeW) otype;
Format format;
Bounds bounds;
Bool isCapability;
Bit#(CapAddressW) address;
Bit#(MW) addrBits;
Perms perms;
Bit#(FlagsW) flags;
Bit#(ResW) reserved;
Bit#(OTypeW) otype;
Format format;
Bounds bounds;
} CapFat deriving(Bits);
// "Architectural FShow"
@@ -221,7 +226,7 @@ function CapFat unpackCap(Capability thin);
match {.f, .b} = decBounds(memCap.bounds);
fat.format = f;
fat.bounds = b;
fat.address = zeroExtend(memCap.address);
fat.address = memCap.address;
// The next few lines are to optimise the critical path of generating addrBits.
// The value of Exp can now be 0 or come from token, so assume they come from the token,
// then select the lower bits at the end if they didn't after all.
@@ -241,20 +246,11 @@ function Capability packCap(CapFat fat);
reserved: fat.reserved,
otype: fat.otype,
bounds: encBounds(fat.format,fat.bounds),
address: truncate(fat.address)
address: fat.address
};
return pack(thin);
endfunction
// XXX needs double checking
function ShortCap getShortCap (CapFat cap);
CapabilityInMemory ret = unpack(packCap(cap));
// put tag bit in highest reserved bit
if (valueOf(ResW)!=0) ret.reserved[valueOf(ResW)-1] = pack(cap.isCapability);
CapBits retbits = truncate(pack(ret));
return zeroExtend(retbits);
endfunction
// The temporary fields
typedef MetaInfo TempFields;
@@ -269,11 +265,10 @@ function LCapAddress getBotFat(CapFat cap, TempFields tf);
CapAddress addBase = signExtend({pack(tf.baseCorrection), cap.bounds.baseBits}) << cap.bounds.exp;
// Build a mask on the high bits of a full length value to extract the high
// bits of the address.
Bit#(TSub#(SizeOf#(CapAddress),MW)) mask = ~0 << cap.bounds.exp;
Bit#(TSub#(CapAddressW,MW)) mask = ~0 << cap.bounds.exp;
// Extract the high bits of the address (and append the implied zeros at the
// bottom), and add with the previously prepared value.
CapAddress adr = truncate(cap.address); // Trim top bits of address.
CapAddress bot = {truncateLSB(adr)&mask,0} + addBase;
CapAddress bot = {truncateLSB(cap.address)&mask,0} + addBase;
return zeroExtend(bot);
endfunction
function LCapAddress getTopFat(CapFat cap, TempFields tf);
@@ -285,7 +280,7 @@ function LCapAddress getTopFat(CapFat cap, TempFields tf);
Bit#(TSub#(SizeOf#(LCapAddress),MW)) mask = ~0 << cap.bounds.exp;
// Extract the high bits of the address (and append the implied zeros at the
// bottom), and add with the previously prepared value.
LCapAddress ret = {truncateLSB(cap.address)&mask,0} + addTop;
LCapAddress ret = {2'b0, truncateLSB(cap.address)&mask,0} + addTop;
// If the bottom and top are more than an address space away from eachother, invert
// the 64th/32nd bit of Top. This corrects for errors that happen when the representable
// space wraps the address space.
@@ -293,9 +288,8 @@ function LCapAddress getTopFat(CapFat cap, TempFields tf);
ret[msbp+2] = 0;
Bit#(2) topTip = ret[msbp+1:msbp];
// Calculate the msb of the base.
CapAddress adr = truncate(cap.address);
// First assume that only the address and correction are involved...
Bit#(TSub#(SizeOf#(CapAddress),MW)) bot = truncateLSB(adr) + (signExtend(pack(tf.baseCorrection)) << cap.bounds.exp);
Bit#(TSub#(CapAddressW,MW)) bot = truncateLSB(cap.address) + (signExtend(pack(tf.baseCorrection)) << cap.bounds.exp);
Bit#(1) botTip = msb(bot);
// If the bit we're interested in are actually coming from baseBits, select the correct one from there.
// exp == (resetExp - 1) doesn't matter since we will not flip unless exp < resetExp-1.
@@ -323,17 +317,12 @@ function Address getOffsetFat(CapFat cap, TempFields tf);
Bit#(TAdd#(MW,2)) base = {pack(tf.baseCorrection),cap.bounds.baseBits};
// Get the offset bits by substracting the previous value from the addrBits
Bit#(TAdd#(MW,2)) offset = zeroExtend(cap.addrBits) - base;
// Grab the bottom bits of the address
Address addrLSB = lAddrToReg(cap.address & ~(~0 << e));
// Grab the bottom bits of the address and sign extend them to the size of Address
Address addrLSB = signExtend(cap.address & ~(~0 << e));
// Return the computed offset bits (sign extended) shifted appropriatly,
// with the low address bits appended
return (signExtend(offset) << e) | addrLSB;
endfunction
function LCapAddress getAddress(CapFat cap) = cap.address;
function Address lAddrToReg(LCapAddress in);
CapAddress retVal = truncate(in);
return signExtend(retVal);
endfunction
function LCapAddress regToLAddr(Address in);
CapAddress retVal = truncate(in);
return zeroExtend(retVal);
@@ -364,35 +353,22 @@ function Bool capInBounds(CapFat cap, TempFields tf, Bool inclusive);
endfunction
function CapFat nullifyCap(CapFat cap);
CapFat ret = nullCap;
CapAddress tmpAddr = truncate(cap.address);
ret.addrBits = {2'b0,truncateLSB(tmpAddr)};
ret.addrBits = {2'b0,truncateLSB(cap.address)};
ret.address = cap.address;
//CapFat ret = cap;
//ret.isCapability = False;
return ret;
endfunction
function CapFat pccJumpUpdate(CapFat pcc, LCapAddress fullBot);
// Set the appropriate fields in PCC when jumping.
pcc.address = fullBot;
pcc.addrBits = pcc.bounds.baseBits;
return pcc;
endfunction
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 = pointer;
ret.address = truncate(pointer);
ret.addrBits = truncate(ret.address >> ret.bounds.exp);
return ret;
endfunction
// Only currently used for algorithm comparison.
function Bool boundsCheck(CapFat cap, Bit#(CapAddressW) off, TempFields tf);
Bit#(TAdd#(CapAddressW,2)) bo = zeroExtend(off);
cap = incOffsetFat(cap, cap.address+truncate(bo), off, tf, False).d;
return cap.isCapability && capInBounds(cap, tf, False);
endfunction
function Bit#(n) smearMSBRight(Bit#(n) x);
Bit#(n) res = x;
for (Integer i = 0; i < valueOf(TLog#(n))-1; i = i + 1)
@@ -400,7 +376,6 @@ function Bit#(n) smearMSBRight(Bit#(n) x);
return res;
endfunction
function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address lengthFull);
CapFat ret = cap;
// Find new exponent by finding the index of the most significant bit of the
@@ -422,8 +397,7 @@ function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address
ret.otype = otype_unsealed;
// Derive new base bits by extracting MW bits from the capability
// address starting at the new exponent's position.
CapAddress tmpAddr = truncate(cap.address);
LCapAddress base = zeroExtend(tmpAddr);
LCapAddress base = zeroExtend(cap.address);
Bit#(TAdd#(MW,1)) newBaseBits = truncate(base>>e);
// Derive new top bits by extracting MW bits from the capability
@@ -540,7 +514,11 @@ function CapFat unseal(CapFat cap, x _);
ret.otype = otype_unsealed;
return ret;
endfunction
function VnD#(CapFat) incOffsetFat(CapFat cap, LCapAddress pointer, Bit#(CapAddressW) offset/*this is the increment in inc offset, and the offset in set offset*/, TempFields tf, Bool setOffset);
function VnD#(CapFat) incOffsetFat( CapFat cap
, LCapAddress pointer
, Bit#(CapAddressW) offset // this is the increment in inc offset, and the offset in set offset
, TempFields tf
, Bool setOffset);
// NOTE:
// The 'offset' argument is the "increment" value when setOffset is false,
// and the actual "offset" value when setOffset is true.
@@ -645,15 +623,16 @@ function VnD#(CapFat) incOffsetFat(CapFat cap, LCapAddress pointer, Bit#(CapAddr
// ------------------------------
if (setOffset) begin
// Get the base and add the offsetAddr. This could be slow, but seems to pass timing.
ret.address = getBotFat(cap,tf) + zeroExtend(offsetAddr);
ret.address = truncate(getBotFat(cap,tf) + zeroExtend(offsetAddr));
// TODO write comments on this
Bit#(TAdd#(MW,2)) newAddrBits = zeroExtend(cap.bounds.baseBits) + zeroExtend(offsetBits);
ret.addrBits = (e == resetExp) ? {1'b0,truncate(newAddrBits)}:truncate(newAddrBits);
ret.addrBits = (e == resetExp) ? {2'b0,truncate(newAddrBits)} :
(e == resetExp-1) ? {1'b0,truncate(newAddrBits)} :
truncate(newAddrBits);
end else begin
// In the incOffset case, the 'pointer' argument already contains the new address
CapAddress tmpAddr = truncate(pointer);
ret.address = zeroExtend(tmpAddr);
ret.addrBits = truncate(tmpAddr >> e);
ret.address = truncate(pointer);
ret.addrBits = truncate(ret.address >> e);
end
// Nullify the capability if the representable bounds check has failed
if (!inBounds) ret.isCapability = False;//nullifyCap(ret);
@@ -1055,7 +1034,7 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
endcase);
endfunction
function getAddr (cap) = truncate(getAddress(cap));
function getAddr (cap) = cap.address;
function setAddr = error("setAddr not implemented for CapReg");
@@ -1085,7 +1064,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);
return setCapPointer(cap, cap.address & {~0,mask});
return setCapPointer(cap, zeroExtend(cap.address) & {~0,mask});
endfunction
function Bool validAsType (CapReg dummy, Bit#(CapAddressW) checkType);
@@ -1189,7 +1168,7 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function getOffset (x) = getOffsetFat(x.capFat, x.tempFields);
function Exact#(CapPipe) modifyOffset (CapPipe cap, Bit#(CapAddressW) offset, Bool doInc);
let result = incOffsetFat(cap.capFat, pack(cap.capFat.address) + zeroExtend(offset), zeroExtend(offset), cap.tempFields, !doInc);
let result = incOffsetFat(cap.capFat, zeroExtend(cap.capFat.address) + zeroExtend(offset), zeroExtend(offset), cap.tempFields, !doInc);
cap.capFat = result.d;
cap.tempFields = getTempFields(cap.capFat);
return Exact {exact: result.v, value: cap};