Memory.bsv


Q&A

  • Who calls this and what is the input?

  • Where does it go?

    • it sends a cache memory request to DCache: dCache.put(req);, see DCache.bsv

Reference 1

MIPS memory module

file cheri/trunk/Memory.bsv

module mkMIPSMemory#(Bit#(16) coreId, CP0Ifc tlb)(MIPSMemory);

MIPS memory interfaces

  • MIPSMemory

    • DataMemory
    • InstructionMemory
    • MemConfiguration
    • Server#(CoProMemAccess, CoProRegs)

      // cheri/trunk/Memory.bsv
      
      interface MIPSMemory;
      interface DataMemory dataMemory;
      interface InstructionMemory instructionMemory;
      interface MemConfiguration configuration;
      `ifdef COP1
      interface Server#(CoProMemAccess, CoProReg) cop1Memory;
      `endif
      `ifdef MULTI
      method Action invalidateICache(PhyAddress addr); 
      method Action invalidateDCache(PhyAddress addr); 
      method ActionValue#(Bool) getInvalidateDone;
      interface Master#(CheriMemRequest, CheriMemResponse) dmemory;
      interface Master#(CheriMemRequest, CheriMemResponse) imemory;
      `else
      interface Master#(CheriMemRequest, CheriMemResponse) memory; // the generic main memory interface as a client.
      `endif
      method Action nextWillCommit(Bool commiting);
      `ifdef STATCOUNTERS
      interface StatCounters statCounters;
      `endif
      endinterface
      

module in/out/states

input

  • Bit#(16) coreId
  • CP0Ifc tlb
  • Interfaces: dataMemory, instructionMemory

output

  • sends memory request to dCache, iCache

states

  • Reg#(CacheRequestInstT) iCacheFetch <- mkConfigRegU;
  • Reg#(Bool) iCacheDelayed <- mkConfigReg(False);
  • FIFOF#(CacheRequestInstT) iCacheOp <- mkUGSizedFIFOF(4);
  • Reg#(CacheRequestDataT) dCacheFetch <- mkConfigRegU;
  • Reg#(Bool) dCacheDelayed <- mkConfigReg(False);
  • PrefetcherIfc pftch <- mkCapPrefetcher(dcachePrefetch);
  • PrefetcherIfc pftch <- mkCapPrefetcher(l2Prefetch);
  • MergeIfc#(2) theMemMerge <- mkMergeFast(); // This module merges the Memory interfaces of the instruction and data caches.
  • TagControllerIfc tagController <- mkTagController();
  • CacheDataIfc dCache <- mkDCache(truncate({coreId,1’b1}));
  • CacheInstIfc iCache <- mkICache(truncate({coreId,1’b0}));
  • L2CacheIfc l2Cache <- mkL2Cache();

Steps:

  • connect iCache.memory and dCache.memory to theMemMerge.slave[0/1]
  • connect theMemMerge.merged to l2Cache.cache
  • connect l2Cache.cache to tagController.cache
  • topMemIfc = tagControllerMemory;// previously the topMemIfc is l2CacheMemory
  • rule: feedICache(iCacheDelayed)
  • rule: feedDCache(dCacheDelayed)
  • rule: iCacheOperation(iCacheOp.notEmpty && !iCacheDelayed)
  • interface DataMemory dataMemory;
  • interface InstructionMemory instructionMemory;
  • interface MemConfiguration configuration;
  • memory = topMemIfc
  • method nextWillCommit = dCache.nextWillCommit;

How does it make connections

mkConnection(iCache.memory, theMemMerge.slave[0]); mkConnection(dCache.memory, theMemMerge.slave1); mkConnection(theMemMerge.merged, l2Cache.cache); mkConnection(l2CacheMemory, tagController.cache);

see mkConnection in BSV

DataMemory

called in MemoryAccess.bsv:157: m.startMem(mi.mem, addr, er.cop, er.storeData, er.memSize, er.test==LL, cap, er.id, er.epoch, er.fromDebug, storeConditional);

Interface decl:

interface DataMemory;
  method Action startMem(MemOp mop, Bit#(64) addr, CacheOperation cop, SizedWord sizedData, MemSize size, Bool ll, Bool cap, InstId instId, Epoch epoch, Bool fromDebug, Bool storeConditional);
  method ActionValue#(MemResponseDataT) getResponse(MIPSReg oldReg, Bool signExtend, Bit#(8) addr, MemSize size, Bool exception, Bool cacheOpResponse);
endinterface

Method startMem

Overview: request tlb, get tlb result, then put mem request to DCache

Condition: !dCacheDelayed

Input:

  • MemOp mop, type of memory operation. Read/Write/Nones
  • Bit#(64) addr,
  • CacheOperation cop, er.cop
  • SizedWord sizedData, er.storeData
  • MemSize size, er.memSize
  • Bool ll,
  • Bool cap,
  • InstId instId,
  • Epoch epoch,
  • Bool fromDebug,
  • Bool storeConditional

Output:

  • get result from TLB, (vaddr -> paddr), assign to req.tr.

  • dCache.put(req);

States:

  • CacheRequestDataT req, contains:

    • cop: CacheOperation{…}
    • byteEnable: signExtend(4’h0),
    • memSize: size
    • data: ?.
    • instId: instId,
    • epoch: epoch,
    • tr: TlbResponse{…}
  • TlbRequest tlbReq = TlbRequest{addr, …};

  • pftch, global prefetch module.

Steps: request tlb, then put request to D/ICache

  • check mop: Read, Write, ICacheOp, DCacheOp, None. Compose the req accordingly.

  • if Read:

    • get byteMask (1,2,4,8) according to the requested size.
    • for CAP: `byteMask = insert (mask, offset) ???
    • req = CacheRequestDataT{cap, ..., size, byteMask, ...}
    • pftch.spyCacheReq(req)
  • if Write:

    • todo
  • if ICacheOp, DCacheOp:

  • if None: exception.

  • invoke TLB query:

    • req.tr <- tlb.tlbLookupData.request(tlbReq);
  • put TLB result to dCache: dCache.put(req);

    interface DataMemory dataMemory;
    method Action startMem(MemOp mop,
                        Bit#(64) addr,
                        CacheOperation cop,
                        SizedWord sizedData,
                        MemSize size,
                        Bool ll,
                        Bool cap,
                        InstId instId,
                        Epoch epoch,
                        Bool fromDebug,
                        Bool storeConditional
                        ) if (!dCacheDelayed);
    TlbRequest tlbReq = TlbRequest{
        addr: alignAddress(addr,size),
        write: mop==Write,
        ll: ll,
        fromDebug: fromDebug,
        exception: None,
        instId: instId
    };
     

InstructionMemory

Overview: request tlb, get tlb result, then put request to ICache


  1. reference ↩
Created May 2, 2020 // Last Updated May 18, 2021

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

... what would you change?