Files
Toooba/src_Testbench/Top/Mem_Model.bsv
2020-07-06 17:39:25 +01:00

172 lines
6.8 KiB
Plaintext

// Copyright (c) 2016-2019 Bluespec, Inc. All Rights Reserved
//
//-
// RVFI_DII + CHERI modifications:
// Copyright (c) 2020 Jonathan Woodruff
// 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.
//
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
//-
//-
// 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;
// ================================================================
// A simulation model of external DRAM memory.
// Uses a register file to model memory.
// ================================================================
// BSV library imports
import RegFile :: *;
import Vector :: *;
import FIFOF :: *;
import GetPut :: *;
import ClientServer :: *;
import Memory :: *;
// ----------------
// BSV additional libs
import Cur_Cycle :: *;
import GetPut_Aux :: *;
// ================================================================
// Project imports
import Mem_Controller :: *;
`ifdef RVFI_DII
import RVFI_DII :: *;
`endif
// ================================================================
// Mem Model interface
interface Mem_Model_IFC;
// The read/write interface
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 'h0080_0000 Zeroed_0_end;
typedef 'h3f00_0000 Zeroed_1_start;
typedef 'h3fff_ff00 Zeroed_1_end;
typedef TLog#(TDiv#(Bits_per_Raw_Mem_Word,8)) ByteOffsetInWord;
typedef 8192 ZeroMemWidth;
typedef TLog#(ZeroMemWidth) LogZMWidth;
Integer lineInZeroesOffsetWidth = valueOf(LogZMWidth);
typedef Bit#(TSub#(TSub#(TLog#(TSub#(Zeroed_0_end, Zeroed_0_start)), LogZMWidth), ByteOffsetInWord)) Offset_Zeroes_0;
typedef Bit#(TSub#(TSub#(TLog#(TSub#(Zeroed_1_end, Zeroed_1_start)), LogZMWidth), ByteOffsetInWord)) Offset_Zeroes_1;
`endif
// ================================================================
// Mem Model implementation
(* synthesize *)
module mkMem_Model (Mem_Model_IFC);
Integer verbosity = 1; // 0 = quiet; 1 = verbose
Raw_Mem_Addr alloc_size = fromInteger(valueOf(TDiv#(TMul#(Bytes_Per_Mem,8), Bits_per_Raw_Mem_Word))); //(raw mem words)
`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);
zeroes_1.upd(reset_count_1, 0);
if (reset_count_0 != 0) reset_count_0 <= reset_count_0 - 1;
if (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 (reset_done);
`ifdef RVFI_DII
Bit#(LogZMWidth) offsetLo = truncate((req.address - zeroed_0_start));
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), "-", fshow(zeroed_0_end),
", zeroed_1_start: ", fshow(zeroed_1_start), "-", fshow(zeroed_1_end));
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);
endinterface
endmodule
// ================================================================
endpackage