Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import CacheTypes;
- import CacheHelpers;
- import MainMemory;
- // ReqStatus (defined in CacheTypes.ms) is used to keep track of the state of the current request
- //typedef enum {
- // Ready, // The cache is ready for a new request
- // Lookup, // Issued a lookup to tag/data arrays
- // Writeback, // In main memory access for dirty writeback
- // Fill // In main memory access for requested data
- //} ReqStatus;
- //
- // Possible flows:
- // HIT: Ready -> Lookup -> Ready
- // MISS, line is clean: Ready -> Lookup -> Fill
- // MISS, line is dirty: Ready -> Lookup -> Writeback -> Fill
- // You may find the following type synonyms helpful to access the tag/data/status arrays
- typedef SRAMReq#(logCacheSets, CacheTag) TagReq;
- typedef SRAMReq#(logCacheSets, Line) DataReq;
- typedef SRAMReq#(logCacheSets, CacheStatus) StatusReq;
- // TODO: Complete the implementation of DirectMappedCache
- // NOTE: Implementing this module requires about 50 lines of additional code
- // (~40 lines in the rule, ~5-10 lines in the data method, and 1 line in the reqEnabled method)
- module DirectMappedCache(MainMemory mainMem);
- // SRAM arrays. Note that, for a direct-mapped cache,
- // number of cache sets == number of cache lines
- SRAM#(logCacheSets, Line) dataArray;
- SRAM#(logCacheSets, CacheTag) tagArray;
- SRAM#(logCacheSets, CacheStatus) statusArray;
- // Registers for holding the current state of the cache and how far along
- // it is in processing a request.
- RegU#(MemReq) curReq;
- Reg#(ReqStatus) state(Ready);
- // Hit/miss counters
- Reg#(Word) hits(0);
- Reg#(Word) misses(0);
- input Maybe#(MemReq) req default = Invalid;
- // TODO return True if the cache can accept a new request
- method Bool reqEnabled = (state == Ready) ? True : False;
- rule tick;
- if (state == Ready && isValid(req)) begin
- //TODO Your code here
- let request = fromMaybe(?, req);
- tagArray.req = Valid(TagReq {write: False,addr: getIndex(request.addr), data: ?});
- statusArray.req = Valid(StatusReq {addr: getIndex(request.addr), write: False, data: ?});
- dataArray.req = Valid(DataReq {write: False, addr: getIndex(request.addr), data: ?});
- state <= Lookup;
- curReq <= request;
- end else if (state == Lookup) begin
- //TODO Your code here
- // HIT: Tag matches, not Invalid
- let status = fromMaybe(?, statusArray.data);
- let tag = fromMaybe(?, tagArray.data);
- let data = fromMaybe(?, dataArray.data);
- //HIT
- if (tag == getTag(curReq.addr) && status != Invalid) begin
- if (curReq.op == St) begin
- data[getWordOffset(curReq.addr)] = curReq.data;
- statusArray.req = Valid(StatusReq {write: True, addr: getIndex(curReq.addr), data: Dirty});
- dataArray.req = Valid(DataReq {write: True, addr: getIndex(curReq.addr), data: data});
- end
- state <= Ready;
- hits <= hits + 1;
- end
- //MISS
- else begin
- misses <= misses + 1;
- //Clean
- if (status == Clean || status == Invalid) begin
- mainMem.req = Valid(LineReq {op: Ld, lineAddr:{getTag(curReq.addr), getIndex(curReq.addr)}, data:?} );
- state <= Fill;
- end
- //Dirty
- else begin
- mainMem.req = Valid(LineReq {op: St, lineAddr: {tag, getIndex(curReq.addr)}, data:data} );
- state <= Writeback;
- end
- end
- end else if (state == Writeback && mainMem.reqEnabled) begin
- //TODO Your code here
- LineReq memReq = LineReq {op: Ld, lineAddr: getLineAddr(curReq.addr), data: ?};
- mainMem.req = Valid(memReq);
- state <= Fill;
- end else if (state == Fill && isValid(mainMem.data)) begin
- //TODO Your code here
- let data = fromMaybe(?, mainMem.data);
- StatusReq statusReq = StatusReq {write: True, addr: getIndex(curReq.addr), data: Clean};
- if (curReq.op == St) begin
- data[getWordOffset(curReq.addr)] = curReq.data;
- statusReq.data = Dirty;
- end
- statusArray.req = Valid(statusReq);
- tagArray.req = Valid(TagReq {write: True, addr: getIndex(curReq.addr), data: getTag(curReq.addr)});
- dataArray.req = Valid(DataReq {write: True, addr: getIndex(curReq.addr), data: data});
- state <= Ready;
- end
- endrule
- method Maybe#(Word) data;
- // This method should return a Valid output in only two cases:
- // 1. On a load hit (we're in the Lookup state, there's a hit, and
- // curReq.op == Ld).
- // 2. On a fill for a load request (we're in the Fill state,
- // mainMem.data is valid, and curReq.op == Ld).
- // In all other cases, the output should be Invalid
- //
- // TODO Your code here.
- let status = fromMaybe(?, statusArray.data);
- let tag = fromMaybe(?, tagArray.data);
- if (state == Fill && curReq.op == Ld && isValid(mainMem.data)) begin
- let line = fromMaybe(?, mainMem.data);
- return Valid(line[getWordOffset(curReq.addr)]);
- end
- else if (state == Lookup && curReq.op == Ld && status != Invalid && tag == getTag(curReq.addr)) begin
- let line = fromMaybe(?, dataArray.data);
- return Valid(line[getWordOffset(curReq.addr)]);
- end
- else return Invalid;
- endmethod
- method Bit#(32) getHits = hits;
- method Bit#(32) getMisses = misses;
- endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement