Files
Toooba/src_Core/Core/TV_Taps.bsv
rsnikhil 113f888d37 Added support for 'debug_external_interrupt_req'
New method 'debug_external_interrupt_req' to support emulation of a
debug module starts at P3_Core interface and is plumbed all the way in
to the CSR register MIP as interrupt [14].  The corresponding MIE[14]
is always 1, so it is never masked. Still todo: should not be masked
by MSTATUS interrupt-enables either.  Also expanded
interrupt-detection logic, mcause etc. to extend up to interrupt 14.

Builds in standalone mode, runs ISA tests.

Builds in src_SSITH_P3, generating RTL.
2019-04-01 12:26:54 -04:00

240 lines
7.0 KiB
Plaintext

// Copyright (c) 2018-2019 Bluespec, Inc. All Rights Reserved.
package TV_Taps;
// ================================================================
// This package defines 'taps' on connections between
// - DM and CPU, on which DM accesses CPU GPRs, FPRs and CSRs
// - DM and memory bus, on which DM accesses memory
// Each tap snoops 'writes', and produces a corresponsing Trace_Data
// write-memory command for the Tandem Verifier, so that it keeps its
// GPRs, FPRs, CSRs and memories in sync.
// ================================================================
// BSV library imports
import Assert :: *;
import BUtils :: *;
import FIFOF :: *;
import GetPut :: *;
import ClientServer :: *;
import Connectable :: *;
// ----------------
// BSV additional libs
import Semi_FIFOF :: *;
import GetPut_Aux :: *;
// ================================================================
// Project imports
import ISA_Decls :: *;
import DM_CPU_Req_Rsp :: *;
import TV_Info :: *;
import AXI4_Types :: *;
import Fabric_Defs :: *;
// ================================================================
// DM-to-memory tap
interface DM_Mem_Tap_IFC;
interface AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) slave;
interface AXI4_Master_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master;
interface Get #(Trace_Data) trace_data_out;
endinterface
(* synthesize *)
module mkDM_Mem_Tap (DM_Mem_Tap_IFC);
// Transactor facing DM
AXI4_Slave_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) slave_xactor <- mkAXI4_Slave_Xactor;
// Transactor facing memory bus
AXI4_Master_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master_xactor <- mkAXI4_Master_Xactor;
// Tap output
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
// ----------------
// AXI requests
// Snoop write requests
rule write_reqs;
let wr_addr = slave_xactor.o_wr_addr.first;
slave_xactor.o_wr_addr.deq;
let wr_data = slave_xactor.o_wr_data.first;
slave_xactor.o_wr_data.deq;
// Pass-through
master_xactor.i_wr_addr.enq (wr_addr);
master_xactor.i_wr_data.enq (wr_data);
// Tap
Bit #(64) paddr = ?;
Bit #(64) stval = ?;
`ifdef FABRIC64
if (wr_data.wstrb == 'h0f) begin
paddr = zeroExtend (wr_addr.awaddr);
stval = (wr_data.wdata & 'h_FFFF_FFFF);
end
else if (wr_data.wstrb == 'hf0) begin
paddr = zeroExtend (wr_addr.awaddr);
stval = ((wr_data.wdata >> 32) & 'h_FFFF_FFFF);
end
else
dynamicAssert(False, "mkDM_Mem_Tap: unsupported byte enables");
`else
paddr = zeroExtend (wr_addr.awaddr);
stval = zeroExtend (wr_data.wdata);
`endif
Trace_Data td = mkTrace_MEM_WRITE (f3_SIZE_W, truncate (stval), paddr);
f_trace_data.enq (td);
endrule
// Read requests, write responses and read responses are not snooped
mkConnection (slave_xactor.o_rd_addr, master_xactor.i_rd_addr);
mkConnection (slave_xactor.i_wr_resp, master_xactor.o_wr_resp);
mkConnection (slave_xactor.i_rd_data, master_xactor.o_rd_data);
// ================================================================
// INTERFACE
// Facing DM
interface slave = slave_xactor.axi_side;
// Facing bus
interface master = master_xactor.axi_side;
// Tap towards verifier
interface Get trace_data_out = toGet (f_trace_data);
endmodule: mkDM_Mem_Tap
// ================================================================
// DM-to-CPU GPR tap (for writes to GPRs)
interface DM_GPR_Tap_IFC;
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) client;
interface Server #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) server;
interface Get #(Trace_Data) trace_data_out;
endinterface
(* synthesize *)
module mkDM_GPR_Tap (DM_GPR_Tap_IFC);
// req from DM
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_in <- mkFIFOF;
// req to CPU
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_out <- mkFIFOF;
// resp CPU->DM
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
// Tap to TV
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
rule request;
let req <- pop (f_req_in);
// Pass-through to CPU
f_req_out.enq(req);
// Snoop writes and send trace data to TV
if (req.write) begin
Trace_Data td;
td = mkTrace_GPR_WRITE (req.address, req.data);
f_trace_data.enq (td);
end
endrule
interface Client client = toGPClient (f_req_out, f_rsp);
interface Server server = toGPServer (f_req_in, f_rsp);
interface Get trace_data_out = toGet (f_trace_data);
endmodule: mkDM_GPR_Tap
// ================================================================
// DM-to-CPU FPR tap (for writes to FPRs)
`ifdef ISA_F_OR_D
interface DM_FPR_Tap_IFC;
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) client;
interface Server #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) server;
interface Get #(Trace_Data) trace_data_out;
endinterface
(* synthesize *)
module mkDM_FPR_Tap (DM_FPR_Tap_IFC);
// req from DM
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_in <- mkFIFOF;
// req to CPU
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_out <- mkFIFOF;
// resp CPU->DM
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
// Tap to TV
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
rule request;
let req <- pop (f_req_in);
// Pass-through to CPU
f_req_out.enq(req);
// Snoop writes and send trace data to TV
if (req.write) begin
Trace_Data td;
td = mkTrace_FPR_WRITE (req.address, req.data);
f_trace_data.enq (td);
end
endrule
interface Client client = toGPClient (f_req_out, f_rsp);
interface Server server = toGPServer (f_req_in, f_rsp);
interface Get trace_data_out = toGet (f_trace_data);
endmodule: mkDM_FPR_Tap
`endif
// ================================================================
// DM-to-CPU CSR tap (for writes to CSRs)
interface DM_CSR_Tap_IFC;
interface Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) client;
interface Server #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) server;
interface Get #(Trace_Data) trace_data_out;
endinterface
(* synthesize *)
module mkDM_CSR_Tap (DM_CSR_Tap_IFC);
// req from DM
FIFOF #(DM_CPU_Req #(12, XLEN)) f_req_in <- mkFIFOF;
// req to CPU
FIFOF #(DM_CPU_Req #(12, XLEN)) f_req_out <- mkFIFOF;
// resp CPU->DM
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
// Tap to TV
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
rule request;
let req <- pop (f_req_in);
// Pass-through to CPU
f_req_out.enq(req);
// Snoop writes and send trace data to TV
if (req.write) begin
Trace_Data td = mkTrace_CSR_WRITE (req.address, req.data);
f_trace_data.enq (td);
end
endrule
interface Client client = toGPClient (f_req_out, f_rsp);
interface Server server = toGPServer (f_req_in, f_rsp);
interface Get trace_data_out = toGet (f_trace_data);
endmodule: mkDM_CSR_Tap
// ================================================================
endpackage