Limit use of large (66-bit) addresses accross CHERICC_Fat (with pdr32 and jdw57)
This commit is contained in:
218
CHERICC_Fat.bsv
218
CHERICC_Fat.bsv
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 Jonathan Woodruff
|
* Copyright (c) 2015-2019 Jonathan Woodruff
|
||||||
* Copyright (c) 2017-2019 Alexandre Joannou
|
* Copyright (c) 2017-2021 Alexandre Joannou
|
||||||
* Copyright (c) 2019 Peter Rugg
|
* Copyright (c) 2019 Peter Rugg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -51,7 +51,7 @@ export Bounds;
|
|||||||
export UPermW;
|
export UPermW;
|
||||||
export CapW;
|
export CapW;
|
||||||
export ExpW;
|
export ExpW;
|
||||||
export CapAddressW;
|
export CapAddrW;
|
||||||
export CBoundsW;
|
export CBoundsW;
|
||||||
export HPerms;
|
export HPerms;
|
||||||
export PermsW;
|
export PermsW;
|
||||||
@@ -80,7 +80,7 @@ typedef struct {
|
|||||||
typedef 6 ExpW;
|
typedef 6 ExpW;
|
||||||
typedef 4 OTypeW;
|
typedef 4 OTypeW;
|
||||||
typedef `FLAGSW FlagsW;
|
typedef `FLAGSW FlagsW;
|
||||||
typedef 32 CapAddressW;
|
typedef 32 CapAddrW;
|
||||||
typedef 64 CapW;
|
typedef 64 CapW;
|
||||||
`else // CAP128 is default
|
`else // CAP128 is default
|
||||||
typedef 4 UPermW;
|
typedef 4 UPermW;
|
||||||
@@ -88,16 +88,16 @@ typedef struct {
|
|||||||
typedef 6 ExpW;
|
typedef 6 ExpW;
|
||||||
typedef 18 OTypeW;
|
typedef 18 OTypeW;
|
||||||
typedef `FLAGSW FlagsW;
|
typedef `FLAGSW FlagsW;
|
||||||
typedef 64 CapAddressW;
|
typedef 64 CapAddrW;
|
||||||
typedef 128 CapW;
|
typedef 128 CapW;
|
||||||
`endif
|
`endif
|
||||||
// The Address type is used to represent the full sized address returned to the
|
// 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
|
// consuming pipeline. In cases where fewer than CapAddrW bits are stored to
|
||||||
// represent a memory address (and remaining bits are usable for storing extra
|
// represent a memory address (and remaining bits are usable for storing extra
|
||||||
// metadata), returning a value of type Address is currently expected to sign
|
// metadata), returning a value of type Address is currently expected to sign
|
||||||
// extend the address.
|
// extend the address.
|
||||||
// SizeOf#(Address) should be greater or equal to CapAddressW
|
// SizeOf#(Address) should be greater or equal to CapAddrW
|
||||||
typedef CapAddressW AddressW;
|
typedef CapAddrW AddressW;
|
||||||
typedef Bit#(AddressW) Address;
|
typedef Bit#(AddressW) Address;
|
||||||
typedef TDiv#(ExpW,2) HalfExpW;
|
typedef TDiv#(ExpW,2) HalfExpW;
|
||||||
typedef TSub#(MW,HalfExpW) UpperMW;
|
typedef TSub#(MW,HalfExpW) UpperMW;
|
||||||
@@ -105,8 +105,10 @@ typedef TSub#(MW,HalfExpW) UpperMW;
|
|||||||
// The compressed bounds field type
|
// The compressed bounds field type
|
||||||
typedef TSub#(TMul#(MW,2),1) CBoundsW;
|
typedef TSub#(TMul#(MW,2),1) CBoundsW;
|
||||||
typedef Bit#(CBoundsW) CBounds;
|
typedef Bit#(CBoundsW) CBounds;
|
||||||
// The pointer CapAddress type
|
// The CapAddr types
|
||||||
typedef Bit#(CapAddressW) CapAddress;
|
typedef Bit#(CapAddrW) CapAddr;
|
||||||
|
typedef Bit#(TAdd#(CapAddrW,1)) CapAddrPlus1;
|
||||||
|
typedef Bit#(TAdd#(CapAddrW,2)) CapAddrPlus2;
|
||||||
// The Hardware permissions type
|
// The Hardware permissions type
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Bool permit_set_CID;
|
Bool permit_set_CID;
|
||||||
@@ -129,16 +131,16 @@ typedef struct {
|
|||||||
} Perms deriving(Bits, Eq, FShow);
|
} Perms deriving(Bits, Eq, FShow);
|
||||||
typedef SizeOf#(Perms) PermsW;
|
typedef SizeOf#(Perms) PermsW;
|
||||||
// The reserved bits
|
// The reserved bits
|
||||||
typedef TSub#(CapW,TAdd#(CapAddressW,TAdd#(OTypeW,TAdd#(CBoundsW,TAdd#(PermsW, FlagsW))))) ResW;
|
typedef TSub#(CapW,TAdd#(CapAddrW,TAdd#(OTypeW,TAdd#(CBoundsW,TAdd#(PermsW, FlagsW))))) ResW;
|
||||||
// The full capability structure, including the "tag" bit.
|
// The full capability structure, including the "tag" bit.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Bool isCapability;
|
Bool isCapability;
|
||||||
Perms perms;
|
Perms perms;
|
||||||
Bit#(ResW) reserved;
|
Bit#(ResW) reserved;
|
||||||
Bit#(FlagsW) flags;
|
Bit#(FlagsW) flags;
|
||||||
Bit#(OTypeW) otype;
|
Bit#(OTypeW) otype;
|
||||||
CBounds bounds;
|
CBounds bounds;
|
||||||
CapAddress address;
|
CapAddr address;
|
||||||
} CapabilityInMemory deriving(Bits, Eq, FShow); // CapW + 1 (tag bit)
|
} CapabilityInMemory deriving(Bits, Eq, FShow); // CapW + 1 (tag bit)
|
||||||
// The full capability structure as Bits, including the "tag" bit.
|
// The full capability structure as Bits, including the "tag" bit.
|
||||||
typedef Bit#(TAdd#(CapW,1)) Capability;
|
typedef Bit#(TAdd#(CapW,1)) Capability;
|
||||||
@@ -151,8 +153,6 @@ staticAssert(valueOf(SizeOf#(CapabilityInMemory))==valueOf(SizeOf#(Capability)),
|
|||||||
*/
|
*/
|
||||||
// Bit type of the debug capability
|
// Bit type of the debug capability
|
||||||
typedef Bit#(CapW) DebugCap;
|
typedef Bit#(CapW) DebugCap;
|
||||||
// large capability address type (with extra bits at the top)
|
|
||||||
typedef Bit#(TAdd#(CapAddressW,2)) LCapAddress;
|
|
||||||
// Format of the cheri concentrate capability
|
// Format of the cheri concentrate capability
|
||||||
typedef enum {Exp0, EmbeddedExp} Format deriving (Bits, Eq, FShow);
|
typedef enum {Exp0, EmbeddedExp} Format deriving (Bits, Eq, FShow);
|
||||||
// Exponent type
|
// Exponent type
|
||||||
@@ -167,15 +167,15 @@ Bit#(OTypeW) otype_res1 = -4;
|
|||||||
|
|
||||||
// unpacked capability format
|
// unpacked capability format
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Bool isCapability;
|
Bool isCapability;
|
||||||
Bit#(CapAddressW) address;
|
Bit#(CapAddrW) address;
|
||||||
Bit#(MW) addrBits;
|
Bit#(MW) addrBits;
|
||||||
Perms perms;
|
Perms perms;
|
||||||
Bit#(FlagsW) flags;
|
Bit#(FlagsW) flags;
|
||||||
Bit#(ResW) reserved;
|
Bit#(ResW) reserved;
|
||||||
Bit#(OTypeW) otype;
|
Bit#(OTypeW) otype;
|
||||||
Format format;
|
Format format;
|
||||||
Bounds bounds;
|
Bounds bounds;
|
||||||
} CapFat deriving(Bits);
|
} CapFat deriving(Bits);
|
||||||
|
|
||||||
// "Architectural FShow"
|
// "Architectural FShow"
|
||||||
@@ -259,37 +259,35 @@ Bool imprecise = True;
|
|||||||
|
|
||||||
// Interface functions
|
// Interface functions
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
function LCapAddress getBotFat(CapFat cap, TempFields tf);
|
function CapAddr getBotFat(CapFat cap, TempFields tf);
|
||||||
// First, construct a full length value with the base bits and the
|
// First, construct a full length value with the base bits and the
|
||||||
// correction bits above, and shift that value to the appropriate spot.
|
// correction bits above, and shift that value to the appropriate spot.
|
||||||
CapAddress addBase = signExtend({pack(tf.baseCorrection), cap.bounds.baseBits}) << cap.bounds.exp;
|
CapAddr 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
|
// Build a mask on the high bits of a full length value to extract the high
|
||||||
// bits of the address.
|
// bits of the address.
|
||||||
Bit#(TSub#(CapAddressW,MW)) mask = ~0 << cap.bounds.exp;
|
Bit#(TSub#(CapAddrW,MW)) mask = ~0 << cap.bounds.exp;
|
||||||
// Extract the high bits of the address (and append the implied zeros at the
|
// Extract the high bits of the address (and append the implied zeros at the
|
||||||
// bottom), and add with the previously prepared value.
|
// bottom), and add with the previously prepared value.
|
||||||
CapAddress bot = {truncateLSB(cap.address)&mask,0} + addBase;
|
return {truncateLSB(cap.address)&mask,0} + addBase;
|
||||||
return zeroExtend(bot);
|
|
||||||
endfunction
|
endfunction
|
||||||
function LCapAddress getTopFat(CapFat cap, TempFields tf);
|
function CapAddrPlus1 getTopFat(CapFat cap, TempFields tf);
|
||||||
// First, construct a full length value with the top bits and the
|
// First, construct a full length value with the top bits and the
|
||||||
// correction bits above, and shift that value to the appropriate spot.
|
// correction bits above, and shift that value to the appropriate spot.
|
||||||
LCapAddress addTop = signExtend({pack(tf.topCorrection), cap.bounds.topBits}) << cap.bounds.exp;
|
CapAddrPlus1 addTop = signExtend({pack(tf.topCorrection), cap.bounds.topBits}) << cap.bounds.exp;
|
||||||
// Build a mask on the high bits of a full length value to extract the high
|
// Build a mask on the high bits of a full length value to extract the high
|
||||||
// bits of the address.
|
// bits of the address.
|
||||||
Bit#(TSub#(SizeOf#(LCapAddress),MW)) mask = ~0 << cap.bounds.exp;
|
Bit#(TSub#(TAdd#(CapAddrW,1),MW)) mask = ~0 << cap.bounds.exp;
|
||||||
// Extract the high bits of the address (and append the implied zeros at the
|
// Extract the high bits of the address (and append the implied zeros at the
|
||||||
// bottom), and add with the previously prepared value.
|
// bottom), and add with the previously prepared value.
|
||||||
LCapAddress ret = {2'b0, truncateLSB(cap.address)&mask,0} + addTop;
|
CapAddrPlus1 ret = {truncateLSB({1'b0,cap.address})&mask,0} + addTop;
|
||||||
// If the bottom and top are more than an address space away from eachother, invert
|
// 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
|
// the 64th/32nd bit of Top. This corrects for errors that happen when the representable
|
||||||
// space wraps the address space.
|
// space wraps the address space.
|
||||||
Integer msbp = valueOf(CapAddressW) - 1;
|
Integer msbp = valueOf(CapAddrW) - 1;
|
||||||
ret[msbp+2] = 0;
|
|
||||||
Bit#(2) topTip = ret[msbp+1:msbp];
|
Bit#(2) topTip = ret[msbp+1:msbp];
|
||||||
// Calculate the msb of the base.
|
// Calculate the msb of the base.
|
||||||
// First assume that only the address and correction are involved...
|
// First assume that only the address and correction are involved...
|
||||||
Bit#(TSub#(CapAddressW,MW)) bot = truncateLSB(cap.address) + (signExtend(pack(tf.baseCorrection)) << cap.bounds.exp);
|
Bit#(TSub#(CapAddrW,MW)) bot = truncateLSB(cap.address) + (signExtend(pack(tf.baseCorrection)) << cap.bounds.exp);
|
||||||
Bit#(1) botTip = msb(bot);
|
Bit#(1) botTip = msb(bot);
|
||||||
// If the bit we're interested in are actually coming from baseBits, select the correct one from there.
|
// 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.
|
// exp == (resetExp - 1) doesn't matter since we will not flip unless exp < resetExp-1.
|
||||||
@@ -301,14 +299,14 @@ function LCapAddress getTopFat(CapFat cap, TempFields tf);
|
|||||||
if (cap.bounds.exp<(resetExp-1) && (topTip - zeroExtend(botTip)) > 1) ret[msbp+1] = ~ret[msbp+1];
|
if (cap.bounds.exp<(resetExp-1) && (topTip - zeroExtend(botTip)) > 1) ret[msbp+1] = ~ret[msbp+1];
|
||||||
return ret;
|
return ret;
|
||||||
endfunction
|
endfunction
|
||||||
function LCapAddress getLengthFat(CapFat cap, TempFields tf);
|
function CapAddrPlus1 getLengthFat(CapFat cap, TempFields tf);
|
||||||
// Get the top and base bits with the 2 correction bits prepended
|
// Get the top and base bits with the 2 correction bits prepended
|
||||||
Bit#(TAdd#(MW,2)) top = {pack(tf.topCorrection),cap.bounds.topBits};
|
Bit#(TAdd#(MW,2)) top = {pack(tf.topCorrection),cap.bounds.topBits};
|
||||||
Bit#(TAdd#(MW,2)) base = {pack(tf.baseCorrection),cap.bounds.baseBits};
|
Bit#(TAdd#(MW,2)) base = {pack(tf.baseCorrection),cap.bounds.baseBits};
|
||||||
// Get the length by substracting base from top and shifting appropriately
|
// Get the length by substracting base from top and shifting appropriately
|
||||||
LCapAddress length = zeroExtend(top - base) << cap.bounds.exp;
|
CapAddrPlus1 length = zeroExtend(top - base) << cap.bounds.exp;
|
||||||
// Return a saturated length in case of big exponent
|
// Return a saturated length in case of big exponent
|
||||||
return (cap.bounds.exp >= resetExp) ? ~0 : length;
|
return (cap.bounds.exp >= resetExp) ? ~0 : truncate(length);
|
||||||
endfunction
|
endfunction
|
||||||
function Address getOffsetFat(CapFat cap, TempFields tf);
|
function Address getOffsetFat(CapFat cap, TempFields tf);
|
||||||
// Get the exponent
|
// Get the exponent
|
||||||
@@ -323,14 +321,6 @@ function Address getOffsetFat(CapFat cap, TempFields tf);
|
|||||||
// with the low address bits appended
|
// with the low address bits appended
|
||||||
return (signExtend(offset) << e) | addrLSB;
|
return (signExtend(offset) << e) | addrLSB;
|
||||||
endfunction
|
endfunction
|
||||||
function LCapAddress regToLAddr(Address in);
|
|
||||||
CapAddress retVal = truncate(in);
|
|
||||||
return zeroExtend(retVal);
|
|
||||||
endfunction
|
|
||||||
function LCapAddress regToSignedLAddr(Address in);
|
|
||||||
CapAddress retVal = truncate(in);
|
|
||||||
return signExtend(retVal);
|
|
||||||
endfunction
|
|
||||||
function Bool isSealed(CapFat cap) = (cap.otype != otype_unsealed);
|
function Bool isSealed(CapFat cap) = (cap.otype != otype_unsealed);
|
||||||
function CType getTypeFat(CapFat cap) = VnD{v: (cap.otype != otype_unsealed), d: cap.otype};
|
function CType getTypeFat(CapFat cap) = VnD{v: (cap.otype != otype_unsealed), d: cap.otype};
|
||||||
function Bit#(31) getPerms(CapFat cap);
|
function Bit#(31) getPerms(CapFat cap);
|
||||||
@@ -359,11 +349,11 @@ function CapFat nullifyCap(CapFat cap);
|
|||||||
//ret.isCapability = False;
|
//ret.isCapability = False;
|
||||||
return ret;
|
return ret;
|
||||||
endfunction
|
endfunction
|
||||||
function CapFat setCapPointer(CapFat cap, LCapAddress pointer);
|
function CapFat setCapPointer(CapFat cap, CapAddr pointer);
|
||||||
// Function to "cheat" and just set the pointer when we know that
|
// Function to "cheat" and just set the pointer when we know that
|
||||||
// it will be in representable bounds by some other means.
|
// it will be in representable bounds by some other means.
|
||||||
CapFat ret = cap;
|
CapFat ret = cap;
|
||||||
ret.address = truncate(pointer);
|
ret.address = pointer;
|
||||||
ret.addrBits = truncate(ret.address >> ret.bounds.exp);
|
ret.addrBits = truncate(ret.address >> ret.bounds.exp);
|
||||||
return ret;
|
return ret;
|
||||||
endfunction
|
endfunction
|
||||||
@@ -376,15 +366,15 @@ function Bit#(n) smearMSBRight(Bit#(n) x);
|
|||||||
return res;
|
return res;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address lengthFull);
|
function SetBoundsReturn#(CapFat, CapAddrW) setBoundsFat(CapFat cap, Address lengthFull);
|
||||||
CapFat ret = cap;
|
CapFat ret = cap;
|
||||||
// Find new exponent by finding the index of the most significant bit of the
|
// 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
|
// length, or counting leading zeros in the high bits of the length, and
|
||||||
// substracting them to the CapAddress width (taking away the bottom MW-1 bits:
|
// substracting them to the CapAddr width (taking away the bottom MW-1 bits:
|
||||||
// trim (MW-1) bits from the bottom of length since any length with a significance
|
// trim (MW-1) bits from the bottom of length since any length with a significance
|
||||||
// that small will yield an exponent of zero).
|
// that small will yield an exponent of zero).
|
||||||
CapAddress length = truncate(lengthFull);
|
CapAddr length = truncate(lengthFull);
|
||||||
Bit#(TSub#(CapAddressW,TSub#(MW,1))) lengthMSBs = truncateLSB(length);
|
Bit#(TSub#(CapAddrW,TSub#(MW,1))) lengthMSBs = truncateLSB(length);
|
||||||
Exp zeros = zeroExtend(countZerosMSB(lengthMSBs));
|
Exp zeros = zeroExtend(countZerosMSB(lengthMSBs));
|
||||||
// Adjust resetExp by one since it's scale reaches 1-bit greater than a 64-bit length
|
// Adjust resetExp by one since it's scale reaches 1-bit greater than a 64-bit length
|
||||||
// can express.
|
// can express.
|
||||||
@@ -397,18 +387,18 @@ function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address
|
|||||||
ret.otype = otype_unsealed;
|
ret.otype = otype_unsealed;
|
||||||
// Derive new base bits by extracting MW bits from the capability
|
// Derive new base bits by extracting MW bits from the capability
|
||||||
// address starting at the new exponent's position.
|
// address starting at the new exponent's position.
|
||||||
LCapAddress base = zeroExtend(cap.address);
|
CapAddrPlus2 base = zeroExtend(cap.address);
|
||||||
Bit#(TAdd#(MW,1)) newBaseBits = truncate(base>>e);
|
Bit#(TAdd#(MW,1)) newBaseBits = truncate(base>>e);
|
||||||
|
|
||||||
// Derive new top bits by extracting MW bits from the capability
|
// Derive new top bits by extracting MW bits from the capability
|
||||||
// address + requested length, starting at the new exponent's position,
|
// address + requested length, starting at the new exponent's position,
|
||||||
// and rounding up if significant bits are lost in the process.
|
// and rounding up if significant bits are lost in the process.
|
||||||
LCapAddress len = zeroExtend(length);
|
CapAddrPlus2 len = zeroExtend(length);
|
||||||
LCapAddress top = base + len;
|
CapAddrPlus2 top = base + len;
|
||||||
|
|
||||||
// Create a mask with all bits set below the MSB of length and then masking all bits
|
// Create a mask with all bits set below the MSB of length and then masking all bits
|
||||||
// below the mantissa bits.
|
// below the mantissa bits.
|
||||||
LCapAddress lmask = smearMSBRight(len);
|
CapAddrPlus2 lmask = smearMSBRight(len);
|
||||||
// The shift amount required to put the most significant set bit of the
|
// 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.
|
// len just above the bottom HalfExpW bits that are taken by the exp.
|
||||||
Integer shiftAmount = valueOf(TSub#(TSub#(MW,2),HalfExpW));
|
Integer shiftAmount = valueOf(TSub#(TSub#(MW,2),HalfExpW));
|
||||||
@@ -420,8 +410,8 @@ function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address
|
|||||||
// shifted out bits or in the HalfExpW bits stolen for the exponent
|
// 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
|
// 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.
|
// more to take in the bits that will be lost for the exponent when it is non-zero.
|
||||||
LCapAddress lmaskLor = lmask>>fromInteger(shiftAmount+1);
|
CapAddrPlus2 lmaskLor = lmask>>fromInteger(shiftAmount+1);
|
||||||
LCapAddress lmaskLo = lmask>>fromInteger(shiftAmount);
|
CapAddrPlus2 lmaskLo = lmask>>fromInteger(shiftAmount);
|
||||||
// For the len, we're not actually losing significance since we're not storing it,
|
// 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
|
// 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.
|
// cause the total length to round up.
|
||||||
@@ -452,8 +442,8 @@ function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address
|
|||||||
// an extra "1" that will be added to the "mantissa" bits of the length, potentially causing overflow.
|
// 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
|
// Finally check how close the requested length is to overflow, and test in relation to how much the
|
||||||
// length will increase.
|
// length will increase.
|
||||||
LCapAddress topLo = (lmaskLor & len) + (lmaskLor & base);
|
CapAddrPlus2 topLo = (lmaskLor & len) + (lmaskLor & base);
|
||||||
LCapAddress mwLsbMask = lmaskLor ^ lmaskLo;
|
CapAddrPlus2 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.
|
// 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 lengthCarryIn = (mwLsbMask & top) != ((mwLsbMask & base)^(mwLsbMask & len));
|
||||||
Bool lengthRoundUp = lostSignificantTop;
|
Bool lengthRoundUp = lostSignificantTop;
|
||||||
@@ -489,11 +479,11 @@ function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Begin calculate newLength in case this is a request just for a representable length:
|
// Begin calculate newLength in case this is a request just for a representable length:
|
||||||
LCapAddress newLength = zeroExtend(length);
|
CapAddrPlus2 newLength = zeroExtend(length);
|
||||||
LCapAddress baseMask = -1; // Override the result from the previous line if we represent everything.
|
CapAddrPlus2 baseMask = -1; // Override the result from the previous line if we represent everything.
|
||||||
if (intExp) begin
|
if (intExp) begin
|
||||||
LCapAddress oneInLsb = (lmask ^ (lmask>>1)) >> shiftAmount;
|
CapAddrPlus2 oneInLsb = (lmask ^ (lmask>>1)) >> shiftAmount;
|
||||||
LCapAddress newLengthRounded = newLength + oneInLsb;
|
CapAddrPlus2 newLengthRounded = newLength + oneInLsb;
|
||||||
newLength = (newLength & (~lmaskLor));
|
newLength = (newLength & (~lmaskLor));
|
||||||
newLengthRounded = (newLengthRounded & (~lmaskLor));
|
newLengthRounded = (newLengthRounded & (~lmaskLor));
|
||||||
if (lostSignificantLen) newLength = newLengthRounded;
|
if (lostSignificantLen) newLength = newLengthRounded;
|
||||||
@@ -515,8 +505,8 @@ function CapFat unseal(CapFat cap, x _);
|
|||||||
return ret;
|
return ret;
|
||||||
endfunction
|
endfunction
|
||||||
function VnD#(CapFat) incOffsetFat( CapFat cap
|
function VnD#(CapFat) incOffsetFat( CapFat cap
|
||||||
, LCapAddress pointer
|
, CapAddr pointer
|
||||||
, Bit#(CapAddressW) offset // this is the increment in inc offset, and the offset in set offset
|
, CapAddr offset // this is the increment in inc offset, and the offset in set offset
|
||||||
, TempFields tf
|
, TempFields tf
|
||||||
, Bool setOffset);
|
, Bool setOffset);
|
||||||
// NOTE:
|
// NOTE:
|
||||||
@@ -548,10 +538,10 @@ function VnD#(CapFat) incOffsetFat( CapFat cap
|
|||||||
// that is −S < 'offset' < S. This test reduces to a check that there are no
|
// that is −S < 'offset' < S. This test reduces to a check that there are no
|
||||||
// significant bits in the high bits of 'offset', that is they are all ones or all
|
// significant bits in the high bits of 'offset', that is they are all ones or all
|
||||||
// zeros.
|
// zeros.
|
||||||
CapAddress offsetAddr = truncate(offset);
|
CapAddr offsetAddr = truncate(offset);
|
||||||
Bit#(TSub#(CapAddressW,MW)) signBits = signExtend(offset[valueOf(TSub#(CapAddressW,1))]);
|
Bit#(TSub#(CapAddrW,MW)) signBits = signExtend(offset[valueOf(TSub#(CapAddrW,1))]);
|
||||||
Bit#(TSub#(CapAddressW,MW)) highOffsetBits = unpack(truncateLSB(offsetAddr));
|
Bit#(TSub#(CapAddrW,MW)) highOffsetBits = unpack(truncateLSB(offsetAddr));
|
||||||
Bit#(TSub#(CapAddressW,MW)) highBitsfilter = -1 << e;
|
Bit#(TSub#(CapAddrW,MW)) highBitsfilter = -1 << e;
|
||||||
highOffsetBits = (highOffsetBits ^ signBits) & highBitsfilter;
|
highOffsetBits = (highOffsetBits ^ signBits) & highBitsfilter;
|
||||||
Bool inRange = (highOffsetBits == 0);
|
Bool inRange = (highOffsetBits == 0);
|
||||||
|
|
||||||
@@ -570,7 +560,7 @@ function VnD#(CapFat) incOffsetFat( CapFat cap
|
|||||||
// to a false positive on the i >= toBounds comparison)
|
// to a false positive on the i >= toBounds comparison)
|
||||||
|
|
||||||
// The sign of the increment
|
// The sign of the increment
|
||||||
Bool posInc = offsetAddr[valueOf(CapAddressW)-1] == 1'b0;
|
Bool posInc = offsetAddr[valueOf(CapAddrW)-1] == 1'b0;
|
||||||
|
|
||||||
// The offsetBits value corresponds to the appropriate slice of the 'offsetAddr' argument
|
// The offsetBits value corresponds to the appropriate slice of the 'offsetAddr' argument
|
||||||
Bit#(MW) offsetBits = truncate(offsetAddr >> e);
|
Bit#(MW) offsetBits = truncate(offsetAddr >> e);
|
||||||
@@ -623,7 +613,7 @@ function VnD#(CapFat) incOffsetFat( CapFat cap
|
|||||||
// ------------------------------
|
// ------------------------------
|
||||||
if (setOffset) begin
|
if (setOffset) begin
|
||||||
// Get the base and add the offsetAddr. This could be slow, but seems to pass timing.
|
// Get the base and add the offsetAddr. This could be slow, but seems to pass timing.
|
||||||
ret.address = truncate(getBotFat(cap,tf) + zeroExtend(offsetAddr));
|
ret.address = getBotFat(cap,tf) + zeroExtend(offsetAddr);
|
||||||
// TODO write comments on this
|
// TODO write comments on this
|
||||||
Bit#(TAdd#(MW,2)) newAddrBits = zeroExtend(cap.bounds.baseBits) + zeroExtend(offsetBits);
|
Bit#(TAdd#(MW,2)) newAddrBits = zeroExtend(cap.bounds.baseBits) + zeroExtend(offsetBits);
|
||||||
ret.addrBits = (e == resetExp) ? {2'b0,truncate(newAddrBits)} :
|
ret.addrBits = (e == resetExp) ? {2'b0,truncate(newAddrBits)} :
|
||||||
@@ -640,15 +630,15 @@ function VnD#(CapFat) incOffsetFat( CapFat cap
|
|||||||
// return updated / invalid capability
|
// return updated / invalid capability
|
||||||
return VnD {v: inBounds, d: ret};
|
return VnD {v: inBounds, d: ret};
|
||||||
endfunction
|
endfunction
|
||||||
function VnD#(CapFat) setAddress(CapFat cap, LCapAddress address, TempFields tf);
|
function VnD#(CapFat) setAddress(CapFat cap, CapAddr address, TempFields tf);
|
||||||
CapFat ret = setCapPointer(cap, address);
|
CapFat ret = setCapPointer(cap, address);
|
||||||
Exp e = cap.bounds.exp;
|
Exp e = cap.bounds.exp;
|
||||||
// Calculate what the upper bits of the new address must be if it is to be in representable bounds.
|
// Calculate what the upper bits of the new address must be if it is to be in representable bounds.
|
||||||
Bool newAddrHi = truncateLSB(ret.addrBits) < tf.repBoundTopBits;
|
Bool newAddrHi = truncateLSB(ret.addrBits) < tf.repBoundTopBits;
|
||||||
// Shift amount needed to look at only the bits above the mantissa.
|
// Shift amount needed to look at only the bits above the mantissa.
|
||||||
Exp toUpperBits = e + fromInteger(valueOf(MW));
|
Exp toUpperBits = e + fromInteger(valueOf(MW));
|
||||||
CapAddress mask = -1 << toUpperBits;
|
CapAddr mask = -1 << toUpperBits;
|
||||||
CapAddress newAddrDiff = (truncate(cap.address)&mask) - (truncate(address)&mask);
|
CapAddr newAddrDiff = (truncate(cap.address)&mask) - (truncate(address)&mask);
|
||||||
// Assert that the bits above the mantissa are all equal.
|
// Assert that the bits above the mantissa are all equal.
|
||||||
Bool inRepBounds = True;
|
Bool inRepBounds = True;
|
||||||
// If the difference between the upper bits of the new address and the current
|
// If the difference between the upper bits of the new address and the current
|
||||||
@@ -678,7 +668,7 @@ endfunction
|
|||||||
|
|
||||||
|
|
||||||
// Exponent that pushes the implied +1 of the top 1 bit outside the address space
|
// Exponent that pushes the implied +1 of the top 1 bit outside the address space
|
||||||
Exp resetExp = fromInteger(valueOf(TSub#(SizeOf#(LCapAddress),MW)));
|
Exp resetExp = fromInteger(valueOf(TSub#(TAdd#(CapAddrW,2),MW)));
|
||||||
|
|
||||||
Bit#(MW) resetTop = {2'b01,0};
|
Bit#(MW) resetTop = {2'b01,0};
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -856,7 +846,7 @@ typedef struct {
|
|||||||
TempFields tempFields;
|
TempFields tempFields;
|
||||||
} CapPipe deriving (Bits);
|
} CapPipe deriving (Bits);
|
||||||
|
|
||||||
instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
|
||||||
function isValidCap (x);
|
function isValidCap (x);
|
||||||
CapabilityInMemory capMem = unpack(x);
|
CapabilityInMemory capMem = unpack(x);
|
||||||
return capMem.isCapability;
|
return capMem.isCapability;
|
||||||
@@ -897,12 +887,12 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
function setSoftPerms = error("setSoftPerms not implemented for CapMem");
|
function setSoftPerms = error("setSoftPerms not implemented for CapMem");
|
||||||
function getKind = error("getKind not implemented for CapMem");
|
function getKind = error("getKind not implemented for CapMem");
|
||||||
function setKind = error("setKind not implemented for CapMem");
|
function setKind = error("setKind not implemented for CapMem");
|
||||||
function Bit#(CapAddressW) getAddr(CapMem cap);
|
function Bit#(CapAddrW) getAddr(CapMem cap);
|
||||||
CapabilityInMemory capMem = unpack(cap);
|
CapabilityInMemory capMem = unpack(cap);
|
||||||
return capMem.address;
|
return capMem.address;
|
||||||
endfunction
|
endfunction
|
||||||
function setAddr = error("setAddr not implemented for CapMem");
|
function setAddr = error("setAddr not implemented for CapMem");
|
||||||
function CapMem setAddrUnsafe (CapMem cap, Bit#(CapAddressW) address);
|
function CapMem setAddrUnsafe (CapMem cap, Bit#(CapAddrW) address);
|
||||||
CapabilityInMemory capMem = unpack(cap);
|
CapabilityInMemory capMem = unpack(cap);
|
||||||
capMem.address = address;
|
capMem.address = address;
|
||||||
return pack(capMem);
|
return pack(capMem);
|
||||||
@@ -921,9 +911,9 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
return cast(res);
|
return cast(res);
|
||||||
endfunction
|
endfunction
|
||||||
function nullCapFromDummy (x) = packCap(null_cap);
|
function nullCapFromDummy (x) = packCap(null_cap);
|
||||||
function Bool validAsType (CapMem dummy, Bit#(CapAddressW) checkType);
|
function Bool validAsType (CapMem dummy, Bit#(CapAddrW) checkType);
|
||||||
UInt#(CapAddressW) checkTypeUnsigned = unpack(checkType);
|
UInt#(CapAddrW) checkTypeUnsigned = unpack(checkType);
|
||||||
UInt#(CapAddressW) otypeMaxUnsigned = unpack(zeroExtend(otype_max));
|
UInt#(CapAddrW) otypeMaxUnsigned = unpack(zeroExtend(otype_max));
|
||||||
return checkTypeUnsigned <= otypeMaxUnsigned;
|
return checkTypeUnsigned <= otypeMaxUnsigned;
|
||||||
endfunction
|
endfunction
|
||||||
function fromMem = error("fromMem not implemented for CapMem");
|
function fromMem = error("fromMem not implemented for CapMem");
|
||||||
@@ -955,7 +945,7 @@ instance Eq #(CapReg);
|
|||||||
// function Bool \/= (CapPipe x, CapPipe y);
|
// function Bool \/= (CapPipe x, CapPipe y);
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
|
||||||
|
|
||||||
function isValidCap (x) = x.isCapability;
|
function isValidCap (x) = x.isCapability;
|
||||||
|
|
||||||
@@ -1038,9 +1028,8 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
function setAddr = error("setAddr not implemented for CapReg");
|
function setAddr = error("setAddr not implemented for CapReg");
|
||||||
|
|
||||||
function CapReg setAddrUnsafe (CapReg cap, Bit#(CapAddressW) address);
|
function CapReg setAddrUnsafe (CapReg cap, Bit#(CapAddrW) address) =
|
||||||
return setCapPointer(cap, zeroExtend(address));
|
setCapPointer(cap, address);
|
||||||
endfunction
|
|
||||||
|
|
||||||
function addAddrUnsafe (cap, inc) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
|
function addAddrUnsafe (cap, inc) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
|
||||||
|
|
||||||
@@ -1051,9 +1040,9 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
function getLength = error("getLength not implemented for CapReg");
|
function getLength = error("getLength not implemented for CapReg");
|
||||||
function isInBounds = error("isInBounds not implemented for CapReg");
|
function isInBounds = error("isInBounds not implemented for CapReg");
|
||||||
|
|
||||||
function SetBoundsReturn#(CapReg, CapAddressW) setBoundsCombined(CapReg cap, Bit#(CapAddressW) length) = setBoundsFat(cap, length);
|
function SetBoundsReturn#(CapReg, CapAddrW) setBoundsCombined(CapReg cap, Bit#(CapAddrW) length) = setBoundsFat(cap, length);
|
||||||
|
|
||||||
function CapReg nullWithAddr (Bit#(CapAddressW) addr) = setAddrUnsafe(null_cap, addr);
|
function CapReg nullWithAddr (Bit#(CapAddrW) addr) = setAddrUnsafe(null_cap, addr);
|
||||||
|
|
||||||
function almightyCap = defaultCapFat;
|
function almightyCap = defaultCapFat;
|
||||||
|
|
||||||
@@ -1063,11 +1052,10 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
function toMem (x) = unpack(cast(x));
|
function toMem (x) = unpack(cast(x));
|
||||||
|
|
||||||
function CapReg maskAddr (CapReg cap, Bit#(TSub#(MW, 3)) mask);
|
function CapReg maskAddr (CapReg cap, Bit#(TSub#(MW, 3)) mask) =
|
||||||
return setCapPointer(cap, zeroExtend(cap.address) & {~0,mask});
|
setCapPointer(cap, cap.address & {~0,mask});
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bool validAsType (CapReg dummy, Bit#(CapAddressW) checkType);
|
function Bool validAsType (CapReg dummy, Bit#(CapAddrW) checkType);
|
||||||
CapMem nullC = nullCap;
|
CapMem nullC = nullCap;
|
||||||
return validAsType(nullC, checkType);
|
return validAsType(nullC, checkType);
|
||||||
endfunction
|
endfunction
|
||||||
@@ -1090,7 +1078,7 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
|
||||||
|
|
||||||
//Functions supported by CapReg are just passed through
|
//Functions supported by CapReg are just passed through
|
||||||
function isValidCap (x) = isValidCap(x.capFat);
|
function isValidCap (x) = isValidCap(x.capFat);
|
||||||
@@ -1115,7 +1103,7 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
function CapPipe maskAddr (CapPipe cap, Bit#(TSub#(MW, 3)) mask);
|
function CapPipe maskAddr (CapPipe cap, Bit#(TSub#(MW, 3)) mask);
|
||||||
return CapPipe {capFat: maskAddr(cap.capFat, mask), tempFields: cap.tempFields};
|
return CapPipe {capFat: maskAddr(cap.capFat, mask), tempFields: cap.tempFields};
|
||||||
endfunction
|
endfunction
|
||||||
function Bool validAsType (CapPipe dummy, Bit#(CapAddressW) checkType);
|
function Bool validAsType (CapPipe dummy, Bit#(CapAddrW) checkType);
|
||||||
return validAsType(dummy.capFat, checkType);
|
return validAsType(dummy.capFat, checkType);
|
||||||
endfunction
|
endfunction
|
||||||
function toMem (cap) = toMem(cap.capFat);
|
function toMem (cap) = toMem(cap.capFat);
|
||||||
@@ -1123,12 +1111,12 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
//Functions supported by CapReg but which require TempFields to be changed
|
//Functions supported by CapReg but which require TempFields to be changed
|
||||||
|
|
||||||
function SetBoundsReturn#(CapPipe, CapAddressW) setBoundsCombined(CapPipe cap, Bit#(CapAddressW) length);
|
function SetBoundsReturn#(CapPipe, CapAddrW) setBoundsCombined(CapPipe cap, Bit#(CapAddrW) length);
|
||||||
let result = setBoundsCombined(cap.capFat, length);
|
let result = setBoundsCombined(cap.capFat, length);
|
||||||
return SetBoundsReturn {cap: CapPipe{capFat: result.cap, tempFields: getTempFields(result.cap)}, exact: result.exact, length: result.length, mask: result.mask};
|
return SetBoundsReturn {cap: CapPipe{capFat: result.cap, tempFields: getTempFields(result.cap)}, exact: result.exact, length: result.length, mask: result.mask};
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function CapPipe nullWithAddr (Bit#(CapAddressW) addr);
|
function CapPipe nullWithAddr (Bit#(CapAddrW) addr);
|
||||||
CapReg res = nullWithAddr(addr);
|
CapReg res = nullWithAddr(addr);
|
||||||
return CapPipe {capFat: res, tempFields: getTempFields(res)};
|
return CapPipe {capFat: res, tempFields: getTempFields(res)};
|
||||||
endfunction
|
endfunction
|
||||||
@@ -1150,14 +1138,14 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
//Functions that require TempFields
|
//Functions that require TempFields
|
||||||
|
|
||||||
function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(CapAddressW) address);
|
function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(CapAddrW) address);
|
||||||
let result = setAddress(cap.capFat, zeroExtend(address), cap.tempFields);
|
let result = setAddress(cap.capFat, address, cap.tempFields);
|
||||||
cap.capFat = result.d;
|
cap.capFat = result.d;
|
||||||
cap.tempFields = getTempFields(cap.capFat);
|
cap.tempFields = getTempFields(cap.capFat);
|
||||||
return Exact {exact: result.v, value: cap};
|
return Exact {exact: result.v, value: cap};
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function CapPipe setAddrUnsafe (CapPipe cap, Bit#(CapAddressW) address);
|
function CapPipe setAddrUnsafe (CapPipe cap, Bit#(CapAddrW) address);
|
||||||
cap.capFat = setAddrUnsafe(cap.capFat, address);
|
cap.capFat = setAddrUnsafe(cap.capFat, address);
|
||||||
cap.tempFields = getTempFields(cap.capFat);
|
cap.tempFields = getTempFields(cap.capFat);
|
||||||
return cap;
|
return cap;
|
||||||
@@ -1167,24 +1155,22 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
|
|||||||
|
|
||||||
function getOffset (x) = getOffsetFat(x.capFat, x.tempFields);
|
function getOffset (x) = getOffsetFat(x.capFat, x.tempFields);
|
||||||
|
|
||||||
function Exact#(CapPipe) modifyOffset (CapPipe cap, Bit#(CapAddressW) offset, Bool doInc);
|
function Exact#(CapPipe) modifyOffset (CapPipe cap, Bit#(CapAddrW) offset, Bool doInc);
|
||||||
let result = incOffsetFat(cap.capFat, zeroExtend(cap.capFat.address) + zeroExtend(offset), zeroExtend(offset), cap.tempFields, !doInc);
|
let result = incOffsetFat(cap.capFat, cap.capFat.address + offset, zeroExtend(offset), cap.tempFields, !doInc);
|
||||||
cap.capFat = result.d;
|
cap.capFat = result.d;
|
||||||
cap.tempFields = getTempFields(cap.capFat);
|
cap.tempFields = getTempFields(cap.capFat);
|
||||||
return Exact {exact: result.v, value: cap};
|
return Exact {exact: result.v, value: cap};
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function Bit#(CapAddressW) getBase (CapPipe cap);
|
function Bit#(CapAddrW) getBase (CapPipe cap);
|
||||||
return truncate(getBotFat(cap.capFat, cap.tempFields));
|
return getBotFat(cap.capFat, cap.tempFields);
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function Bit#(TAdd#(CapAddressW,1)) getTop (CapPipe cap);
|
function Bit#(TAdd#(CapAddrW,1)) getTop (CapPipe cap) =
|
||||||
return truncate(getTopFat(cap.capFat, cap.tempFields));
|
getTopFat(cap.capFat, cap.tempFields);
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bit#(TAdd#(CapAddressW,1)) getLength (CapPipe cap);
|
function Bit#(TAdd#(CapAddrW,1)) getLength (CapPipe cap) =
|
||||||
return truncate(getLengthFat(cap.capFat, cap.tempFields));
|
getLengthFat(cap.capFat, cap.tempFields);
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bool isInBounds (CapPipe cap, Bool inclusive);
|
function Bool isInBounds (CapPipe cap, Bool inclusive);
|
||||||
return capInBounds(cap.capFat, cap.tempFields, inclusive);
|
return capInBounds(cap.capFat, cap.tempFields, inclusive);
|
||||||
@@ -1238,9 +1224,9 @@ instance Cast#(function CapReg f0(t x), function CapPipe f1(t y));
|
|||||||
endfunction
|
endfunction
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
instance Cast#(function CapPipe f0(t y), function Bit#(CapAddressW) f1(t x));
|
instance Cast#(function CapPipe f0(t y), function Bit#(CapAddrW) f1(t x));
|
||||||
function cast(f0);
|
function cast(f0);
|
||||||
function Bit#(CapAddressW) f1(t arg) = getAddr(f0(arg));
|
function Bit#(CapAddrW) f1(t arg) = getAddr(f0(arg));
|
||||||
return f1;
|
return f1;
|
||||||
endfunction
|
endfunction
|
||||||
endinstance
|
endinstance
|
||||||
|
|||||||
Reference in New Issue
Block a user