Files
Toooba/src_Core/ISA/TV_Info.bsv
2019-03-26 14:49:40 -04:00

363 lines
11 KiB
Plaintext

// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
// ================================================================
// Definition of Tandem Verifier Packets.
// The CPU sends out such a packet for each instruction retired.
// A Tandem Verifier contains a "golden model" simulator of the RISC-V
// ISA, and verifies that the information in the packet is correct,
// instruction by instruction.
// ================================================================
package TV_Info;
// ================================================================
// Bluespec library imports
import DefaultValue :: *;
import Vector :: *;
// ================================================================
// Project imports
import ISA_Decls :: *;
// ================================================================
typedef enum {// These are not from instruction flow and do not have a PC or instruction
TRACE_RESET,
TRACE_GPR_WRITE,
TRACE_FPR_WRITE,
TRACE_CSR_WRITE,
TRACE_MEM_WRITE,
// These are from instruction flow and have a PC and instruction
TRACE_OTHER,
TRACE_I_RD, TRACE_F_RD,
TRACE_I_LOAD, TRACE_F_LOAD,
TRACE_STORE,
TRACE_AMO,
TRACE_TRAP,
TRACE_RET,
TRACE_CSRRX,
// These are from an interrupt and has a PC but no instruction
TRACE_INTR
} Trace_Op
deriving (Bits, Eq, FShow);
typedef struct {
Trace_Op op;
WordXL pc;
ISize instr_sz;
Bit #(32) instr;
RegName rd;
WordXL word1;
WordXL word2;
Bit #(64) word3; // Wider than WordXL because can contain paddr (in RV32, paddr can be 34 bits)
WordXL word4;
} Trace_Data
deriving (Bits);
// RESET
// op pc instr_sz instr rd word1 word2 word3 word4
// x
function Trace_Data mkTrace_RESET ();
Trace_Data td = ?;
td.op = TRACE_RESET;
return td;
endfunction
// GPR_WRITE
// op pc instr_sz instr rd word1 word2 word3 word4
// x x rdval
function Trace_Data mkTrace_GPR_WRITE (RegName rd, WordXL rdval);
Trace_Data td = ?;
td.op = TRACE_GPR_WRITE;
td.rd = rd;
td.word1 = rdval;
return td;
endfunction
// FPR_WRITE
// op pc instr_sz instr rd word1 word2 word3 word4
// x x rdval
function Trace_Data mkTrace_FPR_WRITE (RegName rd, WordXL rdval);
Trace_Data td = ?;
td.op = TRACE_FPR_WRITE;
td.rd = rd;
td.word1 = rdval;
return td;
endfunction
// CSR_WRITE
// op pc instr_sz instr rd word1 word2 word3 word4
// x csraddr csrval
function Trace_Data mkTrace_CSR_WRITE (CSR_Addr csraddr, WordXL csrval);
Trace_Data td = ?;
td.op = TRACE_CSR_WRITE;
td.word3 = zeroExtend (csraddr);
td.word4 = csrval;
return td;
endfunction
// MEM_WRITE
// op pc instr_sz instr rd word1 word2 word3 word4
// x sz stval paddr
function Trace_Data mkTrace_MEM_WRITE (MemReqSize sz, WordXL stval, Bit #(64) paddr);
Trace_Data td = ?;
td.op = TRACE_MEM_WRITE;
td.word1 = zeroExtend (sz);
td.word2 = stval;
td.word3 = paddr;
return td;
endfunction
// OTHER
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x
function Trace_Data mkTrace_OTHER (WordXL pc, ISize isize, Bit #(32) instr);
Trace_Data td = ?;
td.op = TRACE_OTHER;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
return td;
endfunction
// I_RD
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval
function Trace_Data mkTrace_I_RD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval);
Trace_Data td = ?;
td.op = TRACE_I_RD;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
return td;
endfunction
// F_RD
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval
function Trace_Data mkTrace_F_RD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval);
Trace_Data td = ?;
td.op = TRACE_F_RD;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
return td;
endfunction
// I_LOAD
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval eaddr
function Trace_Data mkTrace_I_LOAD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval, WordXL eaddr);
Trace_Data td = ?;
td.op = TRACE_I_LOAD;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
td.word3 = zeroExtend (eaddr);
return td;
endfunction
// F_LOAD
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval eaddr
function Trace_Data mkTrace_F_LOAD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval, WordXL eaddr);
Trace_Data td = ?;
td.op = TRACE_F_LOAD;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
td.word3 = zeroExtend (eaddr);
return td;
endfunction
// STORE
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x stval eaddr
function Trace_Data mkTrace_STORE (WordXL pc, ISize isize, Bit #(32) instr, WordXL stval, WordXL eaddr);
Trace_Data td = ?;
td.op = TRACE_STORE;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.word2 = stval;
td.word3 = zeroExtend (eaddr);
return td;
endfunction
// AMO
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval stval eaddr
function Trace_Data mkTrace_AMO (WordXL pc, ISize isize, Bit #(32) instr,
RegName rd, WordXL rdval, WordXL stval, WordXL eaddr);
Trace_Data td = ?;
td.op = TRACE_AMO;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
td.word2 = stval;
td.word3 = zeroExtend (eaddr);
return td;
endfunction
// TRAP
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x priv mstatus mcause mepc mtval
function Trace_Data mkTrace_TRAP (WordXL pc, ISize isize, Bit #(32) instr,
Priv_Mode priv, WordXL mstatus, WordXL mcause, WordXL mepc, WordXL mtval);
Trace_Data td = ?;
td.op = TRACE_TRAP;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = zeroExtend (priv);
td.word1 = mstatus;
td.word2 = mcause;
td.word3 = zeroExtend (mepc);
td.word4 = mtval;
return td;
endfunction
// RET
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x priv mstatus
function Trace_Data mkTrace_RET (WordXL pc, ISize isize, Bit #(32) instr, Priv_Mode priv, WordXL mstatus);
Trace_Data td = ?;
td.op = TRACE_RET;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = zeroExtend (priv);
td.word1 = mstatus;
return td;
endfunction
// CSRRX
// op pc instr_sz instr rd word1 word2 word3 word4
// x x x x x rdval csrvalid csraddr csrval
function Trace_Data mkTrace_CSRRX (WordXL pc, ISize isize, Bit #(32) instr,
RegName rd, WordXL rdval, Bool csrvalid, CSR_Addr csraddr, WordXL csrval);
Trace_Data td = ?;
td.op = TRACE_CSRRX;
td.pc = pc;
td.instr_sz = isize;
td.instr = instr;
td.rd = rd;
td.word1 = rdval;
td.word2 = (csrvalid ? 1 : 0);
td.word3 = zeroExtend (csraddr);
td.word4 = csrval;
return td;
endfunction
// INTR
// op pc instr_sz instr rd word1 word2 word3 word4
// x x priv mstatus mcause mepc mtval
function Trace_Data mkTrace_INTR (WordXL pc,
Priv_Mode priv, WordXL mstatus, WordXL mcause, WordXL mepc, WordXL mtval);
Trace_Data td = ?;
td.op = TRACE_INTR;
td.pc = pc;
td.rd = zeroExtend (priv);
td.word1 = mstatus;
td.word2 = mcause;
td.word3 = zeroExtend (mepc);
td.word4 = mtval;
return td;
endfunction
// ================================================================
// Display of Trace_Data for debugging
instance FShow #(Trace_Data);
function Fmt fshow (Trace_Data td);
Fmt fmt = $format ("Trace_Data{", fshow (td.op));
if (td.op == TRACE_RESET) begin
end
else if ((td.op == TRACE_GPR_WRITE) || (td.op == TRACE_FPR_WRITE))
fmt = fmt + $format (" rd %0d rdval %0h", td.rd, td.word1);
else if (td.op == TRACE_CSR_WRITE)
fmt = fmt + $format (" csraddr %0h csrval %0h", td.word3, td.word4);
else if (td.op == TRACE_MEM_WRITE)
fmt = fmt + $format (" sz %0d stval %0h paddr %0h", td.word1, td.word2, td.word3);
else begin
fmt = fmt + $format (" pc %0h", td.pc);
if (td.op != TRACE_INTR)
fmt = fmt + $format (" instr.%0d %0h:", pack (td.instr_sz), td.instr);
if ((td.op == TRACE_I_RD) || (td.op == TRACE_F_RD))
fmt = fmt + $format (" rd %0d rdval %0h", td.rd, td.word1);
else if ((td.op == TRACE_I_LOAD) || (td.op == TRACE_F_LOAD))
fmt = fmt + $format (" rd %0d rdval %0h eaddr %0h",
td.rd, td.word1, td.word3);
else if (td.op == TRACE_STORE)
fmt = fmt + $format (" stval %0h eaddr %0h", td.word2, td.word3);
else if (td.op == TRACE_AMO)
fmt = fmt + $format (" rd %0d rdval %0h stval %0h eaddr %0h",
td.rd, td.word1, td.word2, td.word3);
else if (td.op == TRACE_CSRRX)
fmt = fmt + $format (" rd %0d rdval %0h csraddr %0h csrval %0h",
td.rd, td.word1, td.word3, td.word4);
else if ((td.op == TRACE_TRAP) || (td.op == TRACE_INTR))
fmt = fmt + $format (" priv %0d mstatus %0h mcause %0h mepc %0h mtval %0h",
td.rd, td.word1, td.word2, td.word3, td.word4);
else if (td.op == TRACE_RET)
fmt = fmt + $format (" priv %0d mstatus %0h", td.rd, td.word1);
end
fmt = fmt + $format ("}");
return fmt;
endfunction
endinstance
// ================================================================
// Trace_Data is encoded in module mkTV_Encode into vectors of bytes,
// which are eventually streamed out to an on-line tandem verifier/
// analyzer (or to a file for off-line tandem-verification/analysis).
// Various 'transactions' produce a Trace_Data struct (e.g., reset,
// each instruction retirement, each GDB write to registers or memory,
// etc.). Each struct is encoded into a vector of bytes; the number
// of bytes depends on the kind of transaction and various encoding
// choices.
typedef 72 TV_VB_SIZE; // max bytes needed for each transaction
typedef Vector #(TV_VB_SIZE, Byte) TV_Vec_Bytes;
// ================================================================
typedef struct {
Bit #(32) num_bytes;
TV_Vec_Bytes vec_bytes;
} Info_CPU_to_Verifier deriving (Bits, FShow);
// ================================================================
endpackage