Files
Toooba/src_Core/Debug_Module/DM_Common.bsv

513 lines
19 KiB
Plaintext

// Copyright (c) 2017-2019 Bluespec, Inc. All Rights Reserved.
package DM_Common;
// ================================================================
// This package has non-implementation-specific definitions, i.e.,
// just encodes things in the spec.
// ================================================================
// BSV library imports
// None
// ================================================================
// Project imports
// None
// ================================================================
// Debug Module Interface (DMI) addresses and data.
// Note: data is always 32b, whether the connected CPU is RV32, RV64 or RV128.
typedef Bit #(7) DM_Addr;
DM_Addr max_DM_Addr = 'h5F;
typedef Bit #(32) DM_Word;
// ================================================================
// Debug Module address map
// ----------------
// Run Control
DM_Addr dm_addr_dmcontrol = 'h10;
DM_Addr dm_addr_dmstatus = 'h11;
DM_Addr dm_addr_hartinfo = 'h12;
DM_Addr dm_addr_haltsum = 'h13;
DM_Addr dm_addr_hawindowsel = 'h14;
DM_Addr dm_addr_hawindow = 'h15;
DM_Addr dm_addr_devtreeaddr0 = 'h19;
DM_Addr dm_addr_authdata = 'h30;
DM_Addr dm_addr_haltregion0 = 'h40;
DM_Addr dm_addr_haltregion31 = 'h5F;
DM_Addr dm_addr_verbosity = 'h60; // Non-standard (not in spec)
// ----------------
// Abstract commands (read/write RISC-V registers and RISC-V CSRs)
DM_Addr dm_addr_abstractcs = 'h16;
DM_Addr dm_addr_command = 'h17;
DM_Addr dm_addr_data0 = 'h04;
DM_Addr dm_addr_data1 = 'h05;
DM_Addr dm_addr_data2 = 'h06;
DM_Addr dm_addr_data3 = 'h07;
DM_Addr dm_addr_data4 = 'h08;
DM_Addr dm_addr_data5 = 'h09;
DM_Addr dm_addr_data6 = 'h0a;
DM_Addr dm_addr_data7 = 'h0b;
DM_Addr dm_addr_data8 = 'h0c;
DM_Addr dm_addr_data9 = 'h0d;
DM_Addr dm_addr_data10 = 'h0d;
DM_Addr dm_addr_data11 = 'h0f;
DM_Addr dm_addr_abstractauto = 'h18;
DM_Addr dm_addr_progbuf0 = 'h20;
// ----------------
// System Bus access (read/write RISC-V memory/devices)
DM_Addr dm_addr_sbcs = 'h38;
DM_Addr dm_addr_sbaddress0 = 'h39;
DM_Addr dm_addr_sbaddress1 = 'h3a;
DM_Addr dm_addr_sbaddress2 = 'h3b;
DM_Addr dm_addr_sbdata0 = 'h3c;
DM_Addr dm_addr_sbdata1 = 'h3d;
DM_Addr dm_addr_sbdata2 = 'h3e;
DM_Addr dm_addr_sbdata3 = 'h3f;
// ================================================================
function Fmt fshow_dm_addr (DM_Addr dm_addr);
return case (dm_addr)
// Run Control
dm_addr_dmcontrol: $format ("dm_addr_dmcontrol");
dm_addr_dmstatus: $format ("dm_addr_dmstatus");
dm_addr_hartinfo: $format ("dm_addr_hartinfo");
dm_addr_haltsum: $format ("dm_addr_haltsum");
dm_addr_hawindowsel: $format ("dm_addr_hawindowsel");
dm_addr_hawindow: $format ("dm_addr_hawindow");
dm_addr_devtreeaddr0: $format ("dm_addr_devtreeaddr0");
dm_addr_authdata: $format ("dm_addr_authdata");
dm_addr_haltregion0: $format ("dm_addr_haltregion0");
dm_addr_haltregion31: $format ("dm_addr_haltregion31");
dm_addr_verbosity: $format ("dm_addr_verbosity");
// Abstract Commands
dm_addr_abstractcs: $format ("dm_addr_abstractcs");
dm_addr_command: $format ("dm_addr_command");
dm_addr_data0: $format ("dm_addr_data0");
dm_addr_data1: $format ("dm_addr_data1");
dm_addr_data2: $format ("dm_addr_data2");
dm_addr_data3: $format ("dm_addr_data3");
dm_addr_data4: $format ("dm_addr_data4");
dm_addr_data5: $format ("dm_addr_data5");
dm_addr_data6: $format ("dm_addr_data6");
dm_addr_data7: $format ("dm_addr_data7");
dm_addr_data8: $format ("dm_addr_data8");
dm_addr_data9: $format ("dm_addr_data9");
dm_addr_data10: $format ("dm_addr_data10");
dm_addr_data11: $format ("dm_addr_data11");
dm_addr_abstractauto: $format ("dm_addr_abstractauto");
dm_addr_progbuf0: $format ("dm_addr_progbuf0");
// System Bus
dm_addr_sbcs: $format ("dm_addr_sbcs");
dm_addr_sbaddress0: $format ("dm_addr_sbaddress0");
dm_addr_sbaddress1: $format ("dm_addr_sbaddress1");
dm_addr_sbaddress2: $format ("dm_addr_sbaddress2");
dm_addr_sbdata0: $format ("dm_addr_sbdata0");
dm_addr_sbdata1: $format ("dm_addr_sbdata1");
dm_addr_sbdata2: $format ("dm_addr_sbdata2");
dm_addr_sbdata3: $format ("dm_addr_sbdata3");
default: $format ("<Unknown dm_abstract_command dm_addr 0x%0h>", dm_addr);
endcase;
endfunction
// ================================================================
// Run Control DM register fields
// ----------------------------------------------------------------
// 'dmcontrol' register
function DM_Word fn_mk_dmcontrol (Bool haltreq,
Bool resumereq,
Bool hartreset,
Bool hasel,
Bit #(10) hartsel,
Bool ndmreset,
Bool dmactive);
return {pack (haltreq),
pack (resumereq),
pack (hartreset),
2'b0,
pack (hasel),
hartsel,
14'b0,
pack (ndmreset),
pack (dmactive)};
endfunction
function Bool fn_dmcontrol_haltreq (DM_Word dm_word);
return unpack (dm_word [31]);
endfunction
function Bool fn_dmcontrol_resumereq (DM_Word dm_word);
return unpack (dm_word [30]);
endfunction
function Bool fn_dmcontrol_hartreset (DM_Word dm_word);
return unpack (dm_word [29]);
endfunction
function Bool fn_dmcontrol_hasel (DM_Word dm_word);
return unpack (dm_word [26]);
endfunction
function Bit #(10) fn_dmcontrol_hartsel (DM_Word dm_word);
return dm_word [25:16];
endfunction
function Bool fn_dmcontrol_ndmreset (DM_Word dm_word);
return unpack (dm_word [1]);
endfunction
function Bool fn_dmcontrol_dmactive (DM_Word dm_word);
return unpack (dm_word [0]);
endfunction
// ----------------------------------------------------------------
// 'dmstatus' register
function Bool fn_dmstatus_allresumeack (DM_Word x);
return unpack (x [17]);
endfunction
function Bool fn_dmstatus_anyresumeack (DM_Word x);
return unpack (x [16]);
endfunction
function Bool fn_dmstatus_allnonexistent (DM_Word x);
return unpack (x [15]);
endfunction
function Bool fn_dmstatus_anynonexistent (DM_Word x);
return unpack (x [14]);
endfunction
function Bool fn_dmstatus_allunavail (DM_Word x);
return unpack (x [13]);
endfunction
function Bool fn_dmstatus_anyunavail (DM_Word x);
return unpack (x [12]);
endfunction
function Bool fn_dmstatus_allrunning (DM_Word x);
return unpack (x [11]);
endfunction
function Bool fn_dmstatus_anyrunning (DM_Word x);
return unpack (x [10]);
endfunction
function Bool fn_dmstatus_allhalted (DM_Word x);
return unpack (x [9]);
endfunction
function Bool fn_dmstatus_anyhalted (DM_Word x);
return unpack (x [8]);
endfunction
function Bool fn_dmstatus_authenticated (DM_Word x);
return unpack (x [7]);
endfunction
function Bool fn_dmstatus_authbusy (DM_Word x);
return unpack (x [6]);
endfunction
function Bool fn_dmstatus_devtreevalid (DM_Word x);
return unpack (x [4]);
endfunction
function Bit #(4) fn_dmstatus_version (DM_Word x);
return unpack (x [3:0]);
endfunction
function Fmt fshow_dmstatus (DM_Word x);
Fmt fmt_version = ( (x[3:0] == 0)
? $format ("v.none")
: ( (x[3:0] == 1)
? $format ("v0.11")
: ( (x[3:0] == 2)
? $format ("v0.13")
: $format ("v??"))));
return ( $format ("(all/any) ")
+ $format ("resumeack %0d/%0d ", x[17], x[16])
+ $format ("nonexistent %0d/%0d ", x[15], x[14])
+ $format ("unavail %0d/%0d ", x[13], x[12])
+ $format ("running %0d/%0d ", x[11], x[10])
+ $format ("halted %0d/%0d ", x[9], x[8])
+ $format ("authenticated %0d ", x[7])
+ $format ("authbusy %0d ", x[6])
+ $format ("devtreevalid %0d ", x[4])
+ fmt_version);
endfunction
// ================================================================
// Abstract Command register fields
// ----------------------------------------------------------------
// 'dm_abstractcs' register
typedef enum {DM_ABSTRACTCS_CMDERR_NONE, // 0
DM_ABSTRACTCS_CMDERR_BUSY, // 1
DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED, // 2
DM_ABSTRACTCS_CMDERR_EXCEPTION, // 3
DM_ABSTRACTCS_CMDERR_HALT_RESUME, // 4
DM_ABSTRACTCS_CMDERR_UNDEF5, // 5
DM_ABSTRACTCS_CMDERR_UNDEF6, // 6
DM_ABSTRACTCS_CMDERR_OTHER // 7
} DM_abstractcs_cmderr
deriving (Bits, Eq, FShow);
// The following is used in writes, to clear cmderr
DM_abstractcs_cmderr dm_cmderr_w1c = DM_ABSTRACTCS_CMDERR_OTHER;
function DM_Word fn_mk_abstractcs (DM_abstractcs_cmderr cmderr);
return { 0, pack (cmderr), 8'h0 };
endfunction
function Bit #(5) fn_abstractcs_progsize (DM_Word dm_word);
return unpack (dm_word [28:24]);
endfunction
function Bool fn_abstractcs_busy (DM_Word dm_word);
return unpack (dm_word [12]);
endfunction
function DM_abstractcs_cmderr fn_abstractcs_cmderr (DM_Word dm_word);
return unpack (dm_word [10:8]);
endfunction
function Bit #(5) fn_abstractcs_datacount (DM_Word dm_word);
return unpack (dm_word [4:0]);
endfunction
// ----------------------------------------------------------------
// 'command' register
typedef enum {DM_COMMAND_CMDTYPE_ACCESS_REG,
DM_COMMAND_CMDTYPE_QUICK_ACCESS
} DM_command_cmdtype
deriving (Bits, Eq, FShow);
typedef enum {DM_COMMAND_ACCESS_REG_SIZE_UNDEF0, // 0
DM_COMMAND_ACCESS_REG_SIZE_UNDEF1, // 1
DM_COMMAND_ACCESS_REG_SIZE_LOWER32, // 2
DM_COMMAND_ACCESS_REG_SIZE_LOWER64, // 3
DM_COMMAND_ACCESS_REG_SIZE_LOWER128, // 4
DM_COMMAND_ACCESS_REG_SIZE_UNDEF5, // 5
DM_COMMAND_ACCESS_REG_SIZE_UNDEF6, // 6
DM_COMMAND_ACCESS_REG_SIZE_UNDEF7 // 7
} DM_command_access_reg_size
deriving (Bits, Eq, FShow);
Integer dm_command_access_reg_regno_csr_0 = 'h0000;
Integer dm_command_access_reg_regno_csr_FFF = 'h0FFF;
Integer dm_command_access_reg_regno_gpr_0 = 'h1000;
Integer dm_command_access_reg_regno_gpr_1F = 'h101F;
Integer dm_command_access_reg_regno_fpr_0 = 'h1020;
Integer dm_command_access_reg_regno_fpr_1F = 'h103F;
function DM_Word fn_mk_command_access_reg (DM_command_access_reg_size size,
Bool postexec,
Bool transfer,
Bool write,
Bit #(16) regno);
Bit #(8) b8_cmdtype = zeroExtend (pack (DM_COMMAND_CMDTYPE_ACCESS_REG));
Bit #(3) b3_size = pack (size);
return {b8_cmdtype,
1'b0,
b3_size,
1'b0,
pack (postexec),
pack (transfer),
pack (write),
regno};
endfunction
function DM_command_cmdtype fn_command_cmdtype (DM_Word dm_word);
return unpack (truncate (dm_word [31:24]));
endfunction
function DM_command_access_reg_size fn_command_access_reg_size (DM_Word dm_word);
return unpack (dm_word [22:20]);
endfunction
function Bool fn_command_access_reg_postexec (DM_Word dm_word);
return unpack (dm_word [18]);
endfunction
function Bool fn_command_access_reg_transfer (DM_Word dm_word);
return unpack (dm_word [17]);
endfunction
function Bool fn_command_access_reg_write (DM_Word dm_word);
return unpack (dm_word [16]);
endfunction
function Bit #(16) fn_command_access_reg_regno (DM_Word dm_word);
return dm_word [15:0];
endfunction
// ================================================================
// System Bus Access DM register fields
// ----------------------------------------------------------------
// 'dm_sbcs' register
typedef enum {DM_SBACCESS_8_BIT,
DM_SBACCESS_16_BIT,
DM_SBACCESS_32_BIT,
DM_SBACCESS_64_BIT,
DM_SBACCESS_128_BIT
} DM_sbaccess
deriving (Bits, Eq, FShow);
function Integer fn_sbaccess_to_addr_incr (DM_sbaccess sbaccess);
case (sbaccess)
DM_SBACCESS_8_BIT: return 1;
DM_SBACCESS_16_BIT: return 2;
DM_SBACCESS_32_BIT: return 4;
DM_SBACCESS_64_BIT: return 8;
DM_SBACCESS_128_BIT: return 16;
endcase
endfunction
typedef enum {DM_SBERROR_NONE, // 0
DM_SBERROR_TIMEOUT, // 1
DM_SBERROR_BADADDR, // 2
DM_SBERROR_OTHER, // 3
DM_SBERROR_BUSY_STALE, // 4
DM_SBERROR_UNDEF5, // 5
DM_SBERROR_UNDEF6, // 6
DM_SBERROR_UNDEF7_W1C // 7, used in writes, to clear sberror
} DM_sberror
deriving (Bits, Eq, FShow);
// Constructor
function DM_Word fn_mk_sbcs_val (Bit #(3) sbversion,
Bool sbbusyerror,
Bool sbbusy,
Bool sbreadonaddr,
DM_sbaccess sbaccess,
Bool sbautoincrement,
Bool sbreadondata,
DM_sberror sberror,
Bit #(7) sbasize,
Bit #(1) sbaccess128,
Bit #(1) sbaccess64,
Bit #(1) sbaccess32,
Bit #(1) sbaccess16,
Bit #(1) sbaccess8);
return {sbversion,
6'b0,
pack (sbbusyerror),
pack (sbbusy),
pack (sbreadonaddr),
pack (sbaccess),
pack (sbautoincrement),
pack (sbreadondata),
pack (sberror),
sbasize,
sbaccess128,
sbaccess64,
sbaccess32,
sbaccess16,
sbaccess8};
endfunction
// Selectors
function Bit #(3) fn_sbcs_sbversion (DM_Word dm_word); return unpack (dm_word [31:29]); endfunction
function Bool fn_sbcs_sbbusyerror (DM_Word dm_word); return unpack (dm_word [22]); endfunction
function Bool fn_sbcs_sbbusy (DM_Word dm_word); return unpack (dm_word [21]); endfunction
function Bool fn_sbcs_sbreadonaddr (DM_Word dm_word); return unpack (dm_word [20]); endfunction
function DM_sbaccess fn_sbcs_sbaccess (DM_Word dm_word); return unpack (dm_word [19:17]); endfunction
function Bool fn_sbcs_sbautoincrement (DM_Word dm_word); return unpack (dm_word [16]); endfunction
function Bool fn_sbcs_sbreadondata (DM_Word dm_word); return unpack (dm_word [15]); endfunction
function DM_sberror fn_sbcs_sberror (DM_Word dm_word); return unpack (dm_word [14:12]); endfunction
function Bit #(7) fn_sbcs_sbasize (DM_Word dm_word); return dm_word [11:5]; endfunction
function Bool fn_sbcs_sbaccess128 (DM_Word dm_word); return unpack (dm_word [4]); endfunction
function Bool fn_sbcs_sbaccess64 (DM_Word dm_word); return unpack (dm_word [3]); endfunction
function Bool fn_sbcs_sbaccess32 (DM_Word dm_word); return unpack (dm_word [2]); endfunction
function Bool fn_sbcs_sbaccess16 (DM_Word dm_word); return unpack (dm_word [1]); endfunction
function Bool fn_sbcs_sbaccess8 (DM_Word dm_word); return unpack (dm_word [0]); endfunction
// Debugging
function Fmt fshow_sbcs (DM_Word dm_word);
return ( $format ("SBCS{")
+ $format ("sbversion %0d", fn_sbcs_sbversion (dm_word))
+ $format (" sbbusyerror %0d", fn_sbcs_sbbusyerror (dm_word))
+ $format (" sbbusy %0d", fn_sbcs_sbbusy (dm_word))
+ $format (" sbreadonaddr ") + fshow (fn_sbcs_sbreadonaddr (dm_word))
+ $format (" sbaccess ") + fshow (fn_sbcs_sbaccess (dm_word))
+ $format (" sbautoincrement ") + fshow (fn_sbcs_sbautoincrement (dm_word))
+ $format (" sbreadondata ") + fshow (fn_sbcs_sbreadondata (dm_word))
+ $format (" sberror ") + fshow (fn_sbcs_sberror (dm_word))
+ $format (" sbasize %0d", fn_sbcs_sbasize (dm_word))
+ $format (" sbaccess")
+ ((fn_sbcs_sbaccess128 (dm_word)) ? $format ("_128") : $format ("x"))
+ ((fn_sbcs_sbaccess64 (dm_word)) ? $format ("_64") : $format ("x"))
+ ((fn_sbcs_sbaccess32 (dm_word)) ? $format ("_32") : $format ("x"))
+ ((fn_sbcs_sbaccess16 (dm_word)) ? $format ("_16") : $format ("x"))
+ ((fn_sbcs_sbaccess8 (dm_word)) ? $format ("_8") : $format ("x"))
+ $format ("}"));
endfunction
// ================================================================
// DCSR 'cause' field values
typedef enum {DCSR_CAUSE_RESERVED0,
DCSR_CAUSE_EBREAK,
DCSR_CAUSE_TRIGGER,
DCSR_CAUSE_HALTREQ,
DCSR_CAUSE_STEP,
DCSR_CAUSE_RESERVED5,
DCSR_CAUSE_RESERVED6,
DCSR_CAUSE_RESERVED7
} DCSR_Cause
deriving (Bits, Eq, FShow);
// ================================================================
// Sub-interface of the Debug Module facing the remote debugger (e.g. GDB)
interface DMI;
method Action read_addr (DM_Addr dm_addr);
method ActionValue #(DM_Word) read_data;
method Action write (DM_Addr dm_addr, DM_Word dm_word);
endinterface
// A dummy interface to tie off DMI if it is not used.
DMI dummy_DMI_ifc = interface DMI;
method Action read_addr (DM_Addr dm_addr) = noAction;
method ActionValue #(DM_Word) read_data = actionvalue
return 0;
endactionvalue;
method Action write (DM_Addr dm_addr, DM_Word dm_word) = noAction;
endinterface;
// ================================================================
endpackage