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.
This commit is contained in:
jon
2020-05-28 10:55:46 +01:00
parent 57129f6383
commit 8a07e18439

View File

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