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.
This commit is contained in:
775
src_Core/BSV_Additional_Libs/AXI4_Stream.bsv
Normal file
775
src_Core/BSV_Additional_Libs/AXI4_Stream.bsv
Normal file
@@ -0,0 +1,775 @@
|
||||
// Copyright (c) 2019 Bluespec, Inc. All Rights Reserved
|
||||
|
||||
package AXI4_Stream;
|
||||
|
||||
// ================================================================
|
||||
// BSV library imports
|
||||
|
||||
import FIFOF :: *;
|
||||
import Connectable :: *;
|
||||
|
||||
// ----------------
|
||||
// BSV additional libs
|
||||
|
||||
import Semi_FIFOF :: *;
|
||||
import EdgeFIFOFs :: *;
|
||||
import AXI4_Types :: *;
|
||||
|
||||
// ================================================================
|
||||
// These are the signal-level interfaces for an AXI4 stream master.
|
||||
// The (*..*) attributes ensure that when bsc compiles this to Verilog,
|
||||
// we get exactly the signals specified in the ARM spec.
|
||||
|
||||
interface AXI4_Stream_Master_IFC #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user);
|
||||
|
||||
(* always_ready, result="tvalid" *) method Bool m_tvalid; // out
|
||||
(* always_ready, result="tid" *) method Bit #(wd_id) m_tid; // out
|
||||
(* always_ready, result="tdata" *) method Bit #(wd_data) m_tdata; // out
|
||||
(* always_ready, result="tstrb" *) method Bit #(TDiv #(wd_data, 8)) m_tstrb; // out
|
||||
(* always_ready, result="tkeep" *) method Bit #(TDiv #(wd_data, 8)) m_tkeep; // out
|
||||
(* always_ready, result="tlast" *) method Bool m_tlast; // out
|
||||
(* always_ready, result="tdest" *) method Bit #(wd_dest) m_tdest; // out
|
||||
(* always_ready, result="tuser" *) method Bit #(wd_user) m_tuser; // out
|
||||
|
||||
(* always_ready, always_enabled, prefix = "" *)
|
||||
method Action m_tready ((* port="tready" *) Bool tready); // in
|
||||
|
||||
endinterface: AXI4_Stream_Master_IFC
|
||||
|
||||
// ================================================================
|
||||
// These are the signal-level interfaces for an AXI4 stream slave.
|
||||
// The (*..*) attributes ensure that when bsc compiles this to Verilog,
|
||||
// we get exactly the signals specified in the ARM spec.
|
||||
|
||||
interface AXI4_Stream_Slave_IFC #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user);
|
||||
(* always_ready, always_enabled, prefix = "" *)
|
||||
method Action m_tvalid ((* port="tvalid" *) Bool tvalid, // in
|
||||
(* port="tid" *) Bit #(wd_id) tid, // in
|
||||
(* port="tdata" *) Bit #(wd_data) tdata, // in
|
||||
(* port="tstrb" *) Bit #(TDiv #(wd_data,8)) tstrb, // in
|
||||
(* port="tkeep" *) Bit #(TDiv #(wd_data,8)) tkeep, // in
|
||||
(* port="tlast" *) Bool tlast, // in
|
||||
(* port="tdest" *) Bit #(wd_dest) tdest, // in
|
||||
(* port="tuser" *) Bit #(wd_user) tuser); // in
|
||||
(* always_ready, result="tready" *)
|
||||
method Bool m_tready; // out
|
||||
endinterface: AXI4_Stream_Slave_IFC
|
||||
|
||||
// ================================================================
|
||||
// Connecting signal-level interfaces
|
||||
|
||||
instance Connectable #(AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user),
|
||||
AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
module mkConnection #(AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user) axim,
|
||||
AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user) axis)
|
||||
(Empty);
|
||||
|
||||
(* fire_when_enabled, no_implicit_conditions *)
|
||||
rule rl_data_channel;
|
||||
axis.m_tvalid (axim.m_tvalid,
|
||||
axim.m_tid,
|
||||
axim.m_tdata,
|
||||
axim.m_tstrb,
|
||||
axim.m_tkeep,
|
||||
axim.m_tlast,
|
||||
axim.m_tdest,
|
||||
axim.m_tuser);
|
||||
axim.m_tready (axis.m_tready);
|
||||
endrule
|
||||
endmodule
|
||||
endinstance
|
||||
|
||||
instance Connectable #(AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user),
|
||||
AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
module mkConnection #(AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user) axis,
|
||||
AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user) axim)
|
||||
(Empty);
|
||||
mkConnection(axim, axis);
|
||||
endmodule
|
||||
endinstance
|
||||
|
||||
// ================================================================
|
||||
// AXI4 dummy master: never produces requests
|
||||
|
||||
AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user) axi4_stream_dummy_master
|
||||
= interface AXI4_Stream_Master_IFC
|
||||
method m_tvalid = False; // out
|
||||
method m_tid = ?; // out
|
||||
method m_tdata = ?; // out
|
||||
method m_tstrb = ?; // out
|
||||
method m_tkeep = ?; // out
|
||||
method m_tlast = ?; // out
|
||||
method m_tdest = ?; // out
|
||||
method m_tuser = ?; // out
|
||||
|
||||
method Action m_tready (wready) = noAction; // in
|
||||
endinterface;
|
||||
|
||||
// ================================================================
|
||||
// AXI4 dummy slave: always accepts requests
|
||||
|
||||
AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user) axi4_stream_dummy_slave
|
||||
= interface AXI4_Stream_Slave_IFC
|
||||
method Action m_tvalid (wvalid,
|
||||
wid,
|
||||
wdata,
|
||||
wstrb,
|
||||
wkeep,
|
||||
wlast,
|
||||
wdest,
|
||||
wuser);
|
||||
noAction;
|
||||
endmethod
|
||||
method Bool m_tready = True;
|
||||
endinterface;
|
||||
|
||||
// ****************************************************************
|
||||
// ****************************************************************
|
||||
// Section: Higher-level FIFO-like interfaces and transactors
|
||||
// ****************************************************************
|
||||
// ****************************************************************
|
||||
|
||||
// ================================================================
|
||||
// Help function: fn_crg_and_rg_to_FIFOF_I
|
||||
// In the modules below, we use a crg_full and a rg_data to represent a fifo.
|
||||
// These functions convert these to FIFOF_I and FIFOF_O interfaces.
|
||||
|
||||
function FIFOF_I #(t) fn_crg_and_rg_to_FIFOF_I (Reg #(Bool) rg_full, Reg #(t) rg_data);
|
||||
return interface FIFOF_I;
|
||||
method Action enq (t x) if (! rg_full);
|
||||
rg_full <= True;
|
||||
rg_data <= x;
|
||||
endmethod
|
||||
method Bool notFull;
|
||||
return (! rg_full);
|
||||
endmethod
|
||||
endinterface;
|
||||
endfunction
|
||||
|
||||
function FIFOF_O #(t) fn_crg_and_rg_to_FIFOF_O (Reg #(Bool) rg_full, Reg #(t) rg_data);
|
||||
return interface FIFOF_O;
|
||||
method t first () if (rg_full);
|
||||
return rg_data;
|
||||
endmethod
|
||||
method Action deq () if (rg_full);
|
||||
rg_full <= False;
|
||||
endmethod
|
||||
method notEmpty;
|
||||
return rg_full;
|
||||
endmethod
|
||||
endinterface;
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Higher-level types for payloads (rather than just bits)
|
||||
|
||||
typedef struct {
|
||||
Bit #(wd_id) tid;
|
||||
Bit #(wd_data) tdata;
|
||||
Bit #(TDiv #(wd_data, 8)) tstrb;
|
||||
Bit #(TDiv #(wd_data, 8)) tkeep;
|
||||
Bool tlast;
|
||||
Bit #(wd_dest) tdest;
|
||||
Bit #(wd_user) tuser;
|
||||
} AXI4_Stream #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user)
|
||||
deriving (Bits, FShow);
|
||||
|
||||
// ================================================================
|
||||
// Master transactor interface
|
||||
|
||||
interface AXI4_Stream_Master_Xactor_IFC #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user);
|
||||
method Action reset;
|
||||
// AXI side
|
||||
interface AXI4_Stream_Master_IFC #(wd_id, wd_dest, wd_data, wd_user) axi_side;
|
||||
// FIFOF side
|
||||
interface FIFOF_I #(AXI4_Stream #(wd_id, wd_dest, wd_data, wd_user)) i_stream;
|
||||
endinterface: AXI4_Stream_Master_Xactor_IFC
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Master transactor
|
||||
// This version uses FIFOFs for total decoupling.
|
||||
|
||||
module mkAXI4_Stream_Master_Xactor (AXI4_Stream_Master_Xactor_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
Bool unguarded = True;
|
||||
Bool guarded = False;
|
||||
|
||||
// Guarded on BSV side, unguarded on AXI side
|
||||
FIFOF #(AXI4_Stream #(wd_id, wd_dest, wd_data, wd_user)) f_data <- mkGFIFOF (guarded, unguarded);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
f_data.clear;
|
||||
endmethod
|
||||
|
||||
// AXI side
|
||||
interface axi_side = interface AXI4_Stream_Master_IFC;
|
||||
method m_tvalid = f_data.notEmpty;
|
||||
method m_tid = f_data.first.tid;
|
||||
method m_tdata = f_data.first.tdata;
|
||||
method m_tstrb = f_data.first.tstrb;
|
||||
method m_tkeep = f_data.first.tkeep;
|
||||
method m_tlast = f_data.first.tlast;
|
||||
method m_tdest = f_data.first.tdest;
|
||||
method m_tuser = f_data.first.tuser;
|
||||
method Action m_tready (Bool tready);
|
||||
if (f_data.notEmpty && tready) f_data.deq;
|
||||
endmethod
|
||||
endinterface;
|
||||
|
||||
// FIFOF side
|
||||
interface i_stream = to_FIFOF_I (f_data);
|
||||
endmodule: mkAXI4_Stream_Master_Xactor
|
||||
|
||||
// ================================================================
|
||||
// Slave transactor interface
|
||||
|
||||
interface AXI4_Stream_Slave_Xactor_IFC #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user);
|
||||
method Action reset;
|
||||
// AXI side
|
||||
interface AXI4_Stream_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user) axi_side;
|
||||
// FIFOF side
|
||||
interface FIFOF_O #(AXI4_Stream #(wd_id, wd_dest, wd_data, wd_user)) o_stream;
|
||||
endinterface: AXI4_Stream_Slave_Xactor_IFC
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Slave transactor
|
||||
// This version uses FIFOFs for total decoupling.
|
||||
|
||||
module mkAXI4_Stream_Slave_Xactor (AXI4_Stream_Slave_Xactor_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
Bool unguarded = True;
|
||||
Bool guarded = False;
|
||||
|
||||
// Guarded on BSV side, unguarded on AXI side
|
||||
FIFOF #(AXI4_Stream #(wd_id, wd_dest, wd_data, wd_user)) f_data <- mkGFIFOF (unguarded, guarded);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
f_data.clear;
|
||||
endmethod
|
||||
|
||||
// AXI side
|
||||
interface axi_side = interface AXI4_Stream_Slave_IFC;
|
||||
method Action m_tvalid (Bool tvalid,
|
||||
Bit #(wd_id) tid,
|
||||
Bit #(wd_data) tdata,
|
||||
Bit #(TDiv #(wd_data, 8)) tstrb,
|
||||
Bit #(TDiv #(wd_data, 8)) tkeep,
|
||||
Bool tlast,
|
||||
Bit #(wd_dest) tdest,
|
||||
Bit #(wd_user) tuser);
|
||||
if (tvalid && f_data.notFull)
|
||||
f_data.enq (AXI4_Stream {tid: tid,
|
||||
tdata: tdata,
|
||||
tstrb: tstrb,
|
||||
tkeep: tkeep,
|
||||
tlast: tlast,
|
||||
tdest: tdest,
|
||||
tuser: tuser});
|
||||
endmethod
|
||||
|
||||
method Bool m_tready;
|
||||
return f_data.notFull;
|
||||
endmethod
|
||||
endinterface;
|
||||
|
||||
// FIFOF side
|
||||
interface o_stream = to_FIFOF_O (f_data);
|
||||
endmodule: mkAXI4_Stream_Slave_Xactor
|
||||
|
||||
/*
|
||||
// ----------------------------------------------------------------
|
||||
// Master transactor
|
||||
// This version uses crgs and regs instead of FIFOFs.
|
||||
// This uses 1/2 the resources, but introduces scheduling dependencies.
|
||||
|
||||
module mkAXI4_Master_Xactor_2 (AXI4_Master_Xactor_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
// Each crg_full, rg_data pair below represents a 1-element fifo.
|
||||
|
||||
Array #(Reg #(Bool)) crg_wr_addr_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Addr #(wd_id, wd_dest, wd_user)) rg_wr_addr <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_wr_data_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Data #(wd_id, wd_data, wd_user)) rg_wr_data <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_wr_resp_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Resp #(wd_id, wd_user)) rg_wr_resp <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_rd_addr_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Rd_Addr #(wd_id, wd_dest, wd_user)) rg_rd_addr <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_rd_data_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Rd_Data #(wd_id, wd_data, wd_user)) rg_rd_data <- mkRegU;
|
||||
|
||||
// The following CReg port indexes specify the relative scheduling of:
|
||||
// {first,deq,notEmpty} {enq,notFull} clear
|
||||
|
||||
// TODO: 'deq/enq/clear = 1/2/0' is unusual, but eliminates a
|
||||
// scheduling cycle in Piccolo's DCache. Normally should be 0/1/2.
|
||||
|
||||
Integer port_deq = 1;
|
||||
Integer port_enq = 2;
|
||||
Integer port_clear = 0;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
crg_wr_addr_full [port_clear] <= False;
|
||||
crg_wr_data_full [port_clear] <= False;
|
||||
crg_wr_resp_full [port_clear] <= False;
|
||||
crg_rd_addr_full [port_clear] <= False;
|
||||
crg_rd_data_full [port_clear] <= False;
|
||||
endmethod
|
||||
|
||||
// AXI side
|
||||
interface axi_side = interface AXI4_Master_IFC;
|
||||
// Wr Addr channel
|
||||
method Bool m_awvalid = crg_wr_addr_full [port_deq];
|
||||
method Bit #(wd_id) m_awid = rg_wr_addr.awid;
|
||||
method Bit #(wd_dest) m_awaddr = rg_wr_addr.awaddr;
|
||||
method Bit #(8) m_awlen = rg_wr_addr.awlen;
|
||||
method AXI4_Size m_awsize = rg_wr_addr.awsize;
|
||||
method Bit #(2) m_awburst = rg_wr_addr.awburst;
|
||||
method Bit #(1) m_awlock = rg_wr_addr.awlock;
|
||||
method Bit #(4) m_awcache = rg_wr_addr.awcache;
|
||||
method Bit #(3) m_awprot = rg_wr_addr.awprot;
|
||||
method Bit #(4) m_awqos = rg_wr_addr.awqos;
|
||||
method Bit #(4) m_awregion = rg_wr_addr.awregion;
|
||||
method Bit #(wd_user) m_awuser = rg_wr_addr.awuser;
|
||||
method Action m_awready (Bool awready);
|
||||
if (crg_wr_addr_full [port_deq] && awready)
|
||||
crg_wr_addr_full [port_deq] <= False; // deq
|
||||
endmethod
|
||||
|
||||
// Wr Data channel
|
||||
method Bool m_wvalid = crg_wr_data_full [port_deq];
|
||||
method Bit #(wd_id) m_wid = rg_wr_data.wid;
|
||||
method Bit #(wd_data) m_wdata = rg_wr_data.wdata;
|
||||
method Bit #(TDiv #(wd_data, 8)) m_wstrb = rg_wr_data.wstrb;
|
||||
method Bool m_wlast = rg_wr_data.wlast;
|
||||
method Bit #(wd_user) m_wuser = rg_wr_data.wuser;
|
||||
method Action m_wready (Bool wready);
|
||||
if (crg_wr_data_full [port_deq] && wready)
|
||||
crg_wr_data_full [port_deq] <= False;
|
||||
endmethod
|
||||
|
||||
// Wr Response channel
|
||||
method Action m_bvalid (Bool bvalid,
|
||||
Bit #(wd_id) bid,
|
||||
Bit #(2) bresp,
|
||||
Bit #(wd_user) buser);
|
||||
if (bvalid && (! (crg_wr_resp_full [port_enq]))) begin
|
||||
crg_wr_resp_full [port_enq] <= True;
|
||||
rg_wr_resp <= AXI4_Wr_Resp {bid: bid,
|
||||
bresp: bresp,
|
||||
buser: buser};
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Bool m_bready;
|
||||
return (! (crg_wr_resp_full [port_enq]));
|
||||
endmethod
|
||||
|
||||
// Rd Addr channel
|
||||
method Bool m_arvalid = crg_rd_addr_full [port_deq];
|
||||
method Bit #(wd_id) m_arid = rg_rd_addr.arid;
|
||||
method Bit #(wd_dest) m_araddr = rg_rd_addr.araddr;
|
||||
method Bit #(8) m_arlen = rg_rd_addr.arlen;
|
||||
method AXI4_Size m_arsize = rg_rd_addr.arsize;
|
||||
method Bit #(2) m_arburst = rg_rd_addr.arburst;
|
||||
method Bit #(1) m_arlock = rg_rd_addr.arlock;
|
||||
method Bit #(4) m_arcache = rg_rd_addr.arcache;
|
||||
method Bit #(3) m_arprot = rg_rd_addr.arprot;
|
||||
method Bit #(4) m_arqos = rg_rd_addr.arqos;
|
||||
method Bit #(4) m_arregion = rg_rd_addr.arregion;
|
||||
method Bit #(wd_user) m_aruser = rg_rd_addr.aruser;
|
||||
method Action m_arready (Bool arready);
|
||||
if (crg_rd_addr_full [port_deq] && arready)
|
||||
crg_rd_addr_full [port_deq] <= False; // deq
|
||||
endmethod
|
||||
|
||||
// Rd Data channel
|
||||
method Action m_rvalid (Bool rvalid,
|
||||
Bit #(wd_id) rid,
|
||||
Bit #(wd_data) rdata,
|
||||
Bit #(2) rresp,
|
||||
Bool rlast,
|
||||
Bit #(wd_user) ruser);
|
||||
if (rvalid && (! (crg_rd_data_full [port_enq])))
|
||||
crg_rd_data_full [port_enq] <= True;
|
||||
rg_rd_data <= (AXI4_Rd_Data {rid: rid,
|
||||
rdata: rdata,
|
||||
rresp: rresp,
|
||||
rlast: rlast,
|
||||
ruser: ruser});
|
||||
endmethod
|
||||
|
||||
method Bool m_rready;
|
||||
return (! (crg_rd_data_full [port_enq]));
|
||||
endmethod
|
||||
|
||||
endinterface;
|
||||
|
||||
// FIFOF side
|
||||
interface i_wr_addr = fn_crg_and_rg_to_FIFOF_I (crg_wr_addr_full [port_enq], rg_wr_addr);
|
||||
interface i_wr_data = fn_crg_and_rg_to_FIFOF_I (crg_wr_data_full [port_enq], rg_wr_data);
|
||||
interface o_wr_resp = fn_crg_and_rg_to_FIFOF_O (crg_wr_resp_full [port_deq], rg_wr_resp);
|
||||
|
||||
interface i_rd_addr = fn_crg_and_rg_to_FIFOF_I (crg_rd_addr_full [port_enq], rg_rd_addr);
|
||||
interface o_rd_data = fn_crg_and_rg_to_FIFOF_O (crg_rd_data_full [port_deq], rg_rd_data);
|
||||
endmodule: mkAXI4_Master_Xactor_2
|
||||
|
||||
// ================================================================
|
||||
// Slave transactor interface
|
||||
|
||||
interface AXI4_Slave_Xactor_IFC #(numeric type wd_id,
|
||||
numeric type wd_dest,
|
||||
numeric type wd_data,
|
||||
numeric type wd_user);
|
||||
method Action reset;
|
||||
|
||||
// AXI side
|
||||
interface AXI4_Slave_IFC #(wd_id, wd_dest, wd_data, wd_user) axi_side;
|
||||
|
||||
// FIFOF side
|
||||
interface FIFOF_O #(AXI4_Wr_Addr #(wd_id, wd_dest, wd_user)) o_wr_addr;
|
||||
interface FIFOF_O #(AXI4_Wr_Data #(wd_id, wd_data, wd_user)) o_wr_data;
|
||||
interface FIFOF_I #(AXI4_Wr_Resp #(wd_id, wd_user)) i_wr_resp;
|
||||
|
||||
interface FIFOF_O #(AXI4_Rd_Addr #(wd_id, wd_dest, wd_user)) o_rd_addr;
|
||||
interface FIFOF_I #(AXI4_Rd_Data #(wd_id, wd_data, wd_user)) i_rd_data;
|
||||
endinterface: AXI4_Slave_Xactor_IFC
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Slave transactor
|
||||
// This version uses FIFOFs for total decoupling.
|
||||
|
||||
module mkAXI4_Slave_Xactor (AXI4_Slave_Xactor_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
Bool unguarded = True;
|
||||
Bool guarded = False;
|
||||
|
||||
// These FIFOs are guarded on BSV side, unguarded on AXI side
|
||||
FIFOF #(AXI4_Wr_Addr #(wd_id, wd_dest, wd_user)) f_wr_addr <- mkGFIFOF (unguarded, guarded);
|
||||
FIFOF #(AXI4_Wr_Data #(wd_id, wd_data, wd_user)) f_wr_data <- mkGFIFOF (unguarded, guarded);
|
||||
FIFOF #(AXI4_Wr_Resp #(wd_id, wd_user)) f_wr_resp <- mkGFIFOF (guarded, unguarded);
|
||||
|
||||
FIFOF #(AXI4_Rd_Addr #(wd_id, wd_dest, wd_user)) f_rd_addr <- mkGFIFOF (unguarded, guarded);
|
||||
FIFOF #(AXI4_Rd_Data #(wd_id, wd_data, wd_user)) f_rd_data <- mkGFIFOF (guarded, unguarded);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
f_wr_addr.clear;
|
||||
f_wr_data.clear;
|
||||
f_wr_resp.clear;
|
||||
f_rd_addr.clear;
|
||||
f_rd_data.clear;
|
||||
endmethod
|
||||
// AXI side
|
||||
interface axi_side = interface AXI4_Slave_IFC;
|
||||
// Wr Addr channel
|
||||
method Action m_awvalid (Bool awvalid,
|
||||
Bit #(wd_id) awid,
|
||||
Bit #(wd_dest) awaddr,
|
||||
Bit #(8) awlen,
|
||||
AXI4_Size awsize,
|
||||
Bit #(2) awburst,
|
||||
Bit #(1) awlock,
|
||||
Bit #(4) awcache,
|
||||
Bit #(3) awprot,
|
||||
Bit #(4) awqos,
|
||||
Bit #(4) awregion,
|
||||
Bit #(wd_user) awuser);
|
||||
if (awvalid && f_wr_addr.notFull)
|
||||
f_wr_addr.enq (AXI4_Wr_Addr {awid: awid,
|
||||
awaddr: awaddr,
|
||||
awlen: awlen,
|
||||
awsize: awsize,
|
||||
awburst: awburst,
|
||||
awlock: awlock,
|
||||
awcache: awcache,
|
||||
awprot: awprot,
|
||||
awqos: awqos,
|
||||
awregion: awregion,
|
||||
awuser: awuser});
|
||||
endmethod
|
||||
|
||||
method Bool m_awready;
|
||||
return f_wr_addr.notFull;
|
||||
endmethod
|
||||
|
||||
// Wr Data channel
|
||||
method Action m_wvalid (Bool wvalid,
|
||||
Bit #(wd_id) wid,
|
||||
Bit #(wd_data) wdata,
|
||||
it #(TDiv #(wd_data, 8)) wstrb,
|
||||
Bool wlast,
|
||||
Bit #(wd_user) wuser);
|
||||
if (wvalid && f_wr_data.notFull)
|
||||
f_wr_data.enq (AXI4_Wr_Data {wid: wid,
|
||||
wdata: wdata,
|
||||
wstrb: wstrb,
|
||||
wlast: wlast,
|
||||
wuser: wuser});
|
||||
endmethod
|
||||
|
||||
method Bool m_wready;
|
||||
return f_wr_data.notFull;
|
||||
endmethod
|
||||
|
||||
// Wr Response channel
|
||||
method Bool m_bvalid = f_wr_resp.notEmpty;
|
||||
method Bit #(wd_id) m_bid = f_wr_resp.first.bid;
|
||||
method Bit #(2) m_bresp = f_wr_resp.first.bresp;
|
||||
method Bit #(wd_user) m_buser = f_wr_resp.first.buser;
|
||||
method Action m_bready (Bool bready);
|
||||
if (bready && f_wr_resp.notEmpty)
|
||||
f_wr_resp.deq;
|
||||
endmethod
|
||||
|
||||
// Rd Addr channel
|
||||
method Action m_arvalid (Bool arvalid,
|
||||
Bit #(wd_id) arid,
|
||||
Bit #(wd_dest) araddr,
|
||||
Bit #(8) arlen,
|
||||
AXI4_Size arsize,
|
||||
Bit #(2) arburst,
|
||||
Bit #(1) arlock,
|
||||
Bit #(4) arcache,
|
||||
Bit #(3) arprot,
|
||||
Bit #(4) arqos,
|
||||
Bit #(4) arregion,
|
||||
Bit #(wd_user) aruser);
|
||||
if (arvalid && f_rd_addr.notFull)
|
||||
f_rd_addr.enq (AXI4_Rd_Addr {arid: arid,
|
||||
araddr: araddr,
|
||||
arlen: arlen,
|
||||
arsize: arsize,
|
||||
arburst: arburst,
|
||||
arlock: arlock,
|
||||
arcache: arcache,
|
||||
arprot: arprot,
|
||||
arqos: arqos,
|
||||
arregion: arregion,
|
||||
aruser: aruser});
|
||||
endmethod
|
||||
|
||||
method Bool m_arready;
|
||||
return f_rd_addr.notFull;
|
||||
endmethod
|
||||
|
||||
// Rd Data channel
|
||||
method Bool m_rvalid = f_rd_data.notEmpty;
|
||||
method Bit #(wd_id) m_rid = f_rd_data.first.rid;
|
||||
method Bit #(wd_data) m_rdata = f_rd_data.first.rdata;
|
||||
method Bit #(2) m_rresp = f_rd_data.first.rresp;
|
||||
method Bool m_rlast = f_rd_data.first.rlast;
|
||||
method Bit #(wd_user) m_ruser = f_rd_data.first.ruser;
|
||||
method Action m_rready (Bool rready);
|
||||
if (rready && f_rd_data.notEmpty)
|
||||
f_rd_data.deq;
|
||||
endmethod
|
||||
endinterface;
|
||||
|
||||
// FIFOF side
|
||||
interface o_wr_addr = to_FIFOF_O (f_wr_addr);
|
||||
interface o_wr_data = to_FIFOF_O (f_wr_data);
|
||||
interface i_wr_resp = to_FIFOF_I (f_wr_resp);
|
||||
|
||||
interface o_rd_addr = to_FIFOF_O (f_rd_addr);
|
||||
interface i_rd_data = to_FIFOF_I (f_rd_data);
|
||||
endmodule: mkAXI4_Slave_Xactor
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Slave transactor
|
||||
// This version uses crgs and regs instead of FIFOFs.
|
||||
// This uses 1/2 the resources, but introduces scheduling dependencies.
|
||||
|
||||
module mkAXI4_Slave_Xactor_2 (AXI4_Slave_Xactor_IFC #(wd_id, wd_dest, wd_data, wd_user));
|
||||
|
||||
// Each crg_full, rg_data pair below represents a 1-element fifo.
|
||||
|
||||
// These FIFOs are guarded on BSV side, unguarded on AXI side
|
||||
Array #(Reg #(Bool)) crg_wr_addr_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Addr #(wd_id, wd_dest, wd_user)) rg_wr_addr <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_wr_data_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Data #(wd_id, wd_data, wd_user)) rg_wr_data <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_wr_resp_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Wr_Resp #(wd_id, wd_user)) rg_wr_resp <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_rd_addr_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Rd_Addr #(wd_id, wd_dest, wd_user)) rg_rd_addr <- mkRegU;
|
||||
|
||||
Array #(Reg #(Bool)) crg_rd_data_full <- mkCReg (3, False);
|
||||
Reg #(AXI4_Rd_Data #(wd_id, wd_data, wd_user)) rg_rd_data <- mkRegU;
|
||||
|
||||
// The following CReg port indexes specify the relative scheduling of:
|
||||
// {first,deq,notEmpty} {enq,notFull} clear
|
||||
Integer port_deq = 0;
|
||||
Integer port_enq = 1;
|
||||
Integer port_clear = 2;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
crg_wr_addr_full [port_clear] <= False;
|
||||
crg_wr_data_full [port_clear] <= False;
|
||||
crg_wr_resp_full [port_clear] <= False;
|
||||
crg_rd_addr_full [port_clear] <= False;
|
||||
crg_rd_data_full [port_clear] <= False;
|
||||
endmethod
|
||||
|
||||
// AXI side
|
||||
interface axi_side = interface AXI4_Slave_IFC;
|
||||
// Wr Addr channel
|
||||
method Action m_awvalid (Bool awvalid,
|
||||
Bit #(wd_id) awid,
|
||||
Bit #(wd_dest) awaddr,
|
||||
Bit #(8) awlen,
|
||||
AXI4_Size awsize,
|
||||
Bit #(2) awburst,
|
||||
Bit #(1) awlock,
|
||||
Bit #(4) awcache,
|
||||
Bit #(3) awprot,
|
||||
Bit #(4) awqos,
|
||||
Bit #(4) awregion,
|
||||
Bit #(wd_user) awuser);
|
||||
|
||||
if (awvalid && (! crg_wr_addr_full [port_enq])) begin
|
||||
crg_wr_addr_full [port_enq] <= True; // enq
|
||||
rg_wr_addr <= AXI4_Wr_Addr {awid: awid,
|
||||
awaddr: awaddr,
|
||||
awlen: awlen,
|
||||
awsize: awsize,
|
||||
awburst: awburst,
|
||||
awlock: awlock,
|
||||
awcache: awcache,
|
||||
awprot: awprot,
|
||||
awqos: awqos,
|
||||
awregion: awregion,
|
||||
awuser: awuser};
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Bool m_awready;
|
||||
return (! crg_wr_addr_full [port_enq]);
|
||||
endmethod
|
||||
|
||||
// Wr Data channel
|
||||
method Action m_wvalid (Bool wvalid,
|
||||
Bit #(wd_id) wid,
|
||||
Bit #(wd_data) wdata,
|
||||
Bit #(TDiv #(wd_data, 8)) wstrb,
|
||||
Bool wlast,
|
||||
Bit #(wd_user) wuser);
|
||||
if (wvalid && (! crg_wr_data_full [port_enq])) begin
|
||||
crg_wr_data_full [port_enq] <= True; // enq
|
||||
rg_wr_data <= AXI4_Wr_Data {wid: wid,
|
||||
wdata: wdata,
|
||||
wstrb: wstrb,
|
||||
wlast: wlast,
|
||||
wuser: wuser};
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Bool m_wready;
|
||||
return (! crg_wr_data_full [port_enq]);
|
||||
endmethod
|
||||
|
||||
// Wr Response channel
|
||||
method Bool m_bvalid = crg_wr_resp_full [port_deq];
|
||||
method Bit #(wd_id) m_bid = rg_wr_resp.bid;
|
||||
method Bit #(2) m_bresp = rg_wr_resp.bresp;
|
||||
method Bit #(wd_user) m_buser = rg_wr_resp.buser;
|
||||
method Action m_bready (Bool bready);
|
||||
if (bready && crg_wr_resp_full [port_deq])
|
||||
crg_wr_resp_full [port_deq] <= False; // deq
|
||||
endmethod
|
||||
|
||||
// Rd Addr channel
|
||||
method Action m_arvalid (Bool arvalid,
|
||||
Bit #(wd_id) arid,
|
||||
Bit #(wd_dest) araddr,
|
||||
Bit #(8) arlen,
|
||||
AXI4_Size arsize,
|
||||
Bit #(2) arburst,
|
||||
Bit #(1) arlock,
|
||||
Bit #(4) arcache,
|
||||
Bit #(3) arprot,
|
||||
Bit #(4) arqos,
|
||||
Bit #(4) arregion,
|
||||
Bit #(wd_user) aruser);
|
||||
if (arvalid && (! crg_rd_addr_full [port_enq])) begin
|
||||
crg_rd_addr_full [port_enq] <= True; // enq
|
||||
rg_rd_addr <= AXI4_Rd_Addr {arid: arid,
|
||||
araddr: araddr,
|
||||
arlen: arlen,
|
||||
arsize: arsize,
|
||||
arburst: arburst,
|
||||
arlock: arlock,
|
||||
arcache: arcache,
|
||||
arprot: arprot,
|
||||
arqos: arqos,
|
||||
arregion: arregion,
|
||||
aruser: aruser};
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Bool m_arready;
|
||||
return (! crg_rd_addr_full [port_enq]);
|
||||
endmethod
|
||||
|
||||
// Rd Data channel
|
||||
method Bool m_rvalid = crg_rd_data_full [port_deq];
|
||||
method Bit #(wd_id) m_rid = rg_rd_data.rid;
|
||||
method Bit #(wd_data) m_rdata = rg_rd_data.rdata;
|
||||
method Bit #(2) m_rresp = rg_rd_data.rresp;
|
||||
method Bool m_rlast = rg_rd_data.rlast;
|
||||
method Bit #(wd_user) m_ruser = rg_rd_data.ruser;
|
||||
method Action m_rready (Bool rready);
|
||||
if (rready && crg_rd_data_full [port_deq])
|
||||
crg_rd_data_full [port_deq] <= False; // deq
|
||||
endmethod
|
||||
endinterface;
|
||||
|
||||
// FIFOF side
|
||||
interface o_wr_addr = fn_crg_and_rg_to_FIFOF_O (crg_wr_addr_full [port_deq], rg_wr_addr);
|
||||
interface o_wr_data = fn_crg_and_rg_to_FIFOF_O (crg_wr_data_full [port_deq], rg_wr_data);
|
||||
interface i_wr_resp = fn_crg_and_rg_to_FIFOF_I (crg_wr_resp_full [port_enq], rg_wr_resp);
|
||||
|
||||
interface o_rd_addr = fn_crg_and_rg_to_FIFOF_O (crg_rd_addr_full [port_deq], rg_rd_addr);
|
||||
interface i_rd_data = fn_crg_and_rg_to_FIFOF_I (crg_rd_data_full [port_enq], rg_rd_data);
|
||||
endmodule: mkAXI4_Slave_Xactor_2
|
||||
*/
|
||||
// ================================================================
|
||||
|
||||
endpackage
|
||||
@@ -11,6 +11,8 @@ package Semi_FIFOF;
|
||||
|
||||
import FIFOF :: *;
|
||||
import Connectable :: *;
|
||||
import GetPut :: *;
|
||||
import FIFOLevel :: *;
|
||||
|
||||
// ================================================================
|
||||
// Semi-FIFOF interfaces
|
||||
@@ -27,22 +29,74 @@ interface FIFOF_O #(type t);
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
// Converters from FIFOF
|
||||
// Converters to and from Semi-FIFOF interfaces
|
||||
|
||||
function FIFOF_I #(t) to_FIFOF_I (FIFOF #(t) f);
|
||||
return interface FIFOF_I;
|
||||
method enq (x) = f.enq (x);
|
||||
method notFull = f.notFull;
|
||||
endinterface;
|
||||
endfunction
|
||||
typeclass To_FIFOF_IO#(type tf, type t)
|
||||
dependencies (tf determines t);
|
||||
|
||||
function FIFOF_O #(t) to_FIFOF_O (FIFOF #(t) f);
|
||||
return interface FIFOF_O;
|
||||
method first = f.first;
|
||||
method deq = f.deq;
|
||||
method notEmpty = f.notEmpty;
|
||||
endinterface;
|
||||
endfunction
|
||||
function FIFOF_I #(t) to_FIFOF_I (tf f);
|
||||
function FIFOF_O #(t) to_FIFOF_O (tf f);
|
||||
endtypeclass
|
||||
|
||||
instance To_FIFOF_IO#(FIFOF#(t), t);
|
||||
function FIFOF_I #(t) to_FIFOF_I (FIFOF #(t) f);
|
||||
return interface FIFOF_I;
|
||||
method enq (x) = f.enq (x);
|
||||
method notFull = f.notFull;
|
||||
endinterface;
|
||||
endfunction
|
||||
|
||||
function FIFOF_O #(t) to_FIFOF_O (FIFOF #(t) f);
|
||||
return interface FIFOF_O;
|
||||
method first = f.first;
|
||||
method deq = f.deq;
|
||||
method notEmpty = f.notEmpty;
|
||||
endinterface;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
instance To_FIFOF_IO#(FIFOLevelIfc#(t,n), t);
|
||||
function FIFOF_I #(t) to_FIFOF_I (FIFOLevelIfc #(t,n) f);
|
||||
return interface FIFOF_I;
|
||||
method enq (x) = f.enq (x);
|
||||
method notFull = f.notFull;
|
||||
endinterface;
|
||||
endfunction
|
||||
|
||||
function FIFOF_O #(t) to_FIFOF_O (FIFOLevelIfc #(t,n) f);
|
||||
return interface FIFOF_O;
|
||||
method first = f.first;
|
||||
method deq = f.deq;
|
||||
method notEmpty = f.notEmpty;
|
||||
endinterface;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Converters to Get/Put interfaces
|
||||
|
||||
instance ToGet#(FIFOF_O#(t), t);
|
||||
function toGet(ff) = (
|
||||
interface Get;
|
||||
method get();
|
||||
actionvalue
|
||||
ff.deq;
|
||||
return ff.first;
|
||||
endactionvalue
|
||||
endmethod
|
||||
endinterface
|
||||
);
|
||||
endinstance
|
||||
|
||||
instance ToPut#(FIFOF_I#(t), t);
|
||||
function toPut(ff) = (
|
||||
interface Put;
|
||||
method Action put(x);
|
||||
ff.enq(x);
|
||||
endmethod
|
||||
endinterface
|
||||
);
|
||||
endinstance
|
||||
|
||||
// ================================================================
|
||||
// Connections
|
||||
@@ -132,6 +186,7 @@ FIFOF_O #(t) dummy_FIFOF_O = interface FIFOF_O;
|
||||
endmethod
|
||||
endinterface;
|
||||
|
||||
|
||||
// ================================================================
|
||||
|
||||
endpackage
|
||||
|
||||
@@ -135,6 +135,9 @@ interface Core;
|
||||
// Bluespec: external interrupt requests targeting Machine and Supervisor modes
|
||||
method Action setMEIP (Bit #(1) v);
|
||||
method Action setSEIP (Bit #(1) v);
|
||||
|
||||
// Bluespec: external interrupt to enter debug mode
|
||||
method Action setDEIP (Bit #(1) v);
|
||||
endinterface
|
||||
|
||||
// fixpoint to instantiate modules
|
||||
@@ -973,5 +976,8 @@ module mkCore#(CoreId coreId)(Core);
|
||||
// Bluespec: external interrupt requests targeting Machine and Supervisor modes
|
||||
method Action setMEIP (v) = csrf.setMEIP (v);
|
||||
method Action setSEIP (v) = csrf.setSEIP (v);
|
||||
|
||||
// Bluespec: external interrupt to enter debug mode
|
||||
method Action setDEIP (v) = csrf.setDEIP (v);
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ interface CsrFile;
|
||||
method Action setMEIP (Bit #(1) v);
|
||||
method Action setSEIP (Bit #(1) v);
|
||||
|
||||
// Bluespec: external interrupt to enter debug mode
|
||||
method Action setDEIP (Bit #(1) v);
|
||||
|
||||
// performance stats is collected or not
|
||||
method Bool doPerfStats;
|
||||
// send/recv updates on stats CSR globally
|
||||
@@ -306,6 +309,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
readOnlyReg(1'b0), mideleg_1_0_reg
|
||||
);
|
||||
// mie
|
||||
Reg #(Bit #(1)) debug_int_en = readOnlyReg (1);
|
||||
Vector#(4, Reg#(Bit#(1))) external_int_en_vec = replicate(readOnlyReg(0));
|
||||
external_int_en_vec[prvU] <- mkCsrReg(0);
|
||||
external_int_en_vec[prvS] <- mkCsrReg(0);
|
||||
@@ -318,8 +322,10 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
software_int_en_vec[prvU] <- mkCsrReg(0);
|
||||
software_int_en_vec[prvS] <- mkCsrReg(0);
|
||||
software_int_en_vec[prvM] <- mkCsrReg(0);
|
||||
Reg#(Data) mie_csr = concatReg13(
|
||||
readOnlyReg(52'b0),
|
||||
Reg#(Data) mie_csr = concatReg15(
|
||||
readOnlyReg(49'b0),
|
||||
debug_int_en, // mie [14]
|
||||
readOnlyReg(2'b0),
|
||||
external_int_en_vec[prvM], readOnlyReg(1'b0),
|
||||
external_int_en_vec[prvS], external_int_en_vec[prvU],
|
||||
timer_int_en_vec[prvM], readOnlyReg(1'b0),
|
||||
@@ -356,6 +362,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
// mtval (mbadaddr in spike)
|
||||
Reg#(Data) mtval_csr <- mkCsrReg(0);
|
||||
// mip
|
||||
Reg #(Bit #(1)) debug_int_pend <- mkCsrReg (0);
|
||||
Vector#(4, Reg#(Bit#(1))) external_int_pend_vec = replicate(readOnlyReg(0));
|
||||
external_int_pend_vec[prvU] <- mkCsrReg(0);
|
||||
external_int_pend_vec[prvS] <- mkCsrReg(0);
|
||||
@@ -368,8 +375,10 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
software_int_pend_vec[prvU] <- mkCsrReg(0);
|
||||
software_int_pend_vec[prvS] <- mkCsrReg(0);
|
||||
software_int_pend_vec[prvM] <- mkCsrReg(0);
|
||||
Reg#(Data) mip_csr = concatReg13(
|
||||
readOnlyReg(52'b0),
|
||||
Reg#(Data) mip_csr = concatReg15(
|
||||
readOnlyReg(49'b0),
|
||||
debug_int_pend,
|
||||
readOnlyReg(2'b0),
|
||||
external_int_pend_vec[prvM], readOnlyReg(1'b0),
|
||||
external_int_pend_vec[prvS], external_int_pend_vec[prvU],
|
||||
readOnlyReg(timer_int_pend_vec[prvM]), // MTIP is read-only to software
|
||||
@@ -829,10 +838,16 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
method Action setMEIP (Bit #(1) v);
|
||||
external_int_pend_vec[prvM] <= v;
|
||||
endmethod
|
||||
|
||||
method Action setSEIP (Bit #(1) v);
|
||||
external_int_pend_vec[prvS] <= v;
|
||||
endmethod
|
||||
|
||||
// Bluespec: external interrupt to enter debug mode
|
||||
method Action setDEIP (Bit #(1) v);
|
||||
debug_int_pend <= v;
|
||||
endmethod
|
||||
|
||||
method terminate = terminate_module.terminate;
|
||||
|
||||
// performance stats
|
||||
|
||||
@@ -61,7 +61,9 @@ import DramCommon::*;
|
||||
import Performance::*;
|
||||
|
||||
// ----------------
|
||||
// From McStriiv
|
||||
// From Tooba
|
||||
|
||||
import ISA_Decls :: *;
|
||||
|
||||
import AXI4_Types :: *;
|
||||
import Fabric_Defs :: *;
|
||||
@@ -72,6 +74,14 @@ import MMIOPlatform :: *;
|
||||
import LLC_AXI4_Adapter :: *;
|
||||
import MMIO_AXI4_Adapter :: *;
|
||||
|
||||
`ifdef INCLUDE_GDB_CONTROL
|
||||
import DM_CPU_Req_Rsp :: *;
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_TANDEM_VERIF
|
||||
import TV_Info :: *;
|
||||
`endif
|
||||
|
||||
// ================================================================
|
||||
|
||||
(* synthesize *)
|
||||
@@ -110,18 +120,18 @@ module mkProc (Proc_IFC);
|
||||
Reg #(Bit #(1)) rg_step_count <- mkReg (0);
|
||||
|
||||
// Debugger GPR read/write request/response
|
||||
FIFOF #(MemoryRequest #(5, XLEN)) f_gpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(MemoryResponse #( XLEN)) f_gpr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_gpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_gpr_rsps <- mkFIFOF1;
|
||||
|
||||
`ifdef ISA_F
|
||||
// Debugger FPR read/write request/response
|
||||
FIFOF #(MemoryRequest #(5, FLEN)) f_fpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(MemoryResponse #( FLEN)) f_fpr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(5, FLEN)) f_fpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(FLEN)) f_fpr_rsps <- mkFIFOF1;
|
||||
`endif
|
||||
|
||||
// Debugger CSR read/write request/response
|
||||
FIFOF #(MemoryRequest #(12, XLEN)) f_csr_reqs <- mkFIFOF1;
|
||||
FIFOF #(MemoryResponse #( XLEN)) f_csr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_csr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_csr_rsps <- mkFIFOF1;
|
||||
|
||||
`endif
|
||||
|
||||
@@ -309,6 +319,13 @@ module mkProc (Proc_IFC);
|
||||
core[0].setSEIP (pack (x));
|
||||
endmethod
|
||||
|
||||
// ----------------
|
||||
// External interrupt [14] to go into Debug Mode
|
||||
|
||||
method Action debug_external_interrupt_req (Bool set_not_clear);
|
||||
core[0].setDEIP (pack (set_not_clear));
|
||||
endmethod
|
||||
|
||||
// ----------------
|
||||
// Non-maskable interrupt
|
||||
|
||||
@@ -343,16 +360,19 @@ module mkProc (Proc_IFC);
|
||||
endinterface
|
||||
|
||||
// GPR access
|
||||
interface MemoryServer hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps);
|
||||
interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps);
|
||||
|
||||
`ifdef ISA_F
|
||||
// FPR access
|
||||
interface MemoryServer hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps);
|
||||
interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps);
|
||||
`endif
|
||||
|
||||
// CSR access
|
||||
interface MemoryServer hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps);
|
||||
interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps);
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
endmodule: mkProc
|
||||
|
||||
// ================================================================
|
||||
|
||||
endpackage
|
||||
|
||||
@@ -5,7 +5,6 @@ package Proc_IFC;
|
||||
// ================================================================
|
||||
// BSV library imports
|
||||
|
||||
import Memory :: *;
|
||||
import GetPut :: *;
|
||||
import ClientServer :: *;
|
||||
|
||||
@@ -14,13 +13,17 @@ import ClientServer :: *;
|
||||
|
||||
import ISA_Decls :: *;
|
||||
|
||||
import AXI4_Types :: *;
|
||||
import Fabric_Defs :: *;
|
||||
|
||||
`ifdef INCLUDE_GDB_CONTROL
|
||||
import DM_CPU_Req_Rsp :: *;
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_TANDEM_VERIF
|
||||
import TV_Info :: *;
|
||||
`endif
|
||||
|
||||
import AXI4_Types :: *;
|
||||
import Fabric_Defs :: *;
|
||||
|
||||
// ================================================================
|
||||
// CPU interface
|
||||
|
||||
@@ -54,6 +57,12 @@ interface Proc_IFC;
|
||||
(* always_ready, always_enabled *)
|
||||
method Action s_external_interrupt_req (Bool set_not_clear);
|
||||
|
||||
// ----------------
|
||||
// External interrupt [14] to go into Debug Mode
|
||||
|
||||
(* always_ready, always_enabled *)
|
||||
method Action debug_external_interrupt_req (Bool set_not_clear);
|
||||
|
||||
// ----------------
|
||||
// Non-maskable interrupt
|
||||
|
||||
@@ -81,15 +90,15 @@ interface Proc_IFC;
|
||||
interface Put #(Bit #(4)) hart0_put_other_req;
|
||||
|
||||
// GPR access
|
||||
interface MemoryServer #(5, XLEN) hart0_gpr_mem_server;
|
||||
interface Server #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_server;
|
||||
|
||||
`ifdef ISA_F
|
||||
// FPR access
|
||||
interface MemoryServer #(5, FLEN) hart0_fpr_mem_server;
|
||||
interface Server #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_server;
|
||||
`endif
|
||||
|
||||
// CSR access
|
||||
interface MemoryServer #(12, XLEN) hart0_csr_mem_server;
|
||||
interface Server #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_server;
|
||||
`endif
|
||||
|
||||
endinterface
|
||||
|
||||
@@ -44,11 +44,11 @@ import SoC_Map :: *;
|
||||
import Debug_Module :: *;
|
||||
`endif
|
||||
|
||||
import Core_IFC :: *;
|
||||
import CoreW_IFC :: *;
|
||||
import PLIC :: *;
|
||||
import PLIC_16_2_7 :: *;
|
||||
import Proc_IFC :: *;
|
||||
import Proc :: *;
|
||||
import Proc_IFC :: *;
|
||||
import Proc :: *;
|
||||
|
||||
`ifdef INCLUDE_TANDEM_VERIF
|
||||
import TV_Info :: *;
|
||||
@@ -66,7 +66,7 @@ import TV_Taps :: *;
|
||||
// The Core module
|
||||
|
||||
(* synthesize *)
|
||||
module mkCoreW (Core_IFC #(N_External_Interrupt_Sources));
|
||||
module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
|
||||
|
||||
// ================================================================
|
||||
// STATE
|
||||
@@ -360,6 +360,13 @@ module mkCoreW (Core_IFC #(N_External_Interrupt_Sources));
|
||||
|
||||
interface core_external_interrupt_sources = plic.v_sources;
|
||||
|
||||
// ----------------
|
||||
// External interrupt [14] to go into Debug Mode
|
||||
|
||||
method Action debug_external_interrupt_req (Bool set_not_clear);
|
||||
proc.debug_external_interrupt_req (set_not_clear);
|
||||
endmethod
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Optional TV interface
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// Copyright (c) 2018-2019 Bluespec, Inc. All Rights Reserved.
|
||||
|
||||
package Core_IFC;
|
||||
package CoreW_IFC;
|
||||
|
||||
// ================================================================
|
||||
// This package defines the interface of a Core module which
|
||||
// This package defines the interface of a CoreW module which
|
||||
// contains:
|
||||
// - mkCPU (the RISC-V CPU)
|
||||
// - mkProc (the RISC-V CPU; this a variant of MIT's RISCY-OOO mkProc)
|
||||
// Note: MIT's RISCY-OOO internally contains a 'mkCore'
|
||||
// and hence this interface and its module is called
|
||||
// 'CoreW', to disambiguate.
|
||||
// - mkFabric_2x3
|
||||
// - mkNear_Mem_IO_AXI4
|
||||
// - mkPLIC_16_2_7
|
||||
@@ -38,9 +41,9 @@ import Debug_Module :: *;
|
||||
`endif
|
||||
|
||||
// ================================================================
|
||||
// The Core interface
|
||||
// The CoreW interface
|
||||
|
||||
interface Core_IFC #(numeric type t_n_interrupt_sources);
|
||||
interface CoreW_IFC #(numeric type t_n_interrupt_sources);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Debugging: set core's verbosity
|
||||
@@ -66,6 +69,12 @@ interface Core_IFC #(numeric type t_n_interrupt_sources);
|
||||
|
||||
interface Vector #(t_n_interrupt_sources, PLIC_Source_IFC) core_external_interrupt_sources;
|
||||
|
||||
// ----------------
|
||||
// External interrupt [14] to go into Debug Mode
|
||||
|
||||
(* always_ready, always_enabled *)
|
||||
method Action debug_external_interrupt_req (Bool set_not_clear);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Optional Tandem Verifier interface output tuples (n,vb),
|
||||
// where 'vb' is a vector of bytes
|
||||
@@ -600,7 +600,6 @@ endfunction
|
||||
|
||||
function Tuple2 #(Bit #(32), Vector #(TV_VB_SIZE, Byte)) encode_mdata (MemReqSize mem_req_size, WordXL word);
|
||||
Vector #(TV_VB_SIZE, Byte) vb = newVector;
|
||||
Bit #(32) n;
|
||||
vb [0] = word[7:0];
|
||||
vb [1] = word [15:8];
|
||||
vb [2] = word [23:16];
|
||||
@@ -611,12 +610,7 @@ function Tuple2 #(Bit #(32), Vector #(TV_VB_SIZE, Byte)) encode_mdata (MemReqSiz
|
||||
vb [6] = word [55:48];
|
||||
vb [7] = word [63:56];
|
||||
`endif
|
||||
n = case (mem_req_size)
|
||||
f3_SIZE_B: 1;
|
||||
f3_SIZE_H: 2;
|
||||
f3_SIZE_W: 4;
|
||||
f3_SIZE_D: 8;
|
||||
endcase;
|
||||
Bit #(32) n = (1 << pack(mem_req_size));
|
||||
return tuple2 (n, vb);
|
||||
endfunction
|
||||
|
||||
@@ -704,7 +698,6 @@ endfunction
|
||||
|
||||
function Tuple2 #(Bit #(32), Vector #(TV_VB_SIZE, Byte)) encode_stval (MemReqSize mem_req_size, WordXL word);
|
||||
Vector #(TV_VB_SIZE, Byte) vb = newVector;
|
||||
Bit #(32) n;
|
||||
vb [0] = te_op_addl_state;
|
||||
vb [1] = case (mem_req_size)
|
||||
f3_SIZE_B: te_op_addl_state_data8;
|
||||
@@ -722,12 +715,7 @@ function Tuple2 #(Bit #(32), Vector #(TV_VB_SIZE, Byte)) encode_stval (MemReqSiz
|
||||
vb [8] = word [55:48];
|
||||
vb [9] = word [63:56];
|
||||
`endif
|
||||
n = case (mem_req_size)
|
||||
f3_SIZE_B: 2 + 1;
|
||||
f3_SIZE_H: 2 + 2;
|
||||
f3_SIZE_W: 2 + 4;
|
||||
f3_SIZE_D: 2 + 8;
|
||||
endcase;
|
||||
Bit #(32) n = (1 << pack(mem_req_size)) + 2;
|
||||
return tuple2 (n, vb);
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import FIFOF :: *;
|
||||
import GetPut :: *;
|
||||
import ClientServer :: *;
|
||||
import Connectable :: *;
|
||||
import Memory :: *;
|
||||
|
||||
// ----------------
|
||||
// BSV additional libs
|
||||
@@ -30,8 +29,9 @@ import GetPut_Aux :: *;
|
||||
// ================================================================
|
||||
// Project imports
|
||||
|
||||
import ISA_Decls :: *;
|
||||
import TV_Info :: *;
|
||||
import ISA_Decls :: *;
|
||||
import DM_CPU_Req_Rsp :: *;
|
||||
import TV_Info :: *;
|
||||
|
||||
import AXI4_Types :: *;
|
||||
import Fabric_Defs :: *;
|
||||
@@ -115,21 +115,21 @@ endmodule: mkDM_Mem_Tap
|
||||
// DM-to-CPU GPR tap (for writes to GPRs)
|
||||
|
||||
interface DM_GPR_Tap_IFC;
|
||||
interface MemoryClient #(5, XLEN) client;
|
||||
interface MemoryServer #(5, XLEN) server;
|
||||
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 #(MemoryRequest #(5, XLEN)) f_req_in <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_in <- mkFIFOF;
|
||||
// req to CPU
|
||||
FIFOF #(MemoryRequest #(5, XLEN)) f_req_out <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_out <- mkFIFOF;
|
||||
// resp CPU->DM
|
||||
FIFOF #(MemoryResponse #(XLEN)) f_rsp <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
|
||||
// Tap to TV
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
|
||||
rule request;
|
||||
let req <- pop (f_req_in);
|
||||
@@ -145,8 +145,8 @@ module mkDM_GPR_Tap (DM_GPR_Tap_IFC);
|
||||
end
|
||||
endrule
|
||||
|
||||
interface MemoryClient client = toGPClient (f_req_out, f_rsp);
|
||||
interface MemoryServer server = toGPServer (f_req_in, f_rsp);
|
||||
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
|
||||
@@ -157,21 +157,21 @@ endmodule: mkDM_GPR_Tap
|
||||
`ifdef ISA_F_OR_D
|
||||
|
||||
interface DM_FPR_Tap_IFC;
|
||||
interface MemoryClient #(5, FLEN) client;
|
||||
interface MemoryServer #(5, FLEN) server;
|
||||
interface Get #(Trace_Data) trace_data_out;
|
||||
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 #(MemoryRequest #(5, FLEN)) f_req_in <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_in <- mkFIFOF;
|
||||
// req to CPU
|
||||
FIFOF #(MemoryRequest #(5, FLEN)) f_req_out <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_req_out <- mkFIFOF;
|
||||
// resp CPU->DM
|
||||
FIFOF #(MemoryResponse #(FLEN)) f_rsp <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
|
||||
// Tap to TV
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
|
||||
rule request;
|
||||
let req <- pop (f_req_in);
|
||||
@@ -187,8 +187,8 @@ module mkDM_FPR_Tap (DM_FPR_Tap_IFC);
|
||||
end
|
||||
endrule
|
||||
|
||||
interface MemoryClient client = toGPClient (f_req_out, f_rsp);
|
||||
interface MemoryServer server = toGPServer (f_req_in, f_rsp);
|
||||
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
|
||||
@@ -199,21 +199,21 @@ endmodule: mkDM_FPR_Tap
|
||||
// DM-to-CPU CSR tap (for writes to CSRs)
|
||||
|
||||
interface DM_CSR_Tap_IFC;
|
||||
interface MemoryClient #(12, XLEN) client;
|
||||
interface MemoryServer #(12, XLEN) server;
|
||||
interface Get #(Trace_Data) trace_data_out;
|
||||
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 #(MemoryRequest #(12, XLEN)) f_req_in <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_req_in <- mkFIFOF;
|
||||
// req to CPU
|
||||
FIFOF #(MemoryRequest #(12, XLEN)) f_req_out <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_req_out <- mkFIFOF;
|
||||
// resp CPU->DM
|
||||
FIFOF #(MemoryResponse #(XLEN)) f_rsp <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_rsp <- mkFIFOF;
|
||||
// Tap to TV
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
|
||||
|
||||
rule request;
|
||||
let req <- pop (f_req_in);
|
||||
@@ -228,8 +228,8 @@ module mkDM_CSR_Tap (DM_CSR_Tap_IFC);
|
||||
end
|
||||
endrule
|
||||
|
||||
interface MemoryClient client = toGPClient (f_req_out, f_rsp);
|
||||
interface MemoryServer server = toGPServer (f_req_in, f_rsp);
|
||||
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
|
||||
|
||||
@@ -9,7 +9,6 @@ package DM_Abstract_Commands;
|
||||
// ================================================================
|
||||
// BSV library imports
|
||||
|
||||
import Memory :: *;
|
||||
import FIFOF :: *;
|
||||
import GetPut :: *;
|
||||
import ClientServer :: *;
|
||||
@@ -23,8 +22,9 @@ import Cur_Cycle :: *;
|
||||
|
||||
// ================================================================
|
||||
|
||||
import ISA_Decls :: *;
|
||||
import DM_Common :: *;
|
||||
import ISA_Decls :: *;
|
||||
import DM_Common :: *;
|
||||
import DM_CPU_Req_Rsp :: *;
|
||||
|
||||
// ================================================================
|
||||
// Interface
|
||||
@@ -39,8 +39,11 @@ interface DM_Abstract_Commands_IFC;
|
||||
|
||||
// ----------------
|
||||
// Facing CPU/hart
|
||||
interface MemoryClient #(5, XLEN) hart0_gpr_mem_client;
|
||||
interface MemoryClient #(12, XLEN) hart0_csr_mem_client;
|
||||
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_client;
|
||||
`ifdef ISA_F
|
||||
interface Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_client;
|
||||
`endif
|
||||
interface Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_client;
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
@@ -55,12 +58,18 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
Reg #(Bool) rg_start_reg_access <- mkReg (False);
|
||||
|
||||
// FIFOs for request/response to access GPRs
|
||||
FIFOF #(MemoryRequest #(5, XLEN)) f_hart0_gpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(MemoryResponse #( XLEN)) f_hart0_gpr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_hart0_gpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_gpr_rsps <- mkFIFOF1;
|
||||
|
||||
// FIFOs for request/response to access FPRs
|
||||
`ifdef ISA_F
|
||||
FIFOF #(DM_CPU_Req #(5, FLEN)) f_hart0_fpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(FLEN)) f_hart0_fpr_rsps <- mkFIFOF1;
|
||||
`endif
|
||||
|
||||
// FIFOs for request/response to access CSRs
|
||||
FIFOF #(MemoryRequest #(12, XLEN)) f_hart0_csr_reqs <- mkFIFOF1;
|
||||
FIFOF #(MemoryResponse #( XLEN)) f_hart0_csr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_hart0_csr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_csr_rsps <- mkFIFOF1;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// rg_data0
|
||||
@@ -95,17 +104,17 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
action
|
||||
if (rg_abstractcs_busy) begin
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_BUSY;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [abstractcs] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [abstractcs] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" DM is busy with a previous abstract command");
|
||||
end
|
||||
else if (fn_abstractcs_cmderr (dm_word) != DM_ABSTRACTCS_CMDERR_NONE) begin
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_NONE;
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [abstractcs]: clearing cmderr", cur_cycle);
|
||||
$display ("%0d: DM_Abstract_Commands.write [abstractcs]: clearing cmderr", cur_cycle);
|
||||
end
|
||||
else begin
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [abstractcs]: cmderr unchanged", cur_cycle);
|
||||
$display ("%0d: DM_Abstract_Commands.write [abstractcs]: cmderr unchanged", cur_cycle);
|
||||
end
|
||||
endaction
|
||||
endfunction
|
||||
@@ -139,20 +148,20 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
|
||||
// Ignore if 'cmderr' is non-zero
|
||||
if (cmderr != DM_ABSTRACTCS_CMDERR_NONE) begin
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" Ignoring since 'cmderr' is 0x%0h", cmderr);
|
||||
end
|
||||
else begin
|
||||
if (rg_abstractcs_busy) begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_BUSY;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" DM is busy with a previous abstract command");
|
||||
end
|
||||
|
||||
// Only 'Access Reg' cmdtype is supported
|
||||
else if (fn_command_cmdtype (dm_word) != DM_COMMAND_CMDTYPE_ACCESS_REG) begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" ", fshow (fn_command_cmdtype (dm_word)), " not supported");
|
||||
end
|
||||
|
||||
@@ -160,7 +169,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
// Only lower 32-bit access is supported
|
||||
else if (size != DM_COMMAND_ACCESS_REG_SIZE_LOWER32) begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" For DM_COMMAND_CMDTYPE_ACCESS_REG, ",
|
||||
fshow (fn_command_access_reg_size (dm_word)), " not supported in RV32 mode");
|
||||
end
|
||||
@@ -170,7 +179,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
else if (size != DM_COMMAND_ACCESS_REG_SIZE_LOWER64)
|
||||
begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" For DM_COMMAND_CMDTYPE_ACCESS_REG, ",
|
||||
fshow (fn_command_access_reg_size (dm_word)), " not supported in RV64 mode");
|
||||
end
|
||||
@@ -179,14 +188,14 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
// 'postexec' is not supported
|
||||
else if (fn_command_access_reg_postexec (dm_word) == True) begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" For DM_COMMAND_CMDTYPE_ACCESS_REG, postexec not supported");
|
||||
end
|
||||
|
||||
// non-'transfer' is not supported
|
||||
else if (fn_command_access_reg_transfer (dm_word) == False) begin
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: ERROR", cur_cycle, dm_word);
|
||||
$display (" For DM_COMMAND_CMDTYPE_ACCESS_REG, no-transfer not supported");
|
||||
end
|
||||
|
||||
@@ -200,7 +209,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
rg_start_reg_access <= True;
|
||||
cmderr = DM_ABSTRACTCS_CMDERR_NONE;
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [command] <= 0x%08h: OKAY", cur_cycle, dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: OKAY", cur_cycle, dm_word);
|
||||
end
|
||||
rg_abstractcs_cmderr <= cmderr;
|
||||
end
|
||||
@@ -208,7 +217,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
endfunction
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Start reads/writes
|
||||
// Register reads and writes
|
||||
|
||||
Bool is_csr = ( (fromInteger (dm_command_access_reg_regno_csr_0) <= rg_command_access_reg_regno)
|
||||
&& (rg_command_access_reg_regno <= fromInteger (dm_command_access_reg_regno_csr_FFF)));
|
||||
@@ -216,173 +225,263 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
Bool is_gpr = ( (fromInteger (dm_command_access_reg_regno_gpr_0) <= rg_command_access_reg_regno)
|
||||
&& (rg_command_access_reg_regno <= fromInteger (dm_command_access_reg_regno_gpr_1F)));
|
||||
|
||||
`ifdef ISA_F
|
||||
Bool is_fpr = ( (fromInteger (dm_command_access_reg_regno_fpr_0) <= rg_command_access_reg_regno)
|
||||
&& (rg_command_access_reg_regno <= fromInteger (dm_command_access_reg_regno_fpr_1F)));
|
||||
`else
|
||||
Bool is_fpr = False;
|
||||
`endif
|
||||
|
||||
Bit #(12) csr_addr = truncate (rg_command_access_reg_regno - fromInteger (dm_command_access_reg_regno_csr_0));
|
||||
Bit #(5) gpr_addr = truncate (rg_command_access_reg_regno - fromInteger (dm_command_access_reg_regno_gpr_0));
|
||||
Bit #(5) fpr_addr = truncate (rg_command_access_reg_regno - fromInteger (dm_command_access_reg_regno_fpr_0));
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Read/Write CSR
|
||||
// Write CSR
|
||||
|
||||
rule rl_start_write_csr ( rg_abstractcs_busy
|
||||
rule rl_csr_write_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& is_csr);
|
||||
if (verbosity != 0)
|
||||
let req = DM_CPU_Req {write: True,
|
||||
address: csr_addr,
|
||||
`ifdef RV32
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: write CSR [0x%0h] <= 0x%08h", cur_cycle,
|
||||
csr_addr, rg_data0);
|
||||
data: rg_data0
|
||||
`endif
|
||||
`ifdef RV64
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: write CSR [0x%0h] <= 0x%016h", cur_cycle,
|
||||
csr_addr, {rg_data1, rg_data0});
|
||||
data: {rg_data1, rg_data0}
|
||||
`endif
|
||||
|
||||
let req = MemoryRequest {write: True, byteen: '1, address: csr_addr,
|
||||
`ifdef RV32
|
||||
data: rg_data0
|
||||
`endif
|
||||
`ifdef RV64
|
||||
data: {rg_data1, rg_data0}
|
||||
`endif
|
||||
};
|
||||
};
|
||||
f_hart0_csr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
rule rl_start_read_csr ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_csr);
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: read CSR [0x%0h]", cur_cycle, csr_addr);
|
||||
|
||||
let req = MemoryRequest {write: False, byteen: '1, address: csr_addr, data: ?};
|
||||
f_hart0_csr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
endrule
|
||||
|
||||
rule rl_finish_csr_read (rg_abstractcs_busy);
|
||||
let rsp <- pop (f_hart0_csr_rsps);
|
||||
`ifdef RV32
|
||||
rg_data0 <= rsp.data;
|
||||
`endif
|
||||
`ifdef RV64
|
||||
rg_data0 <= truncate (rsp.data);
|
||||
rg_data1 <= rsp.data[63:32];
|
||||
`endif
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_NONE;
|
||||
if (verbosity != 0)
|
||||
`ifdef RV32
|
||||
$display ("(%0d): DM_Abstract_Commands: csr read data is 0x%08h", cur_cycle, rsp.data);
|
||||
`endif
|
||||
`ifdef RV64
|
||||
$display ("(%0d): DM_Abstract_Commands: csr read data is 0x%016h", cur_cycle, rsp.data);
|
||||
`endif
|
||||
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Read/Write GPR
|
||||
|
||||
rule rl_start_write_gpr ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& is_gpr);
|
||||
if (verbosity != 0)
|
||||
`ifdef RV32
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: write GPR [0x%0h] <= 0x%08h", cur_cycle,
|
||||
gpr_addr, rg_data0);
|
||||
`endif
|
||||
`ifdef RV64
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: write GPR [0x%0h] <= 0x%016h", cur_cycle,
|
||||
gpr_addr, {rg_data1, rg_data0});
|
||||
`endif
|
||||
|
||||
let req = MemoryRequest {write: True,
|
||||
byteen: '1,
|
||||
address: gpr_addr,
|
||||
`ifdef RV32
|
||||
data: rg_data0
|
||||
`endif
|
||||
`ifdef RV64
|
||||
data: {rg_data1, rg_data0}
|
||||
`endif
|
||||
};
|
||||
|
||||
f_hart0_gpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
rule rl_start_read_gpr ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_gpr);
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: read GPR [0x%0h]", cur_cycle, gpr_addr);
|
||||
|
||||
let req = MemoryRequest {
|
||||
write: False
|
||||
, byteen: '1
|
||||
, address: gpr_addr
|
||||
, data: ?
|
||||
};
|
||||
f_hart0_gpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
endrule
|
||||
|
||||
rule rl_finish_gpr_read (rg_abstractcs_busy);
|
||||
let rsp <- pop (f_hart0_gpr_rsps);
|
||||
`ifdef RV32
|
||||
rg_data0 <= rsp.data;
|
||||
`endif
|
||||
`ifdef RV64
|
||||
rg_data0 <= truncate (rsp.data);
|
||||
rg_data1 <= rsp.data[63:32];
|
||||
`endif
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_NONE;
|
||||
if (verbosity != 0)
|
||||
`ifdef RV32
|
||||
$display ("(%0d): DM_Abstract_Commands: gpr read data is 0x%08h", cur_cycle, rsp.data);
|
||||
`endif
|
||||
`ifdef RV64
|
||||
$display ("(%0d): DM_Abstract_Commands: gpr read data is 0x%016h", cur_cycle, rsp.data);
|
||||
`endif
|
||||
rg_abstractcs_busy <= False;
|
||||
$display ("%0d: DM_Abstract_Commands.rl_csr_write_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
// Read/Write unknown address
|
||||
|
||||
rule rl_start_write_unknown ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& (! is_csr) && (! is_gpr));
|
||||
rule rl_csr_write_finish (rg_abstractcs_busy
|
||||
&& rg_command_access_reg_write
|
||||
&& is_csr);
|
||||
let rsp <- pop (f_hart0_csr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: write unknown RISC-V regno [0x%0h] <= 0x%08h", cur_cycle,
|
||||
rg_command_access_reg_regno, rg_data0);
|
||||
$display ("%0d: DM_Abstract_Commands.rl_csr_write_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_OTHER;
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
rule rl_start_read_unknown ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& (! is_csr) && (! is_gpr));
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write [command]: read unknown RISC-V regno [0x%0h] => ...", cur_cycle,
|
||||
rg_command_access_reg_regno);
|
||||
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_OTHER;
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Finish CSR and GPR reads
|
||||
// Read CSR
|
||||
|
||||
rule rl_csr_read_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_csr);
|
||||
Bit #(XLEN) data = ?;
|
||||
let req = DM_CPU_Req {write: False, address: csr_addr, data: data};
|
||||
f_hart0_csr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_csr_read_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
|
||||
rule rl_csr_read_finish ( rg_abstractcs_busy
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_csr);
|
||||
let rsp <- pop (f_hart0_csr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_csr_read_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
`ifdef RV32
|
||||
rg_data0 <= rsp.data;
|
||||
`endif
|
||||
`ifdef RV64
|
||||
rg_data0 <= truncate (rsp.data);
|
||||
rg_data1 <= rsp.data[63:32];
|
||||
`endif
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Write GPR
|
||||
|
||||
rule rl_gpr_write_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& is_gpr);
|
||||
let req = DM_CPU_Req {write: True,
|
||||
address: gpr_addr,
|
||||
`ifdef RV32
|
||||
data: rg_data0
|
||||
`endif
|
||||
`ifdef RV64
|
||||
data: {rg_data1, rg_data0}
|
||||
`endif
|
||||
};
|
||||
f_hart0_gpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
|
||||
rule rl_gpr_write_finish ( rg_abstractcs_busy
|
||||
&& rg_command_access_reg_write
|
||||
&& is_gpr);
|
||||
let rsp <- pop (f_hart0_gpr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Read GPR
|
||||
|
||||
rule rl_gpr_read_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_gpr);
|
||||
Bit #(XLEN) data = ?;
|
||||
let req = DM_CPU_Req {write: False, address: gpr_addr, data: data };
|
||||
f_hart0_gpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
|
||||
rule rl_gpr_read_finish ( rg_abstractcs_busy
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_gpr);
|
||||
let rsp <- pop (f_hart0_gpr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
`ifdef RV32
|
||||
rg_data0 <= rsp.data;
|
||||
`endif
|
||||
`ifdef RV64
|
||||
rg_data0 <= truncate (rsp.data);
|
||||
rg_data1 <= rsp.data[63:32];
|
||||
`endif
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Write FPR
|
||||
|
||||
`ifdef ISA_F
|
||||
|
||||
rule rl_fpr_write_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& is_fpr);
|
||||
let req = DM_CPU_Req {write: True,
|
||||
address: fpr_addr,
|
||||
`ifdef RV32
|
||||
data: rg_data0
|
||||
`endif
|
||||
`ifdef RV64
|
||||
data: {rg_data1, rg_data0}
|
||||
`endif
|
||||
};
|
||||
f_hart0_fpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
|
||||
rule rl_fpr_write_finish ( rg_abstractcs_busy
|
||||
&& rg_command_access_reg_write
|
||||
&& is_fpr);
|
||||
let rsp <- pop (f_hart0_fpr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Read FPR
|
||||
|
||||
rule rl_fpr_read_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_fpr);
|
||||
Bit #(XLEN) data = ?;
|
||||
let req = DM_CPU_Req {write: False, address: fpr_addr, data: data };
|
||||
f_hart0_fpr_reqs.enq (req);
|
||||
rg_start_reg_access <= False;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_start: ", cur_cycle, fshow (req));
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
|
||||
rule rl_fpr_read_finish ( rg_abstractcs_busy
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& is_fpr);
|
||||
let rsp <- pop (f_hart0_fpr_rsps);
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_finish: ", cur_cycle, fshow (rsp));
|
||||
|
||||
`ifdef RV32
|
||||
rg_data0 <= rsp.data;
|
||||
`endif
|
||||
`ifdef RV64
|
||||
rg_data0 <= truncate (rsp.data);
|
||||
rg_data1 <= rsp.data[63:32];
|
||||
`endif
|
||||
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
`endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Read/Write unknown address
|
||||
|
||||
rule rl_unknown_write_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& rg_command_access_reg_write
|
||||
&& (! is_csr) && (! is_gpr) && (! is_fpr));
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_unknown_write_start: unknown RISC-V regno [0x%0h] <= 0x%08h",
|
||||
cur_cycle, rg_command_access_reg_regno, rg_data0);
|
||||
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_OTHER;
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
rule rl_unknown_read_start ( rg_abstractcs_busy
|
||||
&& rg_start_reg_access
|
||||
&& (! rg_command_access_reg_write)
|
||||
&& (! is_csr) && (! is_gpr) && (! is_fpr));
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: DM_Abstract_Commands.rl_unknown_read_start: unknown RISC-V regno [0x%0h]",
|
||||
cur_cycle, rg_command_access_reg_regno);
|
||||
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_OTHER;
|
||||
rg_start_reg_access <= False;
|
||||
rg_abstractcs_busy <= False;
|
||||
endrule
|
||||
|
||||
// ================================================================
|
||||
// INTERFACE
|
||||
@@ -407,7 +506,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
`endif
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands: reset", cur_cycle);
|
||||
$display ("%0d: DM_Abstract_Commands: reset", cur_cycle);
|
||||
endmethod
|
||||
|
||||
// ----------------
|
||||
@@ -428,7 +527,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
// dm_addr_progbuf0..15
|
||||
endcase;
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.av_read: [", cur_cycle, dm_addr_name, "] => 0x%08h", dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.av_read: [", cur_cycle, dm_addr_name, "] => 0x%08h", dm_word);
|
||||
return dm_word;
|
||||
endactionvalue
|
||||
endmethod
|
||||
@@ -442,7 +541,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
|
||||
else if (rg_abstractcs_cmderr != DM_ABSTRACTCS_CMDERR_NONE) begin
|
||||
if (verbosity != 0) begin
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h: ERROR", dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h: ERROR", dm_word);
|
||||
$display (" Ignoring: previous cmderr ", fshow (rg_abstractcs_cmderr));
|
||||
end
|
||||
end
|
||||
@@ -454,14 +553,14 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
rg_data0 <= dm_word;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h", dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h", dm_word);
|
||||
end
|
||||
`ifdef RV64
|
||||
else if (dm_addr == dm_addr_data1) begin
|
||||
rg_data1 <= dm_word;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h", dm_word);
|
||||
$display ("%0d: DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name, "] <= 0x%08h", dm_word);
|
||||
end
|
||||
`endif
|
||||
else begin
|
||||
@@ -470,7 +569,7 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
// dm_addr_progbuf0..15
|
||||
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED;
|
||||
|
||||
$display ("(%0d): DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name,
|
||||
$display ("%0d: DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name,
|
||||
"] <= 0x%08h: ERROR: not supported", dm_word);
|
||||
end
|
||||
endaction
|
||||
@@ -478,8 +577,11 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
|
||||
// ----------------
|
||||
// Facing CPU/hart
|
||||
interface MemoryClient hart0_gpr_mem_client = toGPClient (f_hart0_gpr_reqs, f_hart0_gpr_rsps);
|
||||
interface MemoryClient hart0_csr_mem_client = toGPClient (f_hart0_csr_reqs, f_hart0_csr_rsps);
|
||||
interface Client hart0_gpr_mem_client = toGPClient (f_hart0_gpr_reqs, f_hart0_gpr_rsps);
|
||||
`ifdef ISA_F
|
||||
interface Client hart0_fpr_mem_client = toGPClient (f_hart0_fpr_reqs, f_hart0_fpr_rsps);
|
||||
`endif
|
||||
interface Client hart0_csr_mem_client = toGPClient (f_hart0_csr_reqs, f_hart0_csr_rsps);
|
||||
endmodule
|
||||
|
||||
// ================================================================
|
||||
|
||||
36
src_Core/Debug_Module/DM_CPU_Req_Rsp.bsv
Normal file
36
src_Core/Debug_Module/DM_CPU_Req_Rsp.bsv
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2017-2019 Bluespec, Inc. All Rights Reserved.
|
||||
|
||||
package DM_CPU_Req_Rsp;
|
||||
|
||||
// ================================================================
|
||||
// This package defines types for register access request and response
|
||||
|
||||
// ================================================================
|
||||
// BSV library imports
|
||||
|
||||
// None
|
||||
|
||||
// ================================================================
|
||||
// Project imports
|
||||
|
||||
// None
|
||||
|
||||
// ================================================================
|
||||
// Requests and responses
|
||||
|
||||
typedef struct {
|
||||
Bool write;
|
||||
Bit #(a) address;
|
||||
Bit #(d) data;
|
||||
} DM_CPU_Req #(numeric type a, numeric type d)
|
||||
deriving (Bits, Eq, FShow);
|
||||
|
||||
typedef struct {
|
||||
Bool ok;
|
||||
Bit #(d) data;
|
||||
} DM_CPU_Rsp #(numeric type d)
|
||||
deriving (Bits, Eq, FShow);
|
||||
|
||||
// ================================================================
|
||||
|
||||
endpackage
|
||||
@@ -177,6 +177,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: ndmreset=1: resetting platform",
|
||||
dm_word);
|
||||
f_ndm_reset_reqs.enq (?);
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_reset!
|
||||
|
||||
// Error-checking
|
||||
if (hartreset) begin
|
||||
@@ -197,6 +198,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: hartreset=1: resetting hart",
|
||||
dm_word);
|
||||
f_hart0_reset_reqs.enq (?);
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_reset!
|
||||
end
|
||||
else begin
|
||||
// Deassert hart reset
|
||||
@@ -273,7 +275,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
method Action reset;
|
||||
f_ndm_reset_reqs.clear;
|
||||
|
||||
rg_hart0_running <= False; // Must be same as initial state of CPU
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_reset!
|
||||
f_hart0_reset_reqs.clear;
|
||||
f_hart0_run_halt_reqs.clear;
|
||||
f_hart0_run_halt_rsps.clear;
|
||||
|
||||
@@ -71,6 +71,7 @@ import AXI4_Types :: *;
|
||||
import Fabric_Defs :: *;
|
||||
|
||||
import DM_Common :: *;
|
||||
import DM_CPU_Req_Rsp :: *;
|
||||
import DM_Run_Control :: *;
|
||||
import DM_Abstract_Commands :: *;
|
||||
import DM_System_Bus :: *;
|
||||
@@ -100,10 +101,15 @@ interface Debug_Module_IFC;
|
||||
interface Get #(Bit #(4)) hart0_get_other_req;
|
||||
|
||||
// GPR access
|
||||
interface MemoryClient #(5, XLEN) hart0_gpr_mem_client;
|
||||
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_client;
|
||||
|
||||
// FPR access
|
||||
`ifdef ISA_F
|
||||
interface Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_client;
|
||||
`endif
|
||||
|
||||
// CSR access
|
||||
interface MemoryClient #(12, XLEN) hart0_csr_mem_client;
|
||||
interface Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_client;
|
||||
|
||||
// ----------------
|
||||
// Facing Platform
|
||||
@@ -267,10 +273,15 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
interface Get hart0_get_other_req = dm_run_control.hart0_get_other_req;
|
||||
|
||||
// GPR access
|
||||
interface MemoryClient hart0_gpr_mem_client = dm_abstract_commands.hart0_gpr_mem_client;
|
||||
interface Client hart0_gpr_mem_client = dm_abstract_commands.hart0_gpr_mem_client;
|
||||
|
||||
// FPR access
|
||||
`ifdef ISA_F
|
||||
interface Client hart0_fpr_mem_client = dm_abstract_commands.hart0_fpr_mem_client;
|
||||
`endif
|
||||
|
||||
// CSR access
|
||||
interface MemoryClient hart0_csr_mem_client = dm_abstract_commands.hart0_csr_mem_client;
|
||||
interface Client hart0_csr_mem_client = dm_abstract_commands.hart0_csr_mem_client;
|
||||
|
||||
// ----------------
|
||||
// Facing Platform
|
||||
|
||||
@@ -443,10 +443,13 @@ typedef enum {
|
||||
MachineTimer = 4'd7,
|
||||
UserExternal = 4'd8,
|
||||
SupervisorExternel = 4'd9,
|
||||
MachineExternal = 4'd11
|
||||
MachineExternal = 4'd11,
|
||||
|
||||
DebugExternal = 4'd14 // Bluespec: for debug mode
|
||||
} Interrupt deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef 12 InterruptNum;
|
||||
// typedef 12 InterruptNum;
|
||||
typedef 15 InterruptNum; // Bluespec: extended to 15 bits for debug interrupt
|
||||
|
||||
// Traps are either an exception or an interrupt
|
||||
typedef union tagged {
|
||||
|
||||
Reference in New Issue
Block a user