MemTypes.bsv


  • Data
  • 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

bytesPerLine

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);

CheriBusBytes

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 12864.

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;

PhyByteAddress

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);

MemoryRequest

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);

CheriMemRequest

Typedef for CheriMemRequest: a 40-bit physical address, 32-bytes line, 32*8=256 DataWidth or 12864 data width:

typedef MemoryRequest#(CheriPhyAddr,CheriMasterID,CheriTransactionID,CheriDataWidth) CheriMemRequest;

One Memory Request contains

  • 4-bit masterID
  • 4-bit transactionID
  • 2-bit error (3 enum values)
  • 1-bit ?? for tagged union {read{bool last}, bool SC, void write}
  • 1/1/2-bit = (data-bus width / capwidth) for CapTags
  • 128256-bit data-bus width

So one memory request contains following bits to send to memory as a request:

  • 4+4+2+1+1+128 = 12-bit control + 128-bit data = 140 bits; for 128-bit cap 128-bit data bus;
  • 4+4+2+1+1+256 = 12 bit control + 256-bit data = 268 bits, for 256-bit cap 256-bit data bus

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);

MemoryResponse

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);

CheriMemResponse

Customized parameters:

  • CheriMasterID
  • CheriTransactionID
  • CheriDataWidth = CheriBusBytes * 8

    typedef MemoryResponse#(CheriMasterID,CheriTransactionID,CheriDataWidth) CheriMemResponse;

  1. beri/cherilibs/trunk/MemTypes.bsv ↩
Created May 3, 2020 // Last Updated May 23, 2020

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?