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:
rsnikhil
2019-04-01 12:26:54 -04:00
parent 85b745be9f
commit 113f888d37
346 changed files with 3296935 additions and 282 deletions

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
// ================================================================

View 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

View File

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

View File

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

View File

@@ -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 {