From 8a07e18439cd8a4222c39d96bf1955e2ca86e7a3 Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 28 May 2020 10:55:46 +0100 Subject: [PATCH] Do memory zeroing on reset when doing RVFI-DII. I couldn't quite use the implementation from Flute as the register was too wide for verilator. This one uses wide memories instead, which is way complicated, but I think it works. The width of the memory can be traded off for reset speed. The width at the moment is 8192 bits, which seems to be fast enough. --- src_Testbench/Top/Mem_Model.bsv | 124 +++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/src_Testbench/Top/Mem_Model.bsv b/src_Testbench/Top/Mem_Model.bsv index 736c5fb..c58f905 100644 --- a/src_Testbench/Top/Mem_Model.bsv +++ b/src_Testbench/Top/Mem_Model.bsv @@ -1,4 +1,14 @@ // Copyright (c) 2016-2019 Bluespec, Inc. All Rights Reserved +//- +// RVFI_DII modifications: +// Copyright (c) 2018 Peter Rugg +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory (Department of Computer Science and +// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the +// DARPA SSITH research programme. +//- package Mem_Model; @@ -26,6 +36,9 @@ import GetPut_Aux :: *; // Project imports import Mem_Controller :: *; +`ifdef RVFI_DII +import RVFI_DII :: *; +`endif // ================================================================ // Mem Model interface @@ -35,44 +48,105 @@ interface Mem_Model_IFC; interface MemoryServer #(Bits_per_Raw_Mem_Addr, Bits_per_Raw_Mem_Word) mem_server; endinterface +typedef 'h4000_0000 Bytes_Per_Mem; +`ifdef RVFI_DII +typedef 'h0000_0000 Zeroed_0_start; +typedef RVFI_DII_Mem_Size Zeroed_0_end; +typedef TLog#(TDiv#(Bits_per_Raw_Mem_Word,8)) ByteOffsetInWord; +typedef 8192 ZeroMemWidth; +typedef TLog#(ZeroMemWidth) LogZMWidth; +Integer wordOffsetWidth = valueOf(ByteOffsetInWord); +Integer lineInZeroesOffsetWidth = valueOf(LogZMWidth) + valueOf(ByteOffsetInWord); +typedef Bit#(TSub#(TLog#(TSub#(Zeroed_0_end, Zeroed_0_start)), TAdd#(LogZMWidth,ByteOffsetInWord))) Offset_Zeroes_0; +typedef Bit#(TSub#(TLog#(TSub#(Zeroed_1_end, Zeroed_1_start)), TAdd#(LogZMWidth,ByteOffsetInWord))) Offset_Zeroes_1; +typedef 'h3f00_0000 Zeroed_1_start; +typedef 'h3fff_ff00 Zeroed_1_end; +`endif + // ================================================================ // Mem Model implementation (* synthesize *) module mkMem_Model (Mem_Model_IFC); - Integer verbosity = 0; // 0 = quiet; 1 = verbose + Integer verbosity = 0; // 0 = quiet; 1 = verbose - Raw_Mem_Addr alloc_size = 'h_80_0000; // 8M raw mem words, or 256MB - - RegFile #(Raw_Mem_Addr, Bit #(Bits_per_Raw_Mem_Word)) rf <- mkRegFileLoad ("Mem.hex", 0, alloc_size - 1); + Raw_Mem_Addr alloc_size = fromInteger(valueOf(TDiv#(TMul#(Bytes_Per_Mem,8), Bits_per_Raw_Mem_Word))); //(raw mem words) - FIFOF #(MemoryResponse #(Bits_per_Raw_Mem_Word)) f_raw_mem_rsps <- mkFIFOF; +`ifdef RVFI_DII + Raw_Mem_Addr zeroed_0_start = fromInteger(valueOf(TDiv#(Zeroed_0_start, TDiv#(Bits_per_Raw_Mem_Word, 8)))); + Raw_Mem_Addr zeroed_0_end = fromInteger(valueOf(TDiv#(Zeroed_0_end, TDiv#(Bits_per_Raw_Mem_Word, 8)))); + Raw_Mem_Addr zeroed_1_start = fromInteger(valueOf(TDiv#(Zeroed_1_start, TDiv#(Bits_per_Raw_Mem_Word, 8)))); + Raw_Mem_Addr zeroed_1_end = fromInteger(valueOf(TDiv#(Zeroed_1_end, TDiv#(Bits_per_Raw_Mem_Word, 8)))); + + RegFile #(Raw_Mem_Addr, Bit #(Bits_per_Raw_Mem_Word)) rf <- mkRegFile (0, alloc_size - 1); + //zeroes register allows quick resetting of memory. If bit of zeroes is 0 then corresponding entry of rf is 0. + + RegFile #(Offset_Zeroes_0, Bit #(ZeroMemWidth)) zeroes_0 <- mkRegFileFull; + RegFile #(Offset_Zeroes_1, Bit #(ZeroMemWidth)) zeroes_1 <- mkRegFileFull; + Reg#(Bool) reset_done <- mkReg(False); + Reg#(Offset_Zeroes_0) reset_count_0 <- mkReg(~0); + Reg#(Offset_Zeroes_1) reset_count_1 <- mkReg(~0); + rule doZeroesReset(!reset_done); + zeroes_0.upd(reset_count_0, 0); + reset_count_0 <= reset_count_0 - 1; + zeroes_1.upd(reset_count_1, 0); + reset_count_1 <= reset_count_1 - 1; + if (reset_count_0 == 0 && reset_count_1 == 0) reset_done <= True; + endrule +`else + RegFile #(Raw_Mem_Addr, Bit #(Bits_per_Raw_Mem_Word)) rf <- mkRegFileLoad ("Mem.hex", 0, alloc_size - 1); + Reg#(Bool) reset_done <- mkReg(True); +`endif + + FIFOF #(MemoryResponse #(Bits_per_Raw_Mem_Word)) f_raw_mem_rsps <- mkFIFOF; // ---------------------------------------------------------------- // INTERFACE interface MemoryServer mem_server; - interface Put request; - method Action put (MemoryRequest #(Bits_per_Raw_Mem_Addr, Bits_per_Raw_Mem_Word) req); - if (req.address >= alloc_size) begin - $display ("%0d: ERROR: Mem_Model.request.put: addr 0x%0h >= size 0x%0h (num raw-mem words)", - cur_cycle, req.address, alloc_size); - $finish (1); // Assertion failure: address out of bounds - end - else if (req.write) begin - rf.upd (req.address, req.data); - if (verbosity != 0) - $display ("%0d: Mem_Model write [0x%0h] <= 0x%0h", cur_cycle, req.address, req.data); - end - else begin - let x = rf.sub (req.address); - let rsp = MemoryResponse {data: x}; - f_raw_mem_rsps.enq (rsp); - if (verbosity != 0) - $display ("%0d: Mem_Model read [0x%0h] => 0x%0h", cur_cycle, req.address, x); - end - endmethod + interface Put request; + method Action put (MemoryRequest #(Bits_per_Raw_Mem_Addr, Bits_per_Raw_Mem_Word) req) if (reset_done); +`ifdef RVFI_DII + Bit#(LogZMWidth) offsetLo = truncate((req.address - zeroed_0_start)>>wordOffsetWidth); + Offset_Zeroes_0 word0 = truncate((req.address - zeroed_0_start)>>lineInZeroesOffsetWidth); + Bit#(ZeroMemWidth) zeroes_0_word = zeroes_0.sub(word0); + Offset_Zeroes_1 word1 = truncate((req.address - zeroed_1_start)>>lineInZeroesOffsetWidth); + Bit#(ZeroMemWidth) zeroes_1_word = zeroes_1.sub(word1); +`endif + if (req.address >= alloc_size) begin + $display ("%0d: ERROR: Mem_Model.request.put: addr 0x%0h >= size 0x%0h (num raw-mem words)", + cur_cycle, req.address, alloc_size); + $finish (1); // Assertion failure: address out of bounds + end + else if (req.write) begin +`ifdef RVFI_DII + if (req.address >= zeroed_0_start && req.address < zeroed_0_end && zeroes_0_word[offsetLo] == 0) begin + zeroes_0_word[offsetLo] = 1; + zeroes_0.upd(word0, zeroes_0_word); + end + if (req.address >= zeroed_1_start && req.address < zeroed_1_end && zeroes_1_word[offsetLo] == 0) begin + zeroes_1_word[offsetLo] = 1; + zeroes_1.upd(word1, zeroes_1_word); + end +`endif + rf.upd (req.address, req.data); + if (verbosity != 0) + $display ("%0d: Mem_Model write [0x%0h] <= 0x%0h", cur_cycle, req.address, req.data); + end + else begin + let x = rf.sub (req.address); +`ifdef RVFI_DII + $display("req addr: ", fshow(req.address), ", zeroed_0_start: ", fshow(zeroed_0_start), ", zeroed_1_start: ", fshow(zeroed_1_start)); + if (req.address < zeroed_0_end && req.address >= zeroed_0_start && zeroes_0.sub(word0)[offsetLo] == 0) x = 0; + if (req.address < zeroed_1_end && req.address >= zeroed_1_start && zeroes_1.sub(word1)[offsetLo] == 0) x = 0; +`endif + let rsp = MemoryResponse {data: x}; + f_raw_mem_rsps.enq (rsp); + if (verbosity != 0) + $display ("%0d: Mem_Model read [0x%0h] => 0x%0h", cur_cycle, req.address, x); + end + endmethod endinterface interface Get response = toGet (f_raw_mem_rsps);