Reference 1 The type of Data#, CapTags, CapsPerFlit, and BytesPerFlit. See CheriBusBytes in MemTypes Data It contains both data and capability tag. TODO: What is the data_width? and the relationship between number of tag bits and this data_width, and the CHERI bits? Data# definition: // Data type typedef struct { `ifdef USECAP // is this frame has capabilities CapTags cap; `endif // actual data Bit#(width) data; } Data#(numeric type width) deriving (Bits, Eq, FShow); CapTags definition
Reference 1
Important types:
Data#(data_width) The struct that contains both tag and tagged data. see Data MemoryRequest#(…) MemoryResponse#(…) CheriMemRequest CheriMemResponse
type of bytesPerLine
is parameter, and is set to be =CheriBusBytes
. That is, one line contains one bus widths data.
Used to define PhyLineNumber, PhyByteOffset, PhyBitOffset, PhyByteAddress, etc:
type of PhyLineNumber
, is the index type for lines at granularity of one line. i.e an address of line.
type of PhyByteOffset
, is the index type inside one line, at granularity of one byte.
type of PhyBitOffset
, is the index type inside one line, at granularity of one bit.
type of PhyByteAddress
, is an byte address representation format with Line address, and byte offset inside the line.
type of PhyBitAddress
, is an bit address representation format with byte address, and the bit offset inside the byte.
typedef Bit#(TSub#(width,TLog#(bytePerLine))) PhyLineNumber#(numeric type width, numeric type bytePerLine);
typedef Bit#(TLog#(bytePerLine)) PhyByteOffset#(numeric type bytePerLine);
typedef Bit#(TAdd#(TLog#(bytePerLine),3)) PhyBitOffset#(numeric type bytePerLine);
// physical byte address type
// CR: width is the TOTAL width of the type; this type is a clever way to allow byte
// slicing from Alexendre.
typedef struct {
PhyLineNumber#(width, bytePerLine) lineNumber;
PhyByteOffset#(bytePerLine) byteOffset;
} PhyByteAddress#(numeric type width, numeric type bytePerLine) deriving (Bits, Eq, Bounded, FShow);
typedef struct {
PhyByteAddress#(width, bytePerLine) byteAddr;
Bit#(3) bitOffset;
} PhyBitAddress#(numeric type width, numeric type bytePerLine) deriving (Bits, Eq, Bounded, FShow);
type of CheriBusBytes
is the total bytes of data on the bus between CPU and memory. Default to be 32 bytes data on the bus, can be set to 16 bytes using MEM128
, 8 bytes using MEM64
.
CheriBusBytes | Bus bit | cheriBusBytes (enum_v) |
---|---|---|
8 bytes | 64 bits | BYTE_8 (3) |
16 bytes | 128 bits | BYTE_16 (4) |
32 bytes | 256 bits | BYTE_32 (5) |
CAP Mode | CAP width | capBytesPerFlit |
---|---|---|
CAP64 | 8 bytes | BYTE_8 (3) |
CAP128 | 16 bytes | BYTE_16 (4) |
CAP | 32 bytes | BYTE_32 (5) |
(type of capBytesPerFlit
seems to be capability version of bytesPerFlit
. Only used once in MIPS.bsv: L2010. A confusing name. According to the test scripts, CAP128 is always used with MEM128, thus by design, cheriBusBytes = capBytesPerFlit, should always be the equal.)
Note: the enum value seems should be used as its semantic meaning, but just a type matching number.
used to define serveral CHERI related types:
type of CapsPerFlit
is defined as the number of capabilities we can have on the bus; thus here the Flit means a bus width data.
type of CapTags
is defined as a vector of bool values that represents the tag values for this flit of data (bus-wide data).
type of CapNumber
is defined as an physical index type aligned at capability width memory. Bit width is BitsOf(MemBus)-BitsOf(Cap)
type of CheriCapAddress
is defined as a full physical byte address with CapNumber
as index of an aligned capability, and offset
as the byte index inside the capability. This type can be packed/unpacked to/from an physical address. For example, see Memory.bsv:dataMemory.getResponse
type of CheriDataWidth
is defined as the number of bits for a capability: 256 by default, or 128⁄64.
type of CheriLineAddrWidth
type of CheriPhyLineNumber
type of CheriPhyAddr
is a byte address composed of Line address and offset in a line via PhyByteAddress
, where total width is 40 bits, and bytes per line is equal to CheriBusBytes
. ==> One line is one bus width.
type of CheriPhyBitAddr
type of CheriPhyByteOffset
type of CheriPhyBitOffset
is the number index of a single bit in a [0, CheriBusBytes * 8]
bits range.
type of CheriPeriphAddr
Related Bluespec code:
// file: cherilibs/trunk/MemTypes.bsv
// physical address for cheri
`ifdef MEM128
typedef 16 CheriBusBytes;
BytesPerFlit cheriBusBytes = BYTE_16;
`elsif MEM64
typedef 8 CheriBusBytes;
BytesPerFlit cheriBusBytes = BYTE_8;
`else
typedef 32 CheriBusBytes;
BytesPerFlit cheriBusBytes = BYTE_32;
`endif
`ifdef CAP
BytesPerFlit capBytesPerFlit = BYTE_32;
`elsif CAP128
BytesPerFlit capBytesPerFlit = BYTE_16;
`elsif CAP64
BytesPerFlit capBytesPerFlit = BYTE_8;
`endif
`ifdef USECAP
typedef TDiv#(CheriBusBytes,CapBytes) CapsPerFlit;
typedef Vector#(CapsPerFlit,Bool) CapTags;
typedef Bit#(TSub#(40,TLog#(CapBytes))) CapNumber;
typedef struct {
CapNumber capNumber;
Bit#(TLog#(CapBytes)) offset;
} CheriCapAddress deriving (Bits, Eq, Bounded, FShow);
`endif
typedef TMul#(CheriBusBytes,8) CheriDataWidth;
typedef TSub#(40,TLog#(CheriBusBytes)) CheriLineAddrWidth;
typedef PhyLineNumber#(40,CheriBusBytes) CheriPhyLineNumber;
typedef PhyByteAddress#(40,CheriBusBytes) CheriPhyAddr;
typedef PhyBitAddress#(40,CheriBusBytes) CheriPhyBitAddr;
typedef PhyByteOffset#(CheriBusBytes) CheriPhyByteOffset;
typedef PhyBitOffset#(CheriBusBytes) CheriPhyBitOffset;
typedef PhyByteAddress#(40,8) CheriPeriphAddr;
type fo PhyByteAddress
, contains a line number, and its byte offset into the line.
// physical byte address type
// CR: width is the TOTAL width of the type; this type is a clever way to allow byte
// slicing from Alexendre.
typedef struct {
PhyLineNumber#(width, bytePerLine) lineNumber;
PhyByteOffset#(bytePerLine) byteOffset;
} PhyByteAddress#(numeric type width, numeric type bytePerLine) deriving (Bits, Eq, Bounded, FShow);
Read or write request format.
For write, contains the data to be written. The data contains one-bit cap tag, and actual data with 256-bit/128/64 width
// cherilibs/trunk/MemTypes.bsv
/////////////////////////////////
// cheri memory request format //
/////////////////////////////////
typedef struct {
// byte address
addr_t addr;
// master ID to identify the requester
// XXX THIS FIELD HAS TO BE MIRRORED BY THE SLAVE XXX
masterid_t masterID;
// transaction ID field used to identify a unique transaction amongst
// several outstanding transactions
// XXX THIS FIELD HAS TO BE MIRRORED BY THE SLAVE XXX
transactionid_t transactionID;
// operation to be performed by the request
union tagged {
// read operation
struct {
// uncached / cached access
Bool uncached;
// LL / standard load
Bool linked;
// number of flits to be returned
UInt#(TLog#(MaxNoOfFlits)) noOfFlits;
// number of bytes per flit
BytesPerFlit bytesPerFlit;
} Read;
struct {
// True for the last flit of the burst
Bool last;
// uncached / cached access
Bool uncached;
// SC / standard write
Bool conditional;
// byte enable vector
Vector#(TDiv#(data_width,8), Bool) byteEnable;
// A bit mask for each byte, enabling bit updates.
Bit#(8) bitEnable;
// line data,
// at the bottom so we can "truncate(pack())" this field
// to get the data without "matches".
Data#(data_width) data;
} Write;
// for a cache operation
CacheOperation CacheOp;
} operation;
} MemoryRequest#(type addr_t, type masterid_t, type transactionid_t, numeric type data_width) deriving (Bits);
Typedef for CheriMemRequest
: a 40-bit physical address, 32-bytes line, 32*8=256 DataWidth or 128⁄64 data width:
typedef MemoryRequest#(CheriPhyAddr,CheriMasterID,CheriTransactionID,CheriDataWidth) CheriMemRequest;
One Memory Request contains
So one memory request contains following bits to send to memory as a request:
The parameter definitions:
// physical address for cheri
`ifdef MEM128
typedef 16 CheriBusBytes;
BytesPerFlit cheriBusBytes = BYTE_16;
`elsif MEM64
typedef 8 CheriBusBytes;
BytesPerFlit cheriBusBytes = BYTE_8;
`else
typedef 32 CheriBusBytes; // CHERI bus has 32 bytes??? A 512-bit Bus?
BytesPerFlit cheriBusBytes = BYTE_32;
`endif
typedef PhyByteAddress#(40,CheriBusBytes) CheriPhyAddr;
typedef Bit#(4) CheriMasterID;
typedef Bit#(4) CheriTransactionID;
typedef TMul#(CheriBusBytes,8) CheriDataWidth; // CheriDataWidth = CheriBusBytes * 8.
PhyByteAddress
: a struct with a line number and byteoffset. The type is 40 bits in width, and each line has 32 bytes (cheri128). What is type here? What is the line here? What is the relation with a physical address?
// physical byte address type
// CR: width is the TOTAL width of the type; this type is a clever way to allow byte
// slicing from Alexendre.
typedef struct {
PhyLineNumber#(width, bytePerLine) lineNumber;
PhyByteOffset#(bytePerLine) byteOffset;
} PhyByteAddress#(numeric type width, numeric type bytePerLine) deriving (Bits, Eq, Bounded, FShow);
Read or Write response struct
If Read, will have Data# back contains, cap tag and actual data with width of 256/128/64.
//////////////////////////////////
// cheri memory response format //
//////////////////////////////////
typedef struct {
// master ID to identify the requester
// XXX THIS FIELD HAS TO BE MIRRORED BY THE SLAVE XXX
masterid_t masterID;
// transaction ID field used to identify a unique transaction amongst
// several outstanding transactions
// XXX THIS FIELD HAS TO BE MIRRORED BY THE SLAVE XXX
transactionid_t transactionID;
// error being returned
Error error;
// content of the response
union tagged {
struct {
// True for the last flit of the burst
Bool last;
} Read;
// no information for write responses
void Write;
// True for a success
Bool SC;
} operation;
// line data for Read (could be in tagged Union, but avoid muxes by putting it here)
Data#(data_width) data;
} MemoryResponse#(type masterid_t, type transactionid_t, numeric type data_width) deriving (Bits);
Customized parameters:
CheriDataWidth = CheriBusBytes * 8
typedef MemoryResponse#(CheriMasterID,CheriTransactionID,CheriDataWidth) CheriMemResponse;
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?