This means FetchStage should now behave in the same way with RVFI-DII as with an I-Cache. A Dii_Parcel_Id is fed alongside PC everywhere relevant and follows very similar logic, but, importantly it's just extra state on the side, it doesn't affect what we do with the branch predictor and parcel combining/instruction decoding logic.
122 lines
4.2 KiB
Plaintext
122 lines
4.2 KiB
Plaintext
/*-
|
|
* Copyright (c) 2018-2019 Peter Rugg
|
|
* 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.
|
|
*
|
|
* @BERI_LICENSE_HEADER_START@
|
|
*
|
|
* Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
|
|
* license agreements. See the NOTICE file distributed with this work for
|
|
* additional information regarding copyright ownership. BERI licenses this
|
|
* file to you under the BERI Hardware-Software License, Version 1.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at:
|
|
*
|
|
* http://www.beri-open-systems.org/legal/license-1-0.txt
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, Work distributed
|
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations under the License.
|
|
*
|
|
* @BERI_LICENSE_HEADER_END@
|
|
*/
|
|
|
|
package Toooba_RVFI_DII_Bridge;
|
|
|
|
// ================================================================
|
|
// BSV library imports
|
|
|
|
import Vector :: *;
|
|
import FIFO :: *;
|
|
import FIFOF :: *;
|
|
import SpecialFIFOs :: *;
|
|
import GetPut :: *;
|
|
import ClientServer :: *;
|
|
import ConfigReg :: *;
|
|
|
|
// ================================================================
|
|
// Project imports
|
|
|
|
`include "ProcConfig.bsv"
|
|
|
|
import Types::*;
|
|
import ProcTypes::*;
|
|
|
|
//import Verifier :: *;
|
|
import RVFI_DII :: *;
|
|
|
|
// ================================================================
|
|
|
|
interface Toooba_RVFI_DII_Bridge_IFC;
|
|
interface Toooba_RVFI_DII_Server rvfi_dii_server;
|
|
interface Server#(Dii_Parcel_Id, Dii_Parcels) dii;
|
|
interface Put#(Rvfi_Traces) rvfi;
|
|
endinterface
|
|
|
|
module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC);
|
|
// DII state
|
|
FIFOF#(Dii_Parcel_Resps) parcel_resps <- mkSizedFIFOF(2048);
|
|
// RVFI state
|
|
FIFO#(Rvfi_Traces) report_vectors <- mkSizedFIFO(2048);
|
|
// Request ID
|
|
FIFO#(Dii_Parcel_Id) seq_req_first <- mkFIFO;
|
|
|
|
Bool verbose = False;
|
|
|
|
function Bool validReport(RVFI_DII_Execution#(DataSz,DataSz) trace);
|
|
return (trace.rvfi_insn != dii_nop);
|
|
endfunction
|
|
|
|
// These two functions convert beteween "Invalid" instructions and "nops".
|
|
// This is because the pipeline currently isn't able to handle Invalid injections,
|
|
// so we replace them with special nops in the bridge that we can filter out in the rvfi trace stream.
|
|
function Bit#(16) noParcelToNop(RVFI_DII_Parcel_Resp in);
|
|
case (in) matches
|
|
tagged DIIParcel .parcel: return parcel;
|
|
tagged DIINoParcel .is_second: return is_second ? dii_nop[31:16] : dii_nop[15:0];
|
|
endcase
|
|
endfunction
|
|
|
|
function Maybe#(RVFI_DII_Execution #(DataSz,DataSz)) nopToMaybe(Maybe#(RVFI_DII_Execution #(DataSz,DataSz)) in);
|
|
Maybe#(RVFI_DII_Execution #(DataSz,DataSz)) ret = in;
|
|
if (ret matches tagged Valid .val &&& !validReport(val)) ret = tagged Invalid;
|
|
return (ret);
|
|
endfunction
|
|
|
|
interface Toooba_RVFI_DII_Server rvfi_dii_server;
|
|
interface Get seqReqFirst = toGet(seq_req_first);
|
|
interface Put parcelResps = toPut(parcel_resps);
|
|
interface Get trace_report = toGet(report_vectors);
|
|
endinterface
|
|
|
|
interface Server dii;
|
|
interface Put request = toPut(seq_req_first);
|
|
interface Get response;
|
|
method ActionValue#(Dii_Parcels) get;
|
|
let resps = parcel_resps.first;
|
|
parcel_resps.deq;
|
|
let parcels = map(noParcelToNop, resps);
|
|
if (verbose)
|
|
$display("%t DII injection: ", $time,
|
|
fshow(parcels)
|
|
);
|
|
return parcels;
|
|
endmethod
|
|
endinterface
|
|
endinterface
|
|
|
|
interface Put rvfi;
|
|
method Action put(Rvfi_Traces in);
|
|
report_vectors.enq(map(nopToMaybe,in));
|
|
endmethod
|
|
endinterface
|
|
endmodule
|
|
|
|
endpackage
|