5 Commits

Author SHA1 Message Date
b772286261 saving current changes
Some checks failed
check properties / tests (push) Has been cancelled
2026-02-23 11:44:35 +00:00
f7884bb932 hack changes
Some checks failed
check properties / tests (push) Has been cancelled
2026-02-20 01:59:12 +00:00
bd95a8b5b1 saving current changes cheri-cap-lib
Some checks failed
check properties / tests (push) Has been cancelled
2026-02-19 18:07:45 +00:00
ed366654f0 saved compile time errors
Some checks failed
check properties / tests (push) Has been cancelled
2026-02-17 15:34:56 +00:00
b8f7b51e8a added latest changes 2026-02-17 14:49:00 +00:00
4 changed files with 534 additions and 556 deletions

View File

@@ -1,452 +1,452 @@
/*- // /*-
* Copyright (c) 2017-2019 Alexandre Joannou // * Copyright (c) 2017-2019 Alexandre Joannou
* All rights reserved. // * All rights reserved.
* // *
* This software was developed by SRI International and the University of // * This software was developed by SRI International and the University of
* Cambridge Computer Laboratory (Department of Computer Science and // * Cambridge Computer Laboratory (Department of Computer Science and
* Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the // * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
* DARPA SSITH research programme. // * DARPA SSITH research programme.
* // *
* @BERI_LICENSE_HEADER_START@ // * @BERI_LICENSE_HEADER_START@
* // *
* Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor // * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for // * license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. BERI licenses this // * additional information regarding copyright ownership. BERI licenses this
* file to you under the BERI Hardware-Software License, Version 1.0 (the // * file to you under the BERI Hardware-Software License, Version 1.0 (the
* "License"); you may not use this file except in compliance with the // * "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at: // * License. You may obtain a copy of the License at:
* // *
* http://www.beri-open-systems.org/legal/license-1-0.txt // * http://www.beri-open-systems.org/legal/license-1-0.txt
* // *
* Unless required by applicable law or agreed to in writing, Work distributed // * Unless required by applicable law or agreed to in writing, Work distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the // * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. // * specific language governing permissions and limitations under the License.
* // *
* @BERI_LICENSE_HEADER_END@ // * @BERI_LICENSE_HEADER_END@
*/ // */
package CHERICC; // package CHERICC;
import CHERICap :: *; // import CHERICap :: *;
export CHERICCCap; // export CHERICCCap;
export CHERICCBounds; // export CHERICCBounds;
`define div2(x) TDiv#(x, 2) // `define div2(x) TDiv#(x, 2)
`define sub2(x) TSub#(x, 2) // `define sub2(x) TSub#(x, 2)
`define i(x) valueOf(x) // `define i(x) valueOf(x)
// CHERICCBounds Bounds type // // CHERICCBounds Bounds type
//////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////
// CHERICC compressed bounds type // // CHERICC compressed bounds type
typedef union tagged { // typedef union tagged {
struct { // struct {
Bit#(1) lenMSB; // Bit#(1) lenMSB;
Bit#(`sub2(base_)) top; // Bit#(`sub2(base_)) top;
Bit#(base_) base; // Bit#(base_) base;
} Exp0; // } Exp0;
struct { // struct {
Bit#(TSub#(`sub2(base_), `div2(e_))) top; // Bit#(TSub#(`sub2(base_), `div2(e_))) top;
Bit#(TSub#(base_, `div2(e_))) base; // Bit#(TSub#(base_, `div2(e_))) base;
Bit#(e_) e; // Bit#(e_) e;
} EmbeddedExp; // } EmbeddedExp;
struct { // struct {
Bit#(TSub#(`sub2(base_), TAdd#(`div2(t_), `div2(e_)))) top; // Bit#(TSub#(`sub2(base_), TAdd#(`div2(t_), `div2(e_)))) top;
Bit#(TSub#(base_, TAdd#(`div2(t_), `div2(e_)))) base; // Bit#(TSub#(base_, TAdd#(`div2(t_), `div2(e_)))) base;
Bit#(t_) otype; // Bit#(t_) otype;
Bit#(e_) e; // Bit#(e_) e;
} Sealed; // } Sealed;
} CHERICCBounds#(numeric type base_, numeric type e_, numeric type t_); // } CHERICCBounds#(numeric type base_, numeric type e_, numeric type t_);
instance Bits#(CHERICCBounds#(b_, e_, t_), TMul#(b_, 2)) provisos( // instance Bits#(CHERICCBounds#(b_, e_, t_), TMul#(b_, 2)) provisos(
// in pack // // in pack
Add#(TDiv#(e_, 2), a__, e_), // truncates on e // Add#(TDiv#(e_, 2), a__, e_), // truncates on e
Add#(TDiv#(t_, 2), b__, t_), // truncates on t // Add#(TDiv#(t_, 2), b__, t_), // truncates on t
Add#(2, c__, b_), // 2 bits stolen from top // Add#(2, c__, b_), // 2 bits stolen from top
// in unpack // // in unpack
Add#(d__, TDiv#(e_, 2), TMul#(b_, 2)), // truncates raw into e // Add#(d__, TDiv#(e_, 2), TMul#(b_, 2)), // truncates raw into e
Add#(e__, TDiv#(t_, 2), TMul#(b_, 2)), // truncates raw into t // Add#(e__, TDiv#(t_, 2), TMul#(b_, 2)), // truncates raw into t
Add#(2, f__, TSub#( // Add#(2, f__, TSub#(
TSub#( // TSub#(
TAdd#(b_, // TAdd#(b_,
TAdd#( // TAdd#(
TDiv#(t_, 2), // TDiv#(t_, 2),
TDiv#(e_, 2))), // TDiv#(e_, 2))),
TDiv#(e_, 2)), // TDiv#(e_, 2)),
TDiv#(t_, 2))) // TDiv#(t_, 2)))
); // );
function pack(ccbounds) = // function pack(ccbounds) =
case (ccbounds) matches // case (ccbounds) matches
tagged Exp0 .x: return {{{1'b0, x.lenMSB}, x.top}, x.base}; // tagged Exp0 .x: return {{{1'b0, x.lenMSB}, x.top}, x.base};
tagged EmbeddedExp .x: begin // tagged EmbeddedExp .x: begin
Bit#(`div2(e_)) eHi = truncateLSB(x.e); // Bit#(`div2(e_)) eHi = truncateLSB(x.e);
Bit#(`div2(e_)) eLo = truncate(x.e); // Bit#(`div2(e_)) eLo = truncate(x.e);
return {{2'b10, x.top, eHi}, {x.base, eLo}}; // return {{2'b10, x.top, eHi}, {x.base, eLo}};
end // end
tagged Sealed .x: begin // tagged Sealed .x: begin
Bit#(`div2(t_)) tHi = truncateLSB(x.otype); // Bit#(`div2(t_)) tHi = truncateLSB(x.otype);
Bit#(`div2(t_)) tLo = truncate(x.otype); // Bit#(`div2(t_)) tLo = truncate(x.otype);
Bit#(`div2(e_)) eHi = truncateLSB(x.e); // Bit#(`div2(e_)) eHi = truncateLSB(x.e);
Bit#(`div2(e_)) eLo = truncate(x.e); // Bit#(`div2(e_)) eLo = truncate(x.e);
return {{2'b11, x.top, tHi, eHi}, {x.base, tLo, eLo}}; // return {{2'b11, x.top, tHi, eHi}, {x.base, tLo, eLo}};
/* // /*
Bit#(TMul#(b_, 2)) acc = 0; // Bit#(TMul#(b_, 2)) acc = 0;
acc = acc | zeroExtend(2'b11); // acc = acc | zeroExtend(2'b11);
acc = (acc << `i(b_)-2-`i(t_)/2-`i(e_)/2) | zeroExtend(x.top); // acc = (acc << `i(b_)-2-`i(t_)/2-`i(e_)/2) | zeroExtend(x.top);
acc = (acc << `i(t_)/2) | zeroExtend(tHi); // acc = (acc << `i(t_)/2) | zeroExtend(tHi);
acc = (acc << `i(e_)/2) | zeroExtend(eHi); // acc = (acc << `i(e_)/2) | zeroExtend(eHi);
acc = (acc << `i(b_)-`i(t_)/2-`i(e_)/2) | zeroExtend(x.base); // acc = (acc << `i(b_)-`i(t_)/2-`i(e_)/2) | zeroExtend(x.base);
acc = (acc << `i(t_)/2) | zeroExtend(tLo); // acc = (acc << `i(t_)/2) | zeroExtend(tLo);
acc = (acc << `i(e_)/2) | zeroExtend(eLo); // acc = (acc << `i(e_)/2) | zeroExtend(eLo);
return acc; // return acc;
*/ // */
end // end
endcase; // endcase;
function unpack(raw); // function unpack(raw);
if (raw[2*`i(b_)-1] == 0) return Exp0 { // if (raw[2*`i(b_)-1] == 0) return Exp0 {
lenMSB: raw[2*`i(b_)-2], // lenMSB: raw[2*`i(b_)-2],
top: raw[2*`i(b_)-3:`i(b_)], // top: raw[2*`i(b_)-3:`i(b_)],
base: raw[`i(b_)-1:0] // base: raw[`i(b_)-1:0]
}; // };
else if (raw[2*`i(b_)-2] == 0) begin // else if (raw[2*`i(b_)-2] == 0) begin
Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_)); // Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_));
Bit#(`div2(e_)) eLo = truncate(raw); // Bit#(`div2(e_)) eLo = truncate(raw);
// XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below // // XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below
Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2; // Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2;
return EmbeddedExp { // return EmbeddedExp {
top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2], // top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2],
base: raw[`i(b_)-1:`i(e_)/2], // base: raw[`i(b_)-1:`i(e_)/2],
e: new_e // e: new_e
}; // };
end else begin // end else begin
Bit#(`div2(t_)) tHi = truncate(raw >> (`i(b_)+(`i(e_)/2))); // Bit#(`div2(t_)) tHi = truncate(raw >> (`i(b_)+(`i(e_)/2)));
Bit#(`div2(t_)) tLo = truncate(raw >> (`i(e_)/2)); // Bit#(`div2(t_)) tLo = truncate(raw >> (`i(e_)/2));
// XXX Bit#(t_) new_t = {tHi, tLo}; XXX simpler provisos with equiv line below // // XXX Bit#(t_) new_t = {tHi, tLo}; XXX simpler provisos with equiv line below
Bit#(t_) new_t = zeroExtend(tLo) | zeroExtend(tHi) << `i(t_)/2; // Bit#(t_) new_t = zeroExtend(tLo) | zeroExtend(tHi) << `i(t_)/2;
Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_)); // Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_));
Bit#(`div2(e_)) eLo = truncate(raw); // Bit#(`div2(e_)) eLo = truncate(raw);
// XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below // // XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below
Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2; // Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2;
return Sealed { // return Sealed {
top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2+`i(t_)/2], // top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2+`i(t_)/2],
base: raw[`i(b_)-1:`i(e_)/2+`i(t_)/2], // base: raw[`i(b_)-1:`i(e_)/2+`i(t_)/2],
otype: new_t, // otype: new_t,
e: new_e // e: new_e
}; // };
end // end
endfunction // endfunction
endinstance // endinstance
// CHERICC capability type // // CHERICC capability type
//////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////
`define CCSoftPerms Bit#(4) // `define CCSoftPerms Bit#(4)
`define AllPermsSz TAdd#(SizeOf#(`CCSoftPerms), SizeOf#(HardPerms)) // `define AllPermsSz TAdd#(SizeOf#(`CCSoftPerms), SizeOf#(HardPerms))
typedef struct { // typedef struct {
Bool isCap; // Bool isCap;
`CCSoftPerms softperms; // `CCSoftPerms softperms;
HardPerms hardperms; // HardPerms hardperms;
Bit#(TSub#(addr_, TAdd#(bounds_, `AllPermsSz))) res; // 15 permission bits and bounds_ bits to deduct // Bit#(TSub#(addr_, TAdd#(bounds_, `AllPermsSz))) res; // 15 permission bits and bounds_ bits to deduct
CHERICCBounds#(`div2(bounds_), e_, t_) bounds; // CHERICCBounds#(`div2(bounds_), e_, t_) bounds;
Bit#(addr_) addr; // Bit#(addr_) addr;
} CHERICCCap#(numeric type addr_, numeric type bounds_, numeric type e_, numeric type t_); // } CHERICCCap#(numeric type addr_, numeric type bounds_, numeric type e_, numeric type t_);
instance Bits#(CHERICCCap#(addr_, bounds_, e_, t_), // instance Bits#(CHERICCCap#(addr_, bounds_, e_, t_),
TAdd#(1, TAdd#(addr_, TAdd#(bounds_, TAdd#(res_, `AllPermsSz))))) provisos( // TAdd#(1, TAdd#(addr_, TAdd#(bounds_, TAdd#(res_, `AllPermsSz))))) provisos(
Bits#(CHERICCBounds#(TDiv#(bounds_, 2), e_, t_), bounds_), // Bits#(CHERICCBounds#(TDiv#(bounds_, 2), e_, t_), bounds_),
Add#(TAdd#(bounds_, `AllPermsSz), res_, addr_) // Add#(TAdd#(bounds_, `AllPermsSz), res_, addr_)
); // );
function pack(cap); // function pack(cap);
Bit#(1) isCap = pack(cap.isCap); // Bit#(1) isCap = pack(cap.isCap);
Bit#(SizeOf#(`CCSoftPerms)) softperms = cap.softperms; // Bit#(SizeOf#(`CCSoftPerms)) softperms = cap.softperms;
Bit#(SizeOf#(HardPerms)) hardperms = pack(cap.hardperms); // Bit#(SizeOf#(HardPerms)) hardperms = pack(cap.hardperms);
Bit#(res_) res = cap.res; // Bit#(res_) res = cap.res;
Bit#(bounds_) bounds = pack(cap.bounds); // Bit#(bounds_) bounds = pack(cap.bounds);
Bit#(addr_) addr = cap.addr; // Bit#(addr_) addr = cap.addr;
return {isCap, softperms, hardperms, res, bounds, addr}; // return {isCap, softperms, hardperms, res, bounds, addr};
endfunction // endfunction
//function pack(cap) = {cap.softperms, pack(cap.perms), cap.res, pack(cap.bounds), cap.addr}; // //function pack(cap) = {cap.softperms, pack(cap.perms), cap.res, pack(cap.bounds), cap.addr};
function unpack(raw) = CHERICCCap { // function unpack(raw) = CHERICCCap {
isCap: unpack(msb(raw)), // isCap: unpack(msb(raw)),
softperms: raw[2*`i(addr_)-1:2*`i(addr_)-`i(SizeOf#(`CCSoftPerms))], // softperms: raw[2*`i(addr_)-1:2*`i(addr_)-`i(SizeOf#(`CCSoftPerms))],
hardperms: unpack(raw[2*`i(addr_)-5:2*`i(addr_)-`i(`AllPermsSz)]), // hardperms: unpack(raw[2*`i(addr_)-5:2*`i(addr_)-`i(`AllPermsSz)]),
res: raw[2*`i(addr_)-`i(`AllPermsSz)-1:`i(addr_)+`i(bounds_)], // res: raw[2*`i(addr_)-`i(`AllPermsSz)-1:`i(addr_)+`i(bounds_)],
bounds: unpack(raw[`i(addr_)+`i(bounds_)-1:`i(addr_)]), // bounds: unpack(raw[`i(addr_)+`i(bounds_)-1:`i(addr_)]),
addr: raw[`i(addr_)-1:0] // addr: raw[`i(addr_)-1:0]
}; // };
endinstance // endinstance
`undef AllPermsSz // `undef AllPermsSz
`undef CCSoftPerms // `undef CCSoftPerms
// CHERICCCap inner helpers // // CHERICCCap inner helpers
//////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////
CHERICCCap#(addr_, bounds_, e_, t_) almightyCC = CHERICCCap { // CHERICCCap#(addr_, bounds_, e_, t_) almightyCC = CHERICCCap {
isCap: True, // isCap: True,
softperms: ~0, // softperms: ~0,
hardperms: unpack(~0), // hardperms: unpack(~0),
res: 0, // res: 0,
bounds: EmbeddedExp { // bounds: EmbeddedExp {
top: 0, // implied top bits of 01 // top: 0, // implied top bits of 01
base: 0, // base: 0,
// position the 1 of top in the addr_'th bit // // position the 1 of top in the addr_'th bit
e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2)) // e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2))
}, // },
addr: 0 // addr: 0
}; // };
CHERICCCap#(addr_, bounds_, e_, t_) nullCC = CHERICCCap { // CHERICCCap#(addr_, bounds_, e_, t_) nullCC = CHERICCCap {
isCap: False, // isCap: False,
softperms: 0, // softperms: 0,
hardperms: unpack(0), // hardperms: unpack(0),
res: 0, // res: 0,
bounds: EmbeddedExp { // bounds: EmbeddedExp {
top: 0, // implied top bits of 01 // top: 0, // implied top bits of 01
base: 0, // base: 0,
e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2)) // position the 1 of top in the addr_'th bit // e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2)) // position the 1 of top in the addr_'th bit
}, // },
addr: 0 // addr: 0
}; // };
function Bit#(e_) getExpCC(CHERICCCap#(addr_, bounds_, e_, t_) cap); // function Bit#(e_) getExpCC(CHERICCCap#(addr_, bounds_, e_, t_) cap);
case (cap.bounds) matches // case (cap.bounds) matches
tagged Exp0 .b: return 0; // tagged Exp0 .b: return 0;
tagged EmbeddedExp .b: return b.e; // tagged EmbeddedExp .b: return b.e;
tagged Sealed .b: return b.e; // tagged Sealed .b: return b.e;
endcase // endcase
endfunction // endfunction
function Bit#(3) getRepBoundCC(CHERICCCap#(addr_, bounds_, e_, t_) cap) // function Bit#(3) getRepBoundCC(CHERICCCap#(addr_, bounds_, e_, t_) cap)
provisos (Add#(3, a__, `div2(bounds_))) = // provisos (Add#(3, a__, `div2(bounds_))) =
truncateLSB(cap.bounds.Exp0.base) - 3'b001; // always 1/8th of representable space below object // truncateLSB(cap.bounds.Exp0.base) - 3'b001; // always 1/8th of representable space below object
function Int#(2) getRegionCorrectionCC(Bit#(3) a, Bit#(3) b, Bit#(3) rep) = // function Int#(2) getRegionCorrectionCC(Bit#(3) a, Bit#(3) b, Bit#(3) rep) =
((b < rep) == (a < rep)) ? 0 : (((b < rep) && (a >= rep)) ? 1 : -1); // ((b < rep) == (a < rep)) ? 0 : (((b < rep) && (a >= rep)) ? 1 : -1);
function Bit#(`div2(bounds_)) // function Bit#(`div2(bounds_))
getTopFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap); // getTopFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap);
Bit#(2) c_carry = 2'b00; // Bit#(2) c_carry = 2'b00;
Bit#(2) c_len = 2'b01; // Bit#(2) c_len = 2'b01;
Bit#(`sub2(`div2(bounds_))) partialTop = 0; // Bit#(`sub2(`div2(bounds_))) partialTop = 0;
case (cap.bounds) matches // case (cap.bounds) matches
tagged Exp0 .b: begin // tagged Exp0 .b: begin
if (zeroExtend(b.top) < b.base) c_carry = 2'b01; // if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
c_len = {1'b0, b.lenMSB}; // c_len = {1'b0, b.lenMSB};
partialTop = b.top; // partialTop = b.top;
end // end
tagged EmbeddedExp .b: begin // tagged EmbeddedExp .b: begin
if (zeroExtend(b.top) < b.base) c_carry = 2'b01; // if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
partialTop = {b.top, 0}; // partialTop = {b.top, 0};
end // end
tagged Sealed .b: begin // tagged Sealed .b: begin
if (zeroExtend(b.top) < b.base) c_carry = 2'b01; // if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
partialTop = {b.top, 0}; // partialTop = {b.top, 0};
end // end
endcase // endcase
return {truncateLSB(cap.bounds.Exp0.base) + c_carry + c_len, partialTop}; // return {truncateLSB(cap.bounds.Exp0.base) + c_carry + c_len, partialTop};
endfunction // endfunction
function Bit#(`div2(bounds_)) // function Bit#(`div2(bounds_))
getBaseFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap) = // getBaseFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap) =
case (cap.bounds) matches // case (cap.bounds) matches
tagged Exp0 .b: b.base; // tagged Exp0 .b: b.base;
tagged EmbeddedExp .b: {b.base, 0}; // tagged EmbeddedExp .b: {b.base, 0};
tagged Sealed .b: {b.base, 0}; // tagged Sealed .b: {b.base, 0};
endcase; // endcase;
// CHERICCCap CHERICap instance // // CHERICCCap CHERICap instance
//////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////
instance CHERICap#(CHERICCCap#(addr_, bounds_, e_, t_), t_, addr_) provisos ( // instance CHERICap#(CHERICCCap#(addr_, bounds_, e_, t_), t_, addr_) provisos (
Add#(3, a__, `div2(bounds_)), // 3 bits of bounds for 1/8th of rep space // Add#(3, a__, `div2(bounds_)), // 3 bits of bounds for 1/8th of rep space
Add#(3, b__, addr_), // same for addr // Add#(3, b__, addr_), // same for addr
Add#(c__, TAdd#(2, `div2(bounds_)), addr_), // for base correction // Add#(c__, TAdd#(2, `div2(bounds_)), addr_), // for base correction
Add#(d__, TAdd#(2, `div2(bounds_)), TAdd#(addr_, 1)), // for top 2 bits of Int#(2) correction // Add#(d__, TAdd#(2, `div2(bounds_)), TAdd#(addr_, 1)), // for top 2 bits of Int#(2) correction
Add#(e__, `div2(bounds_), addr_), // slice addr into smaller bounds field // Add#(e__, `div2(bounds_), addr_), // slice addr into smaller bounds field
Add#(f__, `div2(bounds_), TAdd#(addr_, 1)), // same for addr+1 // Add#(f__, `div2(bounds_), TAdd#(addr_, 1)), // same for addr+1
Add#(g__, e_, TLog#(TAdd#(1, addr_))) // can fit result of countZerosMSB in e_ // Add#(g__, e_, TLog#(TAdd#(1, addr_))) // can fit result of countZerosMSB in e_
); // );
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function isValidCap(cap) = cap.isCap; // function isValidCap(cap) = cap.isCap;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setValidCap(cap, v); // function setValidCap(cap, v);
cap.isCap = v; // cap.isCap = v;
return cap; // return cap;
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getHardPerms(cap) = cap.hardperms; // function getHardPerms(cap) = cap.hardperms;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setHardPerms(cap, hardperms); // function setHardPerms(cap, hardperms);
cap.hardperms = hardperms; // cap.hardperms = hardperms;
return cap; // return cap;
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getSoftPerms(cap) = zeroExtend(cap.softperms); // function getSoftPerms(cap) = zeroExtend(cap.softperms);
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setSoftPerms(cap, softperms); // function setSoftPerms(cap, softperms);
cap.softperms = truncate(softperms); // cap.softperms = truncate(softperms);
return cap; // return cap;
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getKind(cap) = case (cap.bounds) matches // function getKind(cap) = case (cap.bounds) matches
tagged Sealed ._: return SEALED_WITH_TYPE; // tagged Sealed ._: return SEALED_WITH_TYPE;
default: return UNSEALED; // default: return UNSEALED;
endcase; // endcase;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getType(cap) = case (cap.bounds) matches // function getType(cap) = case (cap.bounds) matches
tagged Sealed .b: return zeroExtend(b.otype); // tagged Sealed .b: return zeroExtend(b.otype);
default: return -1; // default: return -1;
endcase; // endcase;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setType(cap, otype); // function setType(cap, otype);
let new_cap = cap; // let new_cap = cap;
let isExact = True; // let isExact = True;
case (cap.bounds) matches // case (cap.bounds) matches
tagged Sealed .b: if (otype == -1) begin // tagged Sealed .b: if (otype == -1) begin
//Bit#(addr_) addrBits = cap.address >> b.e; // //Bit#(addr_) addrBits = cap.address >> b.e;
//let baseMid = addrBits[`sub1(TAdd#(`div2(t_), `div2(e))):`div2(e_)]; // //let baseMid = addrBits[`sub1(TAdd#(`div2(t_), `div2(e))):`div2(e_)];
//let baseLo = addrBits[`sub1(`div2(e_)):0]; // //let baseLo = addrBits[`sub1(`div2(e_)):0];
//let topMid = baseMid; // //let topMid = baseMid;
//let topLo = baseLo; // //let topLo = baseLo;
let baseHi = b.base; // let baseHi = b.base;
let topHi = b.top; // let topHi = b.top;
if (b.e == 0) new_cap.bounds = Exp0 { // if (b.e == 0) new_cap.bounds = Exp0 {
lenMSB: 1, // lenMSB: 1,
top: {topHi, 0}, // top: {topHi, 0},
base: {baseHi, 0} // base: {baseHi, 0}
}; // };
else new_cap.bounds = EmbeddedExp { // else new_cap.bounds = EmbeddedExp {
top: {topHi, 0}, // top: {topHi, 0},
base: {baseHi, 0}, // base: {baseHi, 0},
e: b.e // e: b.e
}; // };
end // end
default: if (otype != -1) begin // default: if (otype != -1) begin
Bit#(e_) new_e = case (cap.bounds) matches // Bit#(e_) new_e = case (cap.bounds) matches
tagged EmbeddedExp .b: b.e; // tagged EmbeddedExp .b: b.e;
default: 0; // default: 0;
endcase; // endcase;
new_cap.bounds = Sealed { // new_cap.bounds = Sealed {
top: truncateLSB(cap.bounds.Exp0.top), // top: truncateLSB(cap.bounds.Exp0.top),
base: truncateLSB(cap.bounds.Exp0.base), // base: truncateLSB(cap.bounds.Exp0.base),
otype: otype, // otype: otype,
e: new_e // e: new_e
}; // };
Bit#(`div2(t_)) zero = 0; // Bit#(`div2(t_)) zero = 0;
isExact = cap.bounds.Exp0.top[`i(t_)/2-1:0] == zero && // isExact = cap.bounds.Exp0.top[`i(t_)/2-1:0] == zero &&
cap.bounds.Exp0.base[`i(t_)/2-1:0] == zero; // cap.bounds.Exp0.base[`i(t_)/2-1:0] == zero;
end // end
endcase // endcase
return Exact{exact: isExact, value: new_cap}; // return Exact{exact: isExact, value: new_cap};
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getAddr(cap) = cap.addr; // function getAddr(cap) = cap.addr;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setAddr(cap) = error("setAddr unimplemented"); // function setAddr(cap) = error("setAddr unimplemented");
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getOffset(cap) = zeroExtend(getAddr(cap)) - getBase(cap); // function getOffset(cap) = zeroExtend(getAddr(cap)) - getBase(cap);
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setOffset(cap, offset); // function setOffset(cap, offset);
Bit#(`div2(bounds_)) e0m = ~(~0 << ((`i(t_)/2)+(`i(e_)/2))); // Bit#(`div2(bounds_)) e0m = ~(~0 << ((`i(t_)/2)+(`i(e_)/2)));
Bit#(TSub#(`div2(bounds_), `div2(e_))) eem = ~(~0 << (`i(t_)/2)); // Bit#(TSub#(`div2(bounds_), `div2(e_))) eem = ~(~0 << (`i(t_)/2));
// extract specific useful values // // extract specific useful values
Bit#(e_) e = getExpCC(cap); // Bit#(e_) e = getExpCC(cap);
Bit#(e_) almighty_e = fromInteger(`i(addr_)-((`i(bounds_)/2)-2)); // position the 1 of top in the addr_'th bit // Bit#(e_) almighty_e = fromInteger(`i(addr_)-((`i(bounds_)/2)-2)); // position the 1 of top in the addr_'th bit
Bit#(addr_) i = offset - getOffset(cap); // Bit#(addr_) i = offset - getOffset(cap);
Bit#(`div2(bounds_)) imid = truncate(i >> e); // Bit#(`div2(bounds_)) imid = truncate(i >> e);
Bit#(`div2(bounds_)) amid = truncate(cap.addr >> e); // Bit#(`div2(bounds_)) amid = truncate(cap.addr >> e);
Bit#(`div2(bounds_)) r = {getRepBoundCC(cap), 0}; // Bit#(`div2(bounds_)) r = {getRepBoundCC(cap), 0};
// perform inRange and inLimit tests // // perform inRange and inLimit tests
Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2)); // Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
Bool inRange = ((i & mask) == mask) || ((i & mask) == 0); // Bool inRange = ((i & mask) == mask) || ((i & mask) == 0);
Bool inLimits = (i >= 0) ? imid < (r - amid - 1) : // Bool inLimits = (i >= 0) ? imid < (r - amid - 1) :
imid >= (r - amid) && r != amid; // imid >= (r - amid) && r != amid;
Bool isExact = ((inRange && inLimits) || e >= almighty_e); // Bool isExact = ((inRange && inLimits) || e >= almighty_e);
// perform the offset update // // perform the offset update
let new_cap = cap; // let new_cap = cap;
new_cap.addr = truncate(getBase(cap) + offset); // new_cap.addr = truncate(getBase(cap) + offset);
return Exact{exact: isExact, value: new_cap}; // return Exact{exact: isExact, value: new_cap};
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getBase(cap); // function getBase(cap);
let baseCC = getBaseFieldCC(cap); // let baseCC = getBaseFieldCC(cap);
let e = getExpCC(cap); // let e = getExpCC(cap);
let correction = getRegionCorrectionCC(truncateLSB(cap.addr), // let correction = getRegionCorrectionCC(truncateLSB(cap.addr),
truncateLSB(baseCC), // truncateLSB(baseCC),
getRepBoundCC(cap)); // getRepBoundCC(cap));
Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2)); // Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
Bit#(addr_) acc = cap.addr & mask; // Bit#(addr_) acc = cap.addr & mask;
return acc + (signExtend({pack(correction), baseCC}) << e); // return acc + (signExtend({pack(correction), baseCC}) << e);
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getTop(cap); // function getTop(cap);
let topCC = getTopFieldCC(cap); // let topCC = getTopFieldCC(cap);
let e = getExpCC(cap); // let e = getExpCC(cap);
let correction = getRegionCorrectionCC(truncateLSB(cap.addr), // let correction = getRegionCorrectionCC(truncateLSB(cap.addr),
truncateLSB(topCC), // truncateLSB(topCC),
getRepBoundCC(cap)); // getRepBoundCC(cap));
Bit#(TAdd#(addr_, 1)) mask = ~0 << (e + fromInteger(`i(bounds_)/2)); // Bit#(TAdd#(addr_, 1)) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
Bit#(TAdd#(addr_, 1)) acc = zeroExtend(cap.addr) & mask; // Bit#(TAdd#(addr_, 1)) acc = zeroExtend(cap.addr) & mask;
return acc + (signExtend({pack(correction), topCC}) << e); // return acc + (signExtend({pack(correction), topCC}) << e);
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function getLength(cap) = getTop(cap) - zeroExtend(getBase(cap)); // function getLength(cap) = getTop(cap) - zeroExtend(getBase(cap));
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function setBounds(cap, length); // function setBounds(cap, length);
let new_cap = cap; // let new_cap = cap;
let isExact = True; // let isExact = True;
// deriving new exponent // // deriving new exponent
Bit#(TLog#(TAdd#(1, addr_))) e = // Bit#(TLog#(TAdd#(1, addr_))) e =
pack(fromInteger(`i(addr_)) // pack(fromInteger(`i(addr_))
- countZerosMSB(length >> ((`i(bounds_)/2)-1))); // - countZerosMSB(length >> ((`i(bounds_)/2)-1)));
// deriving the new base // // deriving the new base
Bit#(`div2(bounds_)) newBase = truncate(cap.addr >> e); // Bit#(`div2(bounds_)) newBase = truncate(cap.addr >> e);
// deriving the new top // // deriving the new top
Bit#(TAdd#(addr_, 1)) fullTop = zeroExtend(cap.addr) + zeroExtend(length); // Bit#(TAdd#(addr_, 1)) fullTop = zeroExtend(cap.addr) + zeroExtend(length);
Bit#(`div2(bounds_)) newTop = truncate(fullTop >> e); // Bit#(`div2(bounds_)) newTop = truncate(fullTop >> e);
// fold the derived values back in the new cap // // fold the derived values back in the new cap
if (e == 0) begin // if (e == 0) begin
new_cap.bounds = Exp0 { // new_cap.bounds = Exp0 {
lenMSB: length[(`i(bounds_)/2)-2], // lenMSB: length[(`i(bounds_)/2)-2],
top: truncate(newTop), // top: truncate(newTop),
base: newBase // base: newBase
}; // };
end else begin // end else begin
// slice the top and base values appropriately // // slice the top and base values appropriately
Bit#(TSub#(`sub2(`div2(bounds_)), `div2(e_))) upperTop = truncateLSB(newTop); // Bit#(TSub#(`sub2(`div2(bounds_)), `div2(e_))) upperTop = truncateLSB(newTop);
Bit#(TSub#(`div2(bounds_), `div2(e_))) upperBase = truncateLSB(newBase); // Bit#(TSub#(`div2(bounds_), `div2(e_))) upperBase = truncateLSB(newBase);
// take care of loss of significant bits in the bits stolen/dropped from fullTop // // take care of loss of significant bits in the bits stolen/dropped from fullTop
Bit#(TAdd#(addr_, 1)) mask = ~(~0 << (e + fromInteger(`i(e_)/2))); // Bit#(TAdd#(addr_, 1)) mask = ~(~0 << (e + fromInteger(`i(e_)/2)));
if ((fullTop & mask) != 0) upperTop = upperTop + 1; // if ((fullTop & mask) != 0) upperTop = upperTop + 1;
new_cap.bounds = EmbeddedExp { // new_cap.bounds = EmbeddedExp {
top: upperTop, // top: upperTop,
base: upperBase, // base: upperBase,
e: truncate(e) // e: truncate(e)
}; // };
// check for exact or not // // check for exact or not
Bit#(addr_) exactMask = ~(~0 << (e - fromInteger(`i(bounds_)/2 - `i(e_)/2 - 1))); // Bit#(addr_) exactMask = ~(~0 << (e - fromInteger(`i(bounds_)/2 - `i(e_)/2 - 1)));
if ((cap.addr & exactMask) != 0) isExact = False; // if ((cap.addr & exactMask) != 0) isExact = False;
if ((length & exactMask) != 0) isExact = False; // if ((length & exactMask) != 0) isExact = False;
end // end
return Exact{exact: isExact, value: new_cap}; // return Exact{exact: isExact, value: new_cap};
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function nullWithAddr(x); // function nullWithAddr(x);
let cap = nullCap; // let cap = nullCap;
cap.addr = x; // cap.addr = x;
return cap; // return cap;
endfunction // endfunction
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function almightyCap = almightyCC; // function almightyCap = almightyCC;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
function nullCap = nullCC; // function nullCap = nullCC;
////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
endinstance // endinstance
`undef div2 // `undef div2
`undef sub2 // `undef sub2
`undef i // `undef i
endpackage // endpackage

View File

@@ -37,13 +37,11 @@ export CapMem;
export CapReg; export CapReg;
export CapPipe; export CapPipe;
export encodeDelta;
export addDelta;
export decodeDelta;
export CapFat; export CapFat;
export MW; export MW;
export OTypeW; export OTypeW;
export Delta;
export setDeltaValue;
export FlagsW; export FlagsW;
export Perms; export Perms;
export ResW; export ResW;
@@ -63,8 +61,8 @@ export Exp;
export MetaInfo; export MetaInfo;
export SetBoundsReturn; export SetBoundsReturn;
export CapTrim; export CapTrim;
export trimCap; // export trimCap;
export untrimCap; // export untrimCap;
export CapAddr; export CapAddr;
export CapAddrPlus1; export CapAddrPlus1;
@@ -88,20 +86,20 @@ typedef 0 UPermW;
typedef 8 MW; typedef 8 MW;
typedef 6 ExpW; typedef 6 ExpW;
typedef 4 OTypeW; typedef 4 OTypeW;
// typedef 24 Delta; typedef 24 Delta;
typedef `FLAGSW FlagsW; typedef `FLAGSW FlagsW;
typedef 32 CapAddrW; typedef 32 CapAddrW;
typedef 64 CapW; typedef 88 CapW;
`else // CAP128 is default `else // CAP128 is default
typedef 4 UPermW; typedef 4 UPermW;
typedef 14 MW; typedef 14 MW;
typedef 6 ExpW; typedef 6 ExpW;
typedef 18 OTypeW; typedef 18 OTypeW;
// typedef 44 Delta; typedef 52 Delta;
typedef `FLAGSW FlagsW; typedef `FLAGSW FlagsW;
typedef 64 CapAddrW; typedef 64 CapAddrW;
// The capability width changes // The capability width changes
typedef 128 CapW; typedef 180 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
@@ -146,8 +144,9 @@ typedef SizeOf#(Perms) PermsW;
// The reserved bits // The reserved bits
typedef TSub#(CapW, TAdd#( CapAddrW typedef TSub#(CapW, TAdd#( CapAddrW
, TAdd#( OTypeW , TAdd#( OTypeW
, TAdd#( Delta
, TAdd#( CBoundsW , TAdd#( CBoundsW
, TAdd#(PermsW, FlagsW))))) ResW; , 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;
@@ -155,14 +154,15 @@ typedef struct {
Bit#(ResW) reserved; Bit#(ResW) reserved;
Bit#(FlagsW) flags; Bit#(FlagsW) flags;
Bit#(OTypeW) otype; Bit#(OTypeW) otype;
// Bit#(Delta) delta; Bit#(Delta) delta;
CBounds bounds; CBounds bounds;
CapAddr 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;
// not including the tag bit // not including the tag bit
typedef Bit#(CapW) CapBits; // Hard-coded
typedef Bit#(128) CapBits;
/* TODO /* TODO
staticAssert(valueOf(SizeOf#(CapabilityInMemory))==valueOf(SizeOf#(Capability)), staticAssert(valueOf(SizeOf#(CapabilityInMemory))==valueOf(SizeOf#(Capability)),
"The CapabilityInMemory type has incorrect size of " + integerToString(valueOf(SizeOf#(CapabilityInMemory))) + " (CapW = " + integerToString(valueOf(CapW)) + ")" "The CapabilityInMemory type has incorrect size of " + integerToString(valueOf(SizeOf#(CapabilityInMemory))) + " (CapW = " + integerToString(valueOf(CapW)) + ")"
@@ -191,7 +191,7 @@ typedef struct {
Bit#(FlagsW) flags; Bit#(FlagsW) flags;
Bit#(ResW) reserved; Bit#(ResW) reserved;
Bit#(OTypeW) otype; Bit#(OTypeW) otype;
// Bit#(Delta) delta; Bit#(Delta) delta;
Format format; Format format;
Bounds bounds; Bounds bounds;
} CapFat deriving (Bits); } CapFat deriving (Bits);
@@ -238,7 +238,7 @@ function CapFat unpackCap(Capability thin);
fat.flags = memCap.flags; fat.flags = memCap.flags;
fat.reserved = memCap.reserved; fat.reserved = memCap.reserved;
fat.otype = memCap.otype; fat.otype = memCap.otype;
// fat.delta = memCap.delta; fat.delta = memCap.delta;
match {.f, .b} = decBounds(memCap.bounds); match {.f, .b} = decBounds(memCap.bounds);
fat.format = f; fat.format = f;
fat.bounds = b; fat.bounds = b;
@@ -262,6 +262,7 @@ function Capability packCap(CapFat fat);
, flags: fat.flags , flags: fat.flags
, reserved: fat.reserved , reserved: fat.reserved
, otype: fat.otype , otype: fat.otype
, delta: fat.delta
, bounds: encBounds(fat.format,fat.bounds) , bounds: encBounds(fat.format,fat.bounds)
, address: fat.address }; , address: fat.address };
return pack(thin); return pack(thin);
@@ -887,6 +888,7 @@ instance DefaultValue #(CapFat);
, flags : 0 , flags : 0
, reserved : 0 , reserved : 0
, otype : otype_unsealed , otype : otype_unsealed
, delta : 0
, format : EmbeddedExp , format : EmbeddedExp
, bounds : defaultValue , bounds : defaultValue
, address : 0 , address : 0
@@ -899,6 +901,7 @@ CapFat null_cap = CapFat {
, flags : 0 , flags : 0
, reserved : 0 , reserved : 0
, otype : otype_unsealed , otype : otype_unsealed
, delta : 0
, format : EmbeddedExp , format : EmbeddedExp
, bounds : defaultValue , bounds : defaultValue
, address : 0 , address : 0
@@ -1055,7 +1058,7 @@ typedef struct {
// Note: commented out methods have a provided default implementation in the // Note: commented out methods have a provided default implementation in the
// CHERICap typeclass definition // CHERICap typeclass definition
instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3)); instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3), Delta);
// capability validity // capability validity
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -1123,7 +1126,7 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
, pack (cap.reserved) , pack (cap.reserved)
, pack (cap.flags) , pack (cap.flags)
, pack (cap.otype) , pack (cap.otype)
// , pack (cap.delta) , pack (cap.delta)
, pack (cap.bounds) }; , pack (cap.bounds) };
endfunction endfunction
function getAddr (capMem); function getAddr (capMem);
@@ -1167,6 +1170,10 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
function setBoundsCombined = function setBoundsCombined =
error ("setBoundsCombined not implemented for CapMem"); error ("setBoundsCombined not implemented for CapMem");
// Create function to set delta value
function setDeltaValue (CapPipe cap, Bit#(Delta) delta) = error ("setDeltaValue not implemented for CapMem");
//function setBounds = error ("setBounds not implemented for CapMem"); //function setBounds = error ("setBounds not implemented for CapMem");
//function roundLength = error ("roundLength not implemented for CapMem"); //function roundLength = error ("roundLength not implemented for CapMem");
//function alignmentMask = error ("alignmentMask not implemented for CapMem"); //function alignmentMask = error ("alignmentMask not implemented for CapMem");
@@ -1185,10 +1192,6 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
function isDerivable = error ("isDerivable not implemented for CapMem"); function isDerivable = error ("isDerivable not implemented for CapMem");
function encodeDelta (cap, delta) = error ("encode delta not implemented");
function addDelta (cap, delta) = error ("addDelta not implemented");
function decodeDelta (cap) = error ("decode delta not implemented");
endinstance endinstance
instance FShow #(CapPipe); instance FShow #(CapPipe);
@@ -1218,7 +1221,7 @@ endinstance
// Note: commented out methods have a provided default implementation in the // Note: commented out methods have a provided default implementation in the
// CHERICap typeclass definition // CHERICap typeclass definition
instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3)); instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3), Delta);
// capability validity // capability validity
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -1343,9 +1346,8 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
function setBoundsCombined (cap, length) = error ("setBoundsCombined not implemented for CapReg"); function setBoundsCombined (cap, length) = error ("setBoundsCombined not implemented for CapReg");
function encodeDelta (cap, delta) = error ("encode delta not implemented"); // Create function to set delta value
function addDelta (cap, delta) = error ("addDelta not implemented"); function setDeltaValue (CapPipe cap, Bit#(Delta) delta) = error ("setDeltaValue not implemented for CapReg");
function decodeDelta (cap) = error ("decode delta not implemented");
//function setBounds = error ("setBounds not implemented for CapReg"); //function setBounds = error ("setBounds not implemented for CapReg");
//function roundLength = error ("roundLength not implemented for CapReg"); //function roundLength = error ("roundLength not implemented for CapReg");
@@ -1371,7 +1373,7 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
endinstance endinstance
instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3)); instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3), Delta);
//Functions supported by CapReg are just passed through //Functions supported by CapReg are just passed through
@@ -1419,36 +1421,21 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
, mask: result.mask }; , mask: result.mask };
endfunction endfunction
// TODO: Similar to set bounds but sets the delta value between the 38th and 64th bit // Create function to set delta value
// function setDeltaValue (cap, length); function setDeltaValue (CapPipe cap, Bit#(Delta) delta);
// endfunction // let result = setDelta(cap.capFat, delta);
cap.capFat.delta = delta;
function encodeDelta(cap, delta);
// Make a test case of adding 3
Bit#(25) d = truncate(delta);
// d = 15;
Bit#(39) va_bits = cap.capFat.address[38:0];
cap.capFat.address = {d, va_bits};
return cap; return cap;
endfunction endfunction
function addDelta(cap, delta);
Bit#(25) d = truncate(delta);
cap.capFat.address = cap.capFat.address + zeroExtend(delta);
return cap;
endfunction
// Extract the delta stored in bits 63:39 of the address
function decodeDelta(cap);
return cap.capFat.address[63:39];
endfunction
function nullWithAddr (addr); function nullWithAddr (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
// A hack to fix compile time check
function fromMem (capBits); function fromMem (capBits);
CapReg res = fromMem(capBits); CapReg res = fromMem(capBits);
return CapPipe { capFat: res, tempFields: getTempFields(res) }; return CapPipe { capFat: res, tempFields: getTempFields(res) };
@@ -1464,10 +1451,18 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
return CapPipe { capFat: res, tempFields: getTempFields(res) }; return CapPipe { capFat: res, tempFields: getTempFields(res) };
endfunction endfunction
typedef struct {
Bit#(39) trueAddr;
Bit#(25) delta;
} MyAddr deriving (Bits);
//Functions that require TempFields //Functions that require TempFields
function setAddr (cap, address); function setAddr (cap, address);
let result = setAddress(cap.capFat, address, cap.tempFields); // todo
MyAddr myAddr = unpack(pack(addr));
myAddr.delta = 42;
let result = setAddress(cap.capFat, pack(myAddr), 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 };
@@ -1570,62 +1565,48 @@ typedef 48 VA_Width;
typedef struct { typedef struct {
Perms perms; Perms perms;
Bit#(FlagsW) flags; Bit#(FlagsW) flags;
// Bit#(Delta) delta; Bit#(Delta) delta;
CBounds bounds; CBounds bounds;
Bit#(VA_Width) address; Bit#(VA_Width) address;
Bool validAddress; Bool validAddress;
} CapTrim deriving(Bits, Eq, FShow); } CapTrim deriving(Bits, Eq, FShow);
function CapTrim trimCap(CapMem cm); // function CapTrim trimCap(CapMem cm);
CapabilityInMemory cap = unpack(cm); // CapabilityInMemory cap = unpack(cm);
Bit#(TSub#(CapAddrW,VA_Width)) addr_upper = truncateLSB(cap.address); // Bit#(TSub#(CapAddrW,VA_Width)) addr_upper = truncateLSB(cap.address);
return CapTrim{perms: cap.perms, // return CapTrim{perms: cap.perms,
flags: cap.flags, // flags: cap.flags,
bounds: cap.bounds, // delta: cap.delta,
address: truncate(cap.address), // bounds: cap.bounds,
validAddress: (addr_upper==signExtend(cap.address[valueOf(VA_Width)-1])) // address: truncate(cap.address),
}; // validAddress: (addr_upper==signExtend(cap.address[valueOf(VA_Width)-1]))
// };
// endfunction
// function CapMem untrimCap(CapTrim ct);
// // Encode an invalid address as the bit above the last valid bit being different.
// Bit#(1) addressMsb = ct.address[valueOf(VA_Width)-1];
// if (!ct.validAddress) addressMsb = ^addressMsb;
// return pack(CapabilityInMemory{
// isCapability: True,
// perms: ct.perms,
// reserved: 0,
// flags: ct.flags,
// otype: otype_unsealed,
// delta: ct.delta,
// bounds: ct.bounds,
// address: signExtend({addressMsb,ct.address})
// });
// endfunction
// Standalone fromMem wrapper for CapPipe
function CapPipe fromMemTest(Tuple2#(Bool, Bit#(CapW)) capBits);
// capBits.fst = Bool tag
// capBits.snd = concatenated bits (e.g., {getAddr(b), getAddr(a)})
// Reconstruct the underlying CapReg (or CapFat)
CapReg res = fromMem(capBits);
// Wrap into CapPipe with tempFields
return CapPipe { capFat: res, tempFields: getTempFields(res) };
endfunction endfunction
function CapMem untrimCap(CapTrim ct);
// Encode an invalid address as the bit above the last valid bit being different.
Bit#(1) addressMsb = ct.address[valueOf(VA_Width)-1];
if (!ct.validAddress) addressMsb = ^addressMsb;
return pack(CapabilityInMemory{
isCapability: True,
perms: ct.perms,
reserved: 0,
flags: ct.flags,
otype: otype_unsealed,
bounds: ct.bounds,
address: signExtend({addressMsb,ct.address})
});
endfunction
// We do not implement the functions as interfaces
// because all them will have the same implementation/
// This negates the purpose of having type classes.
// Create function to set delta value
// function setDeltaValue (CapPipe cap, Bit#(Delta) delta);
// // let result = setDelta(cap.capFat, delta);
// cap.capFat.delta = delta;
// return cap;
// endfunction
// typedef struct {
// CapFat capFat;
// TempFields tempFields;
// } CapPipe deriving (Bits);
// typedef struct {
// Bool isCapability;
// Bit#(CapAddrW) address;
// Bit#(MW) addrBits;
// Perms perms;
// Bit#(FlagsW) flags;
// Bit#(ResW) reserved;
// Bit#(OTypeW) otype;
// // Bit#(Delta) delta;
// Format format;
// Bounds bounds;
// } CapFat deriving (Bits);
endpackage endpackage

View File

@@ -119,7 +119,7 @@ endfunction
// XXX TODO augment with all architectural bounds/ repbounds ? // XXX TODO augment with all architectural bounds/ repbounds ?
function Fmt showCHERICap (capT cap) function Fmt showCHERICap (capT cap)
provisos (CHERICap #(capT , otypeW, flgW, addrW, inMemW, maskableW)); provisos (CHERICap #(capT , otypeW, flgW, addrW, inMemW, maskableW, delta));
return $format( "Valid: 0x%0x", isValidCap(cap)) + return $format( "Valid: 0x%0x", isValidCap(cap)) +
$format(" Perms: 0x%0x", getPerms(cap)) + $format(" Perms: 0x%0x", getPerms(cap)) +
$format(" Kind: ", fshow(getKind(cap))) + $format(" Kind: ", fshow(getKind(cap))) +
@@ -153,8 +153,9 @@ typeclass CHERICap #( type capT // type of the CHERICap capability
, numeric type addrW // width of the address , numeric type addrW // width of the address
, numeric type inMemW // width of the capability in mem , numeric type inMemW // width of the capability in mem
, numeric type maskableW // width of maskable bits , numeric type maskableW // width of maskable bits
, numeric type delta // size of delta (tlb bypass)
) )
dependencies (capT determines (otypeW, flgW, addrW, inMemW, maskableW)); dependencies (capT determines (otypeW, flgW, addrW, inMemW, maskableW, delta));
// capability validity // capability validity
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -172,11 +173,6 @@ typeclass CHERICap #( type capT // type of the CHERICap capability
// Set the flags field // Set the flags field
function capT setFlags (capT cap, Bit #(flgW) flags); function capT setFlags (capT cap, Bit #(flgW) flags);
function capT encodeDelta(capT cap, Bit #(64) delta);
function capT addDelta(capT cap, Bit #(25) delta);
function Bit #(25) decodeDelta(capT cap);
// capability permissions // capability permissions
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -325,8 +321,8 @@ typeclass CHERICap #( type capT // type of the CHERICap capability
// the null capability (requires a dummy proxy) // the null capability (requires a dummy proxy)
function capT nullCapFromDummy (capT dummy); function capT nullCapFromDummy (capT dummy);
// define set delta function (Disabled when we will use the virtual addresses) // define set delta function
// function capT setDeltaValue (capT cap, Bit #(delta) length); function capT setDeltaValue (capT cap, Bit #(delta) length);
// Assert that the encoding is valid // Assert that the encoding is valid
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@@ -1,23 +1,23 @@
module assert_prop_unique( // module assert_prop_unique(
input wire [63 : 0] prop_base, // input wire [63 : 0] prop_base,
input wire [63 : 0] prop_len, // input wire [63 : 0] prop_len,
input wire [63 : 0] prop_newBase, // input wire [63 : 0] prop_newBase,
input wire [63 : 0] prop_newLen // input wire [63 : 0] prop_newLen
); // );
wire prop_ok; // wire prop_ok;
module_prop_unique module_prop_unique_inst ( // module_prop_unique module_prop_unique_inst (
.prop_unique_base(prop_base), // .prop_unique_base(prop_base),
.prop_unique_len(prop_len), // .prop_unique_len(prop_len),
.prop_unique_newBase(prop_newBase), // .prop_unique_newBase(prop_newBase),
.prop_unique_newLen(prop_newLen), // .prop_unique_newLen(prop_newLen),
.prop_unique(prop_ok) // .prop_unique(prop_ok)
); // );
always @(*) begin // always @(*) begin
assert(prop_ok); // assert(prop_ok);
end // end
endmodule // endmodule
module assert_prop_exact( module assert_prop_exact(
input wire [63 : 0] prop_base, input wire [63 : 0] prop_base,
@@ -180,3 +180,4 @@ module assert_prop_setBounds(
always @(*) begin always @(*) begin
assert(prop_ok); assert(prop_ok);
end end
endmodule