URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/orpsocv2/bench
- from Rev 456 to Rev 462
- ↔ Reverse comparison
Rev 456 → Rev 462
/sysc/include/RspPacket.h
31,46 → 31,40
|
#include <iostream> |
|
|
//----------------------------------------------------------------------------- |
//! Class for RSP packets |
|
//! Can't be null terminated, since it may include zero bytes |
//----------------------------------------------------------------------------- |
class RspPacket |
{ |
class RspPacket { |
public: |
|
//! The data buffer. Allow direct access to avoid unnecessary copying. |
char *data; |
//! The data buffer. Allow direct access to avoid unnecessary copying. |
char *data; |
|
// Constructor and destructor |
RspPacket (int _bufSize); |
~RspPacket (); |
// Constructor and destructor |
RspPacket(int _bufSize); |
~RspPacket(); |
|
// Pack a constant string into a packet |
void packStr (const char *str); // For fixed packets |
|
// Accessors |
int getBufSize (); |
int getLen (); |
void setLen (int _len); |
// Pack a constant string into a packet |
void packStr(const char *str); // For fixed packets |
|
// Accessors |
int getBufSize(); |
int getLen(); |
void setLen(int _len); |
|
private: |
|
//! The data buffer size |
int bufSize; |
//! The data buffer size |
int bufSize; |
|
//! Number of chars in the data buffer (<= bufSize) |
int len; |
//! Number of chars in the data buffer (<= bufSize) |
int len; |
|
}; |
|
|
//! Stream output |
std::ostream &operator<< (std::ostream &s, |
RspPacket &p); |
std::ostream & operator<<(std::ostream & s, RspPacket & p); |
|
|
#endif // RSP_PACKET_SC__H |
#endif // RSP_PACKET_SC__H |
/sysc/include/Utils.h
31,36 → 31,30
|
#include <stdint.h> |
|
|
//----------------------------------------------------------------------------- |
//! A class offering a number of convenience utilities for the GDB Server. |
|
//! All static functions. This class is not intended to be instantiated. |
//----------------------------------------------------------------------------- |
class Utils |
{ |
class Utils { |
public: |
|
static uint8_t char2Hex (int c); |
static const char hex2Char (uint8_t d); |
static void reg2Hex (uint32_t val, |
char *buf); |
static uint32_t hex2Reg (char *buf); |
static void ascii2Hex (char *dest, |
char *src); |
static void hex2Ascii (char *dest, |
char *src); |
static int rspUnescape (char *buf, |
int len); |
static uint32_t htotl (uint32_t hostVal); |
static uint32_t ttohl (uint32_t targetVal); |
static uint8_t char2Hex(int c); |
static const char hex2Char(uint8_t d); |
static void reg2Hex(uint32_t val, char *buf); |
static uint32_t hex2Reg(char *buf); |
static void ascii2Hex(char *dest, char *src); |
static void hex2Ascii(char *dest, char *src); |
static int rspUnescape(char *buf, int len); |
static uint32_t htotl(uint32_t hostVal); |
static uint32_t ttohl(uint32_t targetVal); |
|
|
private: |
|
// Private constructor cannot be instantiated |
Utils () {}; |
// Private constructor cannot be instantiated |
Utils() { |
}; |
|
}; // class Utils |
}; // class Utils |
|
#endif // UTILS_H |
#endif // UTILS_H |
/sysc/include/UartSC.h
30,30 → 30,28
|
//! Handle UART I/O |
|
class UartSC |
: public sc_core::sc_module |
{ |
class UartSC:public sc_core::sc_module { |
public: |
|
// Constructor |
UartSC (sc_core::sc_module_name name); |
// Constructor |
UartSC(sc_core::sc_module_name name); |
|
// The ports |
sc_in<bool> clk; |
sc_in<bool> uarttx; |
sc_out<bool> uartrx; |
// The ports |
sc_in < bool > clk; |
sc_in < bool > uarttx; |
sc_out < bool > uartrx; |
|
// Init function |
void initUart (int clk_freq_hz, int uart_baud) ; |
// Transmit (from ORPSoC) handling function |
void checkTx(); |
// Init function |
void initUart(int clk_freq_hz, int uart_baud); |
// Transmit (from ORPSoC) handling function |
void checkTx(); |
|
private: |
int clocks_per_bit; |
uint8_t current_char; |
int counter; |
int bits_received; |
int clocks_per_bit; |
uint8_t current_char; |
int counter; |
int bits_received; |
|
}; // UartSC () |
}; // UartSC () |
|
#endif // UART_SC__H |
#endif // UART_SC__H |
/sysc/include/JtagSC_includes.h
28,7 → 28,6
|
// $Id$ |
|
|
#include "JtagSC.h" |
#include "TapActionDRScan.h" |
#include "TapAction.h" |
/sysc/include/MemCache.h
31,7 → 31,6
|
#include <stdint.h> |
|
|
//! Module for cacheing memory accesses by the debug unit |
|
//! Memory reads and writes through the Debug Unit via JTAG are time |
46,33 → 45,29
//! In the event of a clash on write, the old value is replaced by the new |
//! value. |
|
class MemCache |
{ |
class MemCache { |
public: |
|
// Constructor and destructor |
MemCache (int _tableSize = 1009); |
~MemCache (); |
// Constructor and destructor |
MemCache(int _tableSize = 1009); |
~MemCache(); |
|
// Functions |
void clear (); |
void write (uint32_t addr, |
uint32_t value); |
bool read (uint32_t addr, |
uint32_t &value); |
// Functions |
void clear(); |
void write(uint32_t addr, uint32_t value); |
bool read(uint32_t addr, uint32_t & value); |
|
private: |
|
//! The size of the hash table. A prime number is a good choice. |
int tableSize; |
//! The size of the hash table. A prime number is a good choice. |
int tableSize; |
|
// The hash table, keyed by address. Done as three parallel vectors, |
// allowing unambiguous clearing by use of memset for efficiency. |
bool *tabIsValid; |
uint32_t *tabKeyAddr; |
uint32_t *tabValue; |
// The hash table, keyed by address. Done as three parallel vectors, |
// allowing unambiguous clearing by use of memset for efficiency. |
bool *tabIsValid; |
uint32_t *tabKeyAddr; |
uint32_t *tabValue; |
|
}; // MemCache () |
|
}; // MemCache () |
|
#endif // MEM_CACHE__H |
#endif // MEM_CACHE__H |
/sysc/include/elf.h
21,17 → 21,17
#endif |
|
#ifdef OR32_TYPES |
typedef uint32_t Elf32_Addr; |
typedef uint16_t Elf32_Half; |
typedef uint32_t Elf32_Off; |
typedef int32_t Elf32_Sword; |
typedef uint32_t Elf32_Word; |
typedef uint32_t Elf32_Addr; |
typedef uint16_t Elf32_Half; |
typedef uint32_t Elf32_Off; |
typedef int32_t Elf32_Sword; |
typedef uint32_t Elf32_Word; |
#else |
typedef unsigned long Elf32_Addr; |
typedef unsigned short Elf32_Half; |
typedef unsigned long Elf32_Off; |
typedef long Elf32_Sword; |
typedef unsigned long Elf32_Word; |
typedef unsigned long Elf32_Addr; |
typedef unsigned short Elf32_Half; |
typedef unsigned long Elf32_Off; |
typedef long Elf32_Sword; |
typedef unsigned long Elf32_Word; |
#endif |
|
/* These constants are for the segment types stored in the image headers */ |
61,7 → 61,7
#define EM_386 3 |
#define EM_68K 4 |
#define EM_88K 5 |
#define EM_486 6 /* Perhaps disused */ |
#define EM_486 6 /* Perhaps disused */ |
#define EM_860 7 |
|
#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ |
82,7 → 82,6
*/ |
#define EM_ALPHA 0x9026 |
|
|
/* This is the info that is needed to parse the dynamic section of the file */ |
#define DT_NULL 0 |
#define DT_NEEDED 1 |
127,37 → 126,36
|
/* Symbolic values for the entries in the auxiliary table |
put on the initial stack */ |
#define AT_NULL 0 /* end of vector */ |
#define AT_IGNORE 1 /* entry should be ignored */ |
#define AT_EXECFD 2 /* file descriptor of program */ |
#define AT_PHDR 3 /* program headers for program */ |
#define AT_PHENT 4 /* size of program header entry */ |
#define AT_PHNUM 5 /* number of program headers */ |
#define AT_PAGESZ 6 /* system page size */ |
#define AT_BASE 7 /* base address of interpreter */ |
#define AT_FLAGS 8 /* flags */ |
#define AT_ENTRY 9 /* entry point of program */ |
#define AT_NOTELF 10 /* program is not ELF */ |
#define AT_UID 11 /* real uid */ |
#define AT_EUID 12 /* effective uid */ |
#define AT_GID 13 /* real gid */ |
#define AT_EGID 14 /* effective gid */ |
#define AT_NULL 0 /* end of vector */ |
#define AT_IGNORE 1 /* entry should be ignored */ |
#define AT_EXECFD 2 /* file descriptor of program */ |
#define AT_PHDR 3 /* program headers for program */ |
#define AT_PHENT 4 /* size of program header entry */ |
#define AT_PHNUM 5 /* number of program headers */ |
#define AT_PAGESZ 6 /* system page size */ |
#define AT_BASE 7 /* base address of interpreter */ |
#define AT_FLAGS 8 /* flags */ |
#define AT_ENTRY 9 /* entry point of program */ |
#define AT_NOTELF 10 /* program is not ELF */ |
#define AT_UID 11 /* real uid */ |
#define AT_EUID 12 /* effective uid */ |
#define AT_GID 13 /* real gid */ |
#define AT_EGID 14 /* effective gid */ |
|
|
typedef struct dynamic{ |
Elf32_Sword d_tag; |
union{ |
Elf32_Sword d_val; |
Elf32_Addr d_ptr; |
} d_un; |
typedef struct dynamic { |
Elf32_Sword d_tag; |
union { |
Elf32_Sword d_val; |
Elf32_Addr d_ptr; |
} d_un; |
} Elf32_Dyn; |
|
typedef struct { |
unsigned long long d_tag; /* entry tag value */ |
union { |
unsigned long long d_val; |
unsigned long long d_ptr; |
} d_un; |
unsigned long long d_tag; /* entry tag value */ |
union { |
unsigned long long d_val; |
unsigned long long d_ptr; |
} d_un; |
} Elf64_Dyn; |
|
/* The following are used with relocations */ |
202,80 → 200,79
#define R_68K_RELATIVE 22 |
|
typedef struct elf32_rel { |
Elf32_Addr r_offset; |
Elf32_Word r_info; |
Elf32_Addr r_offset; |
Elf32_Word r_info; |
} Elf32_Rel; |
|
typedef struct elf64_rel { |
unsigned long long r_offset; /* Location at which to apply the action */ |
unsigned long long r_info; /* index and type of relocation */ |
unsigned long long r_offset; /* Location at which to apply the action */ |
unsigned long long r_info; /* index and type of relocation */ |
} Elf64_Rel; |
|
typedef struct elf32_rela{ |
Elf32_Addr r_offset; |
Elf32_Word r_info; |
Elf32_Sword r_addend; |
typedef struct elf32_rela { |
Elf32_Addr r_offset; |
Elf32_Word r_info; |
Elf32_Sword r_addend; |
} Elf32_Rela; |
|
typedef struct elf64_rela { |
unsigned long long r_offset; /* Location at which to apply the action */ |
unsigned long long r_info; /* index and type of relocation */ |
unsigned long long r_addend; /* Constant addend used to compute value */ |
unsigned long long r_offset; /* Location at which to apply the action */ |
unsigned long long r_info; /* index and type of relocation */ |
unsigned long long r_addend; /* Constant addend used to compute value */ |
} Elf64_Rela; |
|
typedef struct elf32_sym{ |
Elf32_Word st_name; |
Elf32_Addr st_value; |
Elf32_Word st_size; |
unsigned char st_info; |
unsigned char st_other; |
Elf32_Half st_shndx; |
typedef struct elf32_sym { |
Elf32_Word st_name; |
Elf32_Addr st_value; |
Elf32_Word st_size; |
unsigned char st_info; |
unsigned char st_other; |
Elf32_Half st_shndx; |
} Elf32_Sym; |
|
typedef struct elf64_sym { |
unsigned int st_name; /* Symbol name, index in string tbl */ |
unsigned char st_info; /* Type and binding attributes */ |
unsigned char st_other; /* No defined meaning, 0 */ |
unsigned short st_shndx; /* Associated section index */ |
unsigned long long st_value; /* Value of the symbol */ |
unsigned long long st_size; /* Associated symbol size */ |
unsigned int st_name; /* Symbol name, index in string tbl */ |
unsigned char st_info; /* Type and binding attributes */ |
unsigned char st_other; /* No defined meaning, 0 */ |
unsigned short st_shndx; /* Associated section index */ |
unsigned long long st_value; /* Value of the symbol */ |
unsigned long long st_size; /* Associated symbol size */ |
} Elf64_Sym; |
|
|
#define EI_NIDENT 16 |
|
typedef struct elf32_hdr{ |
unsigned char e_ident[EI_NIDENT]; |
Elf32_Half e_type; |
Elf32_Half e_machine; |
Elf32_Word e_version; |
Elf32_Addr e_entry; /* Entry point */ |
Elf32_Off e_phoff; |
Elf32_Off e_shoff; |
Elf32_Word e_flags; |
Elf32_Half e_ehsize; |
Elf32_Half e_phentsize; |
Elf32_Half e_phnum; |
Elf32_Half e_shentsize; |
Elf32_Half e_shnum; |
Elf32_Half e_shstrndx; |
typedef struct elf32_hdr { |
unsigned char e_ident[EI_NIDENT]; |
Elf32_Half e_type; |
Elf32_Half e_machine; |
Elf32_Word e_version; |
Elf32_Addr e_entry; /* Entry point */ |
Elf32_Off e_phoff; |
Elf32_Off e_shoff; |
Elf32_Word e_flags; |
Elf32_Half e_ehsize; |
Elf32_Half e_phentsize; |
Elf32_Half e_phnum; |
Elf32_Half e_shentsize; |
Elf32_Half e_shnum; |
Elf32_Half e_shstrndx; |
} Elf32_Ehdr; |
|
typedef struct elf64_hdr { |
unsigned char e_ident[16]; /* ELF "magic number" */ |
short int e_type; |
short unsigned int e_machine; |
int e_version; |
unsigned long long e_entry; /* Entry point virtual address */ |
unsigned long long e_phoff; /* Program header table file offset */ |
unsigned long long e_shoff; /* Section header table file offset */ |
int e_flags; |
short int e_ehsize; |
short int e_phentsize; |
short int e_phnum; |
short int e_shentsize; |
short int e_shnum; |
short int e_shstrndx; |
unsigned char e_ident[16]; /* ELF "magic number" */ |
short int e_type; |
short unsigned int e_machine; |
int e_version; |
unsigned long long e_entry; /* Entry point virtual address */ |
unsigned long long e_phoff; /* Program header table file offset */ |
unsigned long long e_shoff; /* Section header table file offset */ |
int e_flags; |
short int e_ehsize; |
short int e_phentsize; |
short int e_phnum; |
short int e_shentsize; |
short int e_shnum; |
short int e_shstrndx; |
} Elf64_Ehdr; |
|
/* These constants define the permissions on sections in the program |
284,26 → 281,26
#define PF_W 0x2 |
#define PF_X 0x1 |
|
typedef struct elf32_phdr{ |
Elf32_Word p_type; |
Elf32_Off p_offset; |
Elf32_Addr p_vaddr; |
Elf32_Addr p_paddr; |
Elf32_Word p_filesz; |
Elf32_Word p_memsz; |
Elf32_Word p_flags; |
Elf32_Word p_align; |
typedef struct elf32_phdr { |
Elf32_Word p_type; |
Elf32_Off p_offset; |
Elf32_Addr p_vaddr; |
Elf32_Addr p_paddr; |
Elf32_Word p_filesz; |
Elf32_Word p_memsz; |
Elf32_Word p_flags; |
Elf32_Word p_align; |
} Elf32_Phdr; |
|
typedef struct elf64_phdr { |
int p_type; |
int p_flags; |
unsigned long long p_offset; /* Segment file offset */ |
unsigned long long p_vaddr; /* Segment virtual address */ |
unsigned long long p_paddr; /* Segment physical address */ |
unsigned long long p_filesz; /* Segment size in file */ |
unsigned long long p_memsz; /* Segment size in memory */ |
unsigned long long p_align; /* Segment alignment, file & memory */ |
int p_type; |
int p_flags; |
unsigned long long p_offset; /* Segment file offset */ |
unsigned long long p_vaddr; /* Segment virtual address */ |
unsigned long long p_paddr; /* Segment physical address */ |
unsigned long long p_filesz; /* Segment size in file */ |
unsigned long long p_memsz; /* Segment size in memory */ |
unsigned long long p_align; /* Segment alignment, file & memory */ |
} Elf64_Phdr; |
|
/* sh_type */ |
339,34 → 336,34
#define SHN_ABS 0xfff1 |
#define SHN_COMMON 0xfff2 |
#define SHN_HIRESERVE 0xffff |
|
|
typedef struct elf32_shdr { |
Elf32_Word sh_name; |
Elf32_Word sh_type; |
Elf32_Word sh_flags; |
Elf32_Addr sh_addr; |
Elf32_Off sh_offset; |
Elf32_Word sh_size; |
Elf32_Word sh_link; |
Elf32_Word sh_info; |
Elf32_Word sh_addralign; |
Elf32_Word sh_entsize; |
Elf32_Word sh_name; |
Elf32_Word sh_type; |
Elf32_Word sh_flags; |
Elf32_Addr sh_addr; |
Elf32_Off sh_offset; |
Elf32_Word sh_size; |
Elf32_Word sh_link; |
Elf32_Word sh_info; |
Elf32_Word sh_addralign; |
Elf32_Word sh_entsize; |
} Elf32_Shdr; |
|
typedef struct elf64_shdr { |
unsigned int sh_name; /* Section name, index in string tbl */ |
unsigned int sh_type; /* Type of section */ |
unsigned long long sh_flags; /* Miscellaneous section attributes */ |
unsigned long long sh_addr; /* Section virtual addr at execution */ |
unsigned long long sh_offset; /* Section file offset */ |
unsigned long long sh_size; /* Size of section in bytes */ |
unsigned int sh_link; /* Index of another section */ |
unsigned int sh_info; /* Additional section information */ |
unsigned long long sh_addralign; /* Section alignment */ |
unsigned long long sh_entsize; /* Entry size if section holds table */ |
unsigned int sh_name; /* Section name, index in string tbl */ |
unsigned int sh_type; /* Type of section */ |
unsigned long long sh_flags; /* Miscellaneous section attributes */ |
unsigned long long sh_addr; /* Section virtual addr at execution */ |
unsigned long long sh_offset; /* Section file offset */ |
unsigned long long sh_size; /* Size of section in bytes */ |
unsigned int sh_link; /* Index of another section */ |
unsigned int sh_info; /* Additional section information */ |
unsigned long long sh_addralign; /* Section alignment */ |
unsigned long long sh_entsize; /* Entry size if section holds table */ |
} Elf64_Shdr; |
|
#define EI_MAG0 0 /* e_ident[] indexes */ |
#define EI_MAG0 0 /* e_ident[] indexes */ |
#define EI_MAG1 1 |
#define EI_MAG2 2 |
#define EI_MAG3 3 |
375,7 → 372,7
#define EI_VERSION 6 |
#define EI_PAD 7 |
|
#define ELFMAG0 0x7f /* EI_MAG */ |
#define ELFMAG0 0x7f /* EI_MAG */ |
#define ELFMAG1 'E' |
#define ELFMAG2 'L' |
#define ELFMAG3 'F' |
382,16 → 379,16
#define ELFMAG "\177ELF" |
#define SELFMAG 4 |
|
#define ELFCLASSNONE 0 /* EI_CLASS */ |
#define ELFCLASSNONE 0 /* EI_CLASS */ |
#define ELFCLASS32 1 |
#define ELFCLASS64 2 |
#define ELFCLASSNUM 3 |
|
#define ELFDATANONE 0 /* e_ident[EI_DATA] */ |
#define ELFDATANONE 0 /* e_ident[EI_DATA] */ |
#define ELFDATA2LSB 1 |
#define ELFDATA2MSB 2 |
|
#define EV_NONE 0 /* e_version, EI_VERSION */ |
#define EV_NONE 0 /* e_version, EI_VERSION */ |
#define EV_CURRENT 1 |
#define EV_NUM 2 |
|
403,9 → 400,9
|
/* Note header in a PT_NOTE section */ |
typedef struct elf32_note { |
Elf32_Word n_namesz; /* Name size */ |
Elf32_Word n_descsz; /* Content size */ |
Elf32_Word n_type; /* Content type */ |
Elf32_Word n_namesz; /* Name size */ |
Elf32_Word n_descsz; /* Content size */ |
Elf32_Word n_type; /* Content type */ |
} Elf32_Nhdr; |
|
/* Note header in a PT_NOTE section */ |
415,9 → 412,9
* is only 32 bits. |
*/ |
typedef struct elf64_note { |
unsigned int n_namesz; /* Name size */ |
unsigned int n_descsz; /* Content size */ |
unsigned int n_type; /* Content type */ |
unsigned int n_namesz; /* Name size */ |
unsigned int n_descsz; /* Content size */ |
unsigned int n_type; /* Content type */ |
} Elf64_Nhdr; |
|
#ifdef __mc68000__ |
429,7 → 426,7
|
#if ELF_CLASS == ELFCLASS32 |
|
extern Elf32_Dyn _DYNAMIC []; |
extern Elf32_Dyn _DYNAMIC[]; |
#define elfhdr elf32_hdr |
#define elf_phdr elf32_phdr |
#define elf_note elf32_note |
436,7 → 433,7
|
#else |
|
extern Elf64_Dyn _DYNAMIC []; |
extern Elf64_Dyn _DYNAMIC[]; |
#define elfhdr elf64_hdr |
#define elf_phdr elf64_phdr |
#define elf_note elf64_note |
443,5 → 440,4
|
#endif |
|
|
#endif /* _LINUX_ELF_H */ |
/sysc/include/MemoryLoad.h
24,7 → 24,6
/* Here we define some often used caharcters in assembly files. This wil |
probably go into architecture dependent directory. */ |
|
|
#ifndef MEMORYLOAD__H |
#define MEMORYLOAD__H |
|
41,9 → 40,9
#define PRINTF(x...) |
|
/* Basic types for openrisc */ |
typedef uint32_t oraddr_t; /*!< Address as addressed by openrisc */ |
typedef uint32_t uorreg_t; /*!< An unsigned register of openrisc */ |
typedef int32_t orreg_t; /*!< A signed register of openrisc */ |
typedef uint32_t oraddr_t; /*!< Address as addressed by openrisc */ |
typedef uint32_t uorreg_t; /*!< An unsigned register of openrisc */ |
typedef int32_t orreg_t; /*!< A signed register of openrisc */ |
|
/* From abstract.h */ |
#define DEFAULT_MEMORY_START 0 |
73,8 → 72,6
#define ULONGEST unsigned long long |
#endif /* ULONGEST */ |
|
|
|
#define PRIx32 "x" |
#define PRIx16 "hx" |
#define PRIx8 "hhx" |
89,19 → 86,17
#define LE16(x) bswap_16(x) |
|
/*! Instruction queue */ |
struct iqueue_entry |
{ |
int insn_index; |
uint32_t insn; |
oraddr_t insn_addr; |
struct iqueue_entry { |
int insn_index; |
uint32_t insn; |
oraddr_t insn_addr; |
}; |
|
/*! Structure for holding one label per particular memory location */ |
struct label_entry |
{ |
char *name; |
oraddr_t addr; |
struct label_entry *next; |
struct label_entry { |
char *name; |
oraddr_t addr; |
struct label_entry *next; |
}; |
|
/* from arch sim cpu/or1k/opcode/or32.h */ |
108,96 → 103,78
#define MAX_GPRS 32 |
#define PAGE_SIZE 8192 |
|
class MemoryLoad { |
public: |
|
// Constructor |
MemoryLoad(OrpsocAccess * _accessor); |
|
class MemoryLoad |
{ |
public: |
|
// Constructor |
MemoryLoad(OrpsocAccess *_accessor); |
// Label access function |
struct label_entry *get_label(oraddr_t addr); |
|
// Label access function |
struct label_entry* get_label (oraddr_t addr); |
|
uint32_t loadcode (char *filename, |
oraddr_t startaddr, |
oraddr_t virtphy_transl); |
|
|
private: |
|
//! The accessor for the Orpsoc instance |
OrpsocAccess *accessor; |
|
uint32_t loadcode(char *filename, |
oraddr_t startaddr, oraddr_t virtphy_transl); |
|
private: |
|
//! The accessor for the Orpsoc instance |
OrpsocAccess * accessor; |
|
#define MEMORY_LEN 0x100000000ULL |
|
/*!Whether to do immediate statistics. This seems to be for local debugging |
of parse.c */ |
|
/*!Whether to do immediate statistics. This seems to be for local debugging |
of parse.c */ |
#define IMM_STATS 0 |
|
/*!Unused mem memory marker. It is used when allocating program and data |
memory during parsing */ |
unsigned int freemem; |
|
/*!Translation table provided by microkernel. Only used if simulating |
microkernel. */ |
oraddr_t transl_table; |
|
/*!Used to signal whether during loading of programs a translation fault |
occured. */ |
uint32_t transl_error; |
|
|
/*!Unused mem memory marker. It is used when allocating program and data |
memory during parsing */ |
unsigned int freemem; |
|
/*!Translation table provided by microkernel. Only used if simulating |
microkernel. */ |
oraddr_t transl_table; |
|
/*!Used to signal whether during loading of programs a translation fault |
occured. */ |
uint32_t transl_error; |
|
#if IMM_STATS |
int bcnt[33][3] = { 0 }; |
int bsum[3] = { 0 }; |
uint32_t movhi = 0; |
#endif /* IMM_STATS */ |
int bcnt[33][3] = { 0 }; |
int bsum[3] = { 0 }; |
uint32_t movhi = 0; |
#endif /* IMM_STATS */ |
|
// A large number, for the Linux kernel (~8000 functions) |
// A large number, for the Linux kernel (~8000 functions) |
#define LABELS_HASH_SIZE 10000 |
/* Local list of labels (symbols) */ |
struct label_entry *label_hash[LABELS_HASH_SIZE]; |
/* Local list of labels (symbols) */ |
struct label_entry *label_hash[LABELS_HASH_SIZE]; |
|
|
/* Function prototypes for external use */ |
char *strstrip (char *dst, |
const char *src, |
int n); |
/* Function prototypes for external use */ |
char *strstrip(char *dst, const char *src, int n); |
|
oraddr_t translate (oraddr_t laddr, |
int *breakpoint); |
|
|
int bits (uint32_t val); |
|
void check_insn (uint32_t insn); |
|
void addprogram (oraddr_t address, |
uint32_t insn, |
int *breakpoint); |
|
void readfile_coff (char *filename, |
short sections); |
|
void readsyms_coff (char *filename, |
uint32_t symptr, |
uint32_t syms); |
|
void readfile_elf (char *filename); |
|
void identifyfile (char *filename); |
oraddr_t translate(oraddr_t laddr, int *breakpoint); |
|
void init_labels (); |
|
void add_label (oraddr_t addr, char *name); |
int bits(uint32_t val); |
|
struct label_entry* find_label (char *name); |
oraddr_t eval_label (char *name); |
|
void check_insn(uint32_t insn); |
|
void addprogram(oraddr_t address, uint32_t insn); |
|
void readfile_coff(char *filename, short sections); |
|
void readsyms_coff(char *filename, uint32_t symptr, uint32_t syms); |
|
void readfile_elf(char *filename); |
|
void identifyfile(char *filename); |
|
void init_labels(); |
|
void add_label(oraddr_t addr, char *name); |
|
struct label_entry *find_label(char *name); |
oraddr_t eval_label(char *name); |
|
}; |
|
#endif /* MEMORYLOAD__H */ |
#endif /* MEMORYLOAD__H */ |
/sysc/include/ResetSC.h
31,7 → 31,6
|
#include "systemc" |
|
|
//! Provide a SystemC reset signal at startup |
|
//! The reset signal is driven for a specified number of cycles after |
38,27 → 37,24
//! creation. For convenience synchronous versions of the reset signal are |
//! provided in both active high and active low formats. |
|
class ResetSC |
: public sc_core::sc_module |
{ |
class ResetSC:public sc_core::sc_module { |
public: |
|
// Constructor |
ResetSC (sc_core::sc_module_name name, |
int _resetCounter = 5); |
// Constructor |
ResetSC(sc_core::sc_module_name name, int _resetCounter = 5); |
|
// Method to drive the reset |
void driveReset(); |
// Method to drive the reset |
void driveReset(); |
|
// The ports |
sc_core::sc_in<bool> clk; |
sc_core::sc_out<bool> rst; // Active high reset |
sc_core::sc_out<bool> rstn; // Active low reset |
// The ports |
sc_core::sc_in < bool > clk; |
sc_core::sc_out < bool > rst; // Active high reset |
sc_core::sc_out < bool > rstn; // Active low reset |
|
private: |
|
int resetCounter; |
int resetCounter; |
|
}; // ResetSC () |
}; // ResetSC () |
|
#endif // RESET_SC__H |
#endif // RESET_SC__H |
/sysc/include/GdbServerSC.h
41,193 → 41,186
#include "RspPacket.h" |
#include "DebugUnitSC.h" |
|
|
//! Module implementing a GDB RSP server. |
|
//! A thread listens for RSP requests, which are converted to requests to read |
//! and write registers, memory or control the CPU in the debug unit |
|
class GdbServerSC |
: public sc_core::sc_module |
{ |
class GdbServerSC:public sc_core::sc_module { |
public: |
|
// Constructor and destructor |
GdbServerSC (sc_core::sc_module_name name, |
uint32_t _flashStart, |
uint32_t _flashEnd, |
int rspPort, |
sc_core::sc_fifo<TapAction *> *tapActionQueue); |
~GdbServerSC (); |
// Constructor and destructor |
GdbServerSC(sc_core::sc_module_name name, |
uint32_t _flashStart, |
uint32_t _flashEnd, |
int rspPort, |
sc_core::sc_fifo < TapAction * >*tapActionQueue); |
~GdbServerSC(); |
|
private: |
|
//! Definition of GDB target signals. |
//! Definition of GDB target signals. |
|
//! Data taken from the GDB 6.8 source. Only those we use defined here. |
enum TargetSignal { |
TARGET_SIGNAL_NONE = 0, |
TARGET_SIGNAL_INT = 2, |
TARGET_SIGNAL_ILL = 4, |
TARGET_SIGNAL_TRAP = 5, |
TARGET_SIGNAL_FPE = 8, |
TARGET_SIGNAL_BUS = 10, |
TARGET_SIGNAL_SEGV = 11, |
TARGET_SIGNAL_ALRM = 14, |
TARGET_SIGNAL_USR2 = 31, |
TARGET_SIGNAL_PWR = 32 |
}; |
//! Data taken from the GDB 6.8 source. Only those we use defined here. |
enum TargetSignal { |
TARGET_SIGNAL_NONE = 0, |
TARGET_SIGNAL_INT = 2, |
TARGET_SIGNAL_ILL = 4, |
TARGET_SIGNAL_TRAP = 5, |
TARGET_SIGNAL_FPE = 8, |
TARGET_SIGNAL_BUS = 10, |
TARGET_SIGNAL_SEGV = 11, |
TARGET_SIGNAL_ALRM = 14, |
TARGET_SIGNAL_USR2 = 31, |
TARGET_SIGNAL_PWR = 32 |
}; |
|
// Register numbering. Matches GDB client |
static const int MAX_SPRS = 0x10000; //!< Max number of OR1K SPRs |
static const int max_gprs = 32; //!< Max number of OR1K GPRs |
// Register numbering. Matches GDB client |
static const int MAX_SPRS = 0x10000; //!< Max number of OR1K SPRs |
static const int max_gprs = 32; //!< Max number of OR1K GPRs |
|
static const int PPC_REGNUM = max_gprs + 0; //!< Previous PC |
static const int NPC_REGNUM = max_gprs + 1; //!< Next PC |
static const int SR_REGNUM = max_gprs + 2; //!< Supervision Register |
static const int PPC_REGNUM = max_gprs + 0; //!< Previous PC |
static const int NPC_REGNUM = max_gprs + 1; //!< Next PC |
static const int SR_REGNUM = max_gprs + 2; //!< Supervision Register |
|
static const int NUM_REGS = max_gprs + 3; //!< Total GDB registers |
static const int NUM_REGS = max_gprs + 3; //!< Total GDB registers |
|
//! Maximum size of a GDB RSP packet |
//static const int RSP_PKT_MAX = NUM_REGS * 8 + 1; |
static const int RSP_PKT_MAX = 1024*16; |
//! Maximum size of a GDB RSP packet |
//static const int RSP_PKT_MAX = NUM_REGS * 8 + 1; |
static const int RSP_PKT_MAX = 1024 * 16; |
|
// OpenRISC exception addresses. Only the ones we need to know about |
static const uint32_t EXCEPT_NONE = 0x000; //!< No exception |
static const uint32_t EXCEPT_RESET = 0x100; //!< Reset |
// OpenRISC exception addresses. Only the ones we need to know about |
static const uint32_t EXCEPT_NONE = 0x000; //!< No exception |
static const uint32_t EXCEPT_RESET = 0x100; //!< Reset |
|
// SPR numbers |
static const uint16_t SPR_NPC = 0x0010; //!< Next program counter |
static const uint16_t SPR_SR = 0x0011; //!< Supervision register |
static const uint16_t SPR_PPC = 0x0012; //!< Previous program counter |
static const uint16_t SPR_GPR0 = 0x0400; //!< GPR 0 |
// SPR numbers |
static const uint16_t SPR_NPC = 0x0010; //!< Next program counter |
static const uint16_t SPR_SR = 0x0011; //!< Supervision register |
static const uint16_t SPR_PPC = 0x0012; //!< Previous program counter |
static const uint16_t SPR_GPR0 = 0x0400; //!< GPR 0 |
|
static const uint16_t SPR_DVR0 = 0x3000; //!< Debug value register 0 |
static const uint16_t SPR_DVR1 = 0x3001; //!< Debug value register 1 |
static const uint16_t SPR_DVR2 = 0x3002; //!< Debug value register 2 |
static const uint16_t SPR_DVR3 = 0x3003; //!< Debug value register 3 |
static const uint16_t SPR_DVR4 = 0x3004; //!< Debug value register 4 |
static const uint16_t SPR_DVR5 = 0x3005; //!< Debug value register 5 |
static const uint16_t SPR_DVR6 = 0x3006; //!< Debug value register 6 |
static const uint16_t SPR_DVR7 = 0x3007; //!< Debug value register 7 |
static const uint16_t SPR_DVR0 = 0x3000; //!< Debug value register 0 |
static const uint16_t SPR_DVR1 = 0x3001; //!< Debug value register 1 |
static const uint16_t SPR_DVR2 = 0x3002; //!< Debug value register 2 |
static const uint16_t SPR_DVR3 = 0x3003; //!< Debug value register 3 |
static const uint16_t SPR_DVR4 = 0x3004; //!< Debug value register 4 |
static const uint16_t SPR_DVR5 = 0x3005; //!< Debug value register 5 |
static const uint16_t SPR_DVR6 = 0x3006; //!< Debug value register 6 |
static const uint16_t SPR_DVR7 = 0x3007; //!< Debug value register 7 |
|
static const uint16_t SPR_DCR0 = 0x3008; //!< Debug control register 0 |
static const uint16_t SPR_DCR1 = 0x3009; //!< Debug control register 1 |
static const uint16_t SPR_DCR2 = 0x300a; //!< Debug control register 2 |
static const uint16_t SPR_DCR3 = 0x300b; //!< Debug control register 3 |
static const uint16_t SPR_DCR4 = 0x300c; //!< Debug control register 4 |
static const uint16_t SPR_DCR5 = 0x300d; //!< Debug control register 5 |
static const uint16_t SPR_DCR6 = 0x300e; //!< Debug control register 6 |
static const uint16_t SPR_DCR7 = 0x300f; //!< Debug control register 7 |
static const uint16_t SPR_DCR0 = 0x3008; //!< Debug control register 0 |
static const uint16_t SPR_DCR1 = 0x3009; //!< Debug control register 1 |
static const uint16_t SPR_DCR2 = 0x300a; //!< Debug control register 2 |
static const uint16_t SPR_DCR3 = 0x300b; //!< Debug control register 3 |
static const uint16_t SPR_DCR4 = 0x300c; //!< Debug control register 4 |
static const uint16_t SPR_DCR5 = 0x300d; //!< Debug control register 5 |
static const uint16_t SPR_DCR6 = 0x300e; //!< Debug control register 6 |
static const uint16_t SPR_DCR7 = 0x300f; //!< Debug control register 7 |
|
static const uint16_t SPR_DMR1 = 0x3010; //!< Debug mode register 1 |
static const uint16_t SPR_DMR2 = 0x3011; //!< Debug mode register 2 |
static const uint16_t SPR_DSR = 0x3014; //!< Debug stop register |
static const uint16_t SPR_DRR = 0x3015; //!< Debug reason register |
static const uint16_t SPR_DMR1 = 0x3010; //!< Debug mode register 1 |
static const uint16_t SPR_DMR2 = 0x3011; //!< Debug mode register 2 |
static const uint16_t SPR_DSR = 0x3014; //!< Debug stop register |
static const uint16_t SPR_DRR = 0x3015; //!< Debug reason register |
|
// SPR masks and offsets |
static const uint32_t SPR_DMR1_ST = 0x00400000; //!< Single-step trace |
static const uint32_t SPR_DMR2_WGB = 0x003ff000; //!< W/pt generating B/pt |
static const uint32_t SPR_DMR2_WBS = 0xffc00000; //!< W/pt B/pt status |
static const uint32_t SPR_DSR_TE = 0x00002000; //!< Trap |
static const uint32_t SPR_DCR_DP_MASK = 0x00000001; //!< Debug Pair Present |
static const uint32_t SPR_DCR_CC_MASK = 0x0000000e; //!< Compare Condition |
static const uint32_t SPR_DCR_SC_MASK = 0x00000010; //!< Signed Comparison |
static const uint32_t SPR_DCR_CT_MASK = 0x000000e0; //!< Compare To |
static const uint32_t SPR_DMR2_WGB_SHIFT = 12; //!< W/pt Generate B/pt |
// SPR masks and offsets |
static const uint32_t SPR_DMR1_ST = 0x00400000; //!< Single-step trace |
static const uint32_t SPR_DMR2_WGB = 0x003ff000; //!< W/pt generating B/pt |
static const uint32_t SPR_DMR2_WBS = 0xffc00000; //!< W/pt B/pt status |
static const uint32_t SPR_DSR_TE = 0x00002000; //!< Trap |
static const uint32_t SPR_DCR_DP_MASK = 0x00000001; //!< Debug Pair Present |
static const uint32_t SPR_DCR_CC_MASK = 0x0000000e; //!< Compare Condition |
static const uint32_t SPR_DCR_SC_MASK = 0x00000010; //!< Signed Comparison |
static const uint32_t SPR_DCR_CT_MASK = 0x000000e0; //!< Compare To |
static const uint32_t SPR_DMR2_WGB_SHIFT = 12; //!< W/pt Generate B/pt |
|
// DRR (Debug Reason Register) Bits |
static const uint32_t SPR_DRR_RSTE = 0x00000001; //!< Reset |
static const uint32_t SPR_DRR_BUSEE = 0x00000002; //!< Bus error |
static const uint32_t SPR_DRR_DPFE = 0x00000004; //!< Data page fault |
static const uint32_t SPR_DRR_IPFE = 0x00000008; //!< Insn page fault |
static const uint32_t SPR_DRR_TTE = 0x00000010; //!< Tick timer |
static const uint32_t SPR_DRR_AE = 0x00000020; //!< Alignment |
static const uint32_t SPR_DRR_IIE = 0x00000040; //!< Illegal instruction |
static const uint32_t SPR_DRR_IE = 0x00000080; //!< Interrupt |
static const uint32_t SPR_DRR_DME = 0x00000100; //!< DTLB miss |
static const uint32_t SPR_DRR_IME = 0x00000200; //!< ITLB miss |
static const uint32_t SPR_DRR_RE = 0x00000400; //!< Range fault |
static const uint32_t SPR_DRR_SCE = 0x00000800; //!< System call |
static const uint32_t SPR_DRR_FPE = 0x00001000; //!< Floating point |
static const uint32_t SPR_DRR_TE = 0x00002000; //!< Trap |
|
// DRR (Debug Reason Register) Bits |
static const uint32_t SPR_DRR_RSTE = 0x00000001; //!< Reset |
static const uint32_t SPR_DRR_BUSEE = 0x00000002; //!< Bus error |
static const uint32_t SPR_DRR_DPFE = 0x00000004; //!< Data page fault |
static const uint32_t SPR_DRR_IPFE = 0x00000008; //!< Insn page fault |
static const uint32_t SPR_DRR_TTE = 0x00000010; //!< Tick timer |
static const uint32_t SPR_DRR_AE = 0x00000020; //!< Alignment |
static const uint32_t SPR_DRR_IIE = 0x00000040; //!< Illegal instruction |
static const uint32_t SPR_DRR_IE = 0x00000080; //!< Interrupt |
static const uint32_t SPR_DRR_DME = 0x00000100; //!< DTLB miss |
static const uint32_t SPR_DRR_IME = 0x00000200; //!< ITLB miss |
static const uint32_t SPR_DRR_RE = 0x00000400; //!< Range fault |
static const uint32_t SPR_DRR_SCE = 0x00000800; //!< System call |
static const uint32_t SPR_DRR_FPE = 0x00001000; //!< Floating point |
static const uint32_t SPR_DRR_TE = 0x00002000; //!< Trap |
//! RSP Signal valu |
uint32_t rsp_sigval; |
|
//! RSP Signal valu |
uint32_t rsp_sigval; |
//! Trap instruction for OR32 |
static const uint32_t OR1K_TRAP_INSTR = 0x21000001; |
|
//! Trap instruction for OR32 |
static const uint32_t OR1K_TRAP_INSTR = 0x21000001; |
//! Thread ID used by Or1ksim |
static const int OR1KSIM_TID = 1; |
|
//! Thread ID used by Or1ksim |
static const int OR1KSIM_TID = 1; |
// The bounds of flash memory |
uint32_t flashStart; //<! Start of flash memory |
uint32_t flashEnd; //<! End of flash memory |
|
// The bounds of flash memory |
uint32_t flashStart; //<! Start of flash memory |
uint32_t flashEnd; //<! End of flash memory |
//! Our associated Debug Unit |
DebugUnitSC *debugUnit; |
|
//! Our associated Debug Unit |
DebugUnitSC *debugUnit; |
//! Our associated RSP interface (which we create) |
RspConnection *rsp; |
|
//! Our associated RSP interface (which we create) |
RspConnection *rsp; |
//! The packet pointer. There is only ever one packet in use at one time, so |
//! there is no need to repeatedly allocate and delete it. |
RspPacket *pkt; |
|
//! The packet pointer. There is only ever one packet in use at one time, so |
//! there is no need to repeatedly allocate and delete it. |
RspPacket *pkt; |
//! Hash table for matchpoints |
MpHash *mpHash; |
|
//! Hash table for matchpoints |
MpHash *mpHash; |
//! Is the target stopped |
bool targetStopped; |
|
//! Is the target stopped |
bool targetStopped; |
// SystemC thread to listen for and service RSP requests |
void rspServer(); |
|
// SystemC thread to listen for and service RSP requests |
void rspServer (); |
// Main RSP request handler |
void rspClientRequest(); |
|
// Main RSP request handler |
void rspClientRequest (); |
// Handle the various RSP requests |
void rspCheckForException(); |
void rspReportException(); |
void rspContinue(); |
void rspContinue(uint32_t except); |
void rspContinue(uint32_t addr, uint32_t except); |
void rspInterrupt(); |
void rspReadAllRegs(); |
void rspWriteAllRegs(); |
void rspReadMem(); |
void rspWriteMem(); |
void rspReadReg(); |
void rspWriteReg(); |
void rspQuery(); |
void rspCommand(); |
void rspSet(); |
void rspRestart(); |
void rspStep(); |
void rspStep(uint32_t except); |
void rspStep(uint32_t addr, uint32_t except); |
void rspVpkt(); |
void rspWriteMemBin(); |
void rspRemoveMatchpoint(); |
void rspInsertMatchpoint(); |
|
// Handle the various RSP requests |
void rspCheckForException(); |
void rspReportException (); |
void rspContinue (); |
void rspContinue (uint32_t except); |
void rspContinue (uint32_t addr, |
uint32_t except); |
void rspInterrupt (); |
void rspReadAllRegs (); |
void rspWriteAllRegs (); |
void rspReadMem (); |
void rspWriteMem (); |
void rspReadReg (); |
void rspWriteReg (); |
void rspQuery (); |
void rspCommand (); |
void rspSet (); |
void rspRestart (); |
void rspStep (); |
void rspStep (uint32_t except); |
void rspStep (uint32_t addr, |
uint32_t except); |
void rspVpkt (); |
void rspWriteMemBin (); |
void rspRemoveMatchpoint (); |
void rspInsertMatchpoint (); |
// Convenience wrappers for getting particular registers, which are really |
// SPRs. |
uint32_t readNpc(); |
void writeNpc(uint32_t addr); |
|
// Convenience wrappers for getting particular registers, which are really |
// SPRs. |
uint32_t readNpc (); |
void writeNpc (uint32_t addr); |
uint32_t readGpr(int regNum); |
void writeGpr(int regNum, uint32_t value); |
|
uint32_t readGpr (int regNum); |
void writeGpr (int regNum, |
uint32_t value); |
// Check if we got a message from the or1200 monitor module telling us |
// to stall |
bool checkMonitorPipe(); |
|
// Check if we got a message from the or1200 monitor module telling us |
// to stall |
bool checkMonitorPipe (); |
}; // GdbServerSC () |
|
}; // GdbServerSC () |
|
#endif // GDB_SERVER_SC__H |
#endif // GDB_SERVER_SC__H |
/sysc/include/TapStateMachine.h
33,51 → 33,47
//! Last entry is not a state, but a marker of the number of states. Useful |
//! for state transition matrices. |
enum TapState { |
TAP_TEST_LOGIC_RESET = 0, |
TAP_RUN_TEST_IDLE = 1, |
TAP_SELECT_DR_SCAN = 2, |
TAP_CAPTURE_DR = 3, |
TAP_SHIFT_DR = 4, |
TAP_EXIT1_DR = 5, |
TAP_PAUSE_DR = 6, |
TAP_EXIT2_DR = 7, |
TAP_UPDATE_DR = 8, |
TAP_SELECT_IR_SCAN = 9, |
TAP_CAPTURE_IR = 10, |
TAP_SHIFT_IR = 11, |
TAP_EXIT1_IR = 12, |
TAP_PAUSE_IR = 13, |
TAP_EXIT2_IR = 14, |
TAP_UPDATE_IR = 15, |
TAP_SIZE = 16 |
TAP_TEST_LOGIC_RESET = 0, |
TAP_RUN_TEST_IDLE = 1, |
TAP_SELECT_DR_SCAN = 2, |
TAP_CAPTURE_DR = 3, |
TAP_SHIFT_DR = 4, |
TAP_EXIT1_DR = 5, |
TAP_PAUSE_DR = 6, |
TAP_EXIT2_DR = 7, |
TAP_UPDATE_DR = 8, |
TAP_SELECT_IR_SCAN = 9, |
TAP_CAPTURE_IR = 10, |
TAP_SHIFT_IR = 11, |
TAP_EXIT1_IR = 12, |
TAP_PAUSE_IR = 13, |
TAP_EXIT2_IR = 14, |
TAP_UPDATE_IR = 15, |
TAP_SIZE = 16 |
}; // enum TapState |
|
}; // enum TapState |
|
|
//! Textual representation of all the TAP states. |
|
//! Provided for debugging purposes |
static const char *tapStateNames[TAP_SIZE] = { |
"Test-Logic-Reset", |
"Run-Test/Idle", |
"Select-DR-Scan", |
"Capture-DR", |
"Shift-DR", |
"Exit1-DR", |
"Pause-DR", |
"Exit2-DR", |
"Update-DR", |
"Select-IR-Scan", |
"Capture-IR", |
"Shift-IR", |
"Exit1-IR", |
"Pause-IR", |
"Exit2-IR", |
"Update-IR" |
"Test-Logic-Reset", |
"Run-Test/Idle", |
"Select-DR-Scan", |
"Capture-DR", |
"Shift-DR", |
"Exit1-DR", |
"Pause-DR", |
"Exit2-DR", |
"Update-DR", |
"Select-IR-Scan", |
"Capture-IR", |
"Shift-IR", |
"Exit1-IR", |
"Pause-IR", |
"Exit2-IR", |
"Update-IR" |
}; // tapStateNames |
|
}; // tapStateNames |
|
|
//! TAP state machine |
|
//! Tracks the state of the TAP. This should mirror the state of the TAP in |
95,52 → 91,47
//! For convenience of users, this class provides a flag (resetDone::), |
//! with accessors by which reset state can be recorded. |
|
|
class TapStateMachine |
{ |
class TapStateMachine { |
public: |
|
friend class JtagSC; |
friend class TapAction; |
friend class TapActionDRScan; |
friend class TapActionIRScan; |
friend class TapActionReset; |
friend class JtagSC; |
friend class TapAction; |
friend class TapActionDRScan; |
friend class TapActionIRScan; |
friend class TapActionReset; |
|
|
protected: |
|
//! The number of cycles of TMS=1 required to force reset |
static const int TAP_RESET_CYCLES = 5; |
//! The number of cycles of TMS=1 required to force reset |
static const int TAP_RESET_CYCLES = 5; |
|
// Constructor |
TapStateMachine(); |
// Constructor |
TapStateMachine(); |
|
// Accessor for TAP state |
TapState getState (); |
// Accessor for TAP state |
TapState getState(); |
|
// Accessors for TAP reset state |
bool getResetDone (); |
void setResetDone (bool _resetState); |
// Accessors for TAP reset state |
bool getResetDone(); |
void setResetDone(bool _resetState); |
|
// Drive the TAP state machine |
void nextState (bool tms); |
// Drive the TAP state machine |
void nextState(bool tms); |
|
// Determine if we are in a particular target state |
bool targetState (TapState target, |
bool &tms); |
// Determine if we are in a particular target state |
bool targetState(TapState target, bool & tms); |
|
private: |
|
//! The current TAP state |
TapState state; |
//! The current TAP state |
TapState state; |
|
//! True if the TAP state machine has been through a reset. |
//! True if the TAP state machine has been through a reset. |
|
//! The state can be sure to match that of the target. Responsibility of |
//! user classes to set this. |
bool resetDone; |
//! The state can be sure to match that of the target. Responsibility of |
//! user classes to set this. |
bool resetDone; |
|
}; // class TapStateMachine |
}; // class TapStateMachine |
|
|
#endif // TAP_STATE_MACHINE__H |
#endif // TAP_STATE_MACHINE__H |
/sysc/include/OrpsocMain.h
46,6 → 46,10
#ifndef ORPSOC_MAIN__H |
#define ORPSOC_MAIN__H |
|
/* Globals used by other C modules */ |
extern bool gQuiet; |
extern int gSimRunning; |
|
//! The Verilog timescale unit (as SystemC timescale unit) |
#define TIMESCALE_UNIT SC_NS |
|
55,10 → 59,6
//! CPU clock Half period in timescale units |
#define BENCH_CLK_HALFPERIOD 10 |
|
//! System's internal RAM size in byes - found in rtl/verilog/orpsoc_top.v, param for ram_wb module |
//! Currently is 32MB (8M words) |
#define ORPSOC_SRAM_SIZE (8388608*4) |
|
//! Ratio of JTAG clock period to CPU clock period |
#define CLOCK_RATIO 10 |
|
82,4 → 82,4
//! PPC, SR and NPC. Plus one byte for end of string marker. |
#define RSP_MAX_PKT_SIZE ((32 + 3) * 8 + 1) |
|
#endif // ORPSOC_MAIN__H |
#endif // ORPSOC_MAIN__H |
/sysc/include/JtagSC.h
34,7 → 34,6
#include "systemc" |
#include "TapAction.h" |
|
|
//! Default size of the FIFO queuing TAP actions |
#define DEFAULT_TAP_FIFO_SIZE 256 |
|
68,44 → 67,40
//! the action owner of completion, through an sc_event, which is part of the |
//! ::TapAction class. |
//! |
class JtagSC |
: public sc_core::sc_module |
{ |
class JtagSC:public sc_core::sc_module { |
public: |
|
// The ports. Note that the naming of the low level JTAG ports is reversed, |
// because we are driving the inputs! */ |
sc_core::sc_in<bool> sysReset; //!< The system reset (active high) |
// The ports. Note that the naming of the low level JTAG ports is reversed, |
// because we are driving the inputs! */ |
sc_core::sc_in < bool > sysReset; //!< The system reset (active high) |
|
sc_core::sc_in<bool> tck; //!< External JTAG TCK |
sc_core::sc_out<bool> tdi; //!< JTAG TDI pin |
sc_core::sc_in<bool> tdo; //!< JTAG TDO pin |
sc_core::sc_out<bool> tms; //!< JTAG TMS pin |
sc_core::sc_out<bool> trst; //!< JTAG TRST pin |
sc_core::sc_in < bool > tck; //!< External JTAG TCK |
sc_core::sc_out < bool > tdi; //!< JTAG TDI pin |
sc_core::sc_in < bool > tdo; //!< JTAG TDO pin |
sc_core::sc_out < bool > tms; //!< JTAG TMS pin |
sc_core::sc_out < bool > trst; //!< JTAG TRST pin |
|
//! JTAG action queue |
sc_core::sc_fifo<TapAction *> *tapActionQueue; |
//! JTAG action queue |
sc_core::sc_fifo < TapAction * >*tapActionQueue; |
|
// Constructor and destructor |
JtagSC (sc_core::sc_module_name name, |
int fifo_size = DEFAULT_TAP_FIFO_SIZE); |
~JtagSC (); |
// Constructor and destructor |
JtagSC(sc_core::sc_module_name name, |
int fifo_size = DEFAULT_TAP_FIFO_SIZE); |
~JtagSC(); |
|
|
protected: |
|
// Method to process the actions |
void processActions(); |
// Method to process the actions |
void processActions(); |
|
|
private: |
|
//! The TAP state machine |
TapStateMachine *stateMachine; |
//! The TAP state machine |
TapStateMachine * stateMachine; |
|
//! The next TAP action |
TapAction *currentTapAction; |
//! The next TAP action |
TapAction *currentTapAction; |
|
}; // JtagSC () |
}; // JtagSC () |
|
#endif // JTAG_SC__H |
#endif // JTAG_SC__H |
/sysc/include/DebugUnitSC.h
29,7 → 29,6
#ifndef DEBUG_UNIT_SC__H |
#define DEBUG_UNIT_SC__H |
|
|
// Define if no cache is wanted |
#define NOCACHE |
|
42,7 → 41,6
#include "SprCache.h" |
#include "MemCache.h" |
|
|
//----------------------------------------------------------------------------- |
//! Module modeling the OpenRISC 1000 Debug Unit |
|
52,199 → 50,179
//! Provides a low level interface to the Embecosm SystemC JTAG interface, |
//! queueing requests to read and write JTAG registers. |
//----------------------------------------------------------------------------- |
class DebugUnitSC |
: public sc_core::sc_module |
{ |
class DebugUnitSC:public sc_core::sc_module { |
public: |
|
// Constructor and destructor |
DebugUnitSC (sc_core::sc_module_name name, |
sc_core::sc_fifo<TapAction *> *_tapActionQueue); |
~DebugUnitSC (); |
// Constructor and destructor |
DebugUnitSC(sc_core::sc_module_name name, |
sc_core::sc_fifo < TapAction * >*_tapActionQueue); |
~DebugUnitSC(); |
|
// Reset function for the debug unit |
void resetDebugUnit (); |
// Reset function for the debug unit |
void resetDebugUnit(); |
|
// Functions to control and report on the CPU |
void reset (); |
void stall (); |
void unstall (); |
bool isStalled (); |
// Functions to control and report on the CPU |
void reset(); |
void stall(); |
void unstall(); |
bool isStalled(); |
|
// Functions to access SPRs |
uint32_t readSpr (uint16_t sprNum); |
void writeSpr (uint16_t sprNum, |
uint32_t value); |
void andSpr (uint16_t sprNum, |
uint32_t value); |
void orSpr (uint16_t sprNum, |
uint32_t value); |
// Functions to access SPRs |
uint32_t readSpr(uint16_t sprNum); |
void writeSpr(uint16_t sprNum, uint32_t value); |
void andSpr(uint16_t sprNum, uint32_t value); |
void orSpr(uint16_t sprNum, uint32_t value); |
|
// Functions to access memory |
uint32_t readMem32 (uint32_t addr); |
bool writeMem32 (uint32_t addr, |
uint32_t value); |
uint8_t readMem8 (uint32_t addr); |
bool writeMem8 (uint32_t addr, |
uint8_t value); |
// Functions to access memory |
uint32_t readMem32(uint32_t addr); |
bool writeMem32(uint32_t addr, uint32_t value); |
uint8_t readMem8(uint32_t addr); |
bool writeMem8(uint32_t addr, uint8_t value); |
|
private: |
|
// JTAG instructions |
static const uint32_t CHAIN_SELECT_IR = 0x3; //!< Chain Select instruction |
static const uint32_t DEBUG_IR = 0x8; //!< Debug instruction |
// JTAG instructions |
static const uint32_t CHAIN_SELECT_IR = 0x3; //!< Chain Select instruction |
static const uint32_t DEBUG_IR = 0x8; //!< Debug instruction |
|
//! JTAG instruction register length. There is no CRC for this register. |
static const int JTAG_IR_LEN = 4; //!< JTAG instr reg length |
//! JTAG instruction register length. There is no CRC for this register. |
static const int JTAG_IR_LEN = 4; //!< JTAG instr reg length |
|
// DEBUG UNIT CHAIN data register fields |
static const int DUSEL_DR_LEN = 73; //!< total DUSEL DR size |
static const int DUSEL_SEL_OFF = 0; //!< start of select field |
static const int DUSEL_SEL_LEN = 1; //!< length of select field |
static const int DUSEL_OPCODE_OFF = DUSEL_SEL_OFF + DUSEL_SEL_LEN; //!< start of opcode field |
static const int DUSEL_OPCODE_LEN = 4; //!< length of opcode field |
static const int DUSEL_CRC_OFF = DUSEL_OPCODE_OFF + DUSEL_OPCODE_LEN; //!< start of CRC field |
static const int DUSEL_CRC_LEN = 32; //!< length of CRC field |
static const int DUSEL_RESP_STATUS_OFF = DUSEL_CRC_OFF + DUSEL_CRC_LEN; |
static const int DUSEL_RESP_STATUS_LEN = 4; |
static const int DUSEL_RESP_CRC_OFF = DUSEL_RESP_STATUS_OFF + DUSEL_RESP_STATUS_LEN; |
static const int DUSEL_RESP_CRC_LEN = 32; |
// DEBUG UNIT CHAIN data register fields |
static const int DUSEL_DR_LEN = 73; //!< total DUSEL DR size |
static const int DUSEL_SEL_OFF = 0; //!< start of select field |
static const int DUSEL_SEL_LEN = 1; //!< length of select field |
static const int DUSEL_OPCODE_OFF = DUSEL_SEL_OFF + DUSEL_SEL_LEN; //!< start of opcode field |
static const int DUSEL_OPCODE_LEN = 4; //!< length of opcode field |
static const int DUSEL_CRC_OFF = DUSEL_OPCODE_OFF + DUSEL_OPCODE_LEN; //!< start of CRC field |
static const int DUSEL_CRC_LEN = 32; //!< length of CRC field |
static const int DUSEL_RESP_STATUS_OFF = DUSEL_CRC_OFF + DUSEL_CRC_LEN; |
static const int DUSEL_RESP_STATUS_LEN = 4; |
static const int DUSEL_RESP_CRC_OFF = |
DUSEL_RESP_STATUS_OFF + DUSEL_RESP_STATUS_LEN; |
static const int DUSEL_RESP_CRC_LEN = 32; |
|
static const uint32_t DBG_CRC32_POLY = 0x04c11db7; |
|
// OpenRISC 1000 scan chains (values in DUSEL data register field) |
static const int OR1K_SC_UNDEF = -1; //!< Undefined OR1K scan chain |
static const int OR1K_SC_WISHBONE = 0; //!< for memory access |
static const int OR1K_SC_CPU0 = 1; //!< for access to CPU0 |
static const int OR1K_SC_CPU1 = 2; //!< for access to CPU1 |
static const uint32_t DBG_CRC32_POLY = 0x04c11db7; |
|
// OpenRISC 1000 scan chains (values in DUSEL data register field) |
static const int OR1K_SC_UNDEF = -1; //!< Undefined OR1K scan chain |
static const int OR1K_SC_WISHBONE = 0; //!< for memory access |
static const int OR1K_SC_CPU0 = 1; //!< for access to CPU0 |
static const int OR1K_SC_CPU1 = 2; //!< for access to CPU1 |
|
// JTAG RISC_DEBUG (for accessing SPR) data register fields |
static const int RISC_DEBUG_DR_LEN = 74; //!< Total RISC_DEBUG DR size |
static const int RISC_DEBUG_ADDR_OFF = 0; //!< start of address field |
static const int RISC_DEBUG_ADDR_LEN = 32; //!< length of address field |
static const int RISC_DEBUG_RW_OFF = 32; //!< start of read/write field |
static const int RISC_DEBUG_RW_LEN = 1; //!< length of read/write field |
static const int RISC_DEBUG_DATA_OFF = 33; //!< start of data field |
static const int RISC_DEBUG_DATA_LEN = 32; //!< length of data field |
static const int RISC_DEBUG_CRC_OFF = 65; //!< start of CRC field |
static const int RISC_DEBUG_CRC_LEN = 8; //!< length of CRC field |
static const int RISC_DEBUG_SPARE_OFF = 73; //!< start of spare bits |
static const int RISC_DEBUG_SPARE_LEN = 1; //!< length of spare bit field |
|
// JTAG RISC_DEBUG (for accessing SPR) data register fields |
static const int RISC_DEBUG_DR_LEN = 74; //!< Total RISC_DEBUG DR size |
static const int RISC_DEBUG_ADDR_OFF = 0; //!< start of address field |
static const int RISC_DEBUG_ADDR_LEN = 32; //!< length of address field |
static const int RISC_DEBUG_RW_OFF = 32; //!< start of read/write field |
static const int RISC_DEBUG_RW_LEN = 1; //!< length of read/write field |
static const int RISC_DEBUG_DATA_OFF = 33; //!< start of data field |
static const int RISC_DEBUG_DATA_LEN = 32; //!< length of data field |
static const int RISC_DEBUG_CRC_OFF = 65; //!< start of CRC field |
static const int RISC_DEBUG_CRC_LEN = 8; //!< length of CRC field |
static const int RISC_DEBUG_SPARE_OFF = 73; //!< start of spare bits |
static const int RISC_DEBUG_SPARE_LEN = 1; //!< length of spare bit field |
// JTAG REGISTER (for controlling the CPU) data register fields |
static const int REGISTER_DR_LEN = 47; //!< Total REGISTER DR size |
static const int REGISTER_ADDR_OFF = 0; //!< start of address field |
static const int REGISTER_ADDR_LEN = 5; //!< length of address field |
static const int REGISTER_RW_OFF = 5; //!< start of read/write field |
static const int REGISTER_RW_LEN = 1; //!< length of read/write field |
static const int REGISTER_DATA_OFF = 6; //!< start of data field |
static const int REGISTER_DATA_LEN = 32; //!< length of data field |
static const int REGISTER_CRC_OFF = 38; //!< start of CRC field |
static const int REGISTER_CRC_LEN = 8; //!< length of CRC field |
static const int REGISTER_SPARE_OFF = 46; //!< start of spare bits |
static const int REGISTER_SPARE_LEN = 1; //!< length of spare bit field |
|
// JTAG REGISTER (for controlling the CPU) data register fields |
static const int REGISTER_DR_LEN = 47; //!< Total REGISTER DR size |
static const int REGISTER_ADDR_OFF = 0; //!< start of address field |
static const int REGISTER_ADDR_LEN = 5; //!< length of address field |
static const int REGISTER_RW_OFF = 5; //!< start of read/write field |
static const int REGISTER_RW_LEN = 1; //!< length of read/write field |
static const int REGISTER_DATA_OFF = 6; //!< start of data field |
static const int REGISTER_DATA_LEN = 32; //!< length of data field |
static const int REGISTER_CRC_OFF = 38; //!< start of CRC field |
static const int REGISTER_CRC_LEN = 8; //!< length of CRC field |
static const int REGISTER_SPARE_OFF = 46; //!< start of spare bits |
static const int REGISTER_SPARE_LEN = 1; //!< length of spare bit field |
// Register addresses for the REGISTER scan chain |
static const uint8_t OR1K_RSC_RISCOP = 0x04; //!< Used to reset/stall CPU |
|
// Register addresses for the REGISTER scan chain |
static const uint8_t OR1K_RSC_RISCOP = 0x04; //!< Used to reset/stall CPU |
// Bits for the RISCOP register |
static const uint32_t RISCOP_RESET = 0x00000001; //!< Reset the CPU |
static const uint32_t RISCOP_STALL = 0x00000002; //!< Stall the CPU |
|
// Bits for the RISCOP register |
static const uint32_t RISCOP_RESET = 0x00000001; //!< Reset the CPU |
static const uint32_t RISCOP_STALL = 0x00000002; //!< Stall the CPU |
// JTAG WISHBONE (for accessing SPR) data register fields |
static const int WISHBONE_DR_LEN = 74; //!< Total WISHBONE DR size |
static const int WISHBONE_ADDR_OFF = 0; //!< start of address field |
static const int WISHBONE_ADDR_LEN = 32; //!< length of address field |
static const int WISHBONE_RW_OFF = 32; //!< start of read/write field |
static const int WISHBONE_RW_LEN = 1; //!< length of read/write field |
static const int WISHBONE_DATA_OFF = 33; //!< start of data field |
static const int WISHBONE_DATA_LEN = 32; //!< length of data field |
static const int WISHBONE_CRC_OFF = 65; //!< start of CRC field |
static const int WISHBONE_CRC_LEN = 8; //!< length of CRC field |
static const int WISHBONE_SPARE_OFF = 73; //!< start of spare bits |
static const int WISHBONE_SPARE_LEN = 1; //!< length of spare bit field |
|
// JTAG WISHBONE (for accessing SPR) data register fields |
static const int WISHBONE_DR_LEN = 74; //!< Total WISHBONE DR size |
static const int WISHBONE_ADDR_OFF = 0; //!< start of address field |
static const int WISHBONE_ADDR_LEN = 32; //!< length of address field |
static const int WISHBONE_RW_OFF = 32; //!< start of read/write field |
static const int WISHBONE_RW_LEN = 1; //!< length of read/write field |
static const int WISHBONE_DATA_OFF = 33; //!< start of data field |
static const int WISHBONE_DATA_LEN = 32; //!< length of data field |
static const int WISHBONE_CRC_OFF = 65; //!< start of CRC field |
static const int WISHBONE_CRC_LEN = 8; //!< length of CRC field |
static const int WISHBONE_SPARE_OFF = 73; //!< start of spare bits |
static const int WISHBONE_SPARE_LEN = 1; //!< length of spare bit field |
//! The NPC is special, so we need to know about it |
static const int SPR_NPC = 0x10; |
|
//! The NPC is special, so we need to know about it |
static const int SPR_NPC = 0x10; |
//! The JTAG fifo we queue on |
sc_core::sc_fifo < TapAction * >*tapActionQueue; |
|
//! The JTAG fifo we queue on |
sc_core::sc_fifo<TapAction *> *tapActionQueue; |
//! The processor stall state. When stalled we can use cacheing on |
//! reads/writes of memory and SPRs. |
enum { |
UNKNOWN, |
STALLED, |
} stallState; |
|
//! The processor stall state. When stalled we can use cacheing on |
//! reads/writes of memory and SPRs. |
enum { |
UNKNOWN, |
STALLED, |
} stallState; |
//! The currently selected scan chain |
int currentScanChain; |
|
//! The currently selected scan chain |
int currentScanChain; |
|
#ifdef NOCACHE |
//! Even if no cached, we need to cache the NPC |
uint32_t npcCachedValue; |
//! Even if no cached, we need to cache the NPC |
uint32_t npcCachedValue; |
|
//! Cached NPC is valid |
bool npcCacheIsValid; |
//! Cached NPC is valid |
bool npcCacheIsValid; |
|
#else |
//! The SPR cache |
SprCache *sprCache; |
//! The SPR cache |
SprCache *sprCache; |
|
//! The memory cache |
MemCache *memCache; |
//! The memory cache |
MemCache *memCache; |
#endif |
|
// Functions to control the CPU |
uint32_t readRiscop (); |
void writeRiscop (uint32_t value); |
// Functions to control the CPU |
uint32_t readRiscop(); |
void writeRiscop(uint32_t value); |
|
// Or1k JTAG actions |
void selectDebugModule (int chain); |
uint32_t readJtagReg (uint32_t addr); |
uint32_t readJtagReg1 (uint32_t addr, |
int bitSizeNoCrc); |
uint32_t readJtagReg1 (uint64_t *dRegArray, |
uint32_t addr, |
int bitSizeNoCrc); |
void writeJtagReg (uint32_t addr, |
uint32_t data); |
// Or1k JTAG actions |
void selectDebugModule(int chain); |
uint32_t readJtagReg(uint32_t addr); |
uint32_t readJtagReg1(uint32_t addr, int bitSizeNoCrc); |
uint32_t readJtagReg1(uint64_t * dRegArray, |
uint32_t addr, int bitSizeNoCrc); |
void writeJtagReg(uint32_t addr, uint32_t data); |
|
// Utilities to pack and unpack bits to/from data registers. |
void clearBits (uint64_t regArray[], |
int regBits); |
// Utilities to pack and unpack bits to/from data registers. |
void clearBits(uint64_t regArray[], int regBits); |
|
void packBits (uint64_t regArray[], |
int fieldOffset, |
int fieldBits, |
uint64_t fieldVal); |
void packBits(uint64_t regArray[], |
int fieldOffset, int fieldBits, uint64_t fieldVal); |
|
uint64_t unpackBits (uint64_t regArray[], |
int fieldOffset, |
int fieldBits); |
uint64_t unpackBits(uint64_t regArray[], |
int fieldOffset, int fieldBits); |
|
// Utility to compute CRC-8 the OpenRISC way. |
uint8_t crc8 (uint64_t dataArray[], |
int size); |
|
// Utility to compute CRC-32 for the debug unit |
uint32_t crc32 (uint64_t dataArray[], |
int size, |
int offset); |
// Utility to compute CRC-8 the OpenRISC way. |
uint8_t crc8(uint64_t dataArray[], int size); |
|
// Functions to bitreverse values |
uint32_t bit_reverse_swar_2(uint32_t x); |
uint32_t bit_reverse_swar_4(uint32_t x); |
uint32_t bit_reverse_swar_8(uint32_t x); |
uint32_t bit_reverse_swar_16(uint32_t x); |
uint32_t bit_reverse_swar_32(uint32_t x); |
// Utility to compute CRC-32 for the debug unit |
uint32_t crc32(uint64_t dataArray[], int size, int offset); |
|
// Functions to bitreverse values |
uint32_t bit_reverse_swar_2(uint32_t x); |
uint32_t bit_reverse_swar_4(uint32_t x); |
uint32_t bit_reverse_swar_8(uint32_t x); |
uint32_t bit_reverse_swar_16(uint32_t x); |
uint32_t bit_reverse_swar_32(uint32_t x); |
#define BITREV(x,y) bit_reverse_data(x,y) |
uint32_t bit_reverse_data(uint32_t x, int length); |
uint32_t bit_reverse_data(uint32_t x, int length); |
|
}; // DebugUnitSC () |
|
|
}; // DebugUnitSC () |
|
#endif // DEBUG_UNIT_SC__H |
#endif // DEBUG_UNIT_SC__H |
/sysc/include/coff.h
11,11 → 11,10
more information about COFF, then O'Reilly has a very excellent book. |
*/ |
|
#define E_SYMNMLEN 8 /* Number of characters in a symbol name */ |
#define E_FILNMLEN 14 /* Number of characters in a file name */ |
#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */ |
|
#define E_SYMNMLEN 8 /* Number of characters in a symbol name */ |
#define E_FILNMLEN 14 /* Number of characters in a file name */ |
#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */ |
|
/* |
* These defines are byte order independent. There is no alignment of fields |
* permitted in the structures. Therefore they are declared as characters |
45,7 → 44,7
((unsigned long)((unsigned char)ps[2])<<16) |\ |
((unsigned long)((unsigned char)ps[1])<<8) |\ |
((unsigned long)((unsigned char)ps[0]))))) |
|
|
#define KEEP_ENDIAN_SHORT(ps) ((short)(((unsigned short)((unsigned char)ps[0])<<8)|\ |
((unsigned short)((unsigned char)ps[1])))) |
|
64,7 → 63,6
|
/*** coff information for Intel 386/486. */ |
|
|
/* |
* Bits for f_flags: |
* |
100,11 → 98,11
#define COFF_F_PATCH 0002000 |
#define COFF_F_NODF 0002000 |
|
#define COFF_I386MAGIC 0x14c /* Linux's system */ |
#define COFF_I386MAGIC 0x14c /* Linux's system */ |
|
#if 0 /* Perhaps, someday, these formats may be used. */ |
#if 0 /* Perhaps, someday, these formats may be used. */ |
#define COFF_I386PTXMAGIC 0x154 |
#define COFF_I386AIXMAGIC 0x175 /* IBM's AIX system */ |
#define COFF_I386AIXMAGIC 0x175 /* IBM's AIX system */ |
#define COFF_I386BADMAG(x) ((COFF_SHORT((x).f_magic) != COFF_I386MAGIC) \ |
&& COFF_SHORT((x).f_magic) != COFF_I386PTXMAGIC \ |
&& COFF_SHORT((x).f_magic) != COFF_I386AIXMAGIC) |
114,15 → 112,14
|
/********************** FILE HEADER **********************/ |
|
struct coff_filehdr |
{ |
char f_magic[2]; // magic number |
char f_nscns[2]; // number of sections |
char f_timdat[4]; // time & date stamp |
char f_symptr[4]; // file pointer to symtab |
char f_nsyms[4]; // number of symtab entries |
char f_opthdr[2]; // sizeof(optional hdr) |
char f_flags[2]; // flags |
struct coff_filehdr { |
char f_magic[2]; // magic number |
char f_nscns[2]; // number of sections |
char f_timdat[4]; // time & date stamp |
char f_symptr[4]; // file pointer to symtab |
char f_nsyms[4]; // number of symtab entries |
char f_opthdr[2]; // sizeof(optional hdr) |
char f_flags[2]; // flags |
}; |
|
#define COFF_FILHDR struct coff_filehdr |
142,16 → 139,15
*/ |
|
//typedef struct |
struct COFF_aouthdr |
{ |
char magic[2]; /* type of file */ |
char vstamp[2]; /* version stamp */ |
char tsize[4]; /* text size in bytes, padded to FW bdry */ |
char dsize[4]; /* initialized data " " */ |
char bsize[4]; /* uninitialized data " " */ |
char entry[4]; /* entry pt. */ |
char text_start[4]; /* base of text used for this file */ |
char data_start[4]; /* base of data used for this file */ |
struct COFF_aouthdr { |
char magic[2]; /* type of file */ |
char vstamp[2]; /* version stamp */ |
char tsize[4]; /* text size in bytes, padded to FW bdry */ |
char dsize[4]; /* initialized data " " */ |
char bsize[4]; /* uninitialized data " " */ |
char entry[4]; /* entry pt. */ |
char text_start[4]; /* base of text used for this file */ |
char data_start[4]; /* base of data used for this file */ |
}; |
|
#define COFF_AOUTHDR COFF_aouthdr |
159,42 → 155,42
|
#define COFF_STMAGIC 0401 |
#define COFF_OMAGIC 0404 |
#define COFF_JMAGIC 0407 /* dirty text and data image, can't share */ |
#define COFF_DMAGIC 0410 /* dirty text segment, data aligned */ |
#define COFF_ZMAGIC 0413 /* The proper magic number for executables */ |
#define COFF_JMAGIC 0407 /* dirty text and data image, can't share */ |
#define COFF_DMAGIC 0410 /* dirty text segment, data aligned */ |
#define COFF_ZMAGIC 0413 /* The proper magic number for executables */ |
#define COFF_SHMAGIC 0443 /* shared library header */ |
|
/********************** STORAGE CLASSES **********************/ |
|
/* This used to be defined as -1, but now n_sclass is unsigned. */ |
#define C_EFCN 0xff /* physical end of function */ |
#define C_EFCN 0xff /* physical end of function */ |
#define C_NULL 0 |
#define C_AUTO 1 /* automatic variable */ |
#define C_EXT 2 /* external symbol */ |
#define C_STAT 3 /* static */ |
#define C_REG 4 /* register variable */ |
#define C_EXTDEF 5 /* external definition */ |
#define C_LABEL 6 /* label */ |
#define C_ULABEL 7 /* undefined label */ |
#define C_MOS 8 /* member of structure */ |
#define C_ARG 9 /* function argument */ |
#define C_STRTAG 10 /* structure tag */ |
#define C_MOU 11 /* member of union */ |
#define C_UNTAG 12 /* union tag */ |
#define C_TPDEF 13 /* type definition */ |
#define C_USTATIC 14 /* undefined static */ |
#define C_ENTAG 15 /* enumeration tag */ |
#define C_MOE 16 /* member of enumeration */ |
#define C_REGPARM 17 /* register parameter */ |
#define C_FIELD 18 /* bit field */ |
#define C_AUTOARG 19 /* auto argument */ |
#define C_LASTENT 20 /* dummy entry (end of block) */ |
#define C_BLOCK 100 /* ".bb" or ".eb" */ |
#define C_FCN 101 /* ".bf" or ".ef" */ |
#define C_EOS 102 /* end of structure */ |
#define C_FILE 103 /* file name */ |
#define C_AUTO 1 /* automatic variable */ |
#define C_EXT 2 /* external symbol */ |
#define C_STAT 3 /* static */ |
#define C_REG 4 /* register variable */ |
#define C_EXTDEF 5 /* external definition */ |
#define C_LABEL 6 /* label */ |
#define C_ULABEL 7 /* undefined label */ |
#define C_MOS 8 /* member of structure */ |
#define C_ARG 9 /* function argument */ |
#define C_STRTAG 10 /* structure tag */ |
#define C_MOU 11 /* member of union */ |
#define C_UNTAG 12 /* union tag */ |
#define C_TPDEF 13 /* type definition */ |
#define C_USTATIC 14 /* undefined static */ |
#define C_ENTAG 15 /* enumeration tag */ |
#define C_MOE 16 /* member of enumeration */ |
#define C_REGPARM 17 /* register parameter */ |
#define C_FIELD 18 /* bit field */ |
#define C_AUTOARG 19 /* auto argument */ |
#define C_LASTENT 20 /* dummy entry (end of block) */ |
#define C_BLOCK 100 /* ".bb" or ".eb" */ |
#define C_FCN 101 /* ".bf" or ".ef" */ |
#define C_EOS 102 /* end of structure */ |
#define C_FILE 103 /* file name */ |
#define C_LINE 104 /* line # reformatted as symbol table entry */ |
#define C_ALIAS 105 /* duplicate tag */ |
#define C_ALIAS 105 /* duplicate tag */ |
#define C_HIDDEN 106 /* ext symbol in dmert public lib */ |
|
#define C_WEAKEXT 127 /* weak symbol -- GNU extension */ |
206,7 → 202,7
#define C_SYSTEM 23 /* System Wide variable */ |
|
/* New storage classes for WINDOWS_NT */ |
#define C_SECTION 104 /* section name */ |
#define C_SECTION 104 /* section name */ |
#define C_NT_WEAK 105 /* weak external */ |
|
/* New storage classes for 80960 */ |
217,14 → 213,14
#define C_SCALL 107 /* Procedure reachable via system call */ |
#define C_LEAFEXT 108 /* External leaf */ |
#define C_LEAFSTAT 113 /* Static leaf */ |
#define C_OPTVAR 109 /* Optimized variable */ |
#define C_DEFINE 110 /* Preprocessor #define */ |
#define C_PRAGMA 111 /* Advice to compiler or linker */ |
#define C_SEGMENT 112 /* 80960 segment name */ |
#define C_OPTVAR 109 /* Optimized variable */ |
#define C_DEFINE 110 /* Preprocessor #define */ |
#define C_PRAGMA 111 /* Advice to compiler or linker */ |
#define C_SEGMENT 112 /* 80960 segment name */ |
|
/* Storage classes for m88k */ |
#define C_SHADOW 107 /* shadow symbol */ |
#define C_VERSION 108 /* coff version symbol */ |
#define C_SHADOW 107 /* shadow symbol */ |
#define C_VERSION 108 /* coff version symbol */ |
|
/* New storage classes for RS/6000 */ |
#define C_HIDEXT 107 /* Un-named external symbol */ |
249,9 → 245,9
#define C_ESTAT (0x90) |
|
/* Storage classes for Thumb symbols */ |
#define C_THUMBEXT (128 + C_EXT) /* 130 */ |
#define C_THUMBSTAT (128 + C_STAT) /* 131 */ |
#define C_THUMBLABEL (128 + C_LABEL) /* 134 */ |
#define C_THUMBEXT (128 + C_EXT) /* 130 */ |
#define C_THUMBSTAT (128 + C_STAT) /* 131 */ |
#define C_THUMBLABEL (128 + C_LABEL) /* 134 */ |
#define C_THUMBEXTFUNC (C_THUMBEXT + 20) /* 150 */ |
#define C_THUMBSTATFUNC (C_THUMBSTAT + 20) /* 151 */ |
|
258,16 → 254,16
/********************** SECTION HEADER **********************/ |
|
struct COFF_scnhdr { |
char s_name[8]; /* section name */ |
char s_paddr[4]; /* physical address, aliased s_nlib */ |
char s_vaddr[4]; /* virtual address */ |
char s_size[4]; /* section size */ |
char s_scnptr[4]; /* file ptr to raw data for section */ |
char s_relptr[4]; /* file ptr to relocation */ |
char s_lnnoptr[4]; /* file ptr to line numbers */ |
char s_nreloc[2]; /* number of relocation entries */ |
char s_nlnno[2]; /* number of line number entries */ |
char s_flags[4]; /* flags */ |
char s_name[8]; /* section name */ |
char s_paddr[4]; /* physical address, aliased s_nlib */ |
char s_vaddr[4]; /* virtual address */ |
char s_size[4]; /* section size */ |
char s_scnptr[4]; /* file ptr to raw data for section */ |
char s_relptr[4]; /* file ptr to relocation */ |
char s_lnnoptr[4]; /* file ptr to line numbers */ |
char s_nreloc[2]; /* number of relocation entries */ |
char s_nlnno[2]; /* number of line number entries */ |
char s_flags[4]; /* flags */ |
}; |
|
#define COFF_SCNHDR struct COFF_scnhdr |
283,23 → 279,23
#define COFF_COMMENT ".comment" |
#define COFF_LIB ".lib" |
|
#define COFF_SECT_TEXT 0 /* Section for instruction code */ |
#define COFF_SECT_DATA 1 /* Section for initialized globals */ |
#define COFF_SECT_BSS 2 /* Section for un-initialized globals */ |
#define COFF_SECT_REQD 3 /* Minimum number of sections for good file */ |
#define COFF_SECT_TEXT 0 /* Section for instruction code */ |
#define COFF_SECT_DATA 1 /* Section for initialized globals */ |
#define COFF_SECT_BSS 2 /* Section for un-initialized globals */ |
#define COFF_SECT_REQD 3 /* Minimum number of sections for good file */ |
|
#define COFF_STYP_REG 0x00 /* regular segment */ |
#define COFF_STYP_DSECT 0x01 /* dummy segment */ |
#define COFF_STYP_NOLOAD 0x02 /* no-load segment */ |
#define COFF_STYP_GROUP 0x04 /* group segment */ |
#define COFF_STYP_PAD 0x08 /* .pad segment */ |
#define COFF_STYP_COPY 0x10 /* copy section */ |
#define COFF_STYP_TEXT 0x20 /* .text segment */ |
#define COFF_STYP_DATA 0x40 /* .data segment */ |
#define COFF_STYP_BSS 0x80 /* .bss segment */ |
#define COFF_STYP_INFO 0x200 /* .comment section */ |
#define COFF_STYP_OVER 0x400 /* overlay section */ |
#define COFF_STYP_LIB 0x800 /* library section */ |
#define COFF_STYP_REG 0x00 /* regular segment */ |
#define COFF_STYP_DSECT 0x01 /* dummy segment */ |
#define COFF_STYP_NOLOAD 0x02 /* no-load segment */ |
#define COFF_STYP_GROUP 0x04 /* group segment */ |
#define COFF_STYP_PAD 0x08 /* .pad segment */ |
#define COFF_STYP_COPY 0x10 /* copy section */ |
#define COFF_STYP_TEXT 0x20 /* .text segment */ |
#define COFF_STYP_DATA 0x40 /* .data segment */ |
#define COFF_STYP_BSS 0x80 /* .bss segment */ |
#define COFF_STYP_INFO 0x200 /* .comment section */ |
#define COFF_STYP_OVER 0x400 /* overlay section */ |
#define COFF_STYP_LIB 0x800 /* library section */ |
|
/* |
* Shared libraries have the following section header in the data field for |
307,8 → 303,8
*/ |
|
struct COFF_slib { |
char sl_entsz[4]; /* Size of this entry */ |
char sl_pathndx[4]; /* size of the header field */ |
char sl_entsz[4]; /* Size of this entry */ |
char sl_pathndx[4]; /* size of the header field */ |
}; |
|
#define COFF_SLIBHD struct COFF_slib |
323,11 → 319,11
*/ |
|
struct COFF_lineno { |
union { |
char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ |
char l_paddr[4]; /* (physical) address of line number */ |
} l_addr; |
char l_lnno[2]; /* line number */ |
union { |
char l_symndx[4]; /* function name symbol index, iff l_lnno == 0 */ |
char l_paddr[4]; /* (physical) address of line number */ |
} l_addr; |
char l_lnno[2]; /* line number */ |
}; |
|
#define COFF_LINENO struct COFF_lineno |
335,8 → 331,8
|
/********************** SYMBOLS **********************/ |
|
#define COFF_E_SYMNMLEN 8 /* # characters in a short symbol name */ |
#define COFF_E_FILNMLEN 14 /* # characters in a file name */ |
#define COFF_E_SYMNMLEN 8 /* # characters in a short symbol name */ |
#define COFF_E_FILNMLEN 14 /* # characters in a file name */ |
#define COFF_E_DIMNUM 4 /* # array dimensions in auxiliary entry */ |
|
/* |
343,32 → 339,31
* All symbols and sections have the following definition |
*/ |
|
struct COFF_syment |
{ |
union { |
char e_name[E_SYMNMLEN]; /* Symbol name (first 8 characters) */ |
struct { |
char e_zeroes[4]; /* Leading zeros */ |
char e_offset[4]; /* Offset if this is a header section */ |
} e; |
} e; |
struct COFF_syment { |
union { |
char e_name[E_SYMNMLEN]; /* Symbol name (first 8 characters) */ |
struct { |
char e_zeroes[4]; /* Leading zeros */ |
char e_offset[4]; /* Offset if this is a header section */ |
} e; |
} e; |
|
char e_value[4]; /* Value (address) of the segment */ |
char e_scnum[2]; /* Section number */ |
char e_type[2]; /* Type of section */ |
char e_sclass[1]; /* Loader class */ |
char e_numaux[1]; /* Number of auxiliary entries which follow */ |
char e_value[4]; /* Value (address) of the segment */ |
char e_scnum[2]; /* Section number */ |
char e_type[2]; /* Type of section */ |
char e_sclass[1]; /* Loader class */ |
char e_numaux[1]; /* Number of auxiliary entries which follow */ |
}; |
|
#define COFF_N_BTMASK (0xf) /* Mask for important class bits */ |
#define COFF_N_TMASK (0x30) /* Mask for important type bits */ |
#define COFF_N_BTSHFT (4) /* # bits to shift class field */ |
#define COFF_N_TSHIFT (2) /* # bits to shift type field */ |
#define COFF_N_BTMASK (0xf) /* Mask for important class bits */ |
#define COFF_N_TMASK (0x30) /* Mask for important type bits */ |
#define COFF_N_BTSHFT (4) /* # bits to shift class field */ |
#define COFF_N_TSHIFT (2) /* # bits to shift type field */ |
|
/* |
* Auxiliary entries because the main table is too limiting. |
*/ |
|
|
union COFF_auxent { |
|
/* |
375,65 → 370,65
* Debugger information |
*/ |
|
struct { |
char x_tagndx[4]; /* str, un, or enum tag indx */ |
union { |
struct { |
char x_lnno[2]; /* declaration line number */ |
char x_size[2]; /* str/union/array size */ |
} x_lnsz; |
char x_fsize[4]; /* size of function */ |
} x_misc; |
struct { |
char x_tagndx[4]; /* str, un, or enum tag indx */ |
union { |
struct { |
char x_lnno[2]; /* declaration line number */ |
char x_size[2]; /* str/union/array size */ |
} x_lnsz; |
char x_fsize[4]; /* size of function */ |
} x_misc; |
|
union { |
struct { /* if ISFCN, tag, or .bb */ |
char x_lnnoptr[4]; /* ptr to fcn line # */ |
char x_endndx[4]; /* entry ndx past block end */ |
} x_fcn; |
union { |
struct { /* if ISFCN, tag, or .bb */ |
char x_lnnoptr[4]; /* ptr to fcn line # */ |
char x_endndx[4]; /* entry ndx past block end */ |
} x_fcn; |
|
struct { /* if ISARY, up to 4 dimen. */ |
char x_dimen[E_DIMNUM][2]; |
} x_ary; |
} x_fcnary; |
struct { /* if ISARY, up to 4 dimen. */ |
char x_dimen[E_DIMNUM][2]; |
} x_ary; |
} x_fcnary; |
|
char x_tvndx[2]; /* tv index */ |
} x_sym; |
char x_tvndx[2]; /* tv index */ |
} x_sym; |
|
/* |
* Source file names (debugger information) |
*/ |
|
union { |
char x_fname[E_FILNMLEN]; |
struct { |
char x_zeroes[4]; |
char x_offset[4]; |
} x_n; |
} x_file; |
union { |
char x_fname[E_FILNMLEN]; |
struct { |
char x_zeroes[4]; |
char x_offset[4]; |
} x_n; |
} x_file; |
|
/* |
* Section information |
*/ |
|
struct { |
char x_scnlen[4]; /* section length */ |
char x_nreloc[2]; /* # relocation entries */ |
char x_nlinno[2]; /* # line numbers */ |
} x_scn; |
struct { |
char x_scnlen[4]; /* section length */ |
char x_nreloc[2]; /* # relocation entries */ |
char x_nlinno[2]; /* # line numbers */ |
} x_scn; |
|
/* |
* Transfer vector (branch table) |
*/ |
|
struct { |
char x_tvfill[4]; /* tv fill value */ |
char x_tvlen[2]; /* length of .tv */ |
char x_tvran[2][2]; /* tv range */ |
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */ |
|
struct { |
char x_tvfill[4]; /* tv fill value */ |
char x_tvlen[2]; /* length of .tv */ |
char x_tvran[2][2]; /* tv range */ |
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */ |
}; |
|
#define COFF_SYMENT struct COFF_syment |
#define COFF_SYMESZ 18 |
#define COFF_SYMESZ 18 |
#define COFF_AUXENT union COFF_auxent |
#define COFF_AUXESZ 18 |
|
442,9 → 437,9
/********************** RELOCATION DIRECTIVES **********************/ |
|
struct COFF_reloc { |
char r_vaddr[4]; /* Virtual address of item */ |
char r_symndx[4]; /* Symbol index in the symtab */ |
char r_type[2]; /* Relocation type */ |
char r_vaddr[4]; /* Virtual address of item */ |
char r_symndx[4]; /* Symbol index in the symtab */ |
char r_type[2]; /* Relocation type */ |
}; |
|
#define COFF_RELOC struct COFF_reloc |
/sysc/include/TapActionDRScan.h
28,7 → 28,6
|
// $Id$ |
|
|
#ifndef TAP_ACTION_DR_SCAN__H |
#define TAP_ACTION_DR_SCAN__H |
|
37,7 → 36,6
#include "TapAction.h" |
#include "TapStateMachine.h" |
|
|
//! Class to represent a TAP DR-Scan action. |
|
//! JTAG data registers can be huge and are represented generically as arrays |
47,93 → 45,83
//! The SystemC classes for large unsigned ints are fabulously inefficient in |
//! the reference implementation, so are not used here. |
|
class TapActionDRScan |
: public TapAction |
{ |
class TapActionDRScan:public TapAction { |
public: |
|
// Constructors and destructor |
TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegInArray[], |
int _dRegSize); |
TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegIn, |
int _dRegSize); |
TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegInArray[], |
int _dRegSize, |
int _goToPauseState, |
int _bitsBeforePauseState); |
TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegIn, |
int _dRegSize, |
int _goToPauseState, |
int _bitsBeforePauseState); |
~TapActionDRScan (); |
// Constructors and destructor |
TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegInArray[], int _dRegSize); |
TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegIn, int _dRegSize); |
TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegInArray[], |
int _dRegSize, |
int _goToPauseState, int _bitsBeforePauseState); |
TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegIn, |
int _dRegSize, |
int _goToPauseState, int _bitsBeforePauseState); |
~TapActionDRScan(); |
|
// Get the shifted out value |
void getDRegOut (uint64_t dRegArray[]); |
uint64_t getDRegOut (); |
// Get the shifted out value |
void getDRegOut(uint64_t dRegArray[]); |
uint64_t getDRegOut(); |
|
|
protected: |
|
// Process the action for IR-Scan |
bool process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms); |
// Process the action for IR-Scan |
bool process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms); |
|
|
private: |
|
//! Number of bits in the data register |
int dRegBitSize; |
//! Number of bits in the data register |
int dRegBitSize; |
|
//! Number of uint64_t words in the data register |
int dRegWordSize; |
//! Number of uint64_t words in the data register |
int dRegWordSize; |
|
//! Mask for top word in multi-word register |
uint64_t topMask; |
//! Mask for top word in multi-word register |
uint64_t topMask; |
|
//! The value being shifted in |
uint64_t *dRegInArray; |
//! The value being shifted in |
uint64_t *dRegInArray; |
|
//! The value being shifted in (small version optimization) |
uint64_t dRegIn; |
//! The value being shifted in (small version optimization) |
uint64_t dRegIn; |
|
//! The value shifted out |
uint64_t *dRegOutArray; |
//! The value shifted out |
uint64_t *dRegOutArray; |
|
//! The value being shifted out (small version optimization) |
uint64_t dRegOut; |
//! The value being shifted out (small version optimization) |
uint64_t dRegOut; |
|
//! Should we go to PAUSE state and poll tdo during operation? |
int goToPauseState; |
//! Should we go to PAUSE state and poll tdo during operation? |
int goToPauseState; |
|
//! Number of bits to shift before going to PAUSE state and polling tdo |
int bitsBeforePause; |
//! Number of bits to shift before going to PAUSE state and polling tdo |
int bitsBeforePause; |
|
int pauseStateCount; |
int pauseStateCount; |
|
//! Bits shifted so far |
int bitsShifted; |
//! Bits shifted so far |
int bitsShifted; |
|
//! Where we are in the Shift-DR process |
enum { |
SHIFT_DR_PREPARING, |
SHIFT_DR_SHIFTING, |
SHIFT_DR_SHIFTING_BEFORE_PAUSE, |
SHIFT_DR_SHIFTING_PAUSE, |
SHIFT_DR_EXIT2, |
SHIFT_DR_SHIFTING_AFTER_PAUSE, |
SHIFT_DR_UPDATING |
} dRScanState; |
//! Where we are in the Shift-DR process |
enum { |
SHIFT_DR_PREPARING, |
SHIFT_DR_SHIFTING, |
SHIFT_DR_SHIFTING_BEFORE_PAUSE, |
SHIFT_DR_SHIFTING_PAUSE, |
SHIFT_DR_EXIT2, |
SHIFT_DR_SHIFTING_AFTER_PAUSE, |
SHIFT_DR_UPDATING |
} dRScanState; |
|
// Utilities to shift the bottom bit out and top bit in |
bool shiftDRegOut (); |
void shiftDRegIn (bool bitIn); |
// Utilities to shift the bottom bit out and top bit in |
bool shiftDRegOut(); |
void shiftDRegIn(bool bitIn); |
|
}; // TapActionDRScan |
}; // TapActionDRScan |
|
#endif // TAP_ACTION_DR_SCAN__H |
#endif // TAP_ACTION_DR_SCAN__H |
/sysc/include/MpHash.h
31,75 → 31,63
|
#include <stdint.h> |
|
|
//! Default size of the matchpoint hash table. Largest prime < 2^10 |
#define DEFAULT_MP_HASH_SIZE 1021 |
|
|
//! Enumeration of different types of matchpoint. |
|
//! These have explicit values matching the second digit of 'z' and 'Z' |
//! packets. |
enum MpType { |
BP_MEMORY = 0, |
BP_HARDWARE = 1, |
WP_WRITE = 2, |
WP_READ = 3, |
WP_ACCESS = 4 |
BP_MEMORY = 0, |
BP_HARDWARE = 1, |
WP_WRITE = 2, |
WP_READ = 3, |
WP_ACCESS = 4 |
}; |
|
|
class MpHash; |
|
//! A structure for a matchpoint hash table entry |
struct MpEntry |
{ |
struct MpEntry { |
public: |
|
friend class MpHash; // The only one which can get at next |
friend class MpHash; // The only one which can get at next |
|
MpType type; //!< Type of matchpoint |
uint32_t addr; //!< Address with the matchpoint |
uint32_t instr; //!< Substituted instruction |
MpType type; //!< Type of matchpoint |
uint32_t addr; //!< Address with the matchpoint |
uint32_t instr; //!< Substituted instruction |
|
|
private: |
|
MpEntry *next; //!< Next in this slot |
MpEntry * next; //!< Next in this slot |
}; |
|
|
//! A hash table for matchpoints |
|
//! We do this as our own open hash table. Our keys are a pair of entities |
//! (address and type), so STL map is not trivial to use. |
|
class MpHash |
{ |
class MpHash { |
public: |
|
// Constructor and destructor |
MpHash (int _size = DEFAULT_MP_HASH_SIZE); |
~MpHash (); |
// Constructor and destructor |
MpHash(int _size = DEFAULT_MP_HASH_SIZE); |
~MpHash(); |
|
// Accessor methods |
void add (MpType type, |
uint32_t addr, |
uint32_t instr); |
MpEntry *lookup (MpType type, |
uint32_t addr); |
bool remove (MpType type, |
uint32_t addr, |
uint32_t *instr = NULL); |
// Accessor methods |
void add(MpType type, uint32_t addr, uint32_t instr); |
MpEntry *lookup(MpType type, uint32_t addr); |
bool remove(MpType type, uint32_t addr, uint32_t * instr = NULL); |
|
private: |
|
//! The hash table |
MpEntry **hashTab; |
//! The hash table |
MpEntry ** hashTab; |
|
//! Size of the hash table |
int size; |
//! Size of the hash table |
int size; |
|
}; |
|
#endif // MP_HASH__H |
#endif // MP_HASH__H |
/sysc/include/Or1200MonitorSC.h
44,51 → 44,48
//! wakes up on each posedge clock to check for "special" l.nop instructions, |
//! which need processing. |
|
class Or1200MonitorSC |
: public sc_core::sc_module |
{ |
class Or1200MonitorSC:public sc_core::sc_module { |
public: |
|
// Constructor |
Or1200MonitorSC (sc_core::sc_module_name name, |
OrpsocAccess *_accessor, |
MemoryLoad *_memoryload, |
int argc, |
char *argv[]); |
// Constructor |
Or1200MonitorSC(sc_core::sc_module_name name, |
OrpsocAccess * _accessor, |
MemoryLoad * _memoryload, int argc, char *argv[]); |
|
// Method to check instructions |
void checkInstruction(); |
// Method to check instructions |
void checkInstruction(); |
|
// Methods to setup and output state of processor to a file |
void displayState(); |
void displayStateBinary(); |
// Methods to setup and output state of processor to a file |
void displayState(); |
void displayStateBinary(); |
|
// Methods to generate the call and return list during execution |
void callLog(); |
// Methods to generate trace to stdout |
void printTrace(); |
|
// Method to calculate performance of the sim |
void perfSummary(); |
// Methods to generate the call and return list during execution |
void callLog(); |
|
// Method to print out the command-line switches for this module's options |
void printSwitches(); |
// Method to calculate performance of the sim |
void perfSummary(); |
|
// Method to print out the usage for each option |
void printUsage(); |
|
// Method to dump simulation's RAM contents at finish |
void memdump(); |
// Method to print out the command-line switches for this module's options |
void printSwitches(); |
|
// Method used for monitoring and logging transactions on the system bus |
//void busMonitor(); |
|
// Method to do simulator assisted printf'ing |
void simPrintf(uint32_t stackaddr, uint32_t regparam); |
// Method to print out the usage for each option |
void printUsage(); |
|
// Method to dump simulation's RAM contents at finish |
void memdump(); |
|
// Method used for monitoring and logging transactions on the system bus |
//void busMonitor(); |
|
// The ports |
sc_in<bool> clk; |
// Method to do simulator assisted printf'ing |
void simPrintf(uint32_t stackaddr, uint32_t regparam); |
|
// The ports |
sc_in < bool > clk; |
|
private: |
|
#define DEFAULT_EXEC_LOG_FILE "or1200_exec.log" |
96,54 → 93,59
#define DEFAULT_MEMDUMP_FILE "vorpsoc_ram.dump" |
#define DEFAULT_BUS_LOG_FILE "bus_trans.log" |
|
// Special NOP instructions |
static const uint32_t NOP_NOP = 0x15000000; //!< Normal nop instruction |
static const uint32_t NOP_EXIT = 0x15000001; //!< End of simulation |
static const uint32_t NOP_REPORT = 0x15000002; //!< Simple report |
static const uint32_t NOP_PRINTF = 0x15000003; //!< Simprintf instruction |
static const uint32_t NOP_PUTC = 0x15000004; //!< Putc instruction |
static const uint32_t NOP_CNT_RESET = 0x15000005; //!< Reset statistics counters |
static const uint32_t NOP_CNT_RESET1 = 0x15000007; /* Reset statistics counter 1 */ |
static const uint32_t NOP_CNT_RESET2 = 0x15000008; /* Reset statistics counter 2 */ |
static const uint32_t NOP_CNT_RESET3 = 0x15000009; /* Reset statistics counter 3 */ |
static const uint32_t NOP_MEM_STATS_RESET = 0x15000010; //!< Reset memory statistics counters |
static const uint32_t NOP_CNT_RESET_DIFFERENCE = 0x15000006; //!< Reset stats counters, print |
// Special NOP instructions |
static const uint32_t NOP_NOP = 0; //!< Normal nop instruction |
static const uint32_t NOP_EXIT = 1; //!< End of simulation |
static const uint32_t NOP_REPORT = 2; //!< Simple report |
static const uint32_t NOP_PRINTF = 3; //!< Simprintf instruction |
static const uint32_t NOP_PUTC = 4; //!< Putc instruction |
static const uint32_t NOP_CNT_RESET = 5; //!< Reset statistics counters |
static const uint32_t NOP_GET_TICKS = 6; //!< Get # ticks running |
static const uint32_t NOP_GET_PS = 7; //!< Get picosecs/cycle |
|
// Variables for processor status output |
ofstream statusFile; |
ofstream profileFile; |
bool profiling_enabled; |
bool logging_enabled; |
bool logfile_name_provided; |
bool logging_regs; |
bool binary_log_format; |
bool quiet; |
bool monitor_for_crash; |
int lookslikewevecrashed_count, crash_monitor_buffer_head; |
static const uint32_t NOP_CNT_RESET1 = 16; /* Reset statistics counter 1 */ |
static const uint32_t NOP_CNT_RESET2 = 17; /* Reset statistics counter 2 */ |
static const uint32_t NOP_CNT_RESET3 = 18; /* Reset statistics counter 3 */ |
static const uint32_t NOP_MEM_STATS_RESET = 32; //!< Reset memory statistics counters |
static const uint32_t NOP_CNT_RESET_DIFFERENCE = 48; //!< Reset stats counters, print |
|
// Variables for processor status output |
ofstream statusFile; |
ofstream profileFile; |
bool profiling_enabled; |
bool trace_enabled; |
bool logging_enabled; |
bool logfile_name_provided; |
bool logging_regs; |
bool binary_log_format; |
bool perf_summary; |
bool monitor_for_crash; |
int lookslikewevecrashed_count, crash_monitor_buffer_head; |
#define CRASH_MONITOR_BUFFER_SIZE 32 |
uint32_t crash_monitor_buffer[CRASH_MONITOR_BUFFER_SIZE][2]; //PC, Insn |
bool wait_for_stall_cmd_response; |
unsigned long long insn_count, insn_count_rst; |
unsigned long long cycle_count, cycle_count_rst; |
unsigned long long cycles_1, cycles_2, cycles_3; // Cycle counters for l.nop insns |
ofstream memdumpFile; |
string memdumpFileName; |
bool do_memdump; |
int memdump_start_addr, memdump_end_addr; |
bool bus_trans_log_enabled, bus_trans_log_name_provided, bus_trans_log_start_delay_enable; |
sc_time bus_trans_log_start_delay; |
enum busLogStates { BUS_LOG_IDLE, BUS_LOG_WAIT_FOR_ACK }; |
ofstream busTransLog; |
uint32_t crash_monitor_buffer[CRASH_MONITOR_BUFFER_SIZE][2]; //PC, Insn |
bool wait_for_stall_cmd_response; |
unsigned long long insn_count, insn_count_rst; |
unsigned long long cycle_count, cycle_count_rst; |
unsigned long long cycles_1, cycles_2, cycles_3; // Cycle counters for l.nop insns |
ofstream memdumpFile; |
string memdumpFileName; |
bool do_memdump; |
int memdump_start_addr, memdump_end_addr; |
bool bus_trans_log_enabled, bus_trans_log_name_provided, |
bus_trans_log_start_delay_enable; |
sc_time bus_trans_log_start_delay; |
enum busLogStates { BUS_LOG_IDLE, BUS_LOG_WAIT_FOR_ACK }; |
ofstream busTransLog; |
|
//! Time measurement variable - for calculating performance of the sim |
clock_t start; |
//! Time measurement variable - for calculating performance of the sim |
clock_t start; |
|
//! The accessor for the Orpsoc instance |
OrpsocAccess *accessor; |
//! The accessor for the Orpsoc instance |
OrpsocAccess *accessor; |
|
//! The memory loading object |
MemoryLoad *memoryload; |
//! The memory loading object |
MemoryLoad *memoryload; |
|
}; // Or1200MonitorSC () |
}; // Or1200MonitorSC () |
|
#endif // OR1200_MONITOR_SC__H |
#endif // OR1200_MONITOR_SC__H |
/sysc/include/TapAction.h
28,27 → 28,21
|
// $Id$ |
|
|
#ifndef TAP_ACTION__H |
#define TAP_ACTION__H |
|
#include "TapStateMachine.h" |
|
namespace sc_core |
{ |
class sc_event; |
namespace sc_core { |
class sc_event; |
} |
|
|
//! Enumeration of all the TAP actions supported. |
|
//! Enumeration of all the TAP actions supported. |
enum TapActionType { |
TAP_ACTION_RESET = 0, |
TAP_ACTION_SHIFT_DR = 1, |
TAP_ACTION_SHIFT_IR = 2 |
TAP_ACTION_RESET = 0, |
TAP_ACTION_SHIFT_DR = 1, |
TAP_ACTION_SHIFT_IR = 2 |
}; |
|
|
//! Abstract class to represent a TAP action. |
|
//! Subclasses implement specific actions: Reset (TapActionReset::), DR-Scan |
58,42 → 52,36
//! completion. Since we are not a SystemC class, we don't do the notification |
//! ourselves. |
|
class TapAction |
{ |
class TapAction { |
public: |
|
friend class JtagSC; |
friend class JtagSC; |
|
// Constructor |
TapAction (sc_core::sc_event *_doneEvent); |
// Constructor |
TapAction(sc_core::sc_event * _doneEvent); |
|
|
protected: |
|
// Accessor for the SystemC event to notify completion |
sc_core::sc_event *getDoneEvent (); |
// Accessor for the SystemC event to notify completion |
sc_core::sc_event * getDoneEvent(); |
|
// Process the action. Pure virtual, so must be implemented by subclasses. |
virtual bool process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms) = 0; |
// Process the action. Pure virtual, so must be implemented by subclasses. |
virtual bool process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms) = 0; |
|
// Function to drive the TAP to a consistent state, optionally with a |
// warning. |
bool checkResetDone (TapStateMachine *tapStateMachine, |
bool &tms, |
bool warn = false); |
// Function to drive the TAP to a consistent state, optionally with a |
// warning. |
bool checkResetDone(TapStateMachine * tapStateMachine, |
bool & tms, bool warn = false); |
|
|
private: |
|
//! The associated SystemC event to mark completion |
sc_core::sc_event *doneEvent; |
//! The associated SystemC event to mark completion |
sc_core::sc_event * doneEvent; |
|
//! Counter for the reset process |
int resetCounter; |
//! Counter for the reset process |
int resetCounter; |
|
}; // TapAction () |
}; // TapAction () |
|
#endif // TAP_ACTION__H |
#endif // TAP_ACTION__H |
/sysc/include/TapActionIRScan.h
28,7 → 28,6
|
// $Id$ |
|
|
#ifndef TAP_ACTION_IR_SCAN__H |
#define TAP_ACTION_IR_SCAN__H |
|
37,7 → 36,6
#include "TapAction.h" |
#include "TapStateMachine.h" |
|
|
//! Class to represent a TAP IR-Scan action. |
|
//! This class assumes that JTAG instruction registers are relatively |
46,50 → 44,43
//! example uses 5 bits. 32-bits seems more than enough for the largest |
//! applications. |
|
class TapActionIRScan |
: public TapAction |
{ |
class TapActionIRScan:public TapAction { |
public: |
|
// Constructor |
TapActionIRScan (sc_core::sc_event *_doneEvent, |
uint32_t _iRegIn, |
int _iRegSize); |
// Constructor |
TapActionIRScan(sc_core::sc_event * _doneEvent, |
uint32_t _iRegIn, int _iRegSize); |
|
// Get the shifted out value |
uint32_t getIRegOut (); |
// Get the shifted out value |
uint32_t getIRegOut(); |
|
|
protected: |
|
// Process the action for IR-Scan |
bool process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms); |
// Process the action for IR-Scan |
bool process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms); |
|
|
private: |
|
//! The value being shifted in |
uint32_t iRegIn; |
//! The value being shifted in |
uint32_t iRegIn; |
|
//! The number of bits to shift |
int iRegSize; |
//! The number of bits to shift |
int iRegSize; |
|
//! The value shifted out |
uint32_t iRegOut; |
//! The value shifted out |
uint32_t iRegOut; |
|
//! The number of bits shifted so far |
int bitsShifted; |
//! The number of bits shifted so far |
int bitsShifted; |
|
//! Where we are in the IR-scan process |
enum { |
SHIFT_IR_PREPARING, |
SHIFT_IR_SHIFTING, |
SHIFT_IR_UPDATING |
} iRScanState; |
//! Where we are in the IR-scan process |
enum { |
SHIFT_IR_PREPARING, |
SHIFT_IR_SHIFTING, |
SHIFT_IR_UPDATING |
} iRScanState; |
|
}; // TapActionIRScan |
}; // TapActionIRScan |
|
#endif // TAP_ACTION_IR_SCAN__H |
#endif // TAP_ACTION_IR_SCAN__H |
/sysc/include/RspConnection.h
31,11 → 31,9
|
#include "RspPacket.h" |
|
|
//! The default service to use if port number = 0 and no service specified |
#define DEFAULT_RSP_SERVICE "or1ksim-rsp" |
|
|
//----------------------------------------------------------------------------- |
//! Class implementing the RSP connection listener |
|
57,46 → 55,44
//! back to the client. Both must be non-blocking in the SystemC sense |
//! (i.e. allow other SystemC threads to run). |
//----------------------------------------------------------------------------- |
class RspConnection |
{ |
class RspConnection { |
public: |
|
// Constructors and destructor |
RspConnection (int _portNum); |
RspConnection (const char *_serviceName = DEFAULT_RSP_SERVICE); |
~RspConnection (); |
// Constructors and destructor |
RspConnection(int _portNum); |
RspConnection(const char *_serviceName = DEFAULT_RSP_SERVICE); |
~RspConnection(); |
|
// Public interface: manage client connections |
bool rspConnect (); |
void rspClose (); |
bool isConnected (); |
char rspSocketPeek (); |
|
// Public interface: get packets from the stream and put them out |
bool getPkt (RspPacket *pkt); |
bool putPkt (RspPacket *pkt); |
|
int getRspChar (); |
// Public interface: manage client connections |
bool rspConnect(); |
void rspClose(); |
bool isConnected(); |
char rspSocketPeek(); |
|
// Public interface: get packets from the stream and put them out |
bool getPkt(RspPacket * pkt); |
bool putPkt(RspPacket * pkt); |
|
int getRspChar(); |
|
private: |
|
// Generic initializer |
void rspInit (int _portNum, |
const char *_serviceName); |
// Generic initializer |
void rspInit(int _portNum, const char *_serviceName); |
|
// Internal routines to handle individual chars |
bool putRspChar (char c); |
//int getRspChar (); |
// Internal routines to handle individual chars |
bool putRspChar(char c); |
//int getRspChar (); |
|
//! The port number to listen on |
int portNum; |
//! The port number to listen on |
int portNum; |
|
//! The service name to listen on |
const char *serviceName; |
//! The service name to listen on |
const char *serviceName; |
|
//! The client file descriptor |
int clientFd; |
//! The client file descriptor |
int clientFd; |
|
}; // RspConnection () |
}; // RspConnection () |
|
#endif // RSP_CONNECTION__H |
#endif // RSP_CONNECTION__H |
/sysc/include/TraceSC.h
33,53 → 33,46
|
#include "Vorpsoc_top.h" |
|
|
#if VM_TRACE |
#include <SpTraceVcdC.h> |
#endif |
|
|
//! Class to drive the Verilator VCD trace interface. |
|
//! Substantive code is only implemented if trace is enabled. |
|
class TraceSC |
: public sc_core::sc_module |
{ |
class TraceSC:public sc_core::sc_module { |
public: |
|
// Constructor and destructor |
TraceSC (sc_core::sc_module_name name, |
Vorpsoc_top *_traceTarget, |
int argc, |
char * argv[]); |
~TraceSC (); |
// Constructor and destructor |
TraceSC(sc_core::sc_module_name name, |
Vorpsoc_top * _traceTarget, int argc, char *argv[]); |
~TraceSC(); |
|
// Method to drive the trace |
void driveTrace(); |
// Method to drive the trace |
void driveTrace(); |
|
// VCD dump controling vars |
int dump_start_delay, dump_stop_set; |
int dumping_now; |
sc_time dump_start,dump_stop; |
|
/* The port */ |
//sc_in<bool> clk; |
// VCD dump controling vars |
int dump_start_delay, dump_stop_set; |
int dumping_now; |
sc_time dump_start, dump_stop; |
|
/* The port */ |
//sc_in<bool> clk; |
|
private: |
|
//! The ORPSoC module we are tracing |
Vorpsoc_top *traceTarget; |
//! The ORPSoC module we are tracing |
Vorpsoc_top * traceTarget; |
|
|
#if VM_TRACE |
//! The System Perl Trace file |
SpTraceVcdCFile *spTraceFile; |
//! The System Perl Trace file |
SpTraceVcdCFile *spTraceFile; |
#endif |
|
// Set the time resolution |
void setSpTimeResolution (sc_time t); |
// Set the time resolution |
void setSpTimeResolution(sc_time t); |
|
}; // TraceSC () |
}; // TraceSC () |
|
#endif // TRACE_SC__H |
#endif // TRACE_SC__H |
/sysc/include/TapActionReset.h
28,7 → 28,6
|
// $Id$ |
|
|
#ifndef TAP_RESET_ACTION__H |
#define TAP_RESET_ACTION__H |
|
35,35 → 34,28
#include "TapAction.h" |
#include "TapStateMachine.h" |
|
|
//! Class to represent a TAP reset action. |
|
//! This can be very simple, since it reuses the parent class method to do the |
//! reset. |
|
class TapActionReset |
: public TapAction |
{ |
class TapActionReset:public TapAction { |
public: |
|
// Constructor |
TapActionReset (sc_core::sc_event *_doneEvent); |
// Constructor |
TapActionReset(sc_core::sc_event * _doneEvent); |
|
|
protected: |
|
// Process the action for reset |
bool process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms); |
// Process the action for reset |
bool process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms); |
|
|
private: |
|
//!< Flag to mark first call to process method |
bool firstTime; |
//!< Flag to mark first call to process method |
bool firstTime; |
|
}; // TapActionReset |
}; // TapActionReset |
|
#endif // TAP_RESET_ACTION__H |
#endif // TAP_RESET_ACTION__H |
/sysc/include/OrpsocAccess.h
26,7 → 26,6
|
// $Id: OrpsocAccess.h 303 2009-02-16 11:20:17Z jeremy $ |
|
|
#ifndef ORPSOC_ACCESS__H |
#define ORPSOC_ACCESS__H |
|
46,75 → 45,73
// SoC Arbiter class - will also change if any modifications to bus architecture |
//class Vorpsoc_top_wb_conbus_top__pi1; |
|
|
//! Access functions to the Verilator model |
|
//! This class encapsulates access to the Verilator model, allowing other |
//! Classes to access model state, without needing to be built within the |
//! Verilator environment. |
class OrpsocAccess |
{ |
class OrpsocAccess { |
public: |
|
// Constructor |
OrpsocAccess (Vorpsoc_top *orpsoc_top); |
// Constructor |
OrpsocAccess(Vorpsoc_top * orpsoc_top); |
|
// Accessor functions |
bool getExFreeze (); |
bool getWbFreeze (); |
uint32_t getWbInsn (); |
uint32_t getIdInsn (); |
uint32_t getExInsn (); |
uint32_t getWbPC (); |
uint32_t getIdPC (); |
uint32_t getExPC (); |
bool getExceptFlushpipe (); |
bool getExDslot (); |
uint32_t getExceptType(); |
// Get a specific GPR from the register file |
uint32_t getGpr (uint32_t regNum); |
//SPR accessessors |
uint32_t getSprSr (); |
uint32_t getSprEpcr (); |
uint32_t getSprEear (); |
uint32_t getSprEsr (); |
// Accessor functions |
bool getExFreeze(); |
bool getWbFreeze(); |
uint32_t getWbInsn(); |
uint32_t getIdInsn(); |
uint32_t getExInsn(); |
uint32_t getWbPC(); |
uint32_t getIdPC(); |
uint32_t getExPC(); |
bool getExceptFlushpipe(); |
bool getExDslot(); |
uint32_t getExceptType(); |
// Get a specific GPR from the register file |
uint32_t getGpr(uint32_t regNum); |
void setGpr(uint32_t regNum, uint32_t value); |
//SPR accessessors |
uint32_t getSprSr(); |
uint32_t getSprEpcr(); |
uint32_t getSprEear(); |
uint32_t getSprEsr(); |
|
// Wishbone SRAM accessor functions |
uint32_t get_mem32 (uint32_t addr); |
uint8_t get_mem8 (uint32_t addr); |
// Wishbone SRAM accessor functions |
uint32_t get_mem32(uint32_t addr); |
uint8_t get_mem8(uint32_t addr); |
|
void set_mem32 (uint32_t addr, uint32_t data); |
// Trigger a $readmemh for the RAM array |
void do_ram_readmemh (void); |
/* |
// Arbiter access functions |
uint8_t getWbArbGrant (); |
// Master Signal Access functions |
uint32_t getWbArbMastDatI (uint32_t mast_num); |
uint32_t getWbArbMastDatO (uint32_t mast_num); |
uint32_t getWbArbMastAdrI (uint32_t mast_num); |
uint8_t getWbArbMastSelI (uint32_t mast_num); |
uint8_t getWbArbMastSlaveSelDecoded (uint32_t mast_num); |
bool getWbArbMastWeI (uint32_t mast_num); |
bool getWbArbMastCycI (uint32_t mast_num); |
bool getWbArbMastStbI (uint32_t mast_num); |
bool getWbArbMastAckO (uint32_t mast_num); |
bool getWbArbMastErrO (uint32_t mast_num); |
*/ |
void set_mem32(uint32_t addr, uint32_t data); |
// Trigger a $readmemh for the RAM array |
void do_ram_readmemh(void); |
/* |
// Arbiter access functions |
uint8_t getWbArbGrant (); |
// Master Signal Access functions |
uint32_t getWbArbMastDatI (uint32_t mast_num); |
uint32_t getWbArbMastDatO (uint32_t mast_num); |
uint32_t getWbArbMastAdrI (uint32_t mast_num); |
uint8_t getWbArbMastSelI (uint32_t mast_num); |
uint8_t getWbArbMastSlaveSelDecoded (uint32_t mast_num); |
bool getWbArbMastWeI (uint32_t mast_num); |
bool getWbArbMastCycI (uint32_t mast_num); |
bool getWbArbMastStbI (uint32_t mast_num); |
bool getWbArbMastAckO (uint32_t mast_num); |
bool getWbArbMastErrO (uint32_t mast_num); |
*/ |
|
|
private: |
|
// Pointers to modules with accessor functions |
Vorpsoc_top_or1200_ctrl *or1200_ctrl; |
Vorpsoc_top_or1200_except *or1200_except; |
Vorpsoc_top_or1200_sprs *or1200_sprs; |
Vorpsoc_top_or1200_dpram *rf_a; |
/*Vorpsoc_top_ram_wb_sc_sw*//*Vorpsoc_top_ram_wb_sc_sw__D20_A19_M800000*/ /*Vorpsoc_top_wb_ram_b3__D20_A17_M800000 *ram_wb_sc_sw;*/ |
Vorpsoc_top_ram_wb_b3__pi3 *wishbone_ram; |
// Arbiter |
//Vorpsoc_top_wb_conbus_top__pi1 *wb_arbiter; |
// Pointers to modules with accessor functions |
Vorpsoc_top_or1200_ctrl * or1200_ctrl; |
Vorpsoc_top_or1200_except *or1200_except; |
Vorpsoc_top_or1200_sprs *or1200_sprs; |
Vorpsoc_top_or1200_dpram *rf_a; |
/*Vorpsoc_top_ram_wb_sc_sw *//*Vorpsoc_top_ram_wb_sc_sw__D20_A19_M800000 *//*Vorpsoc_top_wb_ram_b3__D20_A17_M800000 *ram_wb_sc_sw; */ |
Vorpsoc_top_ram_wb_b3__pi3 *wishbone_ram; |
// Arbiter |
//Vorpsoc_top_wb_conbus_top__pi1 *wb_arbiter; |
|
}; // OrpsocAccess () |
}; // OrpsocAccess () |
|
#endif // ORPSOC_ACCESS__H |
#endif // ORPSOC_ACCESS__H |
/sysc/include/JtagDriverSC.h
35,104 → 35,92
|
#include "JtagSC_includes.h" |
|
|
//! Module providing TAP requests to JTAG |
|
//! Provides a queue of requests to the JTAG interface. Requests are at the |
//! level of TAP actions for reset, DR-Scan or IR-Scan. |
|
class JtagDriverSC |
: public sc_core::sc_module |
{ |
class JtagDriverSC:public sc_core::sc_module { |
public: |
|
// Constructor |
JtagDriverSC (sc_core::sc_module_name name, |
sc_core::sc_fifo<TapAction *> *_tapActionQueue); |
// Constructor |
JtagDriverSC(sc_core::sc_module_name name, |
sc_core::sc_fifo < TapAction * >*_tapActionQueue); |
|
private: |
|
// JTAG instructions |
static const uint32_t CHAIN_SELECT_IR = 0x3; //!< Chain Select instruction |
static const uint32_t DEBUG_IR = 0x8; //!< Debug instruction |
// JTAG instructions |
static const uint32_t CHAIN_SELECT_IR = 0x3; //!< Chain Select instruction |
static const uint32_t DEBUG_IR = 0x8; //!< Debug instruction |
|
// JTAG register lengths (excluding CRC) |
static const int JTAG_IR_LEN = 4; //!< JTAG instr reg length |
static const int CHAIN_DR_LEN = 4; //!< Length of DR (excl CRC) |
static const int RISC_DEBUG_DR_LEN = 65; //!< Length of DR (excl CRC) |
static const int REGISTER_DR_LEN = 38; //!< Length of DR (excl CRC) |
static const int WISHBONE_DR_LEN = 65; //!< Length of DR (excl CRC) |
// JTAG register lengths (excluding CRC) |
static const int JTAG_IR_LEN = 4; //!< JTAG instr reg length |
static const int CHAIN_DR_LEN = 4; //!< Length of DR (excl CRC) |
static const int RISC_DEBUG_DR_LEN = 65; //!< Length of DR (excl CRC) |
static const int REGISTER_DR_LEN = 38; //!< Length of DR (excl CRC) |
static const int WISHBONE_DR_LEN = 65; //!< Length of DR (excl CRC) |
|
// JTAG register address masks |
static const uint32_t RISC_DEBUG_ADDR_MASK = 0xffffffff; //!< Mask for addr |
static const uint32_t REGISTER_ADDR_MASK = 0x0000001f; //!< Mask for addr |
static const uint32_t WISHBONE_ADDR_MASK = 0xffffffff; //!< Mask for addr |
// JTAG register address masks |
static const uint32_t RISC_DEBUG_ADDR_MASK = 0xffffffff; //!< Mask for addr |
static const uint32_t REGISTER_ADDR_MASK = 0x0000001f; //!< Mask for addr |
static const uint32_t WISHBONE_ADDR_MASK = 0xffffffff; //!< Mask for addr |
|
// JTAG register R/W bit |
static const uint64_t RISC_DEBUG_RW = 0x100000000ULL; //!< R/W bit mask |
static const uint64_t REGISTER_RW = 0x000000020ULL; //!< R/W bit mask |
static const uint64_t WISHBONE_RW = 0x100000000ULL; //!< R/W bit mask |
// JTAG register R/W bit |
static const uint64_t RISC_DEBUG_RW = 0x100000000ULL; //!< R/W bit mask |
static const uint64_t REGISTER_RW = 0x000000020ULL; //!< R/W bit mask |
static const uint64_t WISHBONE_RW = 0x100000000ULL; //!< R/W bit mask |
|
// JTAG register data field offsets |
static const int RISC_DEBUG_DATA_OFF = 33; //!< Offset to data field |
static const int REGISTER_DATA_OFF = 6; //!< Offset to data field |
static const int WISHBONE_DATA_OFF = 33; //!< Offset to data field |
// JTAG register data field offsets |
static const int RISC_DEBUG_DATA_OFF = 33; //!< Offset to data field |
static const int REGISTER_DATA_OFF = 6; //!< Offset to data field |
static const int WISHBONE_DATA_OFF = 33; //!< Offset to data field |
|
//! JTAG register data field sizes (all the same) |
static const int DR_DATA_LEN = 32; |
//! JTAG register data field sizes (all the same) |
static const int DR_DATA_LEN = 32; |
|
//! CRC length |
static const int CRC_LEN = 8; |
//! CRC length |
static const int CRC_LEN = 8; |
|
// OpenRISC 1000 scan chains |
static const int OR1K_SC_UNDEF = -1; //!< Undefined OR1K scan chain |
static const int OR1K_SC_RISC_DEBUG = 1; //!< for access to SPRs |
static const int OR1K_SC_REGISTER = 4; //!< to stall/reset CPU |
static const int OR1K_SC_WISHBONE = 5; //!< for memory access |
// OpenRISC 1000 scan chains |
static const int OR1K_SC_UNDEF = -1; //!< Undefined OR1K scan chain |
static const int OR1K_SC_RISC_DEBUG = 1; //!< for access to SPRs |
static const int OR1K_SC_REGISTER = 4; //!< to stall/reset CPU |
static const int OR1K_SC_WISHBONE = 5; //!< for memory access |
|
//! Register addresses for the REGISTER scan chain |
static const uint8_t OR1K_RSC_RISCOP = 0x04; //!< Used to reset/stall CPU |
//! Register addresses for the REGISTER scan chain |
static const uint8_t OR1K_RSC_RISCOP = 0x04; //!< Used to reset/stall CPU |
|
// Bits for the RISCOP register |
static const uint32_t RISCOP_STALL = 0x00000001; //!< Stall the CPU |
static const uint32_t RISCOP_RESET = 0x00000002; //!< Reset the CPU |
// Bits for the RISCOP register |
static const uint32_t RISCOP_STALL = 0x00000001; //!< Stall the CPU |
static const uint32_t RISCOP_RESET = 0x00000002; //!< Reset the CPU |
|
//! The JTAG fifo we queue on |
sc_core::sc_fifo<TapAction *> *tapActionQueue; |
//! The JTAG fifo we queue on |
sc_core::sc_fifo < TapAction * >*tapActionQueue; |
|
//! The currently selected scan chain |
int currentScanChain; |
//! The currently selected scan chain |
int currentScanChain; |
|
// SystemC thread to queue actions |
void queueActions (); |
// SystemC thread to queue actions |
void queueActions(); |
|
// Or1k JTAG actions |
void reset (); |
void selectChain (int chain); |
uint32_t readReg (uint32_t addr); |
uint32_t readReg1 (uint32_t addr, |
int bitSizeNoCrc); |
uint32_t readReg1 (uint64_t *dRegArray, |
uint32_t addr, |
int bitSizeNoCrc); |
void writeReg (uint32_t addr, |
uint32_t data); |
// Utilities to compute CRC-8 the OpenRISC way. Versions for "big" and |
// "small" numbers. |
uint8_t crc8 (uint64_t data, |
int size); |
uint8_t crc8 (uint64_t *dataArray, |
int size); |
// Or1k JTAG actions |
void reset(); |
void selectChain(int chain); |
uint32_t readReg(uint32_t addr); |
uint32_t readReg1(uint32_t addr, int bitSizeNoCrc); |
uint32_t readReg1(uint64_t * dRegArray, |
uint32_t addr, int bitSizeNoCrc); |
void writeReg(uint32_t addr, uint32_t data); |
// Utilities to compute CRC-8 the OpenRISC way. Versions for "big" and |
// "small" numbers. |
uint8_t crc8(uint64_t data, int size); |
uint8_t crc8(uint64_t * dataArray, int size); |
|
// Utilities to insert and extract bit strings from vectors |
void insertBits (uint64_t str, |
int strLen, |
uint64_t *array, |
int startBit); |
uint64_t extractBits (uint64_t *array, |
int startBit, |
int strLen); |
// Utilities to insert and extract bit strings from vectors |
void insertBits(uint64_t str, |
int strLen, uint64_t * array, int startBit); |
uint64_t extractBits(uint64_t * array, int startBit, int strLen); |
|
}; // JtagDriverSC () |
}; // JtagDriverSC () |
|
#endif // JTAG_DRIVER_SC__H |
#endif // JTAG_DRIVER_SC__H |
/sysc/include/SprCache.h
31,7 → 31,6
|
#include <stdint.h> |
|
|
//----------------------------------------------------------------------------- |
//! Module for cacheing SPR accesses by the debug unit |
|
52,37 → 51,32
//! forward to the first free slot. This works because there is no function to |
//! delete an entry - just to clear the whole table, so holes cannot appear. |
//----------------------------------------------------------------------------- |
class SprCache |
{ |
class SprCache { |
public: |
|
// Constructor and destructor |
SprCache (int _tableSize = 257); |
~SprCache (); |
// Constructor and destructor |
SprCache(int _tableSize = 257); |
~SprCache(); |
|
// Functions |
void clear (); |
void write (uint16_t sprNum, |
uint32_t value, |
bool force); |
bool read (uint16_t sprNum, |
uint32_t &value); |
// Functions |
void clear(); |
void write(uint16_t sprNum, uint32_t value, bool force); |
bool read(uint16_t sprNum, uint32_t & value); |
|
private: |
|
//! The size of the hash table |
int tableSize; |
//! The size of the hash table |
int tableSize; |
|
//! Maximum amount of cache left to use, before cacheing is rejected. |
int maxToUse; |
//! Maximum amount of cache left to use, before cacheing is rejected. |
int maxToUse; |
|
// The cache, keyed by sprNum. Done as two parallel vectors, |
// allowing unambiguous clearing by use of memset for efficiency. |
bool *sprIsValid; |
uint16_t *sprKeyNum; |
uint32_t *sprValue; |
// The cache, keyed by sprNum. Done as two parallel vectors, |
// allowing unambiguous clearing by use of memset for efficiency. |
bool *sprIsValid; |
uint16_t *sprKeyNum; |
uint32_t *sprValue; |
|
}; // SprCache () |
|
}; // SprCache () |
|
#endif // SPR_CACHE__H |
#endif // SPR_CACHE__H |
/sysc/src/Utils.cpp
28,7 → 28,6
|
#include "Utils.h" |
|
|
//----------------------------------------------------------------------------- |
//!Utility to give the value of a hex char |
|
39,46 → 38,42
//! @return The value of the hex character, or -1 if the character is |
//! invalid. |
//----------------------------------------------------------------------------- |
uint8_t |
Utils::char2Hex (int c) |
uint8_t Utils::char2Hex(int c) |
{ |
return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 : |
((c >= '0') && (c <= '9')) ? c - '0' : |
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1; |
return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 : |
((c >= '0') && (c <= '9')) ? c - '0' : |
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1; |
|
} // char2Hex () |
} // char2Hex () |
|
|
//----------------------------------------------------------------------------- |
//! Utility mapping a value to hex character |
|
//! @param[in] d A hexadecimal digit. Any non-hex digit returns a NULL char |
//----------------------------------------------------------------------------- |
const char |
Utils::hex2Char (uint8_t d) |
const char Utils::hex2Char(uint8_t d) |
{ |
static const char map [] = "0123456789abcdef" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
static const char map[] = "0123456789abcdef" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
return map[d]; |
return map[d]; |
|
} // hex2Char () |
} // hex2Char () |
|
|
//----------------------------------------------------------------------------- |
//! Convert a register to a hex digit string |
|
89,21 → 84,17
//! @param[in] val The value to convert |
//! @param[out] buf The buffer for the text string |
//----------------------------------------------------------------------------- |
void |
Utils::reg2Hex (uint32_t val, |
char *buf) |
void Utils::reg2Hex(uint32_t val, char *buf) |
{ |
for (int n = 7; n >= 0; n--) |
{ |
buf[n] = hex2Char (val & 0xf); |
val /= 16; |
} |
for (int n = 7; n >= 0; n--) { |
buf[n] = hex2Char(val & 0xf); |
val /= 16; |
} |
|
buf[8] = 0; // Useful to terminate as string |
buf[8] = 0; // Useful to terminate as string |
|
} // reg2hex () |
} // reg2hex () |
|
|
//----------------------------------------------------------------------------- |
//! Convert a hex digit string to a register value |
|
114,21 → 105,18
|
//! @return The value to convert |
//----------------------------------------------------------------------------- |
uint32_t |
Utils::hex2Reg (char *buf) |
uint32_t Utils::hex2Reg(char *buf) |
{ |
uint32_t val = 0; // The result |
uint32_t val = 0; // The result |
|
for (int n = 0; n < 8; n++) |
{ |
val = val * 16 + char2Hex (buf[n]); |
} |
for (int n = 0; n < 8; n++) { |
val = val * 16 + char2Hex(buf[n]); |
} |
|
return val; |
return val; |
|
} // hex2reg () |
} // hex2reg () |
|
|
//----------------------------------------------------------------------------- |
//! Convert an ASCII character string to pairs of hex digits |
|
137,25 → 125,21
//! @param[out] dest Buffer to store the hex digit pairs (null terminated) |
//! @param[in] src The ASCII string (null terminated) */ |
//----------------------------------------------------------------------------- |
void |
Utils::ascii2Hex (char *dest, |
char *src) |
void Utils::ascii2Hex(char *dest, char *src) |
{ |
int i; |
int i; |
|
// Step through converting the source string |
for (i = 0; src[i] != '\0'; i++) |
{ |
char ch = src[i]; |
// Step through converting the source string |
for (i = 0; src[i] != '\0'; i++) { |
char ch = src[i]; |
|
dest[i * 2] = hex2Char(ch >> 4 & 0xf); |
dest[i * 2 + 1] = hex2Char(ch & 0xf); |
} |
dest[i * 2] = hex2Char(ch >> 4 & 0xf); |
dest[i * 2 + 1] = hex2Char(ch & 0xf); |
} |
|
dest[i * 2] = '\0'; |
|
} // ascii2hex () |
dest[i * 2] = '\0'; |
|
} // ascii2hex () |
|
//----------------------------------------------------------------------------- |
//! Convert pairs of hex digits to an ASCII character string |
165,24 → 149,20
//! @param[out] dest The ASCII string (null terminated) |
//! @param[in] src Buffer holding the hex digit pairs (null terminated) |
//----------------------------------------------------------------------------- |
void |
Utils::hex2Ascii (char *dest, |
char *src) |
void Utils::hex2Ascii(char *dest, char *src) |
{ |
int i; |
int i; |
|
// Step through convering the source hex digit pairs |
for (i = 0; src[i * 2] != '\0' && src[i * 2 + 1] != '\0'; i++) |
{ |
dest[i] = ((char2Hex (src[i * 2]) & 0xf) << 4) | |
(char2Hex (src[i * 2 + 1]) & 0xf); |
} |
// Step through convering the source hex digit pairs |
for (i = 0; src[i * 2] != '\0' && src[i * 2 + 1] != '\0'; i++) { |
dest[i] = ((char2Hex(src[i * 2]) & 0xf) << 4) | |
(char2Hex(src[i * 2 + 1]) & 0xf); |
} |
|
dest[i] = '\0'; |
dest[i] = '\0'; |
|
} // hex2ascii () |
} // hex2ascii () |
|
|
//----------------------------------------------------------------------------- |
//! "Unescape" RSP binary data |
|
195,35 → 175,28
|
//! @return The number of bytes AFTER conversion |
//----------------------------------------------------------------------------- |
int |
Utils::rspUnescape (char *buf, |
int len) |
int Utils::rspUnescape(char *buf, int len) |
{ |
int fromOffset = 0; // Offset to source char |
int toOffset = 0; // Offset to dest char |
int fromOffset = 0; // Offset to source char |
int toOffset = 0; // Offset to dest char |
|
while (fromOffset < len) |
{ |
// Is it escaped |
if ( '}' == buf[fromOffset]) |
{ |
fromOffset++; |
buf[toOffset] = buf[fromOffset] ^ 0x20; |
while (fromOffset < len) { |
// Is it escaped |
if ('}' == buf[fromOffset]) { |
fromOffset++; |
buf[toOffset] = buf[fromOffset] ^ 0x20; |
} else { |
buf[toOffset] = buf[fromOffset]; |
} |
|
fromOffset++; |
toOffset++; |
} |
else |
{ |
buf[toOffset] = buf[fromOffset]; |
} |
|
fromOffset++; |
toOffset++; |
} |
return toOffset; |
|
return toOffset; |
} // rspUnescape () */ |
|
} // rspUnescape () */ |
|
|
//----------------------------------------------------------------------------- |
//! Convert 32-bit value from host to target endianness |
|
234,30 → 207,28
|
//! @return The value in target endianness |
//----------------------------------------------------------------------------- |
uint32_t |
Utils::htotl (uint32_t hostVal) |
uint32_t Utils::htotl(uint32_t hostVal) |
{ |
uint8_t targetBytes[4]; |
uint8_t targetBytes[4]; |
|
#ifdef TARGET_BIG_ENDIAN |
targetBytes[0] = hostVal / 256 / 256 / 256; |
targetBytes[1] = hostVal / 256 / 256; |
targetBytes[2] = hostVal / 256; |
targetBytes[3] = hostVal; |
targetBytes[0] = hostVal / 256 / 256 / 256; |
targetBytes[1] = hostVal / 256 / 256; |
targetBytes[2] = hostVal / 256; |
targetBytes[3] = hostVal; |
#elif defined TARGET_LITTLE_ENDIAN |
targetBytes[0] = hostVal; |
targetBytes[1] = hostVal / 256; |
targetBytes[2] = hostVal / 256 / 256; |
targetBytes[3] = hostVal / 256 / 256 / 256; |
targetBytes[0] = hostVal; |
targetBytes[1] = hostVal / 256; |
targetBytes[2] = hostVal / 256 / 256; |
targetBytes[3] = hostVal / 256 / 256 / 256; |
#else |
#error Must specify TARGET_BIG_ENDIAN or TARGET_LITTLE_ENDIAN |
#endif |
|
return *((uint32_t *)targetBytes); |
return *((uint32_t *) targetBytes); |
|
} // htotl () |
} // htotl () |
|
|
//----------------------------------------------------------------------------- |
//! Convert 32-bit value from target to host endianness |
|
268,26 → 239,25
|
//! @return The value in target endianness |
//----------------------------------------------------------------------------- |
uint32_t |
Utils::ttohl (uint32_t targetVal) |
uint32_t Utils::ttohl(uint32_t targetVal) |
{ |
uint8_t *targetBytes = (uint8_t *)(&targetVal); |
uint32_t hostVal; |
uint8_t *targetBytes = (uint8_t *) (&targetVal); |
uint32_t hostVal; |
|
#ifdef TARGET_BIG_ENDIAN |
hostVal = targetBytes[0]; |
hostVal = hostVal * 256 + targetBytes[1]; |
hostVal = hostVal * 256 + targetBytes[2]; |
hostVal = hostVal * 256 + targetBytes[3]; |
hostVal = targetBytes[0]; |
hostVal = hostVal * 256 + targetBytes[1]; |
hostVal = hostVal * 256 + targetBytes[2]; |
hostVal = hostVal * 256 + targetBytes[3]; |
#elif defined TARGET_LITTLE_ENDIAN |
hostVal = targetBytes[3]; |
hostVal = hostVal * 256 + targetBytes[2]; |
hostVal = hostVal * 256 + targetBytes[1]; |
hostVal = hostVal * 256 + targetBytes[0]; |
hostVal = targetBytes[3]; |
hostVal = hostVal * 256 + targetBytes[2]; |
hostVal = hostVal * 256 + targetBytes[1]; |
hostVal = hostVal * 256 + targetBytes[0]; |
#else |
#error Must specify TARGET_BIG_ENDIAN or TARGET_LITTLE_ENDIAN |
#error Must specify TARGET_BIG_ENDIAN or TARGET_LITTLE_ENDIAN |
#endif |
|
return hostVal; |
return hostVal; |
|
} // ttohl () |
} // ttohl () |
/sysc/src/UartSC.cpp
30,118 → 30,104
|
//#define UART_SC_DEBUG |
|
SC_HAS_PROCESS(UartSC); |
|
SC_HAS_PROCESS( UartSC ); |
|
//! Constructor for the Uart system C model |
|
//! @param[in] name Name of this module, passed to the parent constructor. |
// Todo: Probably some sort of scaler parameter |
|
UartSC::UartSC (sc_core::sc_module_name name): |
sc_module (name) |
UartSC::UartSC(sc_core::sc_module_name name): |
sc_module(name) |
{ |
|
SC_METHOD (checkTx); |
dont_initialize(); |
sensitive << clk.pos(); |
//sensitive << uarttx; |
|
} // UartSC () |
SC_METHOD(checkTx); |
dont_initialize(); |
sensitive << clk.pos(); |
//sensitive << uarttx; |
|
void |
UartSC::initUart (int clk_freq_hz, // Presume in NS |
int uart_baud |
) |
} // UartSC () |
|
void |
UartSC::initUart(int clk_freq_hz, // Presume in NS |
int uart_baud) |
{ |
// Calculate number of clocks per UART bit |
clocks_per_bit = (int)(clk_freq_hz/uart_baud); |
bits_received=0; |
// Calculate number of clocks per UART bit |
clocks_per_bit = (int)(clk_freq_hz / uart_baud); |
bits_received = 0; |
#ifdef UART_SC_DEBUG |
printf("UartSC Initialised: Sys. clk. freq.: %d Hz, Baud: %d, cpb: %d\n", clk_freq_hz, uart_baud, clocks_per_bit); |
printf |
("UartSC Initialised: Sys. clk. freq.: %d Hz, Baud: %d, cpb: %d\n", |
clk_freq_hz, uart_baud, clocks_per_bit); |
#endif |
} |
} |
|
|
// Maybe do this with threads instead?! |
void |
UartSC::checkTx () { |
void UartSC::checkTx() |
{ |
|
#ifdef UART_SC_DEBUG |
//printf("Uart TX activity: level is : 0x%x\n", uarttx.read()&1); |
//printf("Uart TX activity: level is : 0x%x\n", uarttx.read()&1); |
#endif |
|
// Check the number of bits received |
if (bits_received==0) |
{ |
// Check if tx is low |
if ((uarttx.read()&1) == 0) |
{ |
// Line pulled low, begin receive of new char |
current_char = 0; |
// Start |
counter = 1; |
bits_received++; // We got the start bit |
|
// Check the number of bits received |
if (bits_received == 0) { |
// Check if tx is low |
if ((uarttx.read() & 1) == 0) { |
// Line pulled low, begin receive of new char |
current_char = 0; |
// Start |
counter = 1; |
bits_received++; // We got the start bit |
#ifdef UART_SC_DEBUG |
cout << "UartSC checkTx: got start bit at time " << sc_time_stamp() << endl; |
cout << "UartSC checkTx: got start bit at time " << |
sc_time_stamp() << endl; |
#endif |
} |
} |
else if (bits_received > 0 && bits_received < 9) |
{ |
// Check the counter - see if it's time to sample the line |
// We do an extra half-bit delay on first bit read |
if ( ((bits_received==1) && |
(counter == (clocks_per_bit + (clocks_per_bit/2)))) || |
((bits_received > 1) && (counter == clocks_per_bit)) ) |
{ |
//printf("UartSC checkTx: read bit %d as 0x%x at time", bits_received, uarttx.read()&1); |
//cout << sc_time_stamp() << endl; |
} |
} else if (bits_received > 0 && bits_received < 9) { |
// Check the counter - see if it's time to sample the line |
// We do an extra half-bit delay on first bit read |
if (((bits_received == 1) && |
(counter == (clocks_per_bit + (clocks_per_bit / 2)))) || |
((bits_received > 1) && (counter == clocks_per_bit))) { |
//printf("UartSC checkTx: read bit %d as 0x%x at time", bits_received, uarttx.read()&1); |
//cout << sc_time_stamp() << endl; |
|
// Shift in the current value of the tx into our char |
current_char |= ((uarttx.read() & 1) << (bits_received-1)); |
// Reset the counter |
counter = 1; |
// Increment bit number |
bits_received++; |
} |
else |
counter++; |
} |
else if (bits_received == 9) |
{ |
// Now check for stop bit 1 |
if (counter == clocks_per_bit) |
{ |
// Check that the value is 1 - this should be the stop bit |
if ((uarttx.read() & 1) != 1) |
{ |
printf("UART TX framing error at time\n"); |
cout << sc_time_stamp() << endl; |
// Shift in the current value of the tx into our char |
current_char |= |
((uarttx.read() & 1) << (bits_received - 1)); |
// Reset the counter |
counter = 1; |
// Increment bit number |
bits_received++; |
} else |
counter++; |
} else if (bits_received == 9) { |
// Now check for stop bit 1 |
if (counter == clocks_per_bit) { |
// Check that the value is 1 - this should be the stop bit |
if ((uarttx.read() & 1) != 1) { |
printf("UART TX framing error at time\n"); |
cout << sc_time_stamp() << endl; |
|
// Perhaps do something else here to deal with this |
bits_received = 0; |
counter = 0; |
} |
else |
{ |
// Print the char |
// Perhaps do something else here to deal with this |
bits_received = 0; |
counter = 0; |
} else { |
// Print the char |
#ifdef UART_SC_DEBUG |
printf("Char received: 0x%2x time: ", current_char); |
cout << sc_time_stamp() << endl; |
printf("Char received: 0x%2x time: ", |
current_char); |
cout << sc_time_stamp() << endl; |
#endif |
// cout'ing the char didn't work for some systems - jb 090613ol |
//cout << current_char; |
printf("%c",current_char); |
// cout'ing the char didn't work for some systems - jb 090613ol |
//cout << current_char; |
printf("%c", current_char); |
|
bits_received = 0; |
counter = 0; |
} |
bits_received = 0; |
counter = 0; |
} |
} else |
counter++; |
} |
else |
counter++; |
} |
} |
|
|
|
/sysc/src/MemCache.cpp
30,7 → 30,6
|
#include "MemCache.h" |
|
|
//! Constructor |
|
//! Allocate a closed hash table of the specified size and clear it. |
38,42 → 37,38
//! @param[in] _tableSize The desire hash table size. A prime number is |
//! recommended. |
|
MemCache::MemCache (int _tableSize) : |
tableSize (_tableSize) |
MemCache::MemCache(int _tableSize):tableSize(_tableSize) |
{ |
tabIsValid = new bool [tableSize]; |
tabKeyAddr = new uint32_t [tableSize]; |
tabValue = new uint32_t [tableSize]; |
tabIsValid = new bool[tableSize]; |
tabKeyAddr = new uint32_t[tableSize]; |
tabValue = new uint32_t[tableSize]; |
|
clear (); |
clear(); |
|
} // MemCache () |
} // MemCache () |
|
|
//! Destructor |
|
//! Free the hash table arrays |
|
MemCache::~MemCache () |
MemCache::~MemCache() |
{ |
delete [] tabIsValid; |
delete [] tabKeyAddr; |
delete [] tabValue; |
delete[]tabIsValid; |
delete[]tabKeyAddr; |
delete[]tabValue; |
|
} // ~MemCache () |
} // ~MemCache () |
|
|
//! Empty the hash table |
|
//! Only need to worry about the validity field |
void |
MemCache::clear () |
MemCache::clear() |
{ |
memset (tabIsValid, false, sizeof (tabIsValid)); |
memset(tabIsValid, false, sizeof(tabIsValid)); |
|
} // clear () |
} // clear () |
|
|
//! Write a new value into the hash table |
|
//! Will trash anything already there. |
80,19 → 75,16
|
//! @param[in] addr The address being written to |
//! @param[in] value The value to write |
void |
MemCache::write (uint32_t addr, |
uint32_t value) |
void MemCache::write(uint32_t addr, uint32_t value) |
{ |
int keyAddr = addr % tableSize; |
int keyAddr = addr % tableSize; |
|
tabIsValid[keyAddr] = true; |
tabKeyAddr[keyAddr] = addr; |
tabValue[keyAddr] = value; |
tabIsValid[keyAddr] = true; |
tabKeyAddr[keyAddr] = addr; |
tabValue[keyAddr] = value; |
|
} // write () |
} // write () |
|
|
//! Try to read a value from the hash table |
|
//! The entry must be valid and the address must match |
102,19 → 94,14
|
//! @return True if the value was found in the hash table |
|
bool |
MemCache::read (uint32_t addr, |
uint32_t &value) |
bool MemCache::read(uint32_t addr, uint32_t & value) |
{ |
int keyAddr = addr % tableSize; |
|
if (tabIsValid[keyAddr] & (tabKeyAddr[keyAddr] == addr)) |
{ |
value = tabValue[keyAddr]; |
return true; |
} |
else |
{ |
return false; |
} |
} // read () |
int keyAddr = addr % tableSize; |
|
if (tabIsValid[keyAddr] & (tabKeyAddr[keyAddr] == addr)) { |
value = tabValue[keyAddr]; |
return true; |
} else { |
return false; |
} |
} // read () |
/sysc/src/MemoryLoad.cpp
32,7 → 32,6
#include "MemoryLoad.h" |
#include "OrpsocMain.h" |
|
|
//! Constructor for the ORPSoC memory loader class |
|
//! Initializes various values |
40,15 → 39,11
//! @param[in] orpsoc The SystemC Verilated ORPSoC instance |
//! @param[in] accessor Accessor class for this Verilated ORPSoC model |
|
MemoryLoad::MemoryLoad |
( |
OrpsocAccess *_accessor |
) |
MemoryLoad::MemoryLoad(OrpsocAccess * _accessor) |
{ |
accessor = _accessor; |
} // MemoryAccess () |
accessor = _accessor; |
} // MemoryAccess () |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Copy a string with null termination |
|
62,197 → 57,98
|
@return A pointer to dst */ |
/*---------------------------------------------------------------------------*/ |
char * |
MemoryLoad::strstrip (char *dst, |
const char *src, |
int n) |
char *MemoryLoad::strstrip(char *dst, const char *src, int n) |
{ |
strncpy (dst, src, n); |
*(dst + n) = '\0'; |
strncpy(dst, src, n); |
*(dst + n) = '\0'; |
|
return dst; |
return dst; |
|
} /* strstrip () */ |
} /* strstrip () */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Translate logical to physical addresses for the loader |
|
Used only by the simulator loader to translate logical addresses into |
physical. If loadcode() is called with valid @c virtphy_transl pointer to |
a table of translations then translate() performs translation otherwise |
physical address is equal to logical. |
|
Currently NOT used |
|
@param[in] laddr Logical address |
@param[in] breakpoint Unused |
|
@return The physical address */ |
/*---------------------------------------------------------------------------*/ |
oraddr_t |
MemoryLoad::translate (oraddr_t laddr, |
int *breakpoint) |
#if IMM_STATS |
int MemoryLoad::bits(uint32_t val) |
{ |
/* |
int i; |
|
// No translation (i.e. when loading kernel into simulator) |
if (transl_table == 0) |
{ |
return laddr; |
} |
|
// Try to find our translation in the table. |
for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) |
{ |
if ((laddr & ~(PAGE_SIZE - 1)) == eval_direct32 (transl_table + i, 0, 0)) |
{ |
// Page modified |
set_direct32 (transl_table + i + 8, -2, 0, 0); |
PRINTF ("found paddr=%" PRIx32 "\n", |
eval_direct32 (transl_table + i + 4, 0, 0) | |
(laddr & (PAGE_SIZE - 1))); |
return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) | |
(laddr & (oraddr_t) (PAGE_SIZE - 1)); |
int i = 1; |
if (!val) |
return 0; |
while (val != 0 && (int32_t) val != -1) { |
i++; |
val = (int32_t) val >> 1; |
} |
} |
|
// Allocate new phy page for us. |
for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) |
{ |
if (eval_direct32 (transl_table + i + 8, 0, 0) == 0) |
{ |
// VPN |
set_direct32 (transl_table + i, laddr & ~(PAGE_SIZE - 1), 0, 0); |
// PPN |
set_direct32 (transl_table + i + 4, (i / 16) * PAGE_SIZE, 0, 0); |
// Page modified |
//set_direct32 (transl_table + i + 8, -2, 0, 0); |
PRINTF ("newly allocated ppn=%" PRIx32 "\n", |
eval_direct32 (transl_table + i + 4, 0, 0)); |
PRINTF ("newly allocated .ppn=%" PRIxADDR "\n", transl_table + i + 4); |
PRINTF ("newly allocated ofs=%" PRIxADDR "\n", |
(laddr & (PAGE_SIZE - 1))); |
PRINTF ("newly allocated paddr=%" PRIx32 "\n", |
eval_direct32 (transl_table + i + 4, 0, |
0) | (laddr & (PAGE_SIZE - 1))); |
return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) | |
(laddr & (oraddr_t) (PAGE_SIZE - 1)); |
} |
} |
|
// If we come this far then all phy memory is used and we can't find our |
page nor allocate new page. |
transl_error = 1; |
PRINTF ("can't translate %" PRIxADDR "\n", laddr); |
exit (1); |
|
return -1; |
*/ |
return 0; |
|
} /* translate() */ |
|
#if IMM_STATS |
int |
MemoryLoad::bits (uint32_t val) |
{ |
int i = 1; |
if (!val) |
return 0; |
while (val != 0 && (int32_t) val != -1) |
{ |
i++; |
val = (int32_t) val >> 1; |
} |
return i; |
return i; |
} |
|
void |
MemoryLoad::check_insn (uint32_t insn) |
void MemoryLoad::check_insn(uint32_t insn) |
{ |
int insn_index = insn_decode (insn); |
struct insn_op_struct *opd = op_start[insn_index]; |
uint32_t data = 0; |
int dis = 0; |
const char *name; |
if (!insn || insn_index < 0) |
return; |
name = insn_name (insn_index); |
if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0) |
return; |
int insn_index = insn_decode(insn); |
struct insn_op_struct *opd = op_start[insn_index]; |
uint32_t data = 0; |
int dis = 0; |
const char *name; |
if (!insn || insn_index < 0) |
return; |
name = insn_name(insn_index); |
if (strcmp(name, "l.nop") == 0 || strcmp(name, "l.sys") == 0) |
return; |
|
while (1) |
{ |
uint32_t tmp = 0 unsigned int nbits = 0; |
while (1) |
{ |
tmp |= |
((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << |
nbits; |
nbits += opd->data; |
if (opd->type & OPTYPE_OP) |
break; |
opd++; |
} |
while (1) { |
uint32_t tmp = 0 unsigned int nbits = 0; |
while (1) { |
tmp |= |
((insn >> (opd->type & OPTYPE_SHR)) & |
((1 << opd->data) - 1)) << nbits; |
nbits += opd->data; |
if (opd->type & OPTYPE_OP) |
break; |
opd++; |
} |
|
/* Do we have to sign extend? */ |
if (opd->type & OPTYPE_SIG) |
{ |
int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; |
if (tmp & (1 << sbit)) |
tmp |= 0xFFFFFFFF << sbit; |
} |
if (opd->type & OPTYPE_DIS) |
{ |
/* We have to read register later. */ |
data += tmp; |
dis = 1; |
} |
else |
{ |
if (!(opd->type & OPTYPE_REG) || dis) |
{ |
if (!dis) |
data = tmp; |
if (strcmp (name, "l.movhi") == 0) |
{ |
movhi = data << 16; |
/* Do we have to sign extend? */ |
if (opd->type & OPTYPE_SIG) { |
int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; |
if (tmp & (1 << sbit)) |
tmp |= 0xFFFFFFFF << sbit; |
} |
else |
{ |
data |= movhi; |
//PRINTF ("%08x %s\n", data, name); |
if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY)) |
{ |
bcnt[bits (data)][0]++; |
bsum[0]++; |
} |
else |
{ |
if (strcmp (name, "l.bf") == 0 |
|| strcmp (name, "l.bnf") == 0) |
{ |
bcnt[bits (data)][1]++; |
bsum[1]++; |
if (opd->type & OPTYPE_DIS) { |
/* We have to read register later. */ |
data += tmp; |
dis = 1; |
} else { |
if (!(opd->type & OPTYPE_REG) || dis) { |
if (!dis) |
data = tmp; |
if (strcmp(name, "l.movhi") == 0) { |
movhi = data << 16; |
} else { |
data |= movhi; |
//PRINTF ("%08x %s\n", data, name); |
if (! |
(or32_opcodes[insn_index].flags & |
OR32_IF_DELAY)) { |
bcnt[bits(data)][0]++; |
bsum[0]++; |
} else { |
if (strcmp(name, "l.bf") == 0 |
|| strcmp(name, |
"l.bnf") == 0) { |
bcnt[bits(data)][1]++; |
bsum[1]++; |
} else { |
bcnt[bits(data)][2]++; |
bsum[2]++; |
} |
} |
} |
} |
else |
{ |
bcnt[bits (data)][2]++; |
bsum[2]++; |
} |
} |
data = 0; |
dis = 0; |
} |
} |
data = 0; |
dis = 0; |
if (opd->type & OPTYPE_LAST) { |
return; |
} |
opd++; |
} |
if (opd->type & OPTYPE_LAST) |
{ |
return; |
} |
opd++; |
} |
} |
#endif |
|
262,25 → 158,20
@note insn must be in big endian format |
|
@param[in] address The address to use |
@param[in] insn The instruction to add |
@param[in] breakpoint Not used (it is passed to the translate() function, |
which also does not use it. */ |
@param[in] insn The instruction to add */ |
/*---------------------------------------------------------------------------*/ |
void |
MemoryLoad::addprogram (oraddr_t address, |
uint32_t insn, |
int *breakpoint) |
void MemoryLoad::addprogram(oraddr_t address, uint32_t insn) |
{ |
|
int vaddr = (int) address; |
/* Use the whole-word write */ |
accessor->set_mem32(vaddr, insn); |
PRINTF("* addprogram: addr 0x%.8x insn: 0x%.8x (conf: 0x%.8x)\n", vaddr, insn, accessor->get_mem32(vaddr)); |
freemem += 4; |
|
} /* addprogram () */ |
|
int vaddr = (int)address; |
/* Use the whole-word write */ |
accessor->set_mem32(vaddr, insn); |
/*printf("* addprogram: addr 0x%.8x insn: 0x%.8x (conf: 0x%.8x)\n", |
vaddr, insn, accessor->get_mem32(vaddr)); */ |
freemem += 4; |
|
} /* addprogram () */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Load big-endian COFF file |
|
287,108 → 178,97
@param[in] filename File to load |
@param[in] sections Number of sections in file */ |
/*---------------------------------------------------------------------------*/ |
void |
MemoryLoad::readfile_coff (char *filename, |
short sections) |
void MemoryLoad::readfile_coff(char *filename, short sections) |
{ |
FILE *inputfs; |
char inputbuf[4]; |
uint32_t insn; |
int32_t sectsize; |
COFF_AOUTHDR coffaouthdr; |
struct COFF_scnhdr coffscnhdr; |
int len; |
int firstthree = 0; |
int breakpoint = 0; |
FILE *inputfs; |
char inputbuf[4]; |
uint32_t insn; |
int32_t sectsize; |
COFF_AOUTHDR coffaouthdr; |
struct COFF_scnhdr coffscnhdr; |
int len; |
int firstthree = 0; |
int breakpoint = 0; |
|
if (!(inputfs = fopen (filename, "r"))) |
{ |
perror ("readfile_coff"); |
exit (1); |
} |
if (!(inputfs = fopen(filename, "r"))) { |
perror("readfile_coff"); |
exit(1); |
} |
|
if (fseek (inputfs, sizeof (COFF_FILHDR), SEEK_SET) == -1) |
{ |
fclose (inputfs); |
perror ("readfile_coff"); |
exit (1); |
} |
if (fseek(inputfs, sizeof(COFF_FILHDR), SEEK_SET) == -1) { |
fclose(inputfs); |
perror("readfile_coff"); |
exit(1); |
} |
|
if (fread (&coffaouthdr, sizeof (coffaouthdr), 1, inputfs) != 1) |
{ |
fclose (inputfs); |
perror ("readfile_coff"); |
exit (1); |
} |
|
while (sections--) |
{ |
uint32_t scnhdr_pos = |
sizeof (COFF_FILHDR) + sizeof (coffaouthdr) + |
sizeof (struct COFF_scnhdr) * firstthree; |
if (fseek (inputfs, scnhdr_pos, SEEK_SET) == -1) |
{ |
fclose (inputfs); |
perror ("readfile_coff"); |
exit (1); |
if (fread(&coffaouthdr, sizeof(coffaouthdr), 1, inputfs) != 1) { |
fclose(inputfs); |
perror("readfile_coff"); |
exit(1); |
} |
if (fread (&coffscnhdr, sizeof (struct COFF_scnhdr), 1, inputfs) != 1) |
{ |
fclose (inputfs); |
perror ("readfile_coff"); |
exit (1); |
} |
PRINTF ("Section: %s,", coffscnhdr.s_name); |
PRINTF (" paddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_paddr)); |
PRINTF (" vaddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_vaddr)); |
PRINTF (" size: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_size)); |
PRINTF (" scnptr: 0x%.8lx\n", COFF_LONG_H (coffscnhdr.s_scnptr)); |
|
sectsize = COFF_LONG_H (coffscnhdr.s_size); |
++firstthree; |
while (sections--) { |
uint32_t scnhdr_pos = |
sizeof(COFF_FILHDR) + sizeof(coffaouthdr) + |
sizeof(struct COFF_scnhdr) * firstthree; |
if (fseek(inputfs, scnhdr_pos, SEEK_SET) == -1) { |
fclose(inputfs); |
perror("readfile_coff"); |
exit(1); |
} |
if (fread(&coffscnhdr, sizeof(struct COFF_scnhdr), 1, inputfs) |
!= 1) { |
fclose(inputfs); |
perror("readfile_coff"); |
exit(1); |
} |
PRINTF("Section: %s,", coffscnhdr.s_name); |
PRINTF(" paddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_paddr)); |
PRINTF(" vaddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_vaddr)); |
PRINTF(" size: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_size)); |
PRINTF(" scnptr: 0x%.8lx\n", COFF_LONG_H(coffscnhdr.s_scnptr)); |
|
/* loading section */ |
freemem = COFF_LONG_H (coffscnhdr.s_paddr); |
if (fseek (inputfs, COFF_LONG_H (coffscnhdr.s_scnptr), SEEK_SET) == -1) |
{ |
fclose (inputfs); |
perror ("readfile_coff"); |
exit (1); |
} |
while (sectsize > 0 |
&& (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs))) |
{ |
insn = COFF_LONG_H (inputbuf); |
//len = insn_len (insn_decode (insn)); |
len = 4; |
if (len == 2) |
{ |
fseek (inputfs, -2, SEEK_CUR); |
} |
sectsize = COFF_LONG_H(coffscnhdr.s_size); |
++firstthree; |
|
addprogram (freemem, insn, &breakpoint); |
sectsize -= len; |
/* loading section */ |
freemem = COFF_LONG_H(coffscnhdr.s_paddr); |
if (fseek(inputfs, COFF_LONG_H(coffscnhdr.s_scnptr), SEEK_SET) |
== -1) { |
fclose(inputfs); |
perror("readfile_coff"); |
exit(1); |
} |
while (sectsize > 0 |
&& (len = |
fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) { |
insn = COFF_LONG_H(inputbuf); |
//len = insn_len (insn_decode (insn)); |
len = 4; |
if (len == 2) { |
fseek(inputfs, -2, SEEK_CUR); |
} |
|
addprogram(freemem, insn); |
sectsize -= len; |
} |
} |
} |
if (firstthree < 3) |
{ |
PRINTF ("One or more missing sections. At least"); |
PRINTF (" three sections expected (.text, .data, .bss).\n"); |
exit (1); |
} |
if (firstthree > 3) |
{ |
PRINTF ("Warning: one or more extra sections. These"); |
PRINTF (" sections were handled as .data sections.\n"); |
} |
if (firstthree < 3) { |
PRINTF("One or more missing sections. At least"); |
PRINTF(" three sections expected (.text, .data, .bss).\n"); |
exit(1); |
} |
if (firstthree > 3) { |
PRINTF("Warning: one or more extra sections. These"); |
PRINTF(" sections were handled as .data sections.\n"); |
} |
|
fclose (inputfs); |
PRINTF ("Finished loading COFF.\n"); |
return; |
fclose(inputfs); |
PRINTF("Finished loading COFF.\n"); |
return; |
|
} /* readfile_coff () */ |
} /* readfile_coff () */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Load symbols from big-endian COFF file |
|
397,84 → 277,78
@param[in] syms Symbols value */ |
/*---------------------------------------------------------------------------*/ |
|
void |
MemoryLoad::readsyms_coff (char *filename, uint32_t symptr, uint32_t syms) |
void MemoryLoad::readsyms_coff(char *filename, uint32_t symptr, uint32_t syms) |
{ |
FILE *inputfs; |
struct COFF_syment coffsymhdr; |
int count = 0; |
uint32_t nsyms = syms; |
if (!(inputfs = fopen (filename, "r"))) |
{ |
perror ("readsyms_coff"); |
exit (1); |
} |
FILE *inputfs; |
struct COFF_syment coffsymhdr; |
int count = 0; |
uint32_t nsyms = syms; |
if (!(inputfs = fopen(filename, "r"))) { |
perror("readsyms_coff"); |
exit(1); |
} |
|
if (fseek (inputfs, symptr, SEEK_SET) == -1) |
{ |
fclose (inputfs); |
perror ("readsyms_coff"); |
exit (1); |
} |
|
while (syms--) |
{ |
int i, n; |
if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) |
{ |
fclose (inputfs); |
perror ("readsyms_coff"); |
exit (1); |
if (fseek(inputfs, symptr, SEEK_SET) == -1) { |
fclose(inputfs); |
perror("readsyms_coff"); |
exit(1); |
} |
|
n = (unsigned char) coffsymhdr.e_numaux[0]; |
while (syms--) { |
int i, n; |
if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) { |
fclose(inputfs); |
perror("readsyms_coff"); |
exit(1); |
} |
|
/* check whether this symbol belongs to a section and is external |
symbol; ignore all others */ |
if (COFF_SHORT_H (coffsymhdr.e_scnum) >= 0 |
&& coffsymhdr.e_sclass[0] == C_EXT) |
{ |
if (*((uint32_t *) coffsymhdr.e.e.e_zeroes)) |
{ |
if (strlen (coffsymhdr.e.e_name) |
&& strlen (coffsymhdr.e.e_name) < 9) |
add_label (COFF_LONG_H (coffsymhdr.e_value), |
coffsymhdr.e.e_name); |
} |
else |
{ |
uint32_t fpos = ftell (inputfs); |
n = (unsigned char)coffsymhdr.e_numaux[0]; |
|
if (fseek |
(inputfs, |
symptr + nsyms * COFF_SYMESZ + |
COFF_LONG_H (coffsymhdr.e.e.e_offset), SEEK_SET) == 0) |
{ |
char tmp[33], *s = &tmp[0]; |
while (s != &tmp[32]) |
if ((*(s++) = fgetc (inputfs)) == 0) |
break; |
tmp[32] = 0; |
add_label (COFF_LONG_H (coffsymhdr.e_value), &tmp[0]); |
/* check whether this symbol belongs to a section and is external |
symbol; ignore all others */ |
if (COFF_SHORT_H(coffsymhdr.e_scnum) >= 0 |
&& coffsymhdr.e_sclass[0] == C_EXT) { |
if (*((uint32_t *) coffsymhdr.e.e.e_zeroes)) { |
if (strlen(coffsymhdr.e.e_name) |
&& strlen(coffsymhdr.e.e_name) < 9) |
add_label(COFF_LONG_H |
(coffsymhdr.e_value), |
coffsymhdr.e.e_name); |
} else { |
uint32_t fpos = ftell(inputfs); |
|
if (fseek |
(inputfs, |
symptr + nsyms * COFF_SYMESZ + |
COFF_LONG_H(coffsymhdr.e.e.e_offset), |
SEEK_SET) == 0) { |
char tmp[33], *s = &tmp[0]; |
while (s != &tmp[32]) |
if ((*(s++) = |
fgetc(inputfs)) == 0) |
break; |
tmp[32] = 0; |
add_label(COFF_LONG_H |
(coffsymhdr.e_value), |
&tmp[0]); |
} |
fseek(inputfs, fpos, SEEK_SET); |
} |
} |
fseek (inputfs, fpos, SEEK_SET); |
} |
|
for (i = 0; i < n; i++) |
if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) { |
fclose(inputfs); |
perror("readsyms_coff3"); |
exit(1); |
} |
syms -= n; |
count += n; |
} |
|
for (i = 0; i < n; i++) |
if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) |
{ |
fclose (inputfs); |
perror ("readsyms_coff3"); |
exit (1); |
} |
syms -= n; |
count += n; |
} |
|
fclose (inputfs); |
PRINTF ("Finished loading symbols.\n"); |
return; |
fclose(inputfs); |
PRINTF("Finished loading symbols.\n"); |
return; |
} |
|
/*---------------------------------------------------------------------------*/ |
482,349 → 356,324
|
@param[in] filename File to load */ |
/*---------------------------------------------------------------------------*/ |
void |
MemoryLoad::readfile_elf (char *filename) |
void MemoryLoad::readfile_elf(char *filename) |
{ |
|
FILE *inputfs; |
struct elf32_hdr elfhdr; |
struct elf32_phdr *elf_phdata = NULL; |
struct elf32_shdr *elf_spnt, *elf_shdata; |
struct elf32_sym *sym_tbl = (struct elf32_sym *) 0; |
uint32_t syms = 0; |
char *str_tbl = (char *) 0; |
char *s_str = (char *) 0; |
int breakpoint = 0; |
uint32_t inputbuf; |
uint32_t padd; |
uint32_t insn; |
int i, j, sectsize, len; |
FILE *inputfs; |
struct elf32_hdr elfhdr; |
struct elf32_phdr *elf_phdata = NULL; |
struct elf32_shdr *elf_spnt, *elf_shdata; |
struct elf32_sym *sym_tbl = (struct elf32_sym *)0; |
uint32_t syms = 0; |
char *str_tbl = (char *)0; |
char *s_str = (char *)0; |
int breakpoint = 0; |
uint32_t inputbuf; |
uint32_t padd; |
uint32_t insn; |
int i, j, sectsize, len; |
|
if (!(inputfs = fopen (filename, "r"))) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (!(inputfs = fopen(filename, "r"))) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) != 1) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) != 1) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if ((elf_shdata = |
(struct elf32_shdr *) malloc (ELF_SHORT_H (elfhdr.e_shentsize) * |
ELF_SHORT_H (elfhdr.e_shnum))) == NULL) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
|
if (fseek (inputfs, ELF_LONG_H (elfhdr.e_shoff), SEEK_SET) != 0) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
|
if (fread |
(elf_shdata, |
ELF_SHORT_H (elfhdr.e_shentsize) * ELF_SHORT_H (elfhdr.e_shnum), 1, |
inputfs) != 1) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
|
if (ELF_LONG_H (elfhdr.e_phoff)) |
{ |
if ((elf_phdata = |
(struct elf32_phdr *) malloc (ELF_SHORT_H (elfhdr.e_phnum) * |
ELF_SHORT_H (elfhdr.e_phentsize))) == |
NULL) |
if ((elf_shdata = |
(struct elf32_shdr *)malloc(ELF_SHORT_H(elfhdr.e_shentsize) * |
ELF_SHORT_H(elfhdr.e_shnum))) == NULL) |
{ |
perror ("readfile_elf"); |
exit (1); |
perror("readfile_elf"); |
exit(1); |
} |
|
if (fseek (inputfs, ELF_LONG_H (elfhdr.e_phoff), SEEK_SET) != 0) |
{ |
perror ("readfile_elf"); |
exit (1); |
if (fseek(inputfs, ELF_LONG_H(elfhdr.e_shoff), SEEK_SET) != 0) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (fread |
(elf_phdata, |
ELF_SHORT_H (elfhdr.e_phnum) * ELF_SHORT_H (elfhdr.e_phentsize), |
1, inputfs) != 1) |
{ |
perror ("readfile_elf"); |
exit (1); |
if (fread |
(elf_shdata, |
ELF_SHORT_H(elfhdr.e_shentsize) * ELF_SHORT_H(elfhdr.e_shnum), 1, |
inputfs) != 1) { |
perror("readfile_elf"); |
exit(1); |
} |
} |
|
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum); |
i++, elf_spnt++) |
{ |
if (ELF_LONG_H(elfhdr.e_phoff)) { |
if ((elf_phdata = |
(struct elf32_phdr *)malloc(ELF_SHORT_H(elfhdr.e_phnum) * |
ELF_SHORT_H |
(elfhdr.e_phentsize))) == |
NULL) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (ELF_LONG_H (elf_spnt->sh_type) == SHT_STRTAB) |
{ |
if (NULL != str_tbl) |
{ |
free (str_tbl); |
} |
if (fseek(inputfs, ELF_LONG_H(elfhdr.e_phoff), SEEK_SET) != 0) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if ((str_tbl = |
(char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (fread |
(elf_phdata, |
ELF_SHORT_H(elfhdr.e_phnum) * |
ELF_SHORT_H(elfhdr.e_phentsize), 1, inputfs) != 1) { |
perror("readfile_elf"); |
exit(1); |
} |
} |
|
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != |
0) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); |
i++, elf_spnt++) { |
|
if (fread (str_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != |
1) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
} |
else if (ELF_LONG_H (elf_spnt->sh_type) == SHT_SYMTAB) |
{ |
if (ELF_LONG_H(elf_spnt->sh_type) == SHT_STRTAB) { |
if (NULL != str_tbl) { |
free(str_tbl); |
} |
|
if (NULL != sym_tbl) |
{ |
free (sym_tbl); |
} |
if ((str_tbl = |
(char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == |
NULL) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if ((sym_tbl = |
(struct elf32_sym *) malloc (ELF_LONG_H (elf_spnt->sh_size))) |
== NULL) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (fseek |
(inputfs, ELF_LONG_H(elf_spnt->sh_offset), |
SEEK_SET) != 0) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != |
0) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (fread |
(str_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, |
inputfs) != 1) { |
perror("readfile_elf"); |
exit(1); |
} |
} else if (ELF_LONG_H(elf_spnt->sh_type) == SHT_SYMTAB) { |
|
if (fread (sym_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != |
1) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (NULL != sym_tbl) { |
free(sym_tbl); |
} |
|
syms = |
ELF_LONG_H (elf_spnt->sh_size) / |
ELF_LONG_H (elf_spnt->sh_entsize); |
} |
} |
if ((sym_tbl = (struct elf32_sym *) |
malloc(ELF_LONG_H(elf_spnt->sh_size))) |
== NULL) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (ELF_SHORT_H (elfhdr.e_shstrndx) != SHN_UNDEF) |
{ |
elf_spnt = &elf_shdata[ELF_SHORT_H (elfhdr.e_shstrndx)]; |
if (fseek |
(inputfs, ELF_LONG_H(elf_spnt->sh_offset), |
SEEK_SET) != 0) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if ((s_str = (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
if (fread |
(sym_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, |
inputfs) != 1) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != 0) |
{ |
perror ("readfile_elf"); |
exit (1); |
syms = |
ELF_LONG_H(elf_spnt->sh_size) / |
ELF_LONG_H(elf_spnt->sh_entsize); |
} |
} |
|
if (fread (s_str, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != 1) |
{ |
perror ("readfile_elf"); |
exit (1); |
} |
} |
if (ELF_SHORT_H(elfhdr.e_shstrndx) != SHN_UNDEF) { |
elf_spnt = &elf_shdata[ELF_SHORT_H(elfhdr.e_shstrndx)]; |
|
if ((s_str = |
(char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) { |
perror("readfile_elf"); |
exit(1); |
} |
|
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum); |
i++, elf_spnt++) |
{ |
if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != |
0) { |
perror("readfile_elf"); |
exit(1); |
} |
|
if ((ELF_LONG_H (elf_spnt->sh_type) & SHT_PROGBITS) |
&& (ELF_LONG_H (elf_spnt->sh_flags) & SHF_ALLOC)) |
{ |
if (fread(s_str, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != |
1) { |
perror("readfile_elf"); |
exit(1); |
} |
} |
|
padd = ELF_LONG_H (elf_spnt->sh_addr); |
for (j = 0; j < ELF_SHORT_H (elfhdr.e_phnum); j++) |
{ |
if (ELF_LONG_H (elf_phdata[j].p_offset) && |
ELF_LONG_H (elf_phdata[j].p_offset) <= |
ELF_LONG_H (elf_spnt->sh_offset) |
&& (ELF_LONG_H (elf_phdata[j].p_offset) + |
ELF_LONG_H (elf_phdata[j].p_memsz)) > |
ELF_LONG_H (elf_spnt->sh_offset)) |
padd = |
ELF_LONG_H (elf_phdata[j].p_paddr) + |
ELF_LONG_H (elf_spnt->sh_offset) - |
ELF_LONG_H (elf_phdata[j].p_offset); |
} |
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); |
i++, elf_spnt++) { |
|
if ((ELF_LONG_H(elf_spnt->sh_type) & SHT_PROGBITS) |
&& (ELF_LONG_H(elf_spnt->sh_flags) & SHF_ALLOC)) { |
|
padd = ELF_LONG_H(elf_spnt->sh_addr); |
for (j = 0; j < ELF_SHORT_H(elfhdr.e_phnum); j++) { |
if (ELF_LONG_H(elf_phdata[j].p_offset) && |
ELF_LONG_H(elf_phdata[j].p_offset) <= |
ELF_LONG_H(elf_spnt->sh_offset) |
&& (ELF_LONG_H(elf_phdata[j].p_offset) + |
ELF_LONG_H(elf_phdata[j].p_memsz)) > |
ELF_LONG_H(elf_spnt->sh_offset)) |
padd = |
ELF_LONG_H(elf_phdata[j].p_paddr) + |
ELF_LONG_H(elf_spnt->sh_offset) - |
ELF_LONG_H(elf_phdata[j].p_offset); |
} |
|
if (!gQuiet) |
{ |
if (ELF_LONG_H(elf_spnt->sh_name) && s_str) |
printf("* Section: %s,", |
&s_str[ELF_LONG_H(elf_spnt->sh_name)]); |
else |
printf("* Section: noname,"); |
printf("* vaddr: 0x%.8lx,", |
ELF_LONG_H(elf_spnt->sh_addr)); |
printf("* paddr: 0x%" PRIx32, padd); |
printf("* offset: 0x%.8lx,", |
ELF_LONG_H(elf_spnt->sh_offset)); |
printf("* size: 0x%.8lx\n", |
ELF_LONG_H(elf_spnt->sh_size)); |
} |
|
freemem = padd; |
sectsize = ELF_LONG_H(elf_spnt->sh_size); |
|
if (ELF_LONG_H (elf_spnt->sh_name) && s_str) |
//PRINTF ("Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]); |
printf("* Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]); |
else |
//PRINTF ("Section: noname,"); |
printf ("* Section: noname,"); |
printf ("* vaddr: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_addr)); |
printf ("* paddr: 0x%" PRIx32, padd); |
printf ("* offset: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_offset)); |
printf ("* size: 0x%.8lx\n", ELF_LONG_H (elf_spnt->sh_size)); |
if (fseek |
(inputfs, ELF_LONG_H(elf_spnt->sh_offset), |
SEEK_SET) != 0) { |
perror("readfile_elf"); |
free(elf_phdata); |
exit(1); |
} |
|
freemem = padd; |
sectsize = ELF_LONG_H (elf_spnt->sh_size); |
while (sectsize > 0 |
&& (len = |
fread(&inputbuf, sizeof(inputbuf), 1, |
inputfs))) { |
insn = ELF_LONG_H(inputbuf); |
//PRINTF("* addprogram(%.8x, %.8x, %d)\n", freemem, insn, breakpoint); |
addprogram(freemem, insn); |
sectsize -= 4; |
} |
} |
} |
|
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != |
0) |
{ |
perror ("readfile_elf"); |
free (elf_phdata); |
exit (1); |
} |
if (str_tbl) { |
i = 0; |
while (syms--) { |
if (sym_tbl[i].st_name && sym_tbl[i].st_info |
&& ELF_SHORT_H(sym_tbl[i].st_shndx) < 0x8000) { |
add_label(ELF_LONG_H(sym_tbl[i].st_value), |
&str_tbl[ELF_LONG_H |
(sym_tbl[i].st_name)]); |
} |
i++; |
} |
} |
|
while (sectsize > 0 |
&& (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs))) |
{ |
insn = ELF_LONG_H (inputbuf); |
//PRINTF("* addprogram(%.8x, %.8x, %d)\n", freemem, insn, breakpoint); |
addprogram (freemem, insn, &breakpoint); |
sectsize -= 4; |
} |
if (NULL != str_tbl) { |
free(str_tbl); |
} |
} |
|
if (str_tbl) |
{ |
i = 0; |
while (syms--) |
{ |
if (sym_tbl[i].st_name && sym_tbl[i].st_info |
&& ELF_SHORT_H (sym_tbl[i].st_shndx) < 0x8000) |
{ |
add_label (ELF_LONG_H (sym_tbl[i].st_value), |
&str_tbl[ELF_LONG_H (sym_tbl[i].st_name)]); |
} |
i++; |
if (NULL != sym_tbl) { |
free(sym_tbl); |
} |
} |
|
if (NULL != str_tbl) |
{ |
free (str_tbl); |
} |
free(s_str); |
free(elf_phdata); |
free(elf_shdata); |
|
if (NULL != sym_tbl) |
{ |
free (sym_tbl); |
} |
|
free (s_str); |
free (elf_phdata); |
free (elf_shdata); |
|
} |
|
/* Identify file type and call appropriate readfile_X routine. It only |
handles orX-coff-big executables at the moment. */ |
|
void |
MemoryLoad::identifyfile (char *filename) |
void MemoryLoad::identifyfile(char *filename) |
{ |
FILE *inputfs; |
COFF_FILHDR coffhdr; |
struct elf32_hdr elfhdr; |
FILE *inputfs; |
COFF_FILHDR coffhdr; |
struct elf32_hdr elfhdr; |
|
if (!(inputfs = fopen (filename, "r"))) |
{ |
perror (filename); |
fflush (stdout); |
fflush (stderr); |
exit (1); |
} |
|
if (fread (&coffhdr, sizeof (coffhdr), 1, inputfs) == 1) |
{ |
if (COFF_SHORT_H (coffhdr.f_magic) == 0x17a) |
{ |
uint32_t opthdr_size; |
PRINTF ("COFF magic: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_magic)); |
PRINTF ("COFF flags: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_flags)); |
PRINTF ("COFF symptr: 0x%.8lx\n", COFF_LONG_H (coffhdr.f_symptr)); |
if ((COFF_SHORT_H (coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) |
{ |
PRINTF ("This COFF is not an executable.\n"); |
exit (1); |
} |
opthdr_size = COFF_SHORT_H (coffhdr.f_opthdr); |
if (opthdr_size != sizeof (COFF_AOUTHDR)) |
{ |
PRINTF ("COFF optional header is missing or not recognized.\n"); |
PRINTF ("COFF f_opthdr: 0x%" PRIx32 "\n", opthdr_size); |
exit (1); |
} |
fclose (inputfs); |
readfile_coff (filename, COFF_SHORT_H (coffhdr.f_nscns)); |
readsyms_coff (filename, COFF_LONG_H (coffhdr.f_symptr), |
COFF_LONG_H (coffhdr.f_nsyms)); |
return; |
if (!(inputfs = fopen(filename, "r"))) { |
perror(filename); |
fflush(stdout); |
fflush(stderr); |
exit(1); |
} |
else |
{ |
PRINTF ("Not COFF file format\n"); |
fseek (inputfs, 0, SEEK_SET); |
|
if (fread(&coffhdr, sizeof(coffhdr), 1, inputfs) == 1) { |
if (COFF_SHORT_H(coffhdr.f_magic) == 0x17a) { |
uint32_t opthdr_size; |
PRINTF("COFF magic: 0x%.4x\n", |
COFF_SHORT_H(coffhdr.f_magic)); |
PRINTF("COFF flags: 0x%.4x\n", |
COFF_SHORT_H(coffhdr.f_flags)); |
PRINTF("COFF symptr: 0x%.8lx\n", |
COFF_LONG_H(coffhdr.f_symptr)); |
if ((COFF_SHORT_H(coffhdr.f_flags) & COFF_F_EXEC) != |
COFF_F_EXEC) { |
PRINTF("This COFF is not an executable.\n"); |
exit(1); |
} |
opthdr_size = COFF_SHORT_H(coffhdr.f_opthdr); |
if (opthdr_size != sizeof(COFF_AOUTHDR)) { |
PRINTF |
("COFF optional header is missing or not recognized.\n"); |
PRINTF("COFF f_opthdr: 0x%" PRIx32 "\n", |
opthdr_size); |
exit(1); |
} |
fclose(inputfs); |
readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns)); |
readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), |
COFF_LONG_H(coffhdr.f_nsyms)); |
return; |
} else { |
PRINTF("Not COFF file format\n"); |
fseek(inputfs, 0, SEEK_SET); |
} |
} |
} |
if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) == 1) |
{ |
if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45 |
&& elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46) |
{ |
PRINTF ("ELF type: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_type)); |
PRINTF ("ELF machine: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_machine)); |
PRINTF ("ELF version: 0x%.8lx\n", ELF_LONG_H (elfhdr.e_version)); |
PRINTF ("ELF sec = %d\n", ELF_SHORT_H (elfhdr.e_shnum)); |
if (ELF_SHORT_H (elfhdr.e_type) != ET_EXEC) |
{ |
PRINTF ("This ELF is not an executable.\n"); |
exit (1); |
} |
fclose (inputfs); |
readfile_elf (filename); |
return; |
if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) == 1) { |
if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45 |
&& elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46) { |
PRINTF("ELF type: 0x%.4x\n", |
ELF_SHORT_H(elfhdr.e_type)); |
PRINTF("ELF machine: 0x%.4x\n", |
ELF_SHORT_H(elfhdr.e_machine)); |
PRINTF("ELF version: 0x%.8lx\n", |
ELF_LONG_H(elfhdr.e_version)); |
PRINTF("ELF sec = %d\n", ELF_SHORT_H(elfhdr.e_shnum)); |
if (ELF_SHORT_H(elfhdr.e_type) != ET_EXEC) { |
PRINTF("This ELF is not an executable.\n"); |
exit(1); |
} |
fclose(inputfs); |
readfile_elf(filename); |
return; |
} else { |
PRINTF("Not ELF file format.\n"); |
fseek(inputfs, 0, SEEK_SET); |
} |
} |
else |
{ |
PRINTF ("Not ELF file format.\n"); |
fseek (inputfs, 0, SEEK_SET); |
} |
} |
|
perror ("identifyfile2"); |
fclose (inputfs); |
perror("identifyfile2"); |
fclose(inputfs); |
|
return; |
return; |
} |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Load file to memory |
|
839,121 → 688,90
@return zero on success, negative on failure. */ |
/*---------------------------------------------------------------------------*/ |
uint32_t |
MemoryLoad::loadcode (char *filename, oraddr_t startaddr, oraddr_t virtphy_transl) |
MemoryLoad::loadcode(char *filename, oraddr_t startaddr, |
oraddr_t virtphy_transl) |
{ |
//int breakpoint = 0; |
|
init_labels (); // jb |
|
transl_error = 0; |
transl_table = virtphy_transl; |
freemem = startaddr; |
PRINTF ("* MemoryLoad::loadcode: filename %s startaddr=%" PRIxADDR " virtphy_transl=%" |
PRIxADDR "\n", filename, startaddr, virtphy_transl); |
identifyfile (filename); |
init_labels(); // jb |
|
#if IMM_STATS |
{ |
int i = 0, a = 0, b = 0, c = 0; |
PRINTF ("index:arith/branch/jump\n"); |
for (i = 0; i < 33; i++) |
PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i, |
100. * (a += bcnt[i][0]) / bsum[0], 100. * (b += |
bcnt[i][1]) / |
bsum[1], 100. * (c += |
bcnt[i][2]) / bsum[2], bcnt[i][0], |
bcnt[i][1], bcnt[i][2]); |
PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]); |
} |
#endif |
|
/* |
if (transl_error) |
return -1; |
else |
return translate (freemem, &breakpoint); |
*/ |
return (uint32_t) freemem; |
transl_table = virtphy_transl; |
freemem = startaddr; |
/*printf ("* MemoryLoad::loadcode: filename %s startaddr=%" PRIxADDR " virtphy_transl=%" PRIxADDR "\n", filename, startaddr, virtphy_transl); */ |
|
identifyfile(filename); |
|
return (uint32_t) freemem; |
|
} |
|
/* From arch sim labels.c */ |
void |
MemoryLoad::init_labels () |
MemoryLoad::init_labels() |
{ |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) |
label_hash[i] = NULL; |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) |
label_hash[i] = NULL; |
} |
|
void |
MemoryLoad::add_label (oraddr_t addr, char *name) |
void MemoryLoad::add_label(oraddr_t addr, char *name) |
{ |
struct label_entry **tmp; |
tmp = &(label_hash[addr % LABELS_HASH_SIZE]); |
for (; *tmp; tmp = &((*tmp)->next)); |
*tmp = (label_entry *) malloc (sizeof (**tmp)); |
(*tmp)->name = (char *) malloc (strlen (name) + 1); |
(*tmp)->addr = addr; |
strcpy ((*tmp)->name, name); |
(*tmp)->next = NULL; |
struct label_entry **tmp; |
tmp = &(label_hash[addr % LABELS_HASH_SIZE]); |
for (; *tmp; tmp = &((*tmp)->next)) ; |
*tmp = (label_entry *) malloc(sizeof(**tmp)); |
(*tmp)->name = (char *)malloc(strlen(name) + 1); |
(*tmp)->addr = addr; |
strcpy((*tmp)->name, name); |
(*tmp)->next = NULL; |
} |
|
struct label_entry * |
MemoryLoad::get_label (oraddr_t addr) |
struct label_entry *MemoryLoad::get_label(oraddr_t addr) |
{ |
struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE]; |
while (tmp) |
{ |
if (tmp->addr == addr) |
return tmp; |
tmp = tmp->next; |
} |
return NULL; |
struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE]; |
while (tmp) { |
if (tmp->addr == addr) |
return tmp; |
tmp = tmp->next; |
} |
return NULL; |
} |
|
struct label_entry * |
MemoryLoad::find_label (char *name) |
struct label_entry *MemoryLoad::find_label(char *name) |
{ |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) |
{ |
struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE]; |
while (tmp) |
{ |
if (strcmp (tmp->name, name) == 0) |
return tmp; |
tmp = tmp->next; |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) { |
struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE]; |
while (tmp) { |
if (strcmp(tmp->name, name) == 0) |
return tmp; |
tmp = tmp->next; |
} |
} |
} |
return NULL; |
return NULL; |
} |
|
/* Searches mem array for a particular label and returns label's address. |
If label does not exist, returns 0. */ |
oraddr_t |
MemoryLoad::eval_label (char *name) |
oraddr_t MemoryLoad::eval_label(char *name) |
{ |
struct label_entry *le; |
char *plus; |
char *minus; |
int positive_offset = 0; |
int negative_offset = 0; |
struct label_entry *le; |
char *plus; |
char *minus; |
int positive_offset = 0; |
int negative_offset = 0; |
|
if ((plus = strchr (name, '+'))) |
{ |
*plus = '\0'; |
positive_offset = atoi (++plus); |
} |
if ((plus = strchr(name, '+'))) { |
*plus = '\0'; |
positive_offset = atoi(++plus); |
} |
|
if ((minus = strchr (name, '-'))) |
{ |
*minus = '\0'; |
negative_offset = atoi (++minus); |
} |
le = find_label (name); |
if (!le) |
return 0; |
if ((minus = strchr(name, '-'))) { |
*minus = '\0'; |
negative_offset = atoi(++minus); |
} |
le = find_label(name); |
if (!le) |
return 0; |
|
return le->addr + positive_offset - negative_offset; |
return le->addr + positive_offset - negative_offset; |
} |
/sysc/src/ResetSC.cpp
28,7 → 28,7
|
#include "ResetSC.h" |
|
SC_HAS_PROCESS( ResetSC ); |
SC_HAS_PROCESS(ResetSC); |
|
//! Constructor for the reset generator |
|
36,32 → 36,24
//! constructor. |
//! @param resetCounter Number of cycles of reset to provide. |
|
ResetSC::ResetSC (sc_core::sc_module_name name, |
int _resetCounter) : |
sc_module (name), |
resetCounter (_resetCounter) |
ResetSC::ResetSC(sc_core::sc_module_name name, int _resetCounter): |
sc_module(name), resetCounter(_resetCounter) |
{ |
SC_METHOD (driveReset); |
sensitive << clk.neg(); |
|
} // ResetSC () |
SC_METHOD(driveReset); |
sensitive << clk.neg(); |
|
} // ResetSC () |
|
//! Method to drive the reset port (active low). We will be called as an |
//! initialization, which can be used to drive the reset low. |
void |
ResetSC::driveReset() |
void ResetSC::driveReset() |
{ |
if (resetCounter > 0) |
{ |
rst = 1; |
rstn = 0; |
resetCounter--; |
} |
else |
{ |
rst = 0; |
rstn = 1; |
} |
} // driveReset() |
|
if (resetCounter > 0) { |
rst = 1; |
rstn = 0; |
resetCounter--; |
} else { |
rst = 0; |
rstn = 1; |
} |
} // driveReset() |
/sysc/src/GdbServerSC.cpp
35,7 → 35,7
|
#include <errno.h> |
#include <fcntl.h> |
extern int monitor_to_gdb_pipe[2][2]; // [0][] - monitor to gdb, [1][] - gdb to monitor, [][0] - read, [][1] - write |
extern int monitor_to_gdb_pipe[2][2]; // [0][] - monitor to gdb, [1][] - gdb to monitor, [][0] - read, [][1] - write |
|
using std::cerr; |
using std::dec; |
47,9 → 47,8
using sc_core::sc_stop; |
using sc_core::sc_time; |
|
SC_HAS_PROCESS(GdbServerSC); |
|
SC_HAS_PROCESS (GdbServerSC); |
|
//----------------------------------------------------------------------------- |
//! Constructor for the GDB RSP server. |
|
73,53 → 72,50
//! @param[in] _tapActionQueue Pointer to fifo of actions to be performed by |
//! the JTAG interface |
//----------------------------------------------------------------------------- |
GdbServerSC::GdbServerSC (sc_module_name name, |
uint32_t _flashStart, |
uint32_t _flashEnd, |
int rspPort, |
sc_fifo<TapAction *> *tapActionQueue) : |
sc_module (name), |
flashStart (_flashStart), |
flashEnd (_flashEnd) |
GdbServerSC::GdbServerSC(sc_module_name name, |
uint32_t _flashStart, |
uint32_t _flashEnd, |
int rspPort, |
sc_fifo < |
TapAction * >*tapActionQueue):sc_module(name), |
flashStart(_flashStart), flashEnd(_flashEnd) |
{ |
pkt = new RspPacket (RSP_PKT_MAX); |
rsp = new RspConnection (rspPort); |
debugUnit = new DebugUnitSC ("debug-unit", tapActionQueue); |
mpHash = new MpHash (); |
pkt = new RspPacket(RSP_PKT_MAX); |
rsp = new RspConnection(rspPort); |
debugUnit = new DebugUnitSC("debug-unit", tapActionQueue); |
mpHash = new MpHash(); |
|
/* Setup the pipes between or1200 monitor module and GDB stub */ |
pipe(monitor_to_gdb_pipe[0]); |
pipe(monitor_to_gdb_pipe[1]); |
|
// Set non-blocking reads |
#ifdef O_NONBLOCK /* The POSIX way */ |
fcntl (monitor_to_gdb_pipe[0][0], F_SETFL, O_NONBLOCK); |
fcntl (monitor_to_gdb_pipe[1][0], F_SETFL, O_NONBLOCK); |
/* Setup the pipes between or1200 monitor module and GDB stub */ |
pipe(monitor_to_gdb_pipe[0]); |
pipe(monitor_to_gdb_pipe[1]); |
|
// Set non-blocking reads |
#ifdef O_NONBLOCK /* The POSIX way */ |
fcntl(monitor_to_gdb_pipe[0][0], F_SETFL, O_NONBLOCK); |
fcntl(monitor_to_gdb_pipe[1][0], F_SETFL, O_NONBLOCK); |
#elif defined (O_NDELAY) |
fcntl (monitor_to_gdb_pipe[0][0], F_SETFL, O_NDELAY); |
fcntl (monitor_to_gdb_pipe[1][0], F_SETFL, O_NDELAY); |
fcntl(monitor_to_gdb_pipe[0][0], F_SETFL, O_NDELAY); |
fcntl(monitor_to_gdb_pipe[1][0], F_SETFL, O_NDELAY); |
#endif /* O_NONBLOCK */ |
|
SC_THREAD (rspServer); |
SC_THREAD(rspServer); |
|
} // GdbServerSC () |
} // GdbServerSC () |
|
|
//----------------------------------------------------------------------------- |
//! Destructor |
|
//! Free up data structures |
//----------------------------------------------------------------------------- |
GdbServerSC::~GdbServerSC () |
GdbServerSC::~GdbServerSC() |
{ |
delete mpHash; |
delete debugUnit; |
delete rsp; |
delete pkt; |
delete mpHash; |
delete debugUnit; |
delete rsp; |
delete pkt; |
|
} // ~GdbServerSC |
} // ~GdbServerSC |
|
|
//----------------------------------------------------------------------------- |
//! SystemC thread to listen for RSP requests |
|
133,105 → 129,92
//! complete. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspServer () |
GdbServerSC::rspServer() |
{ |
// Reset the debug unit, and wait for ORPSoC to be ready, by noting when it |
// accesses an address outside of flash. Note that we use NPC, not PPC since |
// at reset PPC is zero, and would trigger a false positive. |
|
debugUnit->resetDebugUnit (); |
rsp_sigval = TARGET_SIGNAL_NONE; |
/* |
uint32_t npc; |
do |
{ |
npc = debugUnit->readSpr (SPR_NPC); |
} |
while ((flashStart <= npc) && (npc <= flashEnd)); |
*/ |
debugUnit->stall (); |
targetStopped = true; |
|
// Make sure we are connected. |
while (!rsp->isConnected ()) |
{ |
// Reconnect and stall the processor on a new connection |
if (!rsp->rspConnect ()) |
{ |
// Serious failure. Must abort execution. |
cerr << "*** Unable to continue: ABORTING" << endl; |
sc_stop (); |
} |
|
// Stall the processor until we get a command to handle. |
if (!debugUnit->isStalled ()) |
{ |
debugUnit->stall (); |
} |
|
targetStopped = true; // Processor now not running |
} |
// Reset the debug unit, and wait for ORPSoC to be ready, by noting when it |
// accesses an address outside of flash. Note that we use NPC, not PPC since |
// at reset PPC is zero, and would trigger a false positive. |
|
|
// Loop processing commands forever |
while (true) |
{ |
if (!rsp->isConnected()) |
{ |
sc_stop (); |
return; |
debugUnit->resetDebugUnit(); |
rsp_sigval = TARGET_SIGNAL_NONE; |
/* |
uint32_t npc; |
do |
{ |
npc = debugUnit->readSpr (SPR_NPC); |
} |
while ((flashStart <= npc) && (npc <= flashEnd)); |
*/ |
debugUnit->stall(); |
targetStopped = true; |
|
// Make sure we are connected. |
while (!rsp->isConnected()) { |
// Reconnect and stall the processor on a new connection |
if (!rsp->rspConnect()) { |
// Serious failure. Must abort execution. |
cerr << "*** Unable to continue: ABORTING" << endl; |
sc_stop(); |
} |
// Stall the processor until we get a command to handle. |
if (!debugUnit->isStalled()) { |
debugUnit->stall(); |
} |
|
targetStopped = true; // Processor now not running |
} |
// Wait until the target has stopped. In this simplified implementation, |
// the only reasons for stopping are hitting a breakpoint (l.trap), |
// hardware single stepping or hitting a non-breakpoint l.trap. This |
// last is not cleanly handled at the moment (we ought to redirect the |
// restart through the trap exception vector). |
while (!targetStopped) |
{ |
|
/* First check to see if the or1200 monitor module wants us to stall*/ |
if (checkMonitorPipe()) |
break; |
|
rspCheckForException(); |
|
if (debugUnit->isStalled()) |
{ |
targetStopped = true; |
// Loop processing commands forever |
while (true) { |
if (!rsp->isConnected()) { |
sc_stop(); |
return; |
} |
// Wait until the target has stopped. In this simplified implementation, |
// the only reasons for stopping are hitting a breakpoint (l.trap), |
// hardware single stepping or hitting a non-breakpoint l.trap. This |
// last is not cleanly handled at the moment (we ought to redirect the |
// restart through the trap exception vector). |
while (!targetStopped) { |
|
// If it's a breakpoint, then we need to back up one |
// instruction, so on restart we execute the actual |
// instruction. |
uint32_t ppc = debugUnit->readSpr (SPR_PPC); |
/* First check to see if the or1200 monitor module wants us to stall */ |
if (checkMonitorPipe()) |
break; |
|
if (NULL != mpHash->lookup (BP_MEMORY, ppc) && rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
writeNpc (ppc); |
} |
rspCheckForException(); |
|
// Tell the client we've stopped. |
rspReportException (); |
} |
else if (rsp->rspSocketPeek() > 0) |
{ |
if (rsp->rspSocketPeek() == 0x03) // ETX, end of text control char |
{ |
// Got an interrupt command from GDB, this function should |
// pull the packet off the socket and stall the processor. |
// and then send a stop reply packet with signal |
// TARGET_SIGNAL_NONE. |
rspInterrupt(); |
targetStopped = true; // Processor now not running |
if (debugUnit->isStalled()) { |
targetStopped = true; |
|
// If it's a breakpoint, then we need to back up one |
// instruction, so on restart we execute the actual |
// instruction. |
uint32_t ppc = debugUnit->readSpr(SPR_PPC); |
|
if (NULL != mpHash->lookup(BP_MEMORY, ppc) |
&& rsp_sigval == TARGET_SIGNAL_TRAP) { |
writeNpc(ppc); |
} |
// Tell the client we've stopped. |
rspReportException(); |
} else if (rsp->rspSocketPeek() > 0) { |
if (rsp->rspSocketPeek() == 0x03) // ETX, end of text control char |
{ |
// Got an interrupt command from GDB, this function should |
// pull the packet off the socket and stall the processor. |
// and then send a stop reply packet with signal |
// TARGET_SIGNAL_NONE. |
rspInterrupt(); |
targetStopped = true; // Processor now not running |
} |
} |
} |
} |
|
// Get a RSP client request |
rspClientRequest(); |
} |
} // rspServer () |
|
// Get a RSP client request |
rspClientRequest (); |
} |
} // rspServer () |
|
|
//----------------------------------------------------------------------------- |
//! Deal with a request from the GDB client session |
|
248,241 → 231,263
|
//! @param[in] pkt The received RSP packet |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspClientRequest () |
void GdbServerSC::rspClientRequest() |
{ |
if (!rsp->getPkt (pkt)) |
{ |
rsp->rspClose (); // Comms failure |
return; |
} |
//Uncomment the next line for the RSP client to print out every packet it gets from GDB |
//cerr << "rspClientRequest: " << pkt->data/*[0]*/ << endl; |
switch (pkt->data[0]) |
{ |
case '!': |
// Request for extended remote mode |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
if (!rsp->getPkt(pkt)) { |
rsp->rspClose(); // Comms failure |
return; |
} |
//Uncomment the next line for the RSP client to print out every packet it gets from GDB |
//cerr << "rspClientRequest: " << pkt->data/*[0]*/ << endl; |
switch (pkt->data[0]) { |
case '!': |
// Request for extended remote mode |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
case '?': |
// Return last signal ID |
rspReportException (); |
return; |
case '?': |
// Return last signal ID |
rspReportException(); |
return; |
|
case 'A': |
// Initialization of argv not supported |
cerr << "Warning: RSP 'A' packet not supported: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
case 'A': |
// Initialization of argv not supported |
cerr << "Warning: RSP 'A' packet not supported: ignored" << |
endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
|
case 'b': |
// Setting baud rate is deprecated |
cerr << "Warning: RSP 'b' packet is deprecated and not " |
<< "supported: ignored" << endl; |
return; |
case 'b': |
// Setting baud rate is deprecated |
cerr << "Warning: RSP 'b' packet is deprecated and not " |
<< "supported: ignored" << endl; |
return; |
|
case 'B': |
// Breakpoints should be set using Z packets |
cerr << "Warning: RSP 'B' packet is deprecated (use 'Z'/'z' " |
<< "packets instead): ignored" << endl; |
return; |
case 'B': |
// Breakpoints should be set using Z packets |
cerr << "Warning: RSP 'B' packet is deprecated (use 'Z'/'z' " |
<< "packets instead): ignored" << endl; |
return; |
|
case 'c': |
// Continue |
rspContinue (EXCEPT_NONE); |
return; |
case 'c': |
// Continue |
rspContinue(EXCEPT_NONE); |
return; |
|
case 'C': |
// Continue with signal (in the packet) |
rspContinue (); |
return; |
case 'C': |
// Continue with signal (in the packet) |
rspContinue(); |
return; |
|
case 'd': |
// Disable debug using a general query |
cerr << "Warning: RSP 'd' packet is deprecated (define a 'Q' " |
<< "packet instead: ignored" << endl; |
return; |
case 'd': |
// Disable debug using a general query |
cerr << "Warning: RSP 'd' packet is deprecated (define a 'Q' " |
<< "packet instead: ignored" << endl; |
return; |
|
case 'D': |
// Detach GDB. Do this by closing the client. The rules say that |
// execution should continue, so unstall the processor. |
pkt->packStr("OK"); |
rsp->putPkt (pkt); |
rsp->rspClose (); |
//debugUnit->unstall (); |
return; |
case 'D': |
// Detach GDB. Do this by closing the client. The rules say that |
// execution should continue, so unstall the processor. |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
rsp->rspClose(); |
//debugUnit->unstall (); |
return; |
|
case 'F': |
// File I/O is not currently supported |
cerr << "Warning: RSP file I/O not currently supported: 'F' " |
<< "packet ignored" << endl; |
return; |
case 'F': |
// File I/O is not currently supported |
cerr << "Warning: RSP file I/O not currently supported: 'F' " |
<< "packet ignored" << endl; |
return; |
|
case 'g': |
rspReadAllRegs (); |
return; |
case 'g': |
rspReadAllRegs(); |
return; |
|
case 'G': |
rspWriteAllRegs (); |
return; |
|
case 'H': |
// Set the thread number of subsequent operations. For now ignore |
// silently and just reply "OK" |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
case 'G': |
rspWriteAllRegs(); |
return; |
|
case 'i': |
case 'I': |
// Single cycle step not currently supported. Mark the target as |
// running, so that next time it will be detected as stopped (it is |
// still stalled in reality) and an ack sent back to the client. |
cerr << "Warning: RSP cycle stepping not supported: target " |
<< "stopped immediately" << endl; |
targetStopped = false; |
return; |
case 'H': |
// Set the thread number of subsequent operations. For now ignore |
// silently and just reply "OK" |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
case 'k': |
// Kill request. Do nothing for now. |
return; |
case 'i': |
case 'I': |
// Single cycle step not currently supported. Mark the target as |
// running, so that next time it will be detected as stopped (it is |
// still stalled in reality) and an ack sent back to the client. |
cerr << "Warning: RSP cycle stepping not supported: target " |
<< "stopped immediately" << endl; |
targetStopped = false; |
return; |
|
case 'm': |
// Read memory (symbolic) |
rspReadMem (); |
return; |
case 'k': |
// Kill request. Do nothing for now. |
return; |
|
case 'M': |
// Write memory (symbolic) |
rspWriteMem (); |
return; |
case 'm': |
// Read memory (symbolic) |
rspReadMem(); |
return; |
|
case 'p': |
// Read a register |
rspReadReg (); |
return; |
case 'M': |
// Write memory (symbolic) |
rspWriteMem(); |
return; |
|
case 'P': |
// Write a register |
rspWriteReg (); |
return; |
case 'p': |
// Read a register |
rspReadReg(); |
return; |
|
case 'q': |
// Any one of a number of query packets |
rspQuery (); |
return; |
case 'P': |
// Write a register |
rspWriteReg(); |
return; |
|
case 'Q': |
// Any one of a number of set packets |
rspSet (); |
return; |
case 'q': |
// Any one of a number of query packets |
rspQuery(); |
return; |
|
case 'r': |
// Reset the system. Deprecated (use 'R' instead) |
cerr << "Warning: RSP 'r' packet is deprecated (use 'R' " |
<< "packet instead): ignored" << endl; |
return; |
case 'Q': |
// Any one of a number of set packets |
rspSet(); |
return; |
|
case 'R': |
// Restart the program being debugged. |
rspRestart (); |
return; |
case 'r': |
// Reset the system. Deprecated (use 'R' instead) |
cerr << "Warning: RSP 'r' packet is deprecated (use 'R' " |
<< "packet instead): ignored" << endl; |
return; |
|
case 's': |
// Single step one machine instruction. |
rspStep (EXCEPT_NONE); |
return; |
case 'R': |
// Restart the program being debugged. |
rspRestart(); |
return; |
|
case 'S': |
// Single step one machine instruction. |
rspStep (); |
return; |
case 's': |
// Single step one machine instruction. |
rspStep(EXCEPT_NONE); |
return; |
|
case 't': |
// Search. This is not well defined in the manual and for now we don't |
// support it. No response is defined. |
cerr << "Warning: RSP 't' packet not supported: ignored" |
<< endl; |
return; |
case 'S': |
// Single step one machine instruction. |
rspStep(); |
return; |
|
case 'T': |
// Is the thread alive. We are bare metal, so don't have a thread |
// context. The answer is always "OK". |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
case 't': |
// Search. This is not well defined in the manual and for now we don't |
// support it. No response is defined. |
cerr << "Warning: RSP 't' packet not supported: ignored" |
<< endl; |
return; |
|
case 'v': |
// Any one of a number of packets to control execution |
rspVpkt (); |
return; |
case 'T': |
// Is the thread alive. We are bare metal, so don't have a thread |
// context. The answer is always "OK". |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
case 'X': |
// Write memory (binary) |
rspWriteMemBin (); |
return; |
case 'v': |
// Any one of a number of packets to control execution |
rspVpkt(); |
return; |
|
case 'z': |
// Remove a breakpoint/watchpoint. |
rspRemoveMatchpoint (); |
return; |
case 'X': |
// Write memory (binary) |
rspWriteMemBin(); |
return; |
|
case 'Z': |
// Insert a breakpoint/watchpoint. |
rspInsertMatchpoint (); |
return; |
case 'z': |
// Remove a breakpoint/watchpoint. |
rspRemoveMatchpoint(); |
return; |
|
default: |
// Unknown commands are ignored |
cerr << "Warning: Unknown RSP request" << pkt->data << endl; |
return; |
} |
} // rspClientRequest () |
case 'Z': |
// Insert a breakpoint/watchpoint. |
rspInsertMatchpoint(); |
return; |
|
default: |
// Unknown commands are ignored |
cerr << "Warning: Unknown RSP request" << pkt->data << endl; |
return; |
} |
} // rspClientRequest () |
|
|
//----------------------------------------------------------------------------- |
//! Check if processor is stalled. If it is, read the DRR and return the |
//! target signal code. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspCheckForException() |
void GdbServerSC::rspCheckForException() |
{ |
|
uint32_t drr; |
|
if (!debugUnit->isStalled()) |
{ |
// Processor not stalled. Just return; |
return; |
} |
|
switch ((debugUnit->readSpr(SPR_DRR)&0xffffffff)) |
{ |
case SPR_DRR_RSTE: rsp_sigval = TARGET_SIGNAL_PWR; break; |
case SPR_DRR_BUSEE: rsp_sigval = TARGET_SIGNAL_BUS; break; |
case SPR_DRR_DPFE: rsp_sigval = TARGET_SIGNAL_SEGV; break; |
case SPR_DRR_IPFE: rsp_sigval = TARGET_SIGNAL_SEGV; break; |
case SPR_DRR_TTE: rsp_sigval = TARGET_SIGNAL_ALRM; break; |
case SPR_DRR_AE: rsp_sigval = TARGET_SIGNAL_BUS; break; |
case SPR_DRR_IIE: rsp_sigval = TARGET_SIGNAL_ILL; break; |
case SPR_DRR_IE: rsp_sigval = TARGET_SIGNAL_INT; break; |
case SPR_DRR_DME: rsp_sigval = TARGET_SIGNAL_SEGV; break; |
case SPR_DRR_IME: rsp_sigval = TARGET_SIGNAL_SEGV; break; |
case SPR_DRR_RE: rsp_sigval = TARGET_SIGNAL_FPE; break; |
case SPR_DRR_SCE: rsp_sigval = TARGET_SIGNAL_USR2; break; |
case SPR_DRR_FPE: rsp_sigval = TARGET_SIGNAL_FPE; break; |
case SPR_DRR_TE: rsp_sigval = TARGET_SIGNAL_TRAP; break; |
|
default: |
// This must be the case of single step (which does not set DRR) |
rsp_sigval = TARGET_SIGNAL_TRAP; break; |
} |
uint32_t drr; |
|
return; |
if (!debugUnit->isStalled()) { |
// Processor not stalled. Just return; |
return; |
} |
|
switch ((debugUnit->readSpr(SPR_DRR) & 0xffffffff)) { |
case SPR_DRR_RSTE: |
rsp_sigval = TARGET_SIGNAL_PWR; |
break; |
case SPR_DRR_BUSEE: |
rsp_sigval = TARGET_SIGNAL_BUS; |
break; |
case SPR_DRR_DPFE: |
rsp_sigval = TARGET_SIGNAL_SEGV; |
break; |
case SPR_DRR_IPFE: |
rsp_sigval = TARGET_SIGNAL_SEGV; |
break; |
case SPR_DRR_TTE: |
rsp_sigval = TARGET_SIGNAL_ALRM; |
break; |
case SPR_DRR_AE: |
rsp_sigval = TARGET_SIGNAL_BUS; |
break; |
case SPR_DRR_IIE: |
rsp_sigval = TARGET_SIGNAL_ILL; |
break; |
case SPR_DRR_IE: |
rsp_sigval = TARGET_SIGNAL_INT; |
break; |
case SPR_DRR_DME: |
rsp_sigval = TARGET_SIGNAL_SEGV; |
break; |
case SPR_DRR_IME: |
rsp_sigval = TARGET_SIGNAL_SEGV; |
break; |
case SPR_DRR_RE: |
rsp_sigval = TARGET_SIGNAL_FPE; |
break; |
case SPR_DRR_SCE: |
rsp_sigval = TARGET_SIGNAL_USR2; |
break; |
case SPR_DRR_FPE: |
rsp_sigval = TARGET_SIGNAL_FPE; |
break; |
case SPR_DRR_TE: |
rsp_sigval = TARGET_SIGNAL_TRAP; |
break; |
|
default: |
// This must be the case of single step (which does not set DRR) |
rsp_sigval = TARGET_SIGNAL_TRAP; |
break; |
} |
|
return; |
} |
|
//----------------------------------------------------------------------------- |
490,21 → 495,19
|
//! The only signal we ever see in this implementation is TRAP. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspReportException () |
void GdbServerSC::rspReportException() |
{ |
// Construct a signal received packet |
pkt->data[0] = 'S'; |
pkt->data[1] = Utils::hex2Char (rsp_sigval >> 4); |
pkt->data[2] = Utils::hex2Char (rsp_sigval % 16); |
pkt->data[3] = '\0'; |
pkt->setLen (strlen (pkt->data)); |
// Construct a signal received packet |
pkt->data[0] = 'S'; |
pkt->data[1] = Utils::hex2Char(rsp_sigval >> 4); |
pkt->data[2] = Utils::hex2Char(rsp_sigval % 16); |
pkt->data[3] = '\0'; |
pkt->setLen(strlen(pkt->data)); |
|
rsp->putPkt (pkt); |
rsp->putPkt(pkt); |
|
} // rspReportException () |
} // rspReportException () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP continue request |
|
515,36 → 518,30
|
//! @param[in] except The OpenRISC 1000 exception to use |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspContinue (uint32_t except) |
void GdbServerSC::rspContinue(uint32_t except) |
{ |
uint32_t addr; // Address to continue from, if any |
uint32_t addr; // Address to continue from, if any |
|
// Reject all except 'c' packets |
if ('c' != pkt->data[0]) |
{ |
cerr << "Warning: Continue with signal not currently supported: " |
<< "ignored" << endl; |
return; |
} |
// Reject all except 'c' packets |
if ('c' != pkt->data[0]) { |
cerr << |
"Warning: Continue with signal not currently supported: " << |
"ignored" << endl; |
return; |
} |
// Get an address if we have one |
if (0 == strcmp("c", pkt->data)) { |
addr = readNpc(); // Default uses current NPC |
} else if (1 != sscanf(pkt->data, "c%lx", &addr)) { |
cerr << "Warning: RSP continue address " << pkt->data |
<< " not recognized: ignored" << endl; |
addr = readNpc(); // Default uses current NPC |
} |
|
// Get an address if we have one |
if (0 == strcmp ("c", pkt->data)) |
{ |
addr = readNpc (); // Default uses current NPC |
} |
else if (1 != sscanf (pkt->data, "c%lx", &addr)) |
{ |
cerr << "Warning: RSP continue address " << pkt->data |
<< " not recognized: ignored" << endl; |
addr = readNpc (); // Default uses current NPC |
} |
rspContinue(addr, EXCEPT_NONE); |
|
rspContinue (addr, EXCEPT_NONE); |
} // rspContinue () |
|
} // rspContinue () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP continue with signal request |
|
551,15 → 548,13
//! @todo Currently does nothing. Will use the underlying generic continue |
//! function. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspContinue () |
void GdbServerSC::rspContinue() |
{ |
cerr << "RSP continue with signal '" << pkt->data |
<< "' received" << endl; |
cerr << "RSP continue with signal '" << pkt->data |
<< "' received" << endl; |
|
} // rspContinue () |
} // rspContinue () |
|
|
//----------------------------------------------------------------------------- |
//! Generic processing of a continue request |
|
572,95 → 567,88
//! @param[in] addr Address from which to step |
//! @param[in] except The exception to use (if any) |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspContinue (uint32_t addr, |
uint32_t except) |
void GdbServerSC::rspContinue(uint32_t addr, uint32_t except) |
{ |
// Set the address as the value of the next program counter |
writeNpc (addr); |
|
/* |
// If we're continuing from a breakpoint, replace that instruction in the memory |
// ... actually no, I was wrong about this. |
if (NULL != mpHash->lookup (BP_MEMORY, addr) && rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
MpEntry *entry = mpHash->lookup (BP_MEMORY, addr); |
debugUnit->writeMem32(entry->addr, entry->instr); |
} |
*/ |
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode |
// Register 2 for watchpoints that we triggered to stop this time. |
debugUnit->writeSpr (SPR_DRR, 0); |
if (rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
/* |
Disable last trap generation on watchpoint if this is why we stopped |
last time. |
*/ |
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2); |
if (temp_dmr2 & SPR_DMR2_WBS) |
{ |
/* |
One of these breakpoints is responsible for our stopping, so |
disable it this time we start. GDB will send a packet re-enabling |
it next time we continue. |
*/ |
debugUnit->writeSpr (SPR_DMR2, temp_dmr2 & ~((temp_dmr2&SPR_DMR2_WBS)>>10)); |
} |
} |
// Set the address as the value of the next program counter |
writeNpc(addr); |
|
// Clear the single step trigger in Debug Mode Register 1 and set traps to |
// be handled by the debug unit in the Debug Stop Register |
debugUnit->andSpr (SPR_DMR1, ~SPR_DMR1_ST); |
debugUnit->orSpr ( SPR_DSR, SPR_DSR_TE); |
/* |
// If we're continuing from a breakpoint, replace that instruction in the memory |
// ... actually no, I was wrong about this. |
if (NULL != mpHash->lookup (BP_MEMORY, addr) && rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
MpEntry *entry = mpHash->lookup (BP_MEMORY, addr); |
debugUnit->writeMem32(entry->addr, entry->instr); |
} |
*/ |
|
// Unstall the processor. Note the GDB client is now waiting for a reply, |
// which it will get as soon as the processor stalls again. |
debugUnit->unstall (); |
targetStopped = false; |
// Clear Debug Reason Register and watchpoint break generation in Debug Mode |
// Register 2 for watchpoints that we triggered to stop this time. |
debugUnit->writeSpr(SPR_DRR, 0); |
if (rsp_sigval == TARGET_SIGNAL_TRAP) { |
/* |
Disable last trap generation on watchpoint if this is why we stopped |
last time. |
*/ |
uint32_t temp_dmr2 = debugUnit->readSpr(SPR_DMR2); |
if (temp_dmr2 & SPR_DMR2_WBS) { |
/* |
One of these breakpoints is responsible for our stopping, so |
disable it this time we start. GDB will send a packet re-enabling |
it next time we continue. |
*/ |
debugUnit->writeSpr(SPR_DMR2, |
temp_dmr2 & |
~((temp_dmr2 & SPR_DMR2_WBS) >> |
10)); |
} |
} |
// Clear the single step trigger in Debug Mode Register 1 and set traps to |
// be handled by the debug unit in the Debug Stop Register |
debugUnit->andSpr(SPR_DMR1, ~SPR_DMR1_ST); |
debugUnit->orSpr(SPR_DSR, SPR_DSR_TE); |
|
} // rspContinue () |
// Unstall the processor. Note the GDB client is now waiting for a reply, |
// which it will get as soon as the processor stalls again. |
debugUnit->unstall(); |
targetStopped = false; |
|
} // rspContinue () |
|
|
//------------------------------------------------------------------------------ |
//!Handle an interrupt from GDB |
|
//! Detect an interrupt from GDB and stall the processor |
//------------------------------------------------------------------------------ |
void |
GdbServerSC::rspInterrupt() |
void GdbServerSC::rspInterrupt() |
{ |
unsigned char c; |
unsigned char c; |
|
c = rsp->getRspChar(); |
if (c < 0) |
{ |
// Had issues, just return |
return; |
} |
|
// Ensure this is a ETX control char (0x3), currently, we only call this |
// function when we've peeked and seen it, otherwise, ignore, return and pray |
// things go back to normal... |
if (c != 0x03) |
{ |
cerr << "* Warning: Interrupt character expected but not found on socket" << endl; |
return; |
} |
|
// Otherwise, it's an interrupt packet, stall the processor, and upon return |
// to the main handle_rsp() loop, it will inform GDB. |
c = rsp->getRspChar(); |
if (c < 0) { |
// Had issues, just return |
return; |
} |
// Ensure this is a ETX control char (0x3), currently, we only call this |
// function when we've peeked and seen it, otherwise, ignore, return and pray |
// things go back to normal... |
if (c != 0x03) { |
cerr << |
"* Warning: Interrupt character expected but not found on socket" |
<< endl; |
return; |
} |
// Otherwise, it's an interrupt packet, stall the processor, and upon return |
// to the main handle_rsp() loop, it will inform GDB. |
|
debugUnit->stall (); |
debugUnit->stall(); |
|
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE |
rsp_sigval = TARGET_SIGNAL_NONE; |
rspReportException(); |
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE |
rsp_sigval = TARGET_SIGNAL_NONE; |
rspReportException(); |
|
return; |
|
return; |
|
} |
|
//----------------------------------------------------------------------------- |
672,28 → 660,26
|
//! Each byte is packed as a pair of hex digits. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspReadAllRegs () |
void GdbServerSC::rspReadAllRegs() |
{ |
// The GPRs |
for (int r = 0; r < max_gprs; r++) |
{ |
Utils::reg2Hex (readGpr (r), &(pkt->data[r * 8])); |
} |
// The GPRs |
for (int r = 0; r < max_gprs; r++) { |
Utils::reg2Hex(readGpr(r), &(pkt->data[r * 8])); |
} |
|
// PPC, NPC and SR |
Utils::reg2Hex (debugUnit->readSpr (SPR_PPC), &(pkt->data[PPC_REGNUM * 8])); |
Utils::reg2Hex (readNpc (), &(pkt->data[NPC_REGNUM * 8])); |
Utils::reg2Hex (debugUnit->readSpr (SPR_SR), &(pkt->data[SR_REGNUM * 8])); |
// PPC, NPC and SR |
Utils::reg2Hex(debugUnit->readSpr(SPR_PPC), |
&(pkt->data[PPC_REGNUM * 8])); |
Utils::reg2Hex(readNpc(), &(pkt->data[NPC_REGNUM * 8])); |
Utils::reg2Hex(debugUnit->readSpr(SPR_SR), &(pkt->data[SR_REGNUM * 8])); |
|
// Finalize the packet and send it |
pkt->data[NUM_REGS * 8] = 0; |
pkt->setLen (NUM_REGS * 8); |
rsp->putPkt (pkt); |
// Finalize the packet and send it |
pkt->data[NUM_REGS * 8] = 0; |
pkt->setLen(NUM_REGS * 8); |
rsp->putPkt(pkt); |
|
} // rspReadAllRegs () |
} // rspReadAllRegs () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP write all registers request |
|
707,27 → 693,26
//! warning message, but there is no other check that the right amount |
//! of data is present. The result is always "OK". |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspWriteAllRegs () |
void GdbServerSC::rspWriteAllRegs() |
{ |
// The GPRs |
for (int r = 0; r < max_gprs; r++) |
{ |
writeGpr (r, Utils::hex2Reg (&(pkt->data[r * 8]))); |
} |
// The GPRs |
for (int r = 0; r < max_gprs; r++) { |
writeGpr(r, Utils::hex2Reg(&(pkt->data[r * 8]))); |
} |
|
// PPC, NPC and SR |
debugUnit->writeSpr (SPR_PPC, Utils::hex2Reg (&(pkt->data[PPC_REGNUM * 8]))); |
debugUnit->writeSpr (SPR_SR, Utils::hex2Reg (&(pkt->data[SR_REGNUM * 8]))); |
writeNpc ( Utils::hex2Reg (&(pkt->data[NPC_REGNUM * 8]))); |
// PPC, NPC and SR |
debugUnit->writeSpr(SPR_PPC, |
Utils::hex2Reg(&(pkt->data[PPC_REGNUM * 8]))); |
debugUnit->writeSpr(SPR_SR, |
Utils::hex2Reg(&(pkt->data[SR_REGNUM * 8]))); |
writeNpc(Utils::hex2Reg(&(pkt->data[NPC_REGNUM * 8]))); |
|
// Acknowledge (always OK for now). |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
// Acknowledge (always OK for now). |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
|
} // rspWriteAllRegs () |
} // rspWriteAllRegs () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP read memory (symbolic) request |
|
740,46 → 725,40
|
//! The length given is the number of bytes to be read. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspReadMem () |
void GdbServerSC::rspReadMem() |
{ |
unsigned int addr; // Where to read the memory |
int len; // Number of bytes to read |
int off; // Offset into the memory |
unsigned int addr; // Where to read the memory |
int len; // Number of bytes to read |
int off; // Offset into the memory |
|
if (2 != sscanf (pkt->data, "m%x,%x:", &addr, &len)) |
{ |
cerr << "Warning: Failed to recognize RSP read memory command: " |
<< pkt->data << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
if (2 != sscanf(pkt->data, "m%x,%x:", &addr, &len)) { |
cerr << "Warning: Failed to recognize RSP read memory command: " |
<< pkt->data << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Make sure we won't overflow the buffer (2 chars per byte) |
if ((len * 2) >= pkt->getBufSize()) { |
cerr << "Warning: Memory read " << pkt->data |
<< " too large for RSP packet: truncated" << endl; |
len = (pkt->getBufSize() - 1) / 2; |
} |
//cerr << "rspReadMem: " << len << " bytes@0x"<< hex << addr << endl; |
// Refill the buffer with the reply |
for (off = 0; off < len; off++) { |
unsigned char ch = debugUnit->readMem8(addr + off); |
|
// Make sure we won't overflow the buffer (2 chars per byte) |
if ((len * 2) >= pkt->getBufSize()) |
{ |
cerr << "Warning: Memory read " << pkt->data |
<< " too large for RSP packet: truncated" << endl; |
len = (pkt->getBufSize() - 1) / 2; |
} |
//cerr << "rspReadMem: " << len << " bytes@0x"<< hex << addr << endl; |
// Refill the buffer with the reply |
for (off = 0; off < len; off++) |
{ |
unsigned char ch = debugUnit->readMem8 (addr + off); |
pkt->data[off * 2] = Utils::hex2Char(ch >> 4); |
pkt->data[off * 2 + 1] = Utils::hex2Char(ch & 0xf); |
} |
|
pkt->data[off * 2] = Utils::hex2Char(ch >> 4); |
pkt->data[off * 2 + 1] = Utils::hex2Char(ch & 0xf); |
} |
pkt->data[off * 2] = '\0'; // End of string |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
|
pkt->data[off * 2] = '\0'; // End of string |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} // rsp_read_mem () |
|
} // rsp_read_mem () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP write memory (symbolic) request |
|
792,55 → 771,48
|
//! The length given is the number of bytes to be written. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspWriteMem () |
void GdbServerSC::rspWriteMem() |
{ |
uint32_t addr; // Where to write the memory |
int len; // Number of bytes to write |
uint32_t addr; // Where to write the memory |
int len; // Number of bytes to write |
|
if (2 != sscanf (pkt->data, "M%x,%x:", &addr, &len)) |
{ |
cerr << "Warning: Failed to recognize RSP write memory " |
<< pkt->data << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
if (2 != sscanf(pkt->data, "M%x,%x:", &addr, &len)) { |
cerr << "Warning: Failed to recognize RSP write memory " |
<< pkt->data << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Find the start of the data and check there is the amount we expect. |
char *symDat = (char *)(memchr(pkt->data, ':', pkt->getBufSize())) + 1; |
int datLen = pkt->getLen() - (symDat - pkt->data); |
|
// Find the start of the data and check there is the amount we expect. |
char *symDat = (char *)(memchr (pkt->data, ':', pkt->getBufSize())) + 1; |
int datLen = pkt->getLen() - (symDat - pkt->data); |
// Sanity check |
if (len * 2 != datLen) { |
cerr << "Warning: Write of " << len * |
2 << "digits requested, but " << datLen << |
" digits supplied: packet ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Write the bytes to memory (no check the address is OK here) |
for (int off = 0; off < len; off++) { |
uint8_t nyb1 = Utils::char2Hex(symDat[off * 2]); |
uint8_t nyb2 = Utils::char2Hex(symDat[off * 2 + 1]); |
|
// Sanity check |
if (len * 2 != datLen) |
{ |
cerr << "Warning: Write of " << len * 2 << "digits requested, but " |
<< datLen << " digits supplied: packet ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
|
// Write the bytes to memory (no check the address is OK here) |
for (int off = 0; off < len; off++) |
{ |
uint8_t nyb1 = Utils::char2Hex (symDat[off * 2]); |
uint8_t nyb2 = Utils::char2Hex (symDat[off * 2 + 1]); |
|
if (!debugUnit->writeMem8 (addr + off, (nyb1 << 4) | nyb2)) |
{ |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
if (!debugUnit->writeMem8(addr + off, (nyb1 << 4) | nyb2)) { |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} |
} |
|
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
|
} // rspWriteMem () |
} // rspWriteMem () |
|
|
//----------------------------------------------------------------------------- |
//! Read a single register |
|
850,54 → 822,42
|
//! Each byte is packed as a pair of hex digits. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspReadReg () |
void GdbServerSC::rspReadReg() |
{ |
unsigned int regNum; |
unsigned int regNum; |
|
// Break out the fields from the data |
if (1 != sscanf (pkt->data, "p%x", ®Num)) |
{ |
cerr << "Warning: Failed to recognize RSP read register command: " |
<< pkt->data << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
// Break out the fields from the data |
if (1 != sscanf(pkt->data, "p%x", ®Num)) { |
cerr << |
"Warning: Failed to recognize RSP read register command: " |
<< pkt->data << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Get the relevant register |
if (regNum < max_gprs) { |
Utils::Utils::reg2Hex(readGpr(regNum), pkt->data); |
} else if (PPC_REGNUM == regNum) { |
Utils::Utils::reg2Hex(debugUnit->readSpr(SPR_PPC), pkt->data); |
} else if (NPC_REGNUM == regNum) { |
Utils::Utils::reg2Hex(readNpc(), pkt->data); |
} else if (SR_REGNUM == regNum) { |
Utils::Utils::reg2Hex(debugUnit->readSpr(SPR_SR), pkt->data); |
} else { |
// Error response if we don't know the register |
cerr << "Warning: Attempt to read unknown register" << regNum |
<< ": ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
|
// Get the relevant register |
if (regNum < max_gprs) |
{ |
Utils::Utils::reg2Hex (readGpr (regNum), pkt->data); |
} |
else if (PPC_REGNUM == regNum) |
{ |
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_PPC), pkt->data); |
} |
else if (NPC_REGNUM == regNum) |
{ |
Utils::Utils::reg2Hex (readNpc (), pkt->data); |
} |
else if (SR_REGNUM == regNum) |
{ |
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_SR), pkt->data); |
} |
else |
{ |
// Error response if we don't know the register |
cerr << "Warning: Attempt to read unknown register" << regNum |
<< ": ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
|
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} // rspWriteReg () |
|
} // rspWriteReg () |
|
|
//----------------------------------------------------------------------------- |
//! Write a single register |
|
907,290 → 867,226
|
//! Each byte is packed as a pair of hex digits. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspWriteReg () |
void GdbServerSC::rspWriteReg() |
{ |
unsigned int regNum; |
char valstr[9]; // Allow for EOS on the string |
unsigned int regNum; |
char valstr[9]; // Allow for EOS on the string |
|
// Break out the fields from the data |
if (2 != sscanf (pkt->data, "P%x=%8s", ®Num, valstr)) |
{ |
cerr << "Warning: Failed to recognize RSP write register command " |
<< pkt->data << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
|
// Set the relevant register |
if (regNum < max_gprs) |
{ |
writeGpr (regNum, Utils::hex2Reg (valstr)); |
} |
else if (PPC_REGNUM == regNum) |
{ |
debugUnit->writeSpr (SPR_PPC, Utils::hex2Reg (valstr)); |
} |
else if (NPC_REGNUM == regNum) |
{ |
writeNpc (Utils::hex2Reg (valstr)); |
} |
else if (SR_REGNUM == regNum) |
{ |
debugUnit->writeSpr (SPR_SR, Utils::hex2Reg (valstr)); |
} |
else |
{ |
// Error response if we don't know the register |
cerr << "Warning: Attempt to write unknown register " << regNum |
<< ": ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
// Break out the fields from the data |
if (2 != sscanf(pkt->data, "P%x=%8s", ®Num, valstr)) { |
cerr << |
"Warning: Failed to recognize RSP write register command " |
<< pkt->data << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Set the relevant register |
if (regNum < max_gprs) { |
writeGpr(regNum, Utils::hex2Reg(valstr)); |
} else if (PPC_REGNUM == regNum) { |
debugUnit->writeSpr(SPR_PPC, Utils::hex2Reg(valstr)); |
} else if (NPC_REGNUM == regNum) { |
writeNpc(Utils::hex2Reg(valstr)); |
} else if (SR_REGNUM == regNum) { |
debugUnit->writeSpr(SPR_SR, Utils::hex2Reg(valstr)); |
} else { |
// Error response if we don't know the register |
cerr << "Warning: Attempt to write unknown register " << regNum |
<< ": ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
|
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
|
} // rspWriteReg () |
} // rspWriteReg () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP query request |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspQuery () |
void GdbServerSC::rspQuery() |
{ |
if (0 == strcmp ("qAttached", pkt->data)) |
{ |
// We are always attaching to an existing process with the bare metal |
// embedded system. |
pkt->packStr ("1"); |
rsp->putPkt (pkt); |
} |
else if (0 == strcmp ("qC", pkt->data)) |
{ |
// Return the current thread ID (unsigned hex). A null response |
// indicates to use the previously selected thread. We use the constant |
// OR1KSIM_TID to represent our single thread of control. |
sprintf (pkt->data, "QC%x", OR1KSIM_TID); |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qCRC", pkt->data, strlen ("qCRC"))) |
{ |
// Return CRC of memory area |
cerr << "Warning: RSP CRC query not supported" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
} |
else if (0 == strcmp ("qfThreadInfo", pkt->data)) |
{ |
// Return info about active threads. We return just the constant |
// OR1KSIM_TID to represent our single thread of control. |
sprintf (pkt->data, "m%x", OR1KSIM_TID); |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} |
else if (0 == strcmp ("qsThreadInfo", pkt->data)) |
{ |
// Return info about more active threads. We have no more, so return the |
// end of list marker, 'l' |
pkt->packStr ("l"); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qGetTLSAddr:", pkt->data, strlen ("qGetTLSAddr:"))) |
{ |
// We don't support this feature |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qL", pkt->data, strlen ("qL"))) |
{ |
// Deprecated and replaced by 'qfThreadInfo' |
cerr << "Warning: RSP qL deprecated: no info returned" << endl; |
pkt->packStr ("qM001"); |
rsp->putPkt (pkt); |
} |
else if (0 == strcmp ("qOffsets", pkt->data)) |
{ |
// Report any relocation |
pkt->packStr ("Text=0;Data=0;Bss=0"); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qP", pkt->data, strlen ("qP"))) |
{ |
// Deprecated and replaced by 'qThreadExtraInfo' |
cerr << "Warning: RSP qP deprecated: no info returned" << endl; |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qRcmd,", pkt->data, strlen ("qRcmd,"))) |
{ |
// This is used to interface to commands to do "stuff" |
rspCommand (); |
} |
else if (0 == strncmp ("qSupported", pkt->data, strlen ("qSupported"))) |
{ |
// Report a list of the features we support. For now we just ignore any |
// supplied specific feature queries, but in the future these may be |
// supported as well. Note that the packet size allows for 'G' + all the |
// registers sent to us, or a reply to 'g' with all the registers and an |
// EOS so the buffer is a well formed string. |
sprintf (pkt->data, "PacketSize=%x", pkt->getBufSize()); |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qSymbol:", pkt->data, strlen ("qSymbol:"))) |
{ |
// Offer to look up symbols. Nothing we want (for now). TODO. This just |
// ignores any replies to symbols we looked up, but we didn't want to |
// do that anyway! |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qThreadExtraInfo,", pkt->data, |
strlen ("qThreadExtraInfo,"))) |
{ |
// Report that we are runnable, but the text must be hex ASCI |
// digits. For now do this by steam, reusing the original packet |
sprintf (pkt->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qTStatus", pkt->data, strlen ("qTstatus"))) |
{ |
// We don't support tracing, return empty packet |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("qXfer:", pkt->data, strlen ("qXfer:"))) |
{ |
// For now we support no 'qXfer' requests, but these should not be |
// expected, since they were not reported by 'qSupported' |
cerr << "Warning: RSP 'qXfer' not supported: ignored" << endl; |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else |
{ |
cerr << "Unrecognized RSP query: ignored" << endl; |
} |
} // rspQuery () |
if (0 == strcmp("qAttached", pkt->data)) { |
// We are always attaching to an existing process with the bare metal |
// embedded system. |
pkt->packStr("1"); |
rsp->putPkt(pkt); |
} else if (0 == strcmp("qC", pkt->data)) { |
// Return the current thread ID (unsigned hex). A null response |
// indicates to use the previously selected thread. We use the constant |
// OR1KSIM_TID to represent our single thread of control. |
sprintf(pkt->data, "QC%x", OR1KSIM_TID); |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qCRC", pkt->data, strlen("qCRC"))) { |
// Return CRC of memory area |
cerr << "Warning: RSP CRC query not supported" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
} else if (0 == strcmp("qfThreadInfo", pkt->data)) { |
// Return info about active threads. We return just the constant |
// OR1KSIM_TID to represent our single thread of control. |
sprintf(pkt->data, "m%x", OR1KSIM_TID); |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
} else if (0 == strcmp("qsThreadInfo", pkt->data)) { |
// Return info about more active threads. We have no more, so return the |
// end of list marker, 'l' |
pkt->packStr("l"); |
rsp->putPkt(pkt); |
} else if (0 == |
strncmp("qGetTLSAddr:", pkt->data, strlen("qGetTLSAddr:"))) { |
// We don't support this feature |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qL", pkt->data, strlen("qL"))) { |
// Deprecated and replaced by 'qfThreadInfo' |
cerr << "Warning: RSP qL deprecated: no info returned" << endl; |
pkt->packStr("qM001"); |
rsp->putPkt(pkt); |
} else if (0 == strcmp("qOffsets", pkt->data)) { |
// Report any relocation |
pkt->packStr("Text=0;Data=0;Bss=0"); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qP", pkt->data, strlen("qP"))) { |
// Deprecated and replaced by 'qThreadExtraInfo' |
cerr << "Warning: RSP qP deprecated: no info returned" << endl; |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qRcmd,", pkt->data, strlen("qRcmd,"))) { |
// This is used to interface to commands to do "stuff" |
rspCommand(); |
} else if (0 == strncmp("qSupported", pkt->data, strlen("qSupported"))) { |
// Report a list of the features we support. For now we just ignore any |
// supplied specific feature queries, but in the future these may be |
// supported as well. Note that the packet size allows for 'G' + all the |
// registers sent to us, or a reply to 'g' with all the registers and an |
// EOS so the buffer is a well formed string. |
sprintf(pkt->data, "PacketSize=%x", pkt->getBufSize()); |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qSymbol:", pkt->data, strlen("qSymbol:"))) { |
// Offer to look up symbols. Nothing we want (for now). TODO. This just |
// ignores any replies to symbols we looked up, but we didn't want to |
// do that anyway! |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qThreadExtraInfo,", pkt->data, |
strlen("qThreadExtraInfo,"))) { |
// Report that we are runnable, but the text must be hex ASCI |
// digits. For now do this by steam, reusing the original packet |
sprintf(pkt->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qTStatus", pkt->data, strlen("qTstatus"))) { |
// We don't support tracing, return empty packet |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("qXfer:", pkt->data, strlen("qXfer:"))) { |
// For now we support no 'qXfer' requests, but these should not be |
// expected, since they were not reported by 'qSupported' |
cerr << "Warning: RSP 'qXfer' not supported: ignored" << endl; |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else { |
cerr << "Unrecognized RSP query: ignored" << endl; |
} |
} // rspQuery () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP qRcmd request |
|
//! The actual command follows the "qRcmd," in ASCII encoded to hex |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspCommand () |
void GdbServerSC::rspCommand() |
{ |
char cmd[RSP_PKT_MAX]; |
char cmd[RSP_PKT_MAX]; |
|
Utils::hex2Ascii (cmd, &(pkt->data[strlen ("qRcmd,")])); |
Utils::hex2Ascii(cmd, &(pkt->data[strlen("qRcmd,")])); |
|
// Work out which command it is |
if (0 == strncmp ("readspr ", cmd, strlen ("readspr"))) |
{ |
unsigned int sprNum; |
// Work out which command it is |
if (0 == strncmp("readspr ", cmd, strlen("readspr"))) { |
unsigned int sprNum; |
|
// Parse and return error if we fail |
if( 1 != sscanf (cmd, "readspr %4x", &sprNum)) |
{ |
cerr << "Warning: qRcmd " << cmd |
<< "not recognized: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
// Parse and return error if we fail |
if (1 != sscanf(cmd, "readspr %4x", &sprNum)) { |
cerr << "Warning: qRcmd " << cmd |
<< "not recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// SPR out of range |
if (sprNum > MAX_SPRS) { |
cerr << "Warning: qRcmd readspr " << hex << sprNum |
<< dec << " too large: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Construct the reply |
sprintf(cmd, "%8lx", debugUnit->readSpr(sprNum)); |
Utils::ascii2Hex(pkt->data, cmd); |
pkt->setLen(strlen(pkt->data)); |
rsp->putPkt(pkt); |
} else if (0 == strncmp("writespr ", cmd, strlen("writespr"))) { |
unsigned int sprNum; |
uint32_t val; |
|
// SPR out of range |
if (sprNum > MAX_SPRS) |
{ |
cerr << "Warning: qRcmd readspr " << hex << sprNum |
<< dec << " too large: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
// Parse and return error if we fail |
if (2 != sscanf(cmd, "writespr %4x %8lx", &sprNum, &val)) { |
cerr << "Warning: qRcmd " << cmd << |
" not recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// SPR out of range |
if (sprNum > MAX_SPRS) { |
cerr << "Warning: qRcmd writespr " << hex << sprNum |
<< dec << " too large: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Update the SPR and reply "OK" |
debugUnit->writeSpr(sprNum, val); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
} |
|
// Construct the reply |
sprintf (cmd, "%8lx", debugUnit->readSpr (sprNum)); |
Utils::ascii2Hex (pkt->data, cmd); |
pkt->setLen (strlen (pkt->data)); |
rsp->putPkt (pkt); |
} |
else if (0 == strncmp ("writespr ", cmd, strlen ("writespr"))) |
{ |
unsigned int sprNum; |
uint32_t val; |
} // rspCommand () |
|
// Parse and return error if we fail |
if( 2 != sscanf (cmd, "writespr %4x %8lx", &sprNum, &val)) |
{ |
cerr << "Warning: qRcmd " << cmd << " not recognized: ignored" |
<< endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
|
// SPR out of range |
if (sprNum > MAX_SPRS) |
{ |
cerr << "Warning: qRcmd writespr " << hex << sprNum |
<< dec << " too large: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
|
// Update the SPR and reply "OK" |
debugUnit->writeSpr (sprNum, val); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
} |
|
} // rspCommand () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP set request |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspSet () |
void GdbServerSC::rspSet() |
{ |
if (0 == strncmp ("QPassSignals:", pkt->data, strlen ("QPassSignals:"))) |
{ |
// Passing signals not supported |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else if ((0 == strncmp ("QTDP", pkt->data, strlen ("QTDP"))) || |
(0 == strncmp ("QFrame", pkt->data, strlen ("QFrame"))) || |
(0 == strcmp ("QTStart", pkt->data)) || |
(0 == strcmp ("QTStop", pkt->data)) || |
(0 == strcmp ("QTinit", pkt->data)) || |
(0 == strncmp ("QTro", pkt->data, strlen ("QTro")))) |
{ |
// All tracepoint features are not supported. This reply is really only |
// needed to 'QTDP', since with that the others should not be |
// generated. |
pkt->packStr (""); |
rsp->putPkt (pkt); |
} |
else |
{ |
cerr << "Unrecognized RSP set request: ignored" << endl; |
delete pkt; |
} |
} // rspSet () |
if (0 == strncmp("QPassSignals:", pkt->data, strlen("QPassSignals:"))) { |
// Passing signals not supported |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else if ((0 == strncmp("QTDP", pkt->data, strlen("QTDP"))) || |
(0 == strncmp("QFrame", pkt->data, strlen("QFrame"))) || |
(0 == strcmp("QTStart", pkt->data)) || |
(0 == strcmp("QTStop", pkt->data)) || |
(0 == strcmp("QTinit", pkt->data)) || |
(0 == strncmp("QTro", pkt->data, strlen("QTro")))) { |
// All tracepoint features are not supported. This reply is really only |
// needed to 'QTDP', since with that the others should not be |
// generated. |
pkt->packStr(""); |
rsp->putPkt(pkt); |
} else { |
cerr << "Unrecognized RSP set request: ignored" << endl; |
delete pkt; |
} |
} // rspSet () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP restart request |
|
1199,14 → 1095,12
//! there. There is no point in unstalling the processor, since we'll never |
//! get control back. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspRestart () |
void GdbServerSC::rspRestart() |
{ |
writeNpc (EXCEPT_RESET); |
writeNpc(EXCEPT_RESET); |
|
} // rspRestart () |
} // rspRestart () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP step request |
|
1216,34 → 1110,28
//! @param[in] except The exception to use. Only EXCEPT_NONE should be set |
//! this way. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspStep (uint32_t except) |
void GdbServerSC::rspStep(uint32_t except) |
{ |
uint32_t addr; // The address to step from, if any |
|
// Reject all except 's' packets |
if ('s' != pkt->data[0]) |
{ |
cerr << "Warning: Step with signal not currently supported: " |
<< "ignored" << endl; |
return; |
} |
uint32_t addr; // The address to step from, if any |
|
if (0 == strcmp ("s", pkt->data)) |
{ |
addr = readNpc (); // Default uses current NPC |
} |
else if (1 != sscanf (pkt->data, "s%lx", &addr)) |
{ |
cerr << "Warning: RSP step address " << pkt->data |
<< " not recognized: ignored" << endl; |
addr = readNpc (); // Default uses current NPC |
} |
// Reject all except 's' packets |
if ('s' != pkt->data[0]) { |
cerr << "Warning: Step with signal not currently supported: " |
<< "ignored" << endl; |
return; |
} |
|
rspStep (addr, EXCEPT_NONE); |
if (0 == strcmp("s", pkt->data)) { |
addr = readNpc(); // Default uses current NPC |
} else if (1 != sscanf(pkt->data, "s%lx", &addr)) { |
cerr << "Warning: RSP step address " << pkt->data |
<< " not recognized: ignored" << endl; |
addr = readNpc(); // Default uses current NPC |
} |
|
} // rspStep () |
rspStep(addr, EXCEPT_NONE); |
|
} // rspStep () |
|
//----------------------------------------------------------------------------- |
//! Handle a RSP step with signal request |
1250,14 → 1138,12
|
//! @todo Currently null. Will use the underlying generic step function. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspStep () |
void GdbServerSC::rspStep() |
{ |
cerr << "RSP step with signal '" << pkt->data << "' received" << endl; |
cerr << "RSP step with signal '" << pkt->data << "' received" << endl; |
|
} // rspStep () |
} // rspStep () |
|
|
//----------------------------------------------------------------------------- |
//! Generic processing of a step request |
|
1275,56 → 1161,53
//! @param[in] addr Address from which to step |
//! @param[in] except The exception to use (if any) |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspStep (uint32_t addr, |
uint32_t except) |
void GdbServerSC::rspStep(uint32_t addr, uint32_t except) |
{ |
// Set the address as the value of the next program counter |
writeNpc (addr); |
|
/* |
// If we're continuing from a breakpoint, replace that instruction in the memory |
// ... actually no, I was wrong about this. |
if (NULL != mpHash->lookup (BP_MEMORY, addr) && rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
MpEntry *entry = mpHash->lookup (BP_MEMORY, addr); |
debugUnit->writeMem32(entry->addr, entry->instr); |
} |
*/ |
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode |
// Register 2 for watchpoints that we triggered to stop this time. |
debugUnit->writeSpr (SPR_DRR, 0); |
if (rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
/* |
Disable last trap generation on watchpoint if this is why we stopped |
last time. |
*/ |
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2); |
if (temp_dmr2 & SPR_DMR2_WBS) |
{ |
/* |
One of these breakpoints is responsible for our stopping, so |
disable it this time we start. GDB will send a packet re-enabling |
it next time we continue. |
*/ |
debugUnit->writeSpr (SPR_DMR2, temp_dmr2 & ~((temp_dmr2&SPR_DMR2_WBS)>>10)); |
} |
} |
// Set the address as the value of the next program counter |
writeNpc(addr); |
|
// Set the single step trigger in Debug Mode Register 1 and set traps to be |
// handled by the debug unit in the Debug Stop Register |
debugUnit->orSpr (SPR_DMR1, SPR_DMR1_ST); |
debugUnit->orSpr (SPR_DSR, SPR_DSR_TE); |
/* |
// If we're continuing from a breakpoint, replace that instruction in the memory |
// ... actually no, I was wrong about this. |
if (NULL != mpHash->lookup (BP_MEMORY, addr) && rsp_sigval == TARGET_SIGNAL_TRAP) |
{ |
MpEntry *entry = mpHash->lookup (BP_MEMORY, addr); |
debugUnit->writeMem32(entry->addr, entry->instr); |
} |
*/ |
|
// Unstall the processor. Note the GDB client is now waiting for a reply, |
// which it will get as soon as the processor stalls again. |
debugUnit->unstall (); |
targetStopped = false; |
// Clear Debug Reason Register and watchpoint break generation in Debug Mode |
// Register 2 for watchpoints that we triggered to stop this time. |
debugUnit->writeSpr(SPR_DRR, 0); |
if (rsp_sigval == TARGET_SIGNAL_TRAP) { |
/* |
Disable last trap generation on watchpoint if this is why we stopped |
last time. |
*/ |
uint32_t temp_dmr2 = debugUnit->readSpr(SPR_DMR2); |
if (temp_dmr2 & SPR_DMR2_WBS) { |
/* |
One of these breakpoints is responsible for our stopping, so |
disable it this time we start. GDB will send a packet re-enabling |
it next time we continue. |
*/ |
debugUnit->writeSpr(SPR_DMR2, |
temp_dmr2 & |
~((temp_dmr2 & SPR_DMR2_WBS) >> |
10)); |
} |
} |
// Set the single step trigger in Debug Mode Register 1 and set traps to be |
// handled by the debug unit in the Debug Stop Register |
debugUnit->orSpr(SPR_DMR1, SPR_DMR1_ST); |
debugUnit->orSpr(SPR_DSR, SPR_DSR_TE); |
|
} // rspStep () |
// Unstall the processor. Note the GDB client is now waiting for a reply, |
// which it will get as soon as the processor stalls again. |
debugUnit->unstall(); |
targetStopped = false; |
|
} // rspStep () |
|
//----------------------------------------------------------------------------- |
//! Handle a RSP 'v' packet |
1331,89 → 1214,73
|
//! These are commands associated with executing the code on the target |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspVpkt () |
void GdbServerSC::rspVpkt() |
{ |
if (0 == strncmp ("vAttach;", pkt->data, strlen ("vAttach;"))) |
{ |
// Attaching is a null action, since we have no other process. We just |
// return a stop packet (using TRAP) to indicate we are stopped. |
pkt->packStr ("S05"); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strcmp ("vCont?", pkt->data)) |
{ |
// For now we don't support this. |
pkt->packStr (""); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strncmp ("vCont", pkt->data, strlen ("vCont"))) |
{ |
// This shouldn't happen, because we've reported non-support via vCont? |
// above |
cerr << "Warning: RSP vCont not supported: ignored" << endl; |
return; |
} |
else if (0 == strncmp ("vFile:", pkt->data, strlen ("vFile:"))) |
{ |
// For now we don't support this. |
cerr << "Warning: RSP vFile not supported: ignored" << endl; |
pkt->packStr (""); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strncmp ("vFlashErase:", pkt->data, strlen ("vFlashErase:"))) |
{ |
// For now we don't support this. |
cerr << "Warning: RSP vFlashErase not supported: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strncmp ("vFlashWrite:", pkt->data, strlen ("vFlashWrite:"))) |
{ |
// For now we don't support this. |
cerr << "Warning: RSP vFlashWrite not supported: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strcmp ("vFlashDone", pkt->data)) |
{ |
// For now we don't support this. |
cerr << "Warning: RSP vFlashDone not supported: ignored" << endl;; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
else if (0 == strncmp ("vRun;", pkt->data, strlen ("vRun;"))) |
{ |
// We shouldn't be given any args, but check for this |
if (pkt->getLen () > strlen ("vRun;")) |
{ |
cerr << "Warning: Unexpected arguments to RSP vRun " |
"command: ignored" << endl; |
if (0 == strncmp("vAttach;", pkt->data, strlen("vAttach;"))) { |
// Attaching is a null action, since we have no other process. We just |
// return a stop packet (using TRAP) to indicate we are stopped. |
pkt->packStr("S05"); |
rsp->putPkt(pkt); |
return; |
} else if (0 == strcmp("vCont?", pkt->data)) { |
// For now we don't support this. |
pkt->packStr(""); |
rsp->putPkt(pkt); |
return; |
} else if (0 == strncmp("vCont", pkt->data, strlen("vCont"))) { |
// This shouldn't happen, because we've reported non-support via vCont? |
// above |
cerr << "Warning: RSP vCont not supported: ignored" << endl; |
return; |
} else if (0 == strncmp("vFile:", pkt->data, strlen("vFile:"))) { |
// For now we don't support this. |
cerr << "Warning: RSP vFile not supported: ignored" << endl; |
pkt->packStr(""); |
rsp->putPkt(pkt); |
return; |
} else if (0 == |
strncmp("vFlashErase:", pkt->data, strlen("vFlashErase:"))) { |
// For now we don't support this. |
cerr << "Warning: RSP vFlashErase not supported: ignored" << |
endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} else if (0 == |
strncmp("vFlashWrite:", pkt->data, strlen("vFlashWrite:"))) { |
// For now we don't support this. |
cerr << "Warning: RSP vFlashWrite not supported: ignored" << |
endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} else if (0 == strcmp("vFlashDone", pkt->data)) { |
// For now we don't support this. |
cerr << "Warning: RSP vFlashDone not supported: ignored" << |
endl;; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} else if (0 == strncmp("vRun;", pkt->data, strlen("vRun;"))) { |
// We shouldn't be given any args, but check for this |
if (pkt->getLen() > strlen("vRun;")) { |
cerr << "Warning: Unexpected arguments to RSP vRun " |
"command: ignored" << endl; |
} |
// Restart the current program. However unlike a "R" packet, "vRun" |
// should behave as though it has just stopped. We use signal 5 (TRAP). |
rspRestart(); |
pkt->packStr("S05"); |
rsp->putPkt(pkt); |
} else { |
cerr << "Warning: Unknown RSP 'v' packet type " << pkt->data |
<< ": ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} // rspVpkt () |
|
// Restart the current program. However unlike a "R" packet, "vRun" |
// should behave as though it has just stopped. We use signal 5 (TRAP). |
rspRestart (); |
pkt->packStr ("S05"); |
rsp->putPkt (pkt); |
} |
else |
{ |
cerr << "Warning: Unknown RSP 'v' packet type " << pkt->data |
<< ": ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
} // rspVpkt () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP write memory (binary) request |
|
1429,87 → 1296,76
|
//! The data is in model-endian format, so no transformation is needed. |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspWriteMemBin () |
void GdbServerSC::rspWriteMemBin() |
{ |
uint32_t addr; // Where to write the memory |
int len; // Number of bytes to write |
uint32_t addr; // Where to write the memory |
int len; // Number of bytes to write |
|
if (2 != sscanf (pkt->data, "X%x,%x:", &addr, &len)) |
{ |
cerr << "Warning: Failed to recognize RSP write memory command: %s" |
<< pkt->data << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
if (2 != sscanf(pkt->data, "X%x,%x:", &addr, &len)) { |
cerr << |
"Warning: Failed to recognize RSP write memory command: %s" |
<< pkt->data << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Find the start of the data and "unescape" it. Bindat must be unsigned, or |
// all sorts of horrible sign extensions will happen when val is computed |
// below! |
uint8_t *bindat = (uint8_t *) (memchr(pkt->data, ':', |
pkt->getBufSize())) + 1; |
int off = (char *)bindat - pkt->data; |
int newLen = Utils::rspUnescape((char *)bindat, pkt->getLen() - off); |
|
// Find the start of the data and "unescape" it. Bindat must be unsigned, or |
// all sorts of horrible sign extensions will happen when val is computed |
// below! |
uint8_t *bindat = (uint8_t *)(memchr (pkt->data, ':', |
pkt->getBufSize ())) + 1; |
int off = (char *)bindat - pkt->data; |
int newLen = Utils::rspUnescape ((char *)bindat, pkt->getLen () - off); |
// Sanity check |
if (newLen != len) { |
int minLen = len < newLen ? len : newLen; |
|
// Sanity check |
if (newLen != len) |
{ |
int minLen = len < newLen ? len : newLen; |
cerr << "Warning: Write of " << len << " bytes requested, but " |
<< newLen << " bytes supplied. " << minLen << |
" will be written" << endl; |
len = minLen; |
} |
// Write the bytes to memory. More efficent to do this in 32-bit chunks |
int startBytes = addr & 0x3; |
int endBytes = (addr + len) & 0x3; |
|
cerr << "Warning: Write of " << len << " bytes requested, but " |
<< newLen << " bytes supplied. " << minLen << " will be written" |
<< endl; |
len = minLen; |
} |
|
// Write the bytes to memory. More efficent to do this in 32-bit chunks |
int startBytes = addr & 0x3; |
int endBytes = (addr + len) & 0x3; |
|
// First partial word. Access bindat in an endian independent fashion. |
for (off = 0 ; off < startBytes ; off++) |
{ |
if (!debugUnit->writeMem8 (addr + off, bindat[off])) |
{ |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
// First partial word. Access bindat in an endian independent fashion. |
for (off = 0; off < startBytes; off++) { |
if (!debugUnit->writeMem8(addr + off, bindat[off])) { |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} |
} |
|
// The bulk as words. Convert to model endian before writing. |
for (off = startBytes; off < len; off += 4) |
{ |
uint32_t val = *((uint32_t *)(&(bindat[off]))); |
// The bulk as words. Convert to model endian before writing. |
for (off = startBytes; off < len; off += 4) { |
uint32_t val = *((uint32_t *) (&(bindat[off]))); |
|
if (!debugUnit->writeMem32 (addr + off, Utils::htotl (val))) |
{ |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
if (!debugUnit->writeMem32(addr + off, Utils::htotl(val))) { |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} |
} |
|
// Last partial word. Access bindat in an endian independent fashion. |
for (off = len - endBytes; off < len ; off++) |
{ |
uint32_t base = (addr + len) & 0xfffffffc; |
// Last partial word. Access bindat in an endian independent fashion. |
for (off = len - endBytes; off < len; off++) { |
uint32_t base = (addr + len) & 0xfffffffc; |
|
if (!debugUnit->writeMem8 (base + off, bindat[off])) |
{ |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
if (!debugUnit->writeMem8(base + off, bindat[off])) { |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} |
} |
|
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
|
} // rspWriteMemBin () |
} // rspWriteMemBin () |
|
|
//----------------------------------------------------------------------------- |
//! Handle a RSP remove breakpoint or matchpoint request |
|
1519,155 → 1375,156
|
//! @todo This doesn't work with icache/immu yet |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::rspRemoveMatchpoint () |
void GdbServerSC::rspRemoveMatchpoint() |
{ |
MpType type; // What sort of matchpoint |
uint32_t addr; // Address specified |
uint32_t instr; // Instruction value found |
int len; // Matchpoint length (not used) |
MpType type; // What sort of matchpoint |
uint32_t addr; // Address specified |
uint32_t instr; // Instruction value found |
int len; // Matchpoint length (not used) |
|
// Break out the instruction |
if (3 != sscanf (pkt->data, "z%1d,%lx,%1d", (int *)&type, &addr, &len)) |
{ |
cerr << "Warning: RSP matchpoint deletion request not " |
<< "recognized: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
|
// Sanity check that the length is 4 |
if (4 != len) |
{ |
cerr << "Warning: RSP matchpoint deletion length " << len |
<< "not valid: 4 assumed" << endl; |
len = 4; |
} |
|
// Sort out the type of matchpoint |
switch (type) |
{ |
case BP_MEMORY: |
// Memory breakpoint - replace the original instruction. |
if (mpHash->remove (type, addr, &instr)) |
{ |
//cerr << "rspRemoveMatchpoint at 0x" << hex << addr << " restoring instruction: 0x" << hex << instr <<endl; |
debugUnit->writeMem32 (addr, instr); |
// Break out the instruction |
if (3 != sscanf(pkt->data, "z%1d,%lx,%1d", (int *)&type, &addr, &len)) { |
cerr << "Warning: RSP matchpoint deletion request not " |
<< "recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
|
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
|
case BP_HARDWARE: |
int off; |
for (off=0;off<8;off++) |
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x23)) && |
(debugUnit->readSpr (SPR_DVR0+off) == addr)) |
break; |
if (off > 7) |
{ |
pkt->packStr ("E02"); // Failed ot find breakpoint |
rsp->putPkt (pkt); |
return; |
// Sanity check that the length is 4 |
if (4 != len) { |
cerr << "Warning: RSP matchpoint deletion length " << len |
<< "not valid: 4 assumed" << endl; |
len = 4; |
} |
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0); |
debugUnit->writeSpr (SPR_DVR0+off,0); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
// Sort out the type of matchpoint |
switch (type) { |
case BP_MEMORY: |
// Memory breakpoint - replace the original instruction. |
if (mpHash->remove(type, addr, &instr)) { |
//cerr << "rspRemoveMatchpoint at 0x" << hex << addr << " restoring instruction: 0x" << hex << instr <<endl; |
debugUnit->writeMem32(addr, instr); |
} |
|
case WP_WRITE: |
{ |
int off; |
for (off=0;off<8;off++) |
{ |
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x63)) && |
(debugUnit->readSpr (SPR_DVR0+off) == addr)) |
break; |
} |
if (off > 7) |
{ |
pkt->packStr ("E02"); // Failed ot find breakpoint |
rsp->putPkt (pkt); |
return; |
} |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0); |
debugUnit->writeSpr (SPR_DVR0+off,0); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
|
case WP_READ: |
{ |
int off; |
for (off=0;off<8;off++) |
{ |
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x43)) && |
(debugUnit->readSpr (SPR_DVR0+off) == addr)) |
break; |
} |
if (off > 7) |
{ |
pkt->packStr ("E02"); // Failed ot find breakpoint |
rsp->putPkt (pkt); |
return; |
} |
case BP_HARDWARE: |
int off; |
for (off = 0; off < 8; off++) |
if ((debugUnit->readSpr(SPR_DCR0 + off) == (0x23)) && |
(debugUnit->readSpr(SPR_DVR0 + off) == addr)) |
break; |
if (off > 7) { |
pkt->packStr("E02"); // Failed ot find breakpoint |
rsp->putPkt(pkt); |
return; |
} |
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0); |
debugUnit->writeSpr(SPR_DVR0 + off, 0); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) & ~((1 << off) |
<< |
SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0); |
debugUnit->writeSpr (SPR_DVR0+off,0); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
|
case WP_ACCESS: |
{ |
int off; |
for (off=0;off<8;off++) |
{ |
//printf("WP_ACCESS remove check off=%d DCR=0x%.8x DVR=0x%.8x\n", |
//off,debugUnit->readSpr (SPR_DCR0+off),debugUnit->readSpr (SPR_DVR0+off)); |
if ((debugUnit->readSpr (SPR_DCR0+off) == (0xc3)) && |
(debugUnit->readSpr (SPR_DVR0+off) == addr)) |
break; |
} |
if (off > 7) |
{ |
//printf("rspRemoveWatchpoint: WP_ACCESS remove ERROR, regpair %d for 0x%.8x\n",off, addr); |
pkt->packStr ("E02"); // Failed ot find breakpoint |
rsp->putPkt (pkt); |
return; |
} |
//printf("rspRemoveWatchpoint: WP_ACCESS remove, regpair %d for 0x%.8x\n",off, addr); |
case WP_WRITE: |
{ |
int off; |
for (off = 0; off < 8; off++) { |
if ((debugUnit->readSpr(SPR_DCR0 + off) == |
(0x63)) |
&& (debugUnit->readSpr(SPR_DVR0 + off) == |
addr)) |
break; |
} |
if (off > 7) { |
pkt->packStr("E02"); // Failed ot find breakpoint |
rsp->putPkt(pkt); |
return; |
} |
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0); |
debugUnit->writeSpr(SPR_DVR0 + off, 0); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) & |
~((1 << off) << |
SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0); |
debugUnit->writeSpr (SPR_DVR0+off,0); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
default: |
cerr << "Warning: RSP matchpoint type " << type |
<< " not recognized: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
} // rspRemoveMatchpoint () |
case WP_READ: |
{ |
int off; |
for (off = 0; off < 8; off++) { |
if ((debugUnit->readSpr(SPR_DCR0 + off) == |
(0x43)) |
&& (debugUnit->readSpr(SPR_DVR0 + off) == |
addr)) |
break; |
} |
if (off > 7) { |
pkt->packStr("E02"); // Failed ot find breakpoint |
rsp->putPkt(pkt); |
return; |
} |
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0); |
debugUnit->writeSpr(SPR_DVR0 + off, 0); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) & |
~((1 << off) << |
SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
|
case WP_ACCESS: |
{ |
int off; |
for (off = 0; off < 8; off++) { |
//printf("WP_ACCESS remove check off=%d DCR=0x%.8x DVR=0x%.8x\n", |
//off,debugUnit->readSpr (SPR_DCR0+off),debugUnit->readSpr (SPR_DVR0+off)); |
if ((debugUnit->readSpr(SPR_DCR0 + off) == |
(0xc3)) |
&& (debugUnit->readSpr(SPR_DVR0 + off) == |
addr)) |
break; |
} |
if (off > 7) { |
//printf("rspRemoveWatchpoint: WP_ACCESS remove ERROR, regpair %d for 0x%.8x\n",off, addr); |
pkt->packStr("E02"); // Failed ot find breakpoint |
rsp->putPkt(pkt); |
return; |
} |
//printf("rspRemoveWatchpoint: WP_ACCESS remove, regpair %d for 0x%.8x\n",off, addr); |
|
// Clear DCR's CT and DVR, WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0); |
debugUnit->writeSpr(SPR_DVR0 + off, 0); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) & |
~((1 << off) << |
SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
default: |
cerr << "Warning: RSP matchpoint type " << type |
<< " not recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} // rspRemoveMatchpoint () |
|
//---------------------------------------------------------------------------*/ |
//! Handle a RSP insert breakpoint or matchpoint request |
|
1677,143 → 1534,148
|
//! @todo This doesn't work with icache/immu yet |
//---------------------------------------------------------------------------*/ |
void |
GdbServerSC::rspInsertMatchpoint () |
void GdbServerSC::rspInsertMatchpoint() |
{ |
MpType type; // What sort of matchpoint |
uint32_t addr; // Address specified |
int len; // Matchpoint length (not used) |
|
// Break out the instruction |
if (3 != sscanf (pkt->data, "Z%1d,%lx,%1d", (int *)&type, &addr, &len)) |
{ |
cerr << "Warning: RSP matchpoint insertion request not " |
<< "recognized: ignored" << endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
MpType type; // What sort of matchpoint |
uint32_t addr; // Address specified |
int len; // Matchpoint length (not used) |
|
// Sanity check that the length is 4 |
if (4 != len) |
{ |
cerr << "Warning: RSP matchpoint insertion length " << len |
<< "not valid: 4 assumed" << endl; |
len = 4; |
} |
// Break out the instruction |
if (3 != sscanf(pkt->data, "Z%1d,%lx,%1d", (int *)&type, &addr, &len)) { |
cerr << "Warning: RSP matchpoint insertion request not " |
<< "recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
// Sanity check that the length is 4 |
if (4 != len) { |
cerr << "Warning: RSP matchpoint insertion length " << len |
<< "not valid: 4 assumed" << endl; |
len = 4; |
} |
// Sort out the type of matchpoint |
switch (type) { |
case BP_MEMORY: |
// Memory breakpoint - substitute a TRAP instruction |
mpHash->add(type, addr, debugUnit->readMem32(addr)); |
debugUnit->writeMem32(addr, OR1K_TRAP_INSTR); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
|
// Sort out the type of matchpoint |
switch (type) |
{ |
case BP_MEMORY: |
// Memory breakpoint - substitute a TRAP instruction |
mpHash->add (type, addr, debugUnit->readMem32 (addr)); |
debugUnit->writeMem32 (addr, OR1K_TRAP_INSTR); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
|
case BP_HARDWARE: |
{ |
int off; |
for (off=0;off<8;off++) |
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK)) |
break; |
if (off > 7) |
{ |
pkt->packStr (""); // No room |
rsp->putPkt (pkt); |
return; |
} |
// CC = equal, CT = Instruction fetch EA, set WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0x22); |
debugUnit->writeSpr (SPR_DVR0+off,addr); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
case BP_HARDWARE: |
{ |
int off; |
for (off = 0; off < 8; off++) |
if (! |
(debugUnit->readSpr(SPR_DCR0 + off) & |
SPR_DCR_CT_MASK)) |
break; |
if (off > 7) { |
pkt->packStr(""); // No room |
rsp->putPkt(pkt); |
return; |
} |
// CC = equal, CT = Instruction fetch EA, set WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0x22); |
debugUnit->writeSpr(SPR_DVR0 + off, addr); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) | |
((1 << off) << SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
case WP_WRITE: |
{ |
int off; |
for (off=0;off<8;off++) |
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) |
{ |
pkt->packStr (""); // No room |
rsp->putPkt (pkt); |
return; |
} |
// CC = equal, CT = Store EA, set WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0x62); |
debugUnit->writeSpr (SPR_DVR0+off,addr); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
case WP_WRITE: |
{ |
int off; |
for (off = 0; off < 8; off++) |
if (! |
(debugUnit->readSpr(SPR_DCR0 + off) & |
SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) { |
pkt->packStr(""); // No room |
rsp->putPkt(pkt); |
return; |
} |
// CC = equal, CT = Store EA, set WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0x62); |
debugUnit->writeSpr(SPR_DVR0 + off, addr); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) | |
((1 << off) << SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
case WP_READ: |
{ |
int off; |
for (off=0;off<8;off++) |
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) |
{ |
pkt->packStr (""); // No room |
rsp->putPkt (pkt); |
return; |
} |
// CC = equal, CT = Load EA, set WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0x42); |
debugUnit->writeSpr (SPR_DVR0+off,addr); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
case WP_READ: |
{ |
int off; |
for (off = 0; off < 8; off++) |
if (! |
(debugUnit->readSpr(SPR_DCR0 + off) & |
SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) { |
pkt->packStr(""); // No room |
rsp->putPkt(pkt); |
return; |
} |
// CC = equal, CT = Load EA, set WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0x42); |
debugUnit->writeSpr(SPR_DVR0 + off, addr); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) | |
((1 << off) << SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
pkt->packStr (""); // Not supported |
rsp->putPkt (pkt); |
return; |
pkt->packStr(""); // Not supported |
rsp->putPkt(pkt); |
return; |
|
case WP_ACCESS: |
{ |
int off; |
for (off=0;off<8;off++) |
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_ACCESS, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) |
{ |
pkt->packStr (""); // No room |
rsp->putPkt (pkt); |
return; |
} |
// CC = equal, CT = Load/Store EA, set WGB bit |
debugUnit->writeSpr (SPR_DCR0+off,0xc2); |
debugUnit->writeSpr (SPR_DVR0+off,addr); |
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT)); |
pkt->packStr ("OK"); |
rsp->putPkt (pkt); |
return; |
} |
case WP_ACCESS: |
{ |
int off; |
for (off = 0; off < 8; off++) |
if (! |
(debugUnit->readSpr(SPR_DCR0 + off) & |
SPR_DCR_CT_MASK)) |
break; |
//printf("rspInsertWatchpoint: WP_ACCESS, regpair %d for 0x%.8x\n",off, addr); |
if (off > 7) { |
pkt->packStr(""); // No room |
rsp->putPkt(pkt); |
return; |
} |
// CC = equal, CT = Load/Store EA, set WGB bit |
debugUnit->writeSpr(SPR_DCR0 + off, 0xc2); |
debugUnit->writeSpr(SPR_DVR0 + off, addr); |
debugUnit->writeSpr(SPR_DMR2, |
debugUnit->readSpr(SPR_DMR2) | |
((1 << off) << SPR_DMR2_WGB_SHIFT)); |
pkt->packStr("OK"); |
rsp->putPkt(pkt); |
return; |
} |
|
default: |
cerr << "Warning: RSP matchpoint type " << type |
<< "not recognized: ignored"<< endl; |
pkt->packStr ("E01"); |
rsp->putPkt (pkt); |
return; |
} |
} // rspInsertMatchpoint () |
default: |
cerr << "Warning: RSP matchpoint type " << type |
<< "not recognized: ignored" << endl; |
pkt->packStr("E01"); |
rsp->putPkt(pkt); |
return; |
} |
} // rspInsertMatchpoint () |
|
|
//----------------------------------------------------------------------------- |
//! Read the value of the Next Program Counter (a SPR) |
|
1830,14 → 1692,12
|
//! @return The value of the NPC |
//----------------------------------------------------------------------------- |
uint32_t |
GdbServerSC::readNpc () |
uint32_t GdbServerSC::readNpc() |
{ |
return debugUnit->readSpr (SPR_NPC); |
return debugUnit->readSpr(SPR_NPC); |
|
} // readNpc () |
} // readNpc () |
|
|
//----------------------------------------------------------------------------- |
//! Write the value of the Next Program Counter (a SPR) |
|
1858,16 → 1718,13
|
//! @param[in] The address to write into the NPC |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::writeNpc (uint32_t addr) |
void GdbServerSC::writeNpc(uint32_t addr) |
{ |
if (addr != readNpc()) |
{ |
debugUnit->writeSpr (SPR_NPC, addr); |
} |
} // writeNpc () |
if (addr != readNpc()) { |
debugUnit->writeSpr(SPR_NPC, addr); |
} |
} // writeNpc () |
|
|
//----------------------------------------------------------------------------- |
//! Read the value of an OpenRISC 1000 General Purpose Register |
|
1878,14 → 1735,12
|
//! @return The value of the GPR |
//----------------------------------------------------------------------------- |
uint32_t |
GdbServerSC::readGpr (int regNum) |
uint32_t GdbServerSC::readGpr(int regNum) |
{ |
return debugUnit->readSpr (SPR_GPR0 + regNum); |
return debugUnit->readSpr(SPR_GPR0 + regNum); |
|
} // readGpr () |
} // readGpr () |
|
|
//----------------------------------------------------------------------------- |
//! Write the value of an OpenRISC 1000 General Purpose Register |
|
1896,13 → 1751,11
|
//! @return The value of the GPR |
//----------------------------------------------------------------------------- |
void |
GdbServerSC::writeGpr (int regNum, |
uint32_t value) |
void GdbServerSC::writeGpr(int regNum, uint32_t value) |
{ |
debugUnit->writeSpr (SPR_GPR0 + regNum, value); |
debugUnit->writeSpr(SPR_GPR0 + regNum, value); |
|
} // writeGpr () |
} // writeGpr () |
|
//----------------------------------------------------------------------------- |
//! Check if we received anything via the pipe from the or1200 monitor |
1914,22 → 1767,20
|
//! @return false if nothing received, else true |
//----------------------------------------------------------------------------- |
bool |
GdbServerSC::checkMonitorPipe () |
bool GdbServerSC::checkMonitorPipe() |
{ |
char readChar; |
int n = read(monitor_to_gdb_pipe[0][0], &readChar, sizeof(char)); |
if (!( ((n < 0) && (errno == EAGAIN)) || (n==0) ) && !targetStopped) |
{ |
debugUnit->stall (); |
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE |
rsp_sigval = TARGET_SIGNAL_NONE; |
rspReportException(); |
targetStopped = true; // Processor now not running |
write(monitor_to_gdb_pipe[1][1],&readChar,sizeof(char)); |
return true; |
} |
|
return false; |
|
} // checkMonitorPipe () |
char readChar; |
int n = read(monitor_to_gdb_pipe[0][0], &readChar, sizeof(char)); |
if (!(((n < 0) && (errno == EAGAIN)) || (n == 0)) && !targetStopped) { |
debugUnit->stall(); |
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE |
rsp_sigval = TARGET_SIGNAL_NONE; |
rspReportException(); |
targetStopped = true; // Processor now not running |
write(monitor_to_gdb_pipe[1][1], &readChar, sizeof(char)); |
return true; |
} |
|
return false; |
|
} // checkMonitorPipe () |
/sysc/src/TapStateMachine.cpp
39,14 → 39,12
//! the hardware until it has been through a TAP reset sequence. This is |
//! reflected in the ::tapResetDone flag. |
|
TapStateMachine::TapStateMachine () : |
state (TAP_TEST_LOGIC_RESET), |
resetDone (false) |
TapStateMachine::TapStateMachine(): |
state(TAP_TEST_LOGIC_RESET), resetDone(false) |
{ |
|
} // TapStateMachine () |
} // TapStateMachine () |
|
|
//! Accessor to get the current TAP state |
|
//! Only guaranteed to match the target hardware if it has been through a |
53,14 → 51,12
//! reset sequence. |
|
//! @return The current TAP state |
TapState |
TapStateMachine::getState () |
TapState TapStateMachine::getState() |
{ |
return state; |
return state; |
|
} // getState () |
} // getState () |
|
|
//! Accessor to get the current TAP reset state. |
|
//! It is the responsibility of classes using this class to correctly set this |
67,14 → 63,12
//! state. |
|
//! @return The current TAP reset state |
bool |
TapStateMachine::getResetDone () |
bool TapStateMachine::getResetDone() |
{ |
return resetDone; |
return resetDone; |
|
} // getResetDone () |
} // getResetDone () |
|
|
//! Accessor to set the current TAP reset state. |
|
//! It is the responsibility of classes using this class to correctly set this |
81,61 → 75,59
//! state. |
|
//! @param[in] The desired TAP reset state |
void |
TapStateMachine::setResetDone (bool _resetDone) |
void TapStateMachine::setResetDone(bool _resetDone) |
{ |
resetDone = _resetDone; |
resetDone = _resetDone; |
|
} // setResetDone () |
} // setResetDone () |
|
|
//! Drive the TAP state machine |
|
//! @param tms The JTAG TMS pin |
void |
TapStateMachine::nextState (bool tms) |
void TapStateMachine::nextState(bool tms) |
{ |
static const TapState mapHigh[TAP_SIZE] = { // When TMS = 1/true |
TAP_TEST_LOGIC_RESET, // from TAP_TEST_LOGIC_RESET |
TAP_SELECT_DR_SCAN, // from TAP_RUN_TEST_IDLE |
TAP_SELECT_IR_SCAN, // from TAP_SELECT_DR_SCAN |
TAP_EXIT1_DR, // from TAP_CAPTURE_DR |
TAP_EXIT1_DR, // from TAP_SHIFT_DR |
TAP_UPDATE_DR, // from TAP_EXIT1_DR |
TAP_EXIT2_DR, // from TAP_PAUSE_DR |
TAP_UPDATE_DR, // from TAP_EXIT2_DR |
TAP_SELECT_DR_SCAN, // from TAP_UPDATE_DR |
TAP_TEST_LOGIC_RESET, // from TAP_SELECT_IR_SCAN |
TAP_EXIT1_IR, // from TAP_CAPTURE_IR |
TAP_EXIT1_IR, // from TAP_SHIFT_IR |
TAP_UPDATE_IR, // from TAP_EXIT1_IR |
TAP_EXIT2_IR, // from TAP_PAUSE_IR |
TAP_UPDATE_IR, // from TAP_EXIT2_IR |
TAP_SELECT_DR_SCAN}; // from TAP_UPDATE_IR |
static const TapState mapHigh[TAP_SIZE] = { // When TMS = 1/true |
TAP_TEST_LOGIC_RESET, // from TAP_TEST_LOGIC_RESET |
TAP_SELECT_DR_SCAN, // from TAP_RUN_TEST_IDLE |
TAP_SELECT_IR_SCAN, // from TAP_SELECT_DR_SCAN |
TAP_EXIT1_DR, // from TAP_CAPTURE_DR |
TAP_EXIT1_DR, // from TAP_SHIFT_DR |
TAP_UPDATE_DR, // from TAP_EXIT1_DR |
TAP_EXIT2_DR, // from TAP_PAUSE_DR |
TAP_UPDATE_DR, // from TAP_EXIT2_DR |
TAP_SELECT_DR_SCAN, // from TAP_UPDATE_DR |
TAP_TEST_LOGIC_RESET, // from TAP_SELECT_IR_SCAN |
TAP_EXIT1_IR, // from TAP_CAPTURE_IR |
TAP_EXIT1_IR, // from TAP_SHIFT_IR |
TAP_UPDATE_IR, // from TAP_EXIT1_IR |
TAP_EXIT2_IR, // from TAP_PAUSE_IR |
TAP_UPDATE_IR, // from TAP_EXIT2_IR |
TAP_SELECT_DR_SCAN |
}; // from TAP_UPDATE_IR |
|
static const TapState mapLow[TAP_SIZE] = { // When TMS = 0/false |
TAP_RUN_TEST_IDLE, // from TAP_TEST_LOGIC_RESET |
TAP_RUN_TEST_IDLE, // from TAP_RUN_TEST_IDLE |
TAP_CAPTURE_DR, // from TAP_SELECT_DR_SCAN |
TAP_SHIFT_DR, // from TAP_CAPTURE_DR |
TAP_SHIFT_DR, // from TAP_SHIFT_DR |
TAP_PAUSE_DR, // from TAP_EXIT1_DR |
TAP_PAUSE_DR, // from TAP_PAUSE_DR |
TAP_SHIFT_DR, // from TAP_EXIT2_DR |
TAP_RUN_TEST_IDLE, // from TAP_UPDATE_DR |
TAP_CAPTURE_IR, // from TAP_SELECT_IR_SCAN |
TAP_SHIFT_IR, // from TAP_CAPTURE_IR |
TAP_SHIFT_IR, // from TAP_SHIFT_IR |
TAP_PAUSE_IR, // from TAP_EXIT1_IR |
TAP_PAUSE_IR, // from TAP_PAUSE_IR |
TAP_SHIFT_IR, // from TAP_EXIT2_IR |
TAP_RUN_TEST_IDLE }; // from TAP_UPDATE_IR |
static const TapState mapLow[TAP_SIZE] = { // When TMS = 0/false |
TAP_RUN_TEST_IDLE, // from TAP_TEST_LOGIC_RESET |
TAP_RUN_TEST_IDLE, // from TAP_RUN_TEST_IDLE |
TAP_CAPTURE_DR, // from TAP_SELECT_DR_SCAN |
TAP_SHIFT_DR, // from TAP_CAPTURE_DR |
TAP_SHIFT_DR, // from TAP_SHIFT_DR |
TAP_PAUSE_DR, // from TAP_EXIT1_DR |
TAP_PAUSE_DR, // from TAP_PAUSE_DR |
TAP_SHIFT_DR, // from TAP_EXIT2_DR |
TAP_RUN_TEST_IDLE, // from TAP_UPDATE_DR |
TAP_CAPTURE_IR, // from TAP_SELECT_IR_SCAN |
TAP_SHIFT_IR, // from TAP_CAPTURE_IR |
TAP_SHIFT_IR, // from TAP_SHIFT_IR |
TAP_PAUSE_IR, // from TAP_EXIT1_IR |
TAP_PAUSE_IR, // from TAP_PAUSE_IR |
TAP_SHIFT_IR, // from TAP_EXIT2_IR |
TAP_RUN_TEST_IDLE |
}; // from TAP_UPDATE_IR |
|
state = tms ? mapHigh[state] : mapLow[state]; |
state = tms ? mapHigh[state] : mapLow[state]; |
|
} // nextState() |
} // nextState() |
|
|
//! Determine if we are in a particular TAP state |
|
//! Set TMS to get there optimally |
146,35 → 138,34
//! to loop). |
|
//! @return True if we are already in the target state |
bool |
TapStateMachine::targetState (TapState target, |
bool &tms) |
bool TapStateMachine::targetState(TapState target, bool & tms) |
{ |
// Map of the value of TMS which moves the state machine from the the state |
// in the row (first) to the state in the column (second) |
static const bool map[TAP_SIZE][TAP_SIZE] = { |
// T R S C S E P E U S C S E P E U |
// L T D D D 1 D 2 D I I I 1 I 2 I |
// R I R R R D R D R R R R I R I R |
// S R R S R R |
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // map[TLR][x] |
{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[RTI][x] |
{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, // map[SDRS][x] |
{ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[CDR][x] |
{ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[SDR][x] |
{ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[E1DR][x] |
{ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[PDR][x] |
{ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[E2DR][x] |
{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // map[UDR][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, // map[SIRS][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }, // map[CIR][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }, // map[SIR][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, // map[E1IR][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, // map[PIR][x] |
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, // map[E2IR][x] |
{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }}; // map[UIR][x] |
// Map of the value of TMS which moves the state machine from the the state |
// in the row (first) to the state in the column (second) |
static const bool map[TAP_SIZE][TAP_SIZE] = { |
// T R S C S E P E U S C S E P E U |
// L T D D D 1 D 2 D I I I 1 I 2 I |
// R I R R R D R D R R R R I R I R |
// S R R S R R |
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // map[TLR][x] |
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // map[RTI][x] |
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, // map[SDRS][x] |
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // map[CDR][x] |
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // map[SDR][x] |
{1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, // map[E1DR][x] |
{1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // map[PDR][x] |
{1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, // map[E2DR][x] |
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // map[UDR][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // map[SIRS][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1}, // map[CIR][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1}, // map[SIR][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1}, // map[E1IR][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1}, // map[PIR][x] |
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1}, // map[E2IR][x] |
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} |
}; // map[UIR][x] |
|
tms = map[state][target]; |
return state == target; |
tms = map[state][target]; |
return state == target; |
|
} // targetState() |
} // targetState() |
/sysc/src/OrpsocMain.cpp
10,7 → 10,7
//// //// |
//// Author(s): //// |
//// - Jeremy Bennett jeremy.bennett@embecosm.com //// |
//// - Julius Baxter jb@orsoc.se //// |
//// - Julius Baxter julius@opencores.org //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
42,10 → 42,6
|
#include "OrpsocMain.h" |
|
// TODO - copy orpsoc-defines.h and or1200-defines.h somewhere this can see |
// them and include/exclude RSP stuff. For now is defined |
|
|
#include "Vorpsoc_top.h" |
#include "OrpsocAccess.h" |
#include "MemoryLoad.h" |
55,12 → 51,10
#include "ResetSC.h" |
#include "Or1200MonitorSC.h" |
|
|
// Include Verilog ORPSoC defines file, converted to C include format to be |
// able to detect if the debug unit is to be built in or not. |
#include "orpsoc-defines.h" |
|
|
#ifdef JTAG_DEBUG |
# include "GdbServerSC.h" |
# include "JtagSC_includes.h" |
70,449 → 64,443
# include "UartSC.h" |
#endif |
|
int SIM_RUNNING; |
int sc_main (int argc, |
char *argv[] ) |
/* Global quiet variable */ |
bool gQuiet; |
|
int gSimRunning; |
|
int sc_main(int argc, char *argv[]) |
{ |
sc_set_time_resolution( 1, TIMESCALE_UNIT); |
// CPU clock (also used as JTAG TCK) and reset (both active high and low) |
sc_time clkPeriod (BENCH_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT); |
sc_clock clk ("clk", clkPeriod); |
sc_set_time_resolution(1, TIMESCALE_UNIT); |
// CPU clock (also used as JTAG TCK) and reset (both active high and low) |
sc_time clkPeriod(BENCH_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT); |
sc_clock clk("clk", clkPeriod); |
|
sc_signal<bool> rst; |
sc_signal<bool> rstn; |
sc_signal < bool > rst; |
sc_signal < bool > rstn; |
|
#ifdef JTAG_DEBUG |
sc_time jtagPeriod (JTAG_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT); |
sc_clock jtag_tck ("jtag-clk", jtagPeriod, 0.5, SC_ZERO_TIME, false); |
sc_time jtagPeriod(JTAG_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT); |
sc_clock jtag_tck("jtag-clk", jtagPeriod, 0.5, SC_ZERO_TIME, false); |
|
sc_signal<bool> jtag_tdi; // JTAG interface |
sc_signal<bool> jtag_tdo; |
sc_signal<bool> jtag_tms; |
sc_signal<bool> jtag_trst; |
sc_signal < bool > jtag_tdi; // JTAG interface |
sc_signal < bool > jtag_tdo; |
sc_signal < bool > jtag_tms; |
sc_signal < bool > jtag_trst; |
#endif |
|
#ifdef UART0 |
sc_signal<bool> uart_rx; // External UART |
sc_signal<bool> uart_tx; |
sc_signal < bool > uart_rx; // External UART |
sc_signal < bool > uart_tx; |
#endif |
|
SIM_RUNNING = 0; |
gSimRunning = 0; |
|
// Are we running "quiet"? |
bool quiet = false; |
// Setup the name of the VCD dump file |
bool VCD_enabled = false; |
string dumpNameDefault("vlt-dump.vcd"); |
string testNameString; |
string vcdDumpFile; |
// VCD dump controling vars |
bool dump_start_delay_set = false, dump_stop_set = false; |
bool dumping_now = false; |
int dump_depth = 99; // Default dump depth |
sc_time dump_start,dump_stop, finish_time; |
bool finish_time_set = false; // By default we will let the simulation |
// finish naturally |
VerilatedVcdC *verilatorVCDFile; |
|
/*int*/double time_val; |
bool vcd_file_name_given = false; |
// Are we running "quiet"? |
gQuiet = false; |
// Setup the name of the VCD dump file |
bool VCD_enabled = false; |
string dumpNameDefault("vlt-dump.vcd"); |
string testNameString; |
string vcdDumpFile; |
// VCD dump controling vars |
bool dump_start_delay_set = false, dump_stop_set = false; |
bool dumping_now = false; |
int dump_depth = 99; // Default dump depth |
sc_time dump_start, dump_stop, finish_time; |
bool finish_time_set = false; // By default we will let the simulation |
// finish naturally |
VerilatedVcdC *verilatorVCDFile; |
|
/*int */ double time_val; |
bool vcd_file_name_given = false; |
|
#ifdef JTAG_DEBUG |
bool rsp_server_enabled = false; |
int rsp_server_port = DEFAULT_RSP_PORT; |
bool rsp_server_enabled = false; |
int rsp_server_port = DEFAULT_RSP_PORT; |
#endif |
|
// Executable app load variables |
int do_program_file_load = 0; // Default: we don't require a file, we use the |
// VMEM |
char* program_file; // Old char* style for program name |
// Executable app load variables |
int do_program_file_load = 0; // Default: we don't require a file, we use the |
// VMEM |
char *program_file; // Old char* style for program name |
|
// Verilator accessor |
OrpsocAccess *accessor; |
// Verilator accessor |
OrpsocAccess *accessor; |
|
// Modules |
Vorpsoc_top *orpsoc; // Verilated ORPSoC |
|
MemoryLoad *memoryload; // Memory loader |
|
ResetSC *reset; // Generate a RESET signal |
// Modules |
Vorpsoc_top *orpsoc; // Verilated ORPSoC |
|
Or1200MonitorSC *monitor; // Handle l.nop x instructions |
MemoryLoad *memoryload; // Memory loader |
|
ResetSC *reset; // Generate a RESET signal |
|
Or1200MonitorSC *monitor; // Handle l.nop x instructions |
|
#ifdef JTAG_DEBUG |
JtagSC *jtag; // Generate JTAG signals |
GdbServerSC *gdbServer; // Map RSP requests to debug unit |
JtagSC *jtag; // Generate JTAG signals |
GdbServerSC *gdbServer; // Map RSP requests to debug unit |
#endif |
|
#ifdef UART0 |
UartSC *uart; // Handle UART signals |
UartSC *uart; // Handle UART signals |
#endif |
|
// Instantiate the Verilator model, VCD trace handler and accessor |
orpsoc = new Vorpsoc_top ("orpsoc"); |
|
accessor = new OrpsocAccess (orpsoc); |
|
memoryload = new MemoryLoad (accessor); |
|
monitor = new Or1200MonitorSC ("monitor", accessor, memoryload, |
argc, argv); |
|
// Instantiate the SystemC modules |
reset = new ResetSC ("reset", BENCH_RESET_TIME); |
// Instantiate the Verilator model, VCD trace handler and accessor |
orpsoc = new Vorpsoc_top("orpsoc"); |
|
#ifdef JTAG_DEBUG |
jtag = new JtagSC ("jtag"); |
accessor = new OrpsocAccess(orpsoc); |
|
memoryload = new MemoryLoad(accessor); |
|
monitor = new Or1200MonitorSC("monitor", accessor, memoryload, |
argc, argv); |
|
// Instantiate the SystemC modules |
reset = new ResetSC("reset", BENCH_RESET_TIME); |
|
#ifdef JTAG_DEBUG |
jtag = new JtagSC("jtag"); |
#endif |
|
#ifdef UART0 |
uart = new UartSC("uart"); |
uart = new UartSC("uart"); |
#endif |
|
// Parse command line options |
// Default is for VCD generation OFF, only turned on if specified on command |
// line |
|
// Search through the command line parameters for options |
if (argc > 1) |
{ |
for(int i=1; i<argc; i++) |
{ |
if ( (strcmp(argv[i], "-e")==0) || |
(strcmp(argv[i], "--endtime")==0) ) |
{ |
time_val = strtod(argv[i+1], NULL); |
sc_time opt_end_time(time_val,TIMESCALE_UNIT); |
finish_time = opt_end_time; |
finish_time_set = true; |
} |
else if ( (strcmp(argv[i], "-f")==0) || |
(strcmp(argv[i], "--program")==0) ) |
{ |
do_program_file_load = 1; // Enable program loading - will be |
// done after sim init. |
program_file = argv[i+1]; // Old char* style for program name |
} |
else if ((strcmp(argv[i], "-d")==0) || |
(strcmp(argv[i], "--vcdfile")==0) || |
(strcmp(argv[i], "-v")==0) || |
(strcmp(argv[i], "--vcdon")==0) |
) |
{ |
VCD_enabled = true; |
dumping_now = true; |
vcdDumpFile = dumpNameDefault; |
if (i+1 < argc) |
if(argv[i+1][0] != '-') |
{ |
testNameString = argv[i+1]; |
vcdDumpFile = testNameString; |
i++; |
} |
} |
else if ( (strcmp(argv[i], "-s")==0) || |
(strcmp(argv[i], "--vcdstart")==0) ) |
{ |
VCD_enabled = true; |
time_val = strtod(argv[i+1], NULL); |
sc_time dump_start_time(time_val,TIMESCALE_UNIT); |
dump_start = dump_start_time; |
dump_start_delay_set = true; |
dumping_now = false; |
} |
else if ( (strcmp(argv[i], "-t")==0) || |
(strcmp(argv[i], "--vcdstop")==0) ) |
{ |
VCD_enabled = true; |
time_val = strtod(argv[i+1],NULL); |
sc_time dump_stop_time(time_val,TIMESCALE_UNIT); |
dump_stop = dump_stop_time; |
dump_stop_set = true; |
} |
/* |
Depth setting of VCD doesn't appear to work, I think it's only |
configurable during at compile time . |
*/ |
/* else if ( (strcmp(argv[i], "-p")==0) || |
(strcmp(argv[i], "--vcddepth")==0) ) |
{ |
dump_depth = atoi(argv[i+1]); |
}*/ |
// Parse command line options |
// Default is for VCD generation OFF, only turned on if specified on command |
// line |
|
// Search through the command line parameters for options |
if (argc > 1) { |
for (int i = 1; i < argc; i++) { |
if ((strcmp(argv[i], "-e") == 0) || |
(strcmp(argv[i], "--endtime") == 0)) { |
time_val = strtod(argv[i + 1], NULL); |
sc_time opt_end_time(time_val, TIMESCALE_UNIT); |
finish_time = opt_end_time; |
finish_time_set = true; |
} else if ((strcmp(argv[i], "-q") == 0) || |
(strcmp(argv[i], "--quiet") == 0)) { |
gQuiet = true; |
} else if ((strcmp(argv[i], "-f") == 0) || |
(strcmp(argv[i], "--program") == 0)) { |
do_program_file_load = 1; // Enable program loading - will be |
// done after sim init. |
program_file = argv[i + 1]; // Old char* style for program name |
} else if ((strcmp(argv[i], "-d") == 0) || |
(strcmp(argv[i], "--vcdfile") == 0) || |
(strcmp(argv[i], "-v") == 0) || |
(strcmp(argv[i], "--vcdon") == 0) |
) { |
VCD_enabled = true; |
dumping_now = true; |
vcdDumpFile = dumpNameDefault; |
if (i + 1 < argc) |
if (argv[i + 1][0] != '-') { |
testNameString = argv[i + 1]; |
vcdDumpFile = testNameString; |
i++; |
} |
} else if ((strcmp(argv[i], "-s") == 0) || |
(strcmp(argv[i], "--vcdstart") == 0)) { |
VCD_enabled = true; |
time_val = strtod(argv[i + 1], NULL); |
sc_time dump_start_time(time_val, |
TIMESCALE_UNIT); |
dump_start = dump_start_time; |
dump_start_delay_set = true; |
dumping_now = false; |
} else if ((strcmp(argv[i], "-t") == 0) || |
(strcmp(argv[i], "--vcdstop") == 0)) { |
VCD_enabled = true; |
time_val = strtod(argv[i + 1], NULL); |
sc_time dump_stop_time(time_val, |
TIMESCALE_UNIT); |
dump_stop = dump_stop_time; |
dump_stop_set = true; |
} |
#ifdef JTAG_DEBUG |
else if ( (strcmp(argv[i], "-r")==0) || |
(strcmp(argv[i], "--rsp")==0) ) |
{ |
rsp_server_enabled = true; |
if (i+1 < argc) if(argv[i+1][0] != '-') |
{ |
rsp_server_port = atoi(argv[i+1]); |
i++; |
} |
} |
else if ((strcmp(argv[i], "-r") == 0) || |
(strcmp(argv[i], "--rsp") == 0)) { |
rsp_server_enabled = true; |
if (i + 1 < argc) |
if (argv[i + 1][0] != '-') { |
rsp_server_port = |
atoi(argv[i + 1]); |
i++; |
} |
} |
#endif |
else if ((strcmp(argv[i], "-q")==0) || |
(strcmp(argv[i], "--quiet")==0)) |
{ |
quiet = true; |
} |
else if ( (strcmp(argv[i], "-h")==0) || |
(strcmp(argv[i], "--help")==0) ) |
{ |
printf("Usage: %s [options]\n",argv[0]); |
printf("\n ORPSoCv2 cycle accurate model\n"); |
printf(" For details visit http://opencores.org/openrisc,orpsocv2\n"); |
printf("\n"); |
printf("Options:\n"); |
printf(" -h, --help\t\tPrint this help message\n"); |
printf(" -q, --quiet\t\tDisable all except UART print out\n"); |
printf("\nSimulation control:\n"); |
printf(" -f, --program <file> \tLoad program from OR32 ELF <file>\n"); |
printf(" -e, --endtime <val> \tStop the sim at <val> ns\n"); |
printf("\nVCD generation:\n"); |
printf(" -v, --vcdon\t\tEnable VCD generation\n"); |
printf(" -d, --vcdfile <file>\tEnable and save VCD to <file>\n"); |
else if ((strcmp(argv[i], "-h") == 0) || |
(strcmp(argv[i], "--help") == 0)) { |
printf("Usage: %s [options]\n", argv[0]); |
printf("\n ORPSoCv2 cycle accurate model\n"); |
printf |
(" For details visit http://opencores.org/openrisc,orpsocv2\n"); |
printf("\n"); |
printf("Options:\n"); |
printf |
(" -h, --help\t\tPrint this help message\n"); |
printf |
(" -q, --quiet\t\tDisable all except UART print out\n"); |
printf("\nSimulation control:\n"); |
printf |
(" -f, --program <file> \tLoad program from OR32 ELF <file>\n"); |
printf |
(" -e, --endtime <val> \tStop the sim at <val> ns\n"); |
printf("\nVCD generation:\n"); |
printf |
(" -v, --vcdon\t\tEnable VCD generation\n"); |
printf |
(" -d, --vcdfile <file>\tEnable and save VCD to <file>\n"); |
|
printf(" -s, --vcdstart <val>\tEnable and delay VCD generation until <val> ns\n"); |
printf(" -t, --vcdstop <val> \tEnable and terminate VCD generation at <val> ns\n"); |
printf |
(" -s, --vcdstart <val>\tEnable and delay VCD generation until <val> ns\n"); |
printf |
(" -t, --vcdstop <val> \tEnable and terminate VCD generation at <val> ns\n"); |
#ifdef JTAG_DEBUG |
printf("\nRemote debugging:\n"); |
printf(" -r, --rsp [<port>]\tEnable RSP debugging server, opt. specify <port>\n"); |
printf("\nRemote debugging:\n"); |
printf |
(" -r, --rsp [<port>]\tEnable RSP debugging server, opt. specify <port>\n"); |
#endif |
monitor->printUsage(); |
printf("\n"); |
return 0; |
} |
|
monitor->printUsage(); |
printf("\n"); |
return 0; |
} |
|
} |
} |
} |
|
// Determine if we're going to setup a VCD dump: |
// Pretty much setting any related option will enable VCD dumping. |
if (VCD_enabled) |
{ |
|
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay_set) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
cout << endl; |
} |
#ifdef JTAG_DEBUG |
if (rsp_server_enabled) |
gdbServer = new GdbServerSC ("gdb-server", FLASH_START, FLASH_END, |
rsp_server_port, jtag->tapActionQueue); |
else |
gdbServer = NULL; |
// Determine if we're going to setup a VCD dump: |
// Pretty much setting any related option will enable VCD dumping. |
if (VCD_enabled) { |
|
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay_set) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
cout << endl; |
} |
#ifdef JTAG_DEBUG |
if (rsp_server_enabled) |
gdbServer = |
new GdbServerSC("gdb-server", FLASH_START, FLASH_END, |
rsp_server_port, jtag->tapActionQueue); |
else |
gdbServer = NULL; |
#endif |
|
// Connect up ORPSoC |
orpsoc->clk_pad_i (clk); |
orpsoc->rst_n_pad_i (rstn); |
|
// Connect up ORPSoC |
orpsoc->clk_pad_i(clk); |
orpsoc->rst_n_pad_i(rstn); |
|
#ifdef JTAG_DEBUG |
orpsoc->tck_pad_i (jtag_tck); // JTAG interface |
orpsoc->tdi_pad_i (jtag_tdi); |
orpsoc->tms_pad_i (jtag_tms); |
orpsoc->tdo_pad_o (jtag_tdo); |
orpsoc->tck_pad_i(jtag_tck); // JTAG interface |
orpsoc->tdi_pad_i(jtag_tdi); |
orpsoc->tms_pad_i(jtag_tms); |
orpsoc->tdo_pad_o(jtag_tdo); |
#endif |
|
#ifdef UART0 |
orpsoc->uart0_srx_pad_i (uart_rx); // External UART |
orpsoc->uart0_stx_pad_o (uart_tx); |
orpsoc->uart0_srx_pad_i(uart_rx); // External UART |
orpsoc->uart0_stx_pad_o(uart_tx); |
#endif |
|
// Connect up the SystemC modules |
reset->clk (clk); // Reset |
reset->rst (rst); |
reset->rstn (rstn); |
// Connect up the SystemC modules |
reset->clk(clk); // Reset |
reset->rst(rst); |
reset->rstn(rstn); |
|
monitor->clk (clk); // Monitor |
monitor->clk(clk); // Monitor |
|
#ifdef JTAG_DEBUG |
jtag->sysReset (rst); // JTAG |
jtag->tck (jtag_tck); |
jtag->tdi (jtag_tdi); |
jtag->tdo (jtag_tdo); |
jtag->tms (jtag_tms); |
jtag->trst (jtag_trst); |
jtag->sysReset(rst); // JTAG |
jtag->tck(jtag_tck); |
jtag->tdi(jtag_tdi); |
jtag->tdo(jtag_tdo); |
jtag->tms(jtag_tms); |
jtag->trst(jtag_trst); |
#endif |
|
#ifdef UART0 |
uart->clk (clk); // Uart |
uart->uartrx (uart_rx); // orpsoc's receive line |
uart->uarttx (uart_tx); // orpsoc's transmit line |
uart->clk(clk); // Uart |
uart->uartrx(uart_rx); // orpsoc's receive line |
uart->uarttx(uart_tx); // orpsoc's transmit line |
#endif |
|
// Tie off signals |
// Tie off signals |
#ifdef JTAG_DEBUG |
jtag_tdi = 1; // Tie off the JTAG inputs |
jtag_tms = 1; |
jtag_tdi = 1; // Tie off the JTAG inputs |
jtag_tms = 1; |
#endif |
|
if (VCD_enabled) |
{ |
Verilated::traceEverOn (true); |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
verilatorVCDFile = new VerilatedVcdC (); |
|
orpsoc->trace (verilatorVCDFile, dump_depth); |
|
if (dumping_now) |
{ |
verilatorVCDFile->open (vcdDumpFile.c_str()); |
if (VCD_enabled) { |
Verilated::traceEverOn(true); |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
verilatorVCDFile = new VerilatedVcdC(); |
|
orpsoc->trace(verilatorVCDFile, dump_depth); |
|
if (dumping_now) { |
verilatorVCDFile->open(vcdDumpFile.c_str()); |
} |
} |
} |
//printf("* Beginning test\n"); |
|
//printf("* Beginning test\n"); |
|
#ifdef UART0 |
// Init the UART function |
uart->initUart(50000000, 115200); |
// Init the UART function |
uart->initUart(50000000, 115200); |
#endif |
|
if (do_program_file_load) // Did the user specify a file to load? |
{ |
cout << "* Loading program from " << program_file << endl; |
if (memoryload->loadcode(program_file,0,0) < 0) |
if (do_program_file_load) // Did the user specify a file to load? |
{ |
cout << "* Error: executable file " << program_file << |
" not loaded" << endl; |
} |
} |
else // No ELF file specified, default is to load SRAM from VMEM file |
{ |
if (!quiet) |
cout << "* Loading memory with image from default file, sram.vmem" |
<< endl; |
accessor->do_ram_readmemh(); |
} |
|
SIM_RUNNING = 1; |
|
// First check how we should run the sim. |
if (VCD_enabled || finish_time_set) |
{ // We'll run sim with step |
|
if (!VCD_enabled && finish_time_set) |
if (!gQuiet) |
cout << "* Loading program from " << program_file << |
endl; |
if (memoryload->loadcode(program_file, 0, 0) < 0) { |
cout << "* Error: executable file " << program_file << |
" not loaded" << endl; |
goto finish_up; |
|
} |
} else |
{ |
// We just run the sim until the set finish time |
sc_start((double)(finish_time.to_double()), TIMESCALE_UNIT); |
SIM_RUNNING=0; |
sc_stop(); |
// Print performance summary |
monitor->perfSummary(); |
// Do memdump if enabled |
monitor->memdump(); |
/* No ELF file specified, default is to load from VMEM file */ |
if (!gQuiet) |
cout << |
"* Loading memory with image from default file, sram.vmem" |
<< endl; |
accessor->do_ram_readmemh(); |
} |
else |
{ |
if (dump_start_delay_set) |
{ |
// Run the sim until we want to dump |
sc_start((double)(dump_start.to_double()),TIMESCALE_UNIT); |
// Open the trace file |
verilatorVCDFile->open (vcdDumpFile.c_str()); |
dumping_now = 1; |
} |
|
if (dumping_now) |
{ |
// Step the sim and generate the trace |
// Execute until we stop |
while(!Verilated::gotFinish()) |
{ |
if (SIM_RUNNING) // Changed by Or1200MonitorSC when finish NOP |
sc_start (1,TIMESCALE_UNIT); // Step the sim |
else |
{ |
verilatorVCDFile->close(); |
break; |
} |
|
verilatorVCDFile->dump (sc_time_stamp().to_double()); |
|
if (dump_stop_set) |
{ |
if (sc_time_stamp() >= dump_stop) |
{ |
// Close dump file |
verilatorVCDFile->close(); |
// Now continue on again until the end |
if (!finish_time_set) |
sc_start(); |
else |
{ |
// Determine how long we should run for |
sc_time sim_time_remaining = |
finish_time - sc_time_stamp(); |
sc_start((double)(sim_time_remaining.to_double()), |
TIMESCALE_UNIT); |
// Officially stop the sim |
sc_stop(); |
// Print performance summary |
monitor->perfSummary(); |
// Do memdump if enabled |
monitor->memdump(); |
} |
break; |
gSimRunning = 1; |
|
// First check how we should run the sim. |
if (VCD_enabled || finish_time_set) { // We'll run sim with step |
|
if (!VCD_enabled && finish_time_set) { |
// We just run the sim until the set finish time |
sc_start((double)(finish_time.to_double()), |
TIMESCALE_UNIT); |
gSimRunning = 0; |
sc_stop(); |
// Print performance summary |
monitor->perfSummary(); |
// Do memdump if enabled |
monitor->memdump(); |
} else { |
if (dump_start_delay_set) { |
// Run the sim until we want to dump |
sc_start((double)(dump_start.to_double()), |
TIMESCALE_UNIT); |
// Open the trace file |
verilatorVCDFile->open(vcdDumpFile.c_str()); |
dumping_now = 1; |
} |
} |
if (finish_time_set) |
{ |
if (sc_time_stamp() >= finish_time) |
{ |
// Officially stop the sim |
sc_stop(); |
// Close dump file |
verilatorVCDFile->close(); |
// Do memdump if enabled |
monitor->memdump(); |
// Print performance summary |
monitor->perfSummary(); |
break; |
|
if (dumping_now) { |
// Step the sim and generate the trace |
// Execute until we stop |
while (!Verilated::gotFinish()) { |
// gSimRunning value changed by the |
// monitor when sim should finish. |
if (gSimRunning) |
// Step the sim |
sc_start(1, TIMESCALE_UNIT); |
else { |
verilatorVCDFile->close(); |
break; |
} |
|
verilatorVCDFile->dump(sc_time_stamp(). |
to_double()); |
|
if (dump_stop_set) { |
if (sc_time_stamp() >= |
dump_stop) { |
// Close dump file |
verilatorVCDFile->close |
(); |
// Now continue on again until the end |
if (!finish_time_set) |
sc_start(); |
else { |
// Determine how long we should run for |
sc_time |
sim_time_remaining |
= |
finish_time |
- |
sc_time_stamp |
(); |
sc_start((double)(sim_time_remaining.to_double()), TIMESCALE_UNIT); |
// Officially stop the sim |
sc_stop(); |
// Print performance summary |
monitor-> |
perfSummary |
(); |
// Do memdump if enabled |
monitor->memdump |
(); |
} |
break; |
} |
} |
if (finish_time_set) { |
if (sc_time_stamp() >= |
finish_time) { |
// Officially stop the sim |
sc_stop(); |
// Close dump file |
verilatorVCDFile->close |
(); |
// Do memdump if enabled |
monitor->memdump(); |
// Print performance summary |
monitor->perfSummary(); |
break; |
} |
} |
} |
} |
} |
} |
} |
} else { |
// Simple run case |
// Ideally a "l.nop 1" will terminate the simulation gracefully. |
// Need to step at clock period / 4, otherwise model appears to skip the |
// monitor and logging functions sometimes (?!?) |
while (gSimRunning) |
sc_start(BENCH_CLK_HALFPERIOD / 2, TIMESCALE_UNIT); |
//sc_start(); |
} |
} |
else |
{ |
// Simple run case |
// Ideally a "l.nop 1" will terminate the simulation gracefully. |
// Need to step at clock period / 4, otherwise model appears to skip the |
// monitor and logging functions sometimes (?!?) |
while (SIM_RUNNING) |
sc_start(BENCH_CLK_HALFPERIOD / 2, TIMESCALE_UNIT); |
//sc_start(); |
} |
|
|
// Free memory |
|
|
finish_up: |
// Free memory |
#ifdef JTAG_DEBUG |
if (rsp_server_enabled) |
delete gdbServer; |
if (rsp_server_enabled) |
delete gdbServer; |
|
delete jtag; |
delete jtag; |
#endif |
|
delete monitor; |
delete monitor; |
|
delete reset; |
delete reset; |
|
delete accessor; |
delete accessor; |
|
//delete trace; |
//delete trace; |
|
delete orpsoc; |
delete orpsoc; |
|
return 0; |
return 0; |
|
} /* sc_main() */ |
} /* sc_main() */ |
/sysc/src/JtagSC.cpp
30,9 → 30,8
|
#include "JtagSC.h" |
|
SC_HAS_PROCESS(JtagSC); |
|
SC_HAS_PROCESS( JtagSC ); |
|
//! Constructor for the JTAG handler. |
|
//! @param[in] name Name of this module, passed to the parent |
39,79 → 38,68
//! constructor. |
//! @param[in] fifo_size Size of the FIFO on which to queue TAP actions. |
|
JtagSC::JtagSC (sc_core::sc_module_name name, |
int fifo_size) : |
sc_module (name), |
currentTapAction (NULL) |
JtagSC::JtagSC(sc_core::sc_module_name name, int fifo_size): |
sc_module(name), currentTapAction(NULL) |
{ |
tapActionQueue = new sc_core::sc_fifo<TapAction *> (fifo_size); |
stateMachine = new TapStateMachine (); |
tapActionQueue = new sc_core::sc_fifo < TapAction * >(fifo_size); |
stateMachine = new TapStateMachine(); |
|
SC_METHOD (processActions); |
sensitive << tck.pos (); |
|
} // JtagSC () |
SC_METHOD(processActions); |
sensitive << tck.pos(); |
|
} // JtagSC () |
|
//! Destructor for the JTAG handler. |
|
//! Give up our state machine and FIFO |
|
JtagSC::~JtagSC () |
JtagSC::~JtagSC() |
{ |
delete stateMachine; |
delete tapActionQueue; |
delete stateMachine; |
delete tapActionQueue; |
|
} // ~JtagSC () |
} // ~JtagSC () |
|
|
//! Method to drive the jtag ports. |
|
//! Initial version just drives the reset. |
|
void |
JtagSC::processActions() |
JtagSC::processActions() |
{ |
// TRST is driven as the inverse of the system reset |
trst = !sysReset; |
// TRST is driven as the inverse of the system reset |
trst = !sysReset; |
|
// Do nothing else if in CPU reset (active high) |
if (sysReset) |
{ |
return; |
} |
// Do nothing else if in CPU reset (active high) |
if (sysReset) { |
return; |
} |
// Functions setting the outputs will need bools (they are not generally |
// SystemC modules, so don't handle the likes of sc_in<> correctly). |
bool tdi_o; |
bool tms_o; |
|
// Functions setting the outputs will need bools (they are not generally |
// SystemC modules, so don't handle the likes of sc_in<> correctly). |
bool tdi_o; |
bool tms_o; |
// Try to get an action if we don't have one |
if (NULL == currentTapAction) { |
if (false == tapActionQueue->nb_read(currentTapAction)) { |
// Nothing there, so head for Run-Test/Idle state. |
stateMachine->targetState(TAP_RUN_TEST_IDLE, tms_o); |
tms = tms_o; |
|
// Try to get an action if we don't have one |
if (NULL == currentTapAction) |
{ |
if (false == tapActionQueue->nb_read (currentTapAction)) |
{ |
// Nothing there, so head for Run-Test/Idle state. |
stateMachine->targetState (TAP_RUN_TEST_IDLE, tms_o); |
tms = tms_o; |
return; |
} |
} |
// Process the action, notifying the originator when done. |
|
return; |
if (currentTapAction->process(stateMachine, tdi_o, tdo, tms_o)) { |
currentTapAction->getDoneEvent()->notify(); |
currentTapAction = NULL; |
} |
} |
|
// Process the action, notifying the originator when done. |
// Select the new TAP state |
stateMachine->nextState(tms_o); |
|
if (currentTapAction->process (stateMachine, tdi_o, tdo, tms_o)) |
{ |
currentTapAction->getDoneEvent()->notify(); |
currentTapAction = NULL; |
} |
// Drive the signal ports |
tdi = tdi_o; |
tms = tms_o; |
|
// Select the new TAP state |
stateMachine->nextState (tms_o); |
|
// Drive the signal ports |
tdi = tdi_o; |
tms = tms_o; |
|
} // processActions() |
} // processActions() |
/sysc/src/DebugUnitSC.cpp
34,12 → 34,10
#include "DebugUnitSC.h" |
#include "Utils.h" |
|
|
using sc_core::sc_event; |
using sc_core::sc_fifo; |
using sc_core::sc_module_name; |
|
|
//----------------------------------------------------------------------------- |
//! Constructor for the Debug Unit |
|
62,38 → 60,34
//! @param[in] _tapActionQueue Pointer to fifo of actions to be performed by |
//! the JTAG interface |
//----------------------------------------------------------------------------- |
DebugUnitSC::DebugUnitSC (sc_module_name name, |
sc_fifo<TapAction *> *_tapActionQueue) : |
sc_module (name), |
tapActionQueue (_tapActionQueue), |
stallState (UNKNOWN), |
currentScanChain (OR1K_SC_UNDEF) |
DebugUnitSC::DebugUnitSC(sc_module_name name, sc_fifo < TapAction * >*_tapActionQueue): |
sc_module(name), |
tapActionQueue(_tapActionQueue), |
stallState(UNKNOWN), currentScanChain(OR1K_SC_UNDEF) |
{ |
#ifdef NOCACHE |
npcCacheIsValid = false; // Always cache NPC |
npcCacheIsValid = false; // Always cache NPC |
#else |
sprCache = new SprCache (); |
memCache = new MemCache (); |
sprCache = new SprCache(); |
memCache = new MemCache(); |
#endif |
|
} // DebugUnitSC () |
} // DebugUnitSC () |
|
|
//----------------------------------------------------------------------------- |
//! Destructor |
|
//! Free up data structures |
//----------------------------------------------------------------------------- |
DebugUnitSC::~DebugUnitSC () |
DebugUnitSC::~DebugUnitSC() |
{ |
#ifndef NOCACHE |
delete memCache; |
delete sprCache; |
delete memCache; |
delete sprCache; |
#endif |
|
} // ~DebugUnitSC |
} // ~DebugUnitSC |
|
|
//----------------------------------------------------------------------------- |
//! Reset the Debug Unit |
|
103,21 → 97,20
//! @note Must be called from a SystemC thread, because of the use of wait() |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::resetDebugUnit () |
DebugUnitSC::resetDebugUnit() |
{ |
sc_event *done = new sc_event(); |
TapActionReset *resetAction; |
|
// Create and queue the reset action and wait for it to complete |
resetAction = new TapActionReset (done); |
tapActionQueue->write (resetAction); |
wait (*done); |
sc_event *done = new sc_event(); |
TapActionReset *resetAction; |
|
delete resetAction; |
delete done; |
// Create and queue the reset action and wait for it to complete |
resetAction = new TapActionReset(done); |
tapActionQueue->write(resetAction); |
wait(*done); |
|
} // resetDebugUnit () |
delete resetAction; |
delete done; |
|
} // resetDebugUnit () |
|
//----------------------------------------------------------------------------- |
//! Reset the processor |
126,29 → 119,25
|
//! After reset, the processor is known to be unstalled. |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::reset () |
void DebugUnitSC::reset() |
{ |
writeRiscop (readRiscop () | RISCOP_RESET); |
stallState = UNKNOWN; |
writeRiscop(readRiscop() | RISCOP_RESET); |
stallState = UNKNOWN; |
|
} // reset () |
} // reset () |
|
|
//----------------------------------------------------------------------------- |
//! Stall the processor |
|
//! Read the RISCOP register, OR in the stall bit and write it back. |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::stall () |
void DebugUnitSC::stall() |
{ |
writeRiscop (/*readRiscop () |*/ RISCOP_STALL); |
stallState = STALLED; |
writeRiscop( /*readRiscop () | */ RISCOP_STALL); |
stallState = STALLED; |
|
} // stall () |
} // stall () |
|
|
//----------------------------------------------------------------------------- |
//! Unstall the processor |
|
158,23 → 147,21
//! @note Don't be tempted to read back for confirmation. Single stepping |
//! will already have stalled the processor again! |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::unstall () |
void DebugUnitSC::unstall() |
{ |
writeRiscop (/*readRiscop () & ~RISCOP_STALL*/ 0); |
stallState = UNKNOWN; |
writeRiscop( /*readRiscop () & ~RISCOP_STALL */ 0); |
stallState = UNKNOWN; |
|
#ifdef NOCACHE |
npcCacheIsValid = false; // Always cache NPC |
npcCacheIsValid = false; // Always cache NPC |
#else |
// Clear the caches |
sprCache->clear (); |
memCache->clear (); |
// Clear the caches |
sprCache->clear(); |
memCache->clear(); |
#endif |
|
} // unstall () |
} // unstall () |
|
|
//----------------------------------------------------------------------------- |
//! Report if the processor is stalled. |
|
184,25 → 171,22
|
//! @return TRUE if the processor is known to be stalled |
//----------------------------------------------------------------------------- |
bool |
DebugUnitSC::isStalled () |
bool DebugUnitSC::isStalled() |
{ |
if (STALLED == stallState) |
{ |
return true; |
} |
if (STALLED == stallState) { |
return true; |
} |
|
uint32_t riscop = readRiscop (); |
/* For some reason the reset bit is skipped over somewhere, so we should |
just get riscop = 1 if it's stalled */ |
|
//stallState = (RISCOP_STALL == (riscop & RISCOP_STALL)) ? STALLED : UNKNOWN; |
stallState = riscop ? STALLED : UNKNOWN; |
uint32_t riscop = readRiscop(); |
/* For some reason the reset bit is skipped over somewhere, so we should |
just get riscop = 1 if it's stalled */ |
|
return STALLED == stallState; |
//stallState = (RISCOP_STALL == (riscop & RISCOP_STALL)) ? STALLED : UNKNOWN; |
stallState = riscop ? STALLED : UNKNOWN; |
|
} // isStalled () |
return STALLED == stallState; |
|
} // isStalled () |
|
//----------------------------------------------------------------------------- |
//! Read the value of an OpenRISC 1000 Special Purpose Register |
215,49 → 199,43
|
//! @return The value of the SPR |
//----------------------------------------------------------------------------- |
uint32_t |
DebugUnitSC::readSpr (uint16_t sprNum) |
uint32_t DebugUnitSC::readSpr(uint16_t sprNum) |
{ |
uint32_t cachedValue; |
uint32_t cachedValue; |
|
#ifdef NOCACHE |
// Always check NPC cache |
if ((STALLED == stallState) && (sprNum == SPR_NPC) && npcCacheIsValid) |
{ |
return npcCachedValue; |
} |
// Always check NPC cache |
if ((STALLED == stallState) && (sprNum == SPR_NPC) && npcCacheIsValid) { |
return npcCachedValue; |
} |
#else |
// Use any cached value if we are stalled. |
if ((STALLED == stallState) && sprCache->read (sprNum, cachedValue)) |
{ |
return cachedValue; // Already there, no more to do |
} |
// Use any cached value if we are stalled. |
if ((STALLED == stallState) && sprCache->read(sprNum, cachedValue)) { |
return cachedValue; // Already there, no more to do |
} |
#endif |
|
// Read the value |
selectDebugModule (OR1K_SC_CPU0); |
cachedValue = readJtagReg (sprNum); |
// Read the value |
selectDebugModule(OR1K_SC_CPU0); |
cachedValue = readJtagReg(sprNum); |
|
#ifdef NOCACHE |
// Always update the NPC cache |
if ((STALLED == stallState) && (sprNum == SPR_NPC)) |
{ |
npcCachedValue = cachedValue; |
npcCacheIsValid = true; |
} |
// Always update the NPC cache |
if ((STALLED == stallState) && (sprNum == SPR_NPC)) { |
npcCachedValue = cachedValue; |
npcCacheIsValid = true; |
} |
#else |
// Update the cache if we are stalled |
if (STALLED == stallState) |
{ |
sprCache->write (sprNum, cachedValue, sprNum == SPR_NPC); |
} |
// Update the cache if we are stalled |
if (STALLED == stallState) { |
sprCache->write(sprNum, cachedValue, sprNum == SPR_NPC); |
} |
#endif |
|
return cachedValue; |
return cachedValue; |
|
} // readSpr () |
} // readSpr () |
|
|
//----------------------------------------------------------------------------- |
//! Write the value of an OpenRISC 1000 Special Purpose Register |
|
270,49 → 248,38
//! @param[in] sprNum The SPR to write |
//! @param[in] value The value to write |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::writeSpr (uint16_t sprNum, |
uint32_t value) |
void DebugUnitSC::writeSpr(uint16_t sprNum, uint32_t value) |
{ |
#ifdef NOCACHE |
// Always cache the NPC |
if ((STALLED == stallState) && (SPR_NPC == sprNum)) |
{ |
// Have we already cached this NPC value? |
if (npcCacheIsValid && (value == npcCachedValue)) |
{ |
return; |
// Always cache the NPC |
if ((STALLED == stallState) && (SPR_NPC == sprNum)) { |
// Have we already cached this NPC value? |
if (npcCacheIsValid && (value == npcCachedValue)) { |
return; |
} else { |
npcCachedValue = value; |
npcCacheIsValid = true; |
} |
} |
else |
{ |
npcCachedValue = value; |
npcCacheIsValid = true; |
} |
} |
#else |
if (STALLED == stallState) |
{ |
// Have we already cached this value? |
uint32_t cachedValue; |
if (sprCache->read (sprNum, cachedValue) && |
(value == cachedValue)) |
{ |
return; // Already there, no more to do |
if (STALLED == stallState) { |
// Have we already cached this value? |
uint32_t cachedValue; |
if (sprCache->read(sprNum, cachedValue) && |
(value == cachedValue)) { |
return; // Already there, no more to do |
} else { |
sprCache->write(sprNum, value, sprNum == SPR_NPC); |
} |
} |
else |
{ |
sprCache->write (sprNum, value, sprNum == SPR_NPC); |
} |
} |
#endif |
|
// Write the SPR |
selectDebugModule (OR1K_SC_CPU0); |
writeJtagReg (sprNum, value); |
// Write the SPR |
selectDebugModule(OR1K_SC_CPU0); |
writeJtagReg(sprNum, value); |
|
} // writeSpr () |
} // writeSpr () |
|
|
//----------------------------------------------------------------------------- |
//! AND the contents of an SPR with a value |
|
321,15 → 288,12
//! @param[in] sprNum The SPR to write |
//! @param[in] value The value to AND into the register |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::andSpr (uint16_t sprNum, |
uint32_t value) |
void DebugUnitSC::andSpr(uint16_t sprNum, uint32_t value) |
{ |
writeSpr (sprNum, readSpr (sprNum) & value); |
writeSpr(sprNum, readSpr(sprNum) & value); |
|
} // andSpr () |
} // andSpr () |
|
|
//----------------------------------------------------------------------------- |
//! OR the contents of an SPR with a value |
|
338,15 → 302,12
//! @param[in] sprNum The SPR to write |
//! @param[in] value The value to OR into the register |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::orSpr (uint16_t sprNum, |
uint32_t value) |
void DebugUnitSC::orSpr(uint16_t sprNum, uint32_t value) |
{ |
writeSpr (sprNum, readSpr (sprNum) | value); |
writeSpr(sprNum, readSpr(sprNum) | value); |
|
} // orSpr () |
} // orSpr () |
|
|
//----------------------------------------------------------------------------- |
//! Read a 32-bit word from the OpenRISC 1000 memory |
|
359,36 → 320,32
|
//! @return The 32-bit value read |
//----------------------------------------------------------------------------- |
uint32_t |
DebugUnitSC::readMem32 (uint32_t addr) |
uint32_t DebugUnitSC::readMem32(uint32_t addr) |
{ |
uint32_t cachedValue; |
uint32_t cachedValue; |
|
#ifndef NOCACHE |
// Use any cached value if we are stalled. |
if ((STALLED == stallState) && memCache->read (addr, cachedValue)) |
{ |
return cachedValue; // Already there, no more to do |
} |
// Use any cached value if we are stalled. |
if ((STALLED == stallState) && memCache->read(addr, cachedValue)) { |
return cachedValue; // Already there, no more to do |
} |
#endif |
|
// Read the value |
selectDebugModule (OR1K_SC_WISHBONE); |
cachedValue = readJtagReg (addr); |
// Read the value |
selectDebugModule(OR1K_SC_WISHBONE); |
cachedValue = readJtagReg(addr); |
|
#ifndef NOCACHE |
// Update the cache if we are stalled |
if (STALLED == stallState) |
{ |
memCache->write (addr, cachedValue); |
} |
// Update the cache if we are stalled |
if (STALLED == stallState) { |
memCache->write(addr, cachedValue); |
} |
#endif |
|
return cachedValue; |
return cachedValue; |
|
} // readMem32 () |
} // readMem32 () |
|
|
//----------------------------------------------------------------------------- |
//! Write a 32-bit word to the OpenRISC 1000 memory |
|
403,36 → 360,28
//! @return True if the write was successful. For now all writes are |
// successful. |
//----------------------------------------------------------------------------- |
bool |
DebugUnitSC::writeMem32 (uint32_t addr, |
uint32_t value) |
bool DebugUnitSC::writeMem32(uint32_t addr, uint32_t value) |
{ |
#ifndef NOCACHE |
if (STALLED == stallState) |
{ |
// Have we already cached this value? |
uint32_t cachedValue; |
if (memCache->read (addr, cachedValue) && |
(value == cachedValue)) |
{ |
return true; // Already there, no more to do |
if (STALLED == stallState) { |
// Have we already cached this value? |
uint32_t cachedValue; |
if (memCache->read(addr, cachedValue) && (value == cachedValue)) { |
return true; // Already there, no more to do |
} else { |
memCache->write(addr, value); // Write for the future |
} |
} |
else |
{ |
memCache->write (addr, value); // Write for the future |
} |
} |
#endif |
|
// Write the memory |
selectDebugModule (OR1K_SC_WISHBONE); |
writeJtagReg (addr, value); |
// Write the memory |
selectDebugModule(OR1K_SC_WISHBONE); |
writeJtagReg(addr, value); |
|
return true; |
return true; |
|
} // writeMem32 () |
} // writeMem32 () |
|
|
//----------------------------------------------------------------------------- |
//! Read a byte from the OpenRISC 1000 main memory |
|
449,18 → 398,16
//! @param[in] addr The address to read from |
//! @return The byte read |
//----------------------------------------------------------------------------- |
uint8_t |
DebugUnitSC::readMem8 (uint32_t addr) |
uint8_t DebugUnitSC::readMem8(uint32_t addr) |
{ |
uint32_t word = Utils::ttohl (readMem32 (addr & 0xfffffffc)); |
uint8_t *bytes = (uint8_t *)(&word); |
int offset = addr & 0x3; |
uint32_t word = Utils::ttohl(readMem32(addr & 0xfffffffc)); |
uint8_t *bytes = (uint8_t *) (&word); |
int offset = addr & 0x3; |
|
return bytes[offset]; |
return bytes[offset]; |
|
} // readMem8 () |
} // readMem8 () |
|
|
//----------------------------------------------------------------------------- |
//! Write a byte to the OpenRISC 1000 main memory |
|
481,76 → 428,72
//! @return True if the write was successful. For now all writes are |
// successful. |
//----------------------------------------------------------------------------- |
bool |
DebugUnitSC::writeMem8 (uint32_t addr, |
uint8_t value) |
bool DebugUnitSC::writeMem8(uint32_t addr, uint8_t value) |
{ |
uint32_t currWord = Utils::ttohl (readMem32 (addr & 0xfffffffc)); |
uint8_t *currBytes = (uint8_t *)(&currWord); |
int offset = addr & 0x3; |
uint32_t currWord = Utils::ttohl(readMem32(addr & 0xfffffffc)); |
uint8_t *currBytes = (uint8_t *) (&currWord); |
int offset = addr & 0x3; |
|
currBytes[offset] = value; |
currBytes[offset] = value; |
|
return writeMem32 (addr & 0xfffffffc, Utils::htotl (currWord)); |
return writeMem32(addr & 0xfffffffc, Utils::htotl(currWord)); |
|
} // writeMem8 () |
} // writeMem8 () |
|
|
//----------------------------------------------------------------------------- |
//! Get the debug interface CPU0 control register value |
|
//! @return The value in the RISCOP register |
//----------------------------------------------------------------------------- |
uint32_t |
DebugUnitSC::readRiscop () |
uint32_t DebugUnitSC::readRiscop() |
{ |
selectDebugModule (OR1K_SC_CPU0); |
|
int drLen; // Size of the data register |
|
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 1+4+32+52+4+32; |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t [(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t [(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits (dRegIn, drLen); |
|
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, BITREV(0x3,4)); // We're reading CPU0 control reg |
uint32_t crc32_send = crc32 (dRegIn, 0+1+4, 0); |
packBits (dRegIn, 0+1+4, 32, BITREV(crc32_send,32)); |
selectDebugModule(OR1K_SC_CPU0); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, drLen); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut,1+4+32+52,4); |
calc_recv_crc = crc32(dRegOut,52+4,1+4+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+32+52+4,32),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
int drLen; // Size of the data register |
|
// All done |
uint32_t res = BITREV(unpackBits (dRegOut, (1+4+32),2),2); |
|
delete [] dRegIn; |
delete [] dRegOut; |
delete done; |
return res; |
} // readRiscop () |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 1 + 4 + 32 + 52 + 4 + 32; |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t[(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t[(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits(dRegIn, drLen); |
|
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, BITREV(0x3, 4)); // We're reading CPU0 control reg |
uint32_t crc32_send = crc32(dRegIn, 0 + 1 + 4, 0); |
packBits(dRegIn, 0 + 1 + 4, 32, BITREV(crc32_send, 32)); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = |
new TapActionDRScan(done, dRegIn, drLen); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = unpackBits(dRegOut, 1 + 4 + 32 + 52, 4); |
calc_recv_crc = crc32(dRegOut, 52 + 4, 1 + 4 + 32); |
recv_crc = |
BITREV(unpackBits(dRegOut, 1 + 4 + 32 + 52 + 4, 32), 32); |
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
// All done |
uint32_t res = BITREV(unpackBits(dRegOut, (1 + 4 + 32), 2), 2); |
|
delete[]dRegIn; |
delete[]dRegOut; |
delete done; |
return res; |
} // readRiscop () |
|
//----------------------------------------------------------------------------- |
//! Set the RISCOP control register |
|
558,56 → 501,55
|
//! @param[in] value The value to write into the RISCOP register |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::writeRiscop (uint32_t value) |
void DebugUnitSC::writeRiscop(uint32_t value) |
{ |
selectDebugModule (OR1K_SC_CPU0); |
|
int drLen; // Size of the data register |
|
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 1+4+32+52+4+32; |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t [(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t [(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits (dRegIn, drLen); |
|
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, BITREV(0x4,4)); // We're writing CPU0 control reg |
packBits (dRegIn, 5, 1, value&RISCOP_RESET); // First bit is reset |
packBits (dRegIn, 6, 1, (value&RISCOP_STALL)>>1); // Next bit is stall |
/* Next 50 bits should be zero */ |
uint32_t crc32_send = crc32 (dRegIn, 1+4+52, 0); |
packBits (dRegIn, 1+4+52, 32, BITREV(crc32_send,32)); |
selectDebugModule(OR1K_SC_CPU0); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, drLen); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut,1+4+32+52,4); |
calc_recv_crc = crc32(dRegOut,4,1+4+52+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+52+32+4,32),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
|
delete [] dRegIn; |
delete [] dRegOut; |
delete done; |
int drLen; // Size of the data register |
|
} // writeRiscop () |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 1 + 4 + 32 + 52 + 4 + 32; |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t[(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t[(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits(dRegIn, drLen); |
|
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, BITREV(0x4, 4)); // We're writing CPU0 control reg |
packBits(dRegIn, 5, 1, value & RISCOP_RESET); // First bit is reset |
packBits(dRegIn, 6, 1, (value & RISCOP_STALL) >> 1); // Next bit is stall |
/* Next 50 bits should be zero */ |
uint32_t crc32_send = crc32(dRegIn, 1 + 4 + 52, 0); |
packBits(dRegIn, 1 + 4 + 52, 32, BITREV(crc32_send, 32)); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = |
new TapActionDRScan(done, dRegIn, drLen); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = unpackBits(dRegOut, 1 + 4 + 32 + 52, 4); |
calc_recv_crc = crc32(dRegOut, 4, 1 + 4 + 52 + 32); |
recv_crc = |
BITREV(unpackBits(dRegOut, 1 + 4 + 52 + 32 + 4, 32), 32); |
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
delete[]dRegIn; |
delete[]dRegOut; |
delete done; |
|
} // writeRiscop () |
|
//----------------------------------------------------------------------------- |
//! Select a module attached to the debug module |
|
615,60 → 557,64
|
//! @param[in] chain The desired module |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::selectDebugModule (int module) |
void DebugUnitSC::selectDebugModule(int module) |
{ |
|
if (module == currentScanChain) |
{ |
return; |
} |
else |
{ |
currentScanChain = module; |
} |
if (module == currentScanChain) { |
return; |
} else { |
currentScanChain = module; |
} |
|
sc_event *done = new sc_event(); |
TapActionIRScan *iRScan; |
TapActionDRScan *dRScan; |
sc_event *done = new sc_event(); |
TapActionIRScan *iRScan; |
TapActionDRScan *dRScan; |
|
// Create and queue the IR-Scan action for DEBUG (no CRC) |
iRScan = new TapActionIRScan (done, DEBUG_IR, JTAG_IR_LEN); |
tapActionQueue->write (iRScan); |
wait (*done); |
// Create and queue the IR-Scan action for DEBUG (no CRC) |
iRScan = new TapActionIRScan(done, DEBUG_IR, JTAG_IR_LEN); |
tapActionQueue->write(iRScan); |
wait(*done); |
|
delete iRScan; |
delete iRScan; |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t [(DUSEL_DR_LEN + 63) / 64]; |
uint64_t *dRegOut = new uint64_t [(DUSEL_DR_LEN + 63) / 64]; |
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t[(DUSEL_DR_LEN + 63) / 64]; |
uint64_t *dRegOut = new uint64_t[(DUSEL_DR_LEN + 63) / 64]; |
|
clearBits (dRegIn, DUSEL_DR_LEN); |
packBits (dRegIn, DUSEL_SEL_OFF, DUSEL_SEL_LEN, 0x1); |
packBits (dRegIn, DUSEL_OPCODE_OFF, DUSEL_OPCODE_LEN, bit_reverse_data(module,4)); |
uint32_t crc32_send = crc32 (dRegIn, DUSEL_CRC_OFF, 0); |
packBits (dRegIn, DUSEL_CRC_OFF, DUSEL_CRC_LEN, bit_reverse_data(crc32_send,32) ); |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, DUSEL_DR_LEN); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut, DUSEL_RESP_STATUS_OFF, DUSEL_RESP_STATUS_LEN); |
calc_recv_crc = crc32(dRegOut, DUSEL_RESP_STATUS_LEN, DUSEL_RESP_STATUS_OFF); |
recv_crc = bit_reverse_data(unpackBits (dRegOut, DUSEL_RESP_CRC_OFF, DUSEL_RESP_CRC_LEN),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
clearBits(dRegIn, DUSEL_DR_LEN); |
packBits(dRegIn, DUSEL_SEL_OFF, DUSEL_SEL_LEN, 0x1); |
packBits(dRegIn, DUSEL_OPCODE_OFF, DUSEL_OPCODE_LEN, |
bit_reverse_data(module, 4)); |
uint32_t crc32_send = crc32(dRegIn, DUSEL_CRC_OFF, 0); |
packBits(dRegIn, DUSEL_CRC_OFF, DUSEL_CRC_LEN, |
bit_reverse_data(crc32_send, 32)); |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = |
new TapActionDRScan(done, dRegIn, DUSEL_DR_LEN); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = |
unpackBits(dRegOut, DUSEL_RESP_STATUS_OFF, |
DUSEL_RESP_STATUS_LEN); |
calc_recv_crc = |
crc32(dRegOut, DUSEL_RESP_STATUS_LEN, |
DUSEL_RESP_STATUS_OFF); |
recv_crc = |
bit_reverse_data(unpackBits |
(dRegOut, DUSEL_RESP_CRC_OFF, |
DUSEL_RESP_CRC_LEN), 32); |
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
delete [] dRegIn; |
delete [] dRegOut; |
delete done; |
delete[]dRegIn; |
delete[]dRegOut; |
delete done; |
|
} // selectDebugModule() |
|
} // selectDebugModule() |
|
//----------------------------------------------------------------------------- |
//! Read a 32-bit value via the debug interface |
679,86 → 625,93
|
//! @return The register value read |
//----------------------------------------------------------------------------- |
uint32_t |
DebugUnitSC::readJtagReg (uint32_t addr) |
uint32_t DebugUnitSC::readJtagReg(uint32_t addr) |
{ |
int drLen; // Size of the data register |
|
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 125; // Size of write command command (bigger than data read) |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t [(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t [(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits (dRegIn, drLen); |
|
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, BITREV(0x2,4)); // We're writing a command |
packBits (dRegIn, 1+4, 4, BITREV(0x6,4)); // Access type, 0x6 = 32-bit READ |
packBits (dRegIn, 1+4+4, 32, BITREV(addr,32)); // Address |
packBits (dRegIn, 1+4+4+32, 16, BITREV(0x3,16)); // Length (always 32-bit,n=(32/8)-1=3) |
uint32_t crc32_send = crc32 (dRegIn, 1+4+4+32+16, 0); |
packBits (dRegIn, 1+4+4+32+16, 32, BITREV(crc32_send,32)); |
int drLen; // Size of the data register |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, 125); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut,1+4+4+32+16+32,4); |
calc_recv_crc = crc32(dRegOut,4,1+4+4+32+16+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+4+32+16+32+4,32),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
clearBits (dRegIn, drLen); |
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, 0x0); // We're GO'ing command |
crc32_send = crc32 (dRegIn,1+4,0); |
packBits (dRegIn, 1+4, 32, BITREV(crc32_send,32)); // CRC |
|
uint32_t result; |
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, (1+4+32+36+((3+1)*8))); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = BITREV(unpackBits (dRegOut,1+4+32+((3+1)*8),4),4); |
if (status_ret) |
{ |
printf("readJtagReg(): Addr: 0x%.8x Status err: 0x%x\n",addr,status_ret); |
result = 0; |
break; |
drLen = 125; // Size of write command command (bigger than data read) |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t[(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t[(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits(dRegIn, drLen); |
|
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, BITREV(0x2, 4)); // We're writing a command |
packBits(dRegIn, 1 + 4, 4, BITREV(0x6, 4)); // Access type, 0x6 = 32-bit READ |
packBits(dRegIn, 1 + 4 + 4, 32, BITREV(addr, 32)); // Address |
packBits(dRegIn, 1 + 4 + 4 + 32, 16, BITREV(0x3, 16)); // Length (always 32-bit,n=(32/8)-1=3) |
uint32_t crc32_send = crc32(dRegIn, 1 + 4 + 4 + 32 + 16, 0); |
packBits(dRegIn, 1 + 4 + 4 + 32 + 16, 32, BITREV(crc32_send, 32)); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = |
new TapActionDRScan(done, dRegIn, 125); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = unpackBits(dRegOut, 1 + 4 + 4 + 32 + 16 + 32, 4); |
calc_recv_crc = crc32(dRegOut, 4, 1 + 4 + 4 + 32 + 16 + 32); |
recv_crc = |
BITREV(unpackBits |
(dRegOut, 1 + 4 + 4 + 32 + 16 + 32 + 4, 32), 32); |
} |
calc_recv_crc = crc32(dRegOut,((3+1)*8)+4,1+4+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+32+((3+1)*8)+4,32),32); |
result = BITREV(unpackBits (dRegOut, (1+4+32), ((3+1)*8)),32); |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
|
// All done |
|
delete [] dRegIn; |
delete [] dRegOut; |
delete done; |
return result; |
clearBits(dRegIn, drLen); |
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, 0x0); // We're GO'ing command |
crc32_send = crc32(dRegIn, 1 + 4, 0); |
packBits(dRegIn, 1 + 4, 32, BITREV(crc32_send, 32)); // CRC |
|
} // readJtagReg () |
uint32_t result; |
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = new TapActionDRScan(done, dRegIn, |
(1 + 4 + 32 + 36 + |
((3 + 1) * 8))); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = |
BITREV(unpackBits(dRegOut, 1 + 4 + 32 + ((3 + 1) * 8), 4), |
4); |
if (status_ret) { |
printf("readJtagReg(): Addr: 0x%.8x Status err: 0x%x\n", |
addr, status_ret); |
result = 0; |
break; |
} |
calc_recv_crc = crc32(dRegOut, ((3 + 1) * 8) + 4, 1 + 4 + 32); |
recv_crc = |
BITREV(unpackBits |
(dRegOut, 1 + 4 + 32 + ((3 + 1) * 8) + 4, 32), 32); |
result = |
BITREV(unpackBits(dRegOut, (1 + 4 + 32), ((3 + 1) * 8)), |
32); |
|
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
// All done |
|
delete[]dRegIn; |
delete[]dRegOut; |
delete done; |
return result; |
|
} // readJtagReg () |
|
//----------------------------------------------------------------------------- |
//! Write a 32-bit value via the debug interface |
|
767,76 → 720,78
//! @param[in] addr The address of the register |
//! @param[in] data The register data to write |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::writeJtagReg (uint32_t addr, |
uint32_t data) |
void DebugUnitSC::writeJtagReg(uint32_t addr, uint32_t data) |
{ |
int drLen; // Size of the data register |
|
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
drLen = 125; // Size of write command command (bigger than data read) |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t [(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t [(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits (dRegIn, drLen); |
|
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, BITREV(0x2,4)); // We're writing a command |
packBits (dRegIn, 1+4, 4, BITREV(0x2,4)); // Access type, 0x2 = 32-bit WRITE |
packBits (dRegIn, 1+4+4, 32, BITREV(addr,32)); // Address |
packBits (dRegIn, 1+4+4+32, 16, BITREV(0x3,16)); // Length (always 32-bit,n=(32/8)-1=3) |
uint32_t crc32_send = crc32 (dRegIn, 1+4+4+32+16, 0); |
packBits (dRegIn, 1+4+4+32+16, 32, BITREV(crc32_send,32)); |
int drLen; // Size of the data register |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, 125); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut,1+4+4+32+16+32,4); |
calc_recv_crc = crc32(dRegOut,4,1+4+4+32+16+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+4+32+16+32+4,32),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
|
clearBits (dRegIn, drLen); |
packBits (dRegIn, 0, 1, 0); |
packBits (dRegIn, 0+1, 4, 0x0); // We're GO'ing command |
packBits (dRegIn, 0+1+4, 32, BITREV(data,32)); // Add in data |
crc32_send = crc32 (dRegIn,1+4+32,0); |
packBits (dRegIn, 1+4+32, 32, BITREV(crc32_send,32)); // CRC |
|
// Loop until status is OK and CRCs match. |
do |
{ |
TapActionDRScan *dRScan = new TapActionDRScan (done, dRegIn, (1+4+((3+1)*8)+32+36)); |
tapActionQueue->write (dRScan); |
wait (*done); |
dRScan->getDRegOut (dRegOut); |
delete dRScan; |
status_ret = unpackBits (dRegOut,1+4+32+32,4); |
calc_recv_crc = crc32(dRegOut,4,1+4+32+32); |
recv_crc = BITREV(unpackBits (dRegOut,1+4+32+32+4,32),32); |
} |
while ((0 != status_ret) || ( calc_recv_crc != recv_crc)); |
|
delete [] dRegIn; |
delete [] dRegOut; |
delete done; |
uint32_t calc_recv_crc = 0, recv_crc, status_ret; |
|
} // writeJtagReg () |
drLen = 125; // Size of write command command (bigger than data read) |
|
// Initialize the register fields |
uint64_t *dRegIn = new uint64_t[(drLen + 63) / 64]; |
uint64_t *dRegOut = new uint64_t[(drLen + 63) / 64]; |
|
// Write the READ command |
clearBits(dRegIn, drLen); |
|
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, BITREV(0x2, 4)); // We're writing a command |
packBits(dRegIn, 1 + 4, 4, BITREV(0x2, 4)); // Access type, 0x2 = 32-bit WRITE |
packBits(dRegIn, 1 + 4 + 4, 32, BITREV(addr, 32)); // Address |
packBits(dRegIn, 1 + 4 + 4 + 32, 16, BITREV(0x3, 16)); // Length (always 32-bit,n=(32/8)-1=3) |
uint32_t crc32_send = crc32(dRegIn, 1 + 4 + 4 + 32 + 16, 0); |
packBits(dRegIn, 1 + 4 + 4 + 32 + 16, 32, BITREV(crc32_send, 32)); |
|
// Allocate a SystemC completion event |
sc_event *done = new sc_event(); |
|
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = |
new TapActionDRScan(done, dRegIn, 125); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = unpackBits(dRegOut, 1 + 4 + 4 + 32 + 16 + 32, 4); |
calc_recv_crc = crc32(dRegOut, 4, 1 + 4 + 4 + 32 + 16 + 32); |
recv_crc = |
BITREV(unpackBits |
(dRegOut, 1 + 4 + 4 + 32 + 16 + 32 + 4, 32), 32); |
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
clearBits(dRegIn, drLen); |
packBits(dRegIn, 0, 1, 0); |
packBits(dRegIn, 0 + 1, 4, 0x0); // We're GO'ing command |
packBits(dRegIn, 0 + 1 + 4, 32, BITREV(data, 32)); // Add in data |
crc32_send = crc32(dRegIn, 1 + 4 + 32, 0); |
packBits(dRegIn, 1 + 4 + 32, 32, BITREV(crc32_send, 32)); // CRC |
|
// Loop until status is OK and CRCs match. |
do { |
TapActionDRScan *dRScan = new TapActionDRScan(done, dRegIn, |
(1 + 4 + |
((3 + 1) * 8) + |
32 + 36)); |
tapActionQueue->write(dRScan); |
wait(*done); |
dRScan->getDRegOut(dRegOut); |
delete dRScan; |
status_ret = unpackBits(dRegOut, 1 + 4 + 32 + 32, 4); |
calc_recv_crc = crc32(dRegOut, 4, 1 + 4 + 32 + 32); |
recv_crc = |
BITREV(unpackBits(dRegOut, 1 + 4 + 32 + 32 + 4, 32), 32); |
} |
while ((0 != status_ret) || (calc_recv_crc != recv_crc)); |
|
delete[]dRegIn; |
delete[]dRegOut; |
delete done; |
|
} // writeJtagReg () |
|
//----------------------------------------------------------------------------- |
//! Clear the bits in a data register |
|
849,15 → 804,12
//! @param[in,out] regArray The data register to clear |
//! @param[in] regBits Size of the data register (in bits) |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::clearBits (uint64_t regArray[], |
int regBits) |
void DebugUnitSC::clearBits(uint64_t regArray[], int regBits) |
{ |
memset ((char *)regArray, 0, ((regBits + 63) / 64) * 8); |
memset((char *)regArray, 0, ((regBits + 63) / 64) * 8); |
|
} // clearBits () |
} // clearBits () |
|
|
//----------------------------------------------------------------------------- |
//! Set a bit field in a data register |
|
872,43 → 824,37
//! @param[in] fieldBits Size of the field (in bits) |
//! @param[in] fieldVal Value to set in the field |
//----------------------------------------------------------------------------- |
void |
DebugUnitSC::packBits (uint64_t regArray[], |
int fieldOffset, |
int fieldBits, |
uint64_t fieldVal) |
void DebugUnitSC::packBits(uint64_t regArray[], |
int fieldOffset, int fieldBits, uint64_t fieldVal) |
{ |
fieldVal &= (1ULL << fieldBits) - 1ULL; // Mask the supplied value |
fieldVal &= (1ULL << fieldBits) - 1ULL; // Mask the supplied value |
|
int startWord = fieldOffset / 64; |
int endWord = (fieldOffset + fieldBits - 1) / 64; |
int startWord = fieldOffset / 64; |
int endWord = (fieldOffset + fieldBits - 1) / 64; |
|
fieldOffset = fieldOffset % 64; // Now refers to target word |
fieldOffset = fieldOffset % 64; // Now refers to target word |
|
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << fieldBits) - 1ULL) << fieldOffset; |
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << fieldBits) - 1ULL) << fieldOffset; |
|
regArray[startWord] &= ~startMask; |
regArray[startWord] |= fieldVal << fieldOffset; |
regArray[startWord] &= ~startMask; |
regArray[startWord] |= fieldVal << fieldOffset; |
|
// If we were all in one word, we can give up now. |
if (startWord == endWord) |
{ |
return; |
} |
// If we were all in one word, we can give up now. |
if (startWord == endWord) { |
return; |
} |
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (fieldOffset + fieldBits) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
|
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (fieldOffset + fieldBits) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
regArray[endWord] &= ~endMask; |
regArray[endWord] |= fieldVal >> (fieldBits - bitsToDo); |
|
regArray[endWord] &= ~endMask; |
regArray[endWord] |= fieldVal >> (fieldBits - bitsToDo); |
} // packBits () |
|
} // packBits () |
|
|
//----------------------------------------------------------------------------- |
//! Extract a bit field from a data register |
|
925,39 → 871,34
//! @return The value in the field |
//----------------------------------------------------------------------------- |
uint64_t |
DebugUnitSC::unpackBits (uint64_t regArray[], |
int fieldOffset, |
int fieldBits) |
DebugUnitSC::unpackBits(uint64_t regArray[], int fieldOffset, int fieldBits) |
{ |
int startWord = fieldOffset / 64; |
int endWord = (fieldOffset + fieldBits - 1) / 64; |
int startWord = fieldOffset / 64; |
int endWord = (fieldOffset + fieldBits - 1) / 64; |
|
fieldOffset = fieldOffset % 64; // Now refers to target word |
fieldOffset = fieldOffset % 64; // Now refers to target word |
|
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << fieldBits) - 1ULL) << fieldOffset; |
uint64_t res = (regArray[startWord] & startMask) >> fieldOffset; |
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << fieldBits) - 1ULL) << fieldOffset; |
uint64_t res = (regArray[startWord] & startMask) >> fieldOffset; |
|
// If we were all in one word, we can give up now. |
if (startWord == endWord) |
{ |
res &= (1ULL << fieldBits) - 1ULL; // Mask off any unwanted bits |
return res; |
} |
// If we were all in one word, we can give up now. |
if (startWord == endWord) { |
res &= (1ULL << fieldBits) - 1ULL; // Mask off any unwanted bits |
return res; |
} |
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (fieldOffset + fieldBits) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
|
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (fieldOffset + fieldBits) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
res = res | ((regArray[endWord] & endMask) << (fieldBits - bitsToDo)); |
res &= (1ULL << fieldBits) - 1ULL; // Mask off any unwanted bits |
return res; |
|
res = res | ((regArray[endWord] & endMask) << (fieldBits - bitsToDo)); |
res &= (1ULL << fieldBits) - 1ULL; // Mask off any unwanted bits |
return res; |
} // unpackBits () |
|
} // unpackBits () |
|
|
//----------------------------------------------------------------------------- |
//! Compute CRC-8-ATM |
|
974,99 → 915,101
//! @param dataArray The array of data whose CRC is desired |
//! @param size The number of bits in the data |
//----------------------------------------------------------------------------- |
uint8_t |
DebugUnitSC::crc8 (uint64_t dataArray[], |
int size) |
uint8_t DebugUnitSC::crc8(uint64_t dataArray[], int size) |
{ |
uint8_t crc = 0; |
uint8_t crc = 0; |
|
for (int i = 0; i < size; i++) |
{ |
uint8_t d = (dataArray[i / 64] >> (i % 64)) & 1; |
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
for (int i = 0; i < size; i++) { |
uint8_t d = (dataArray[i / 64] >> (i % 64)) & 1; |
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
|
crc = ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | newCrc0; |
} |
crc = |
((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | |
newCrc0; |
} |
|
return crc; |
return crc; |
|
} // crc8 () |
} // crc8 () |
|
/* Crc of current read or written data. */ |
uint32_t crc_r, crc_w = 0; |
|
/* Generates new crc, sending in new bit input_bit */ |
uint32_t |
DebugUnitSC::crc32(uint64_t dataArray[], |
int size, |
int offset) |
uint32_t DebugUnitSC::crc32(uint64_t dataArray[], int size, int offset) |
{ |
uint32_t crc = 0xffffffff; |
for (int i = offset; i < size+offset; i++) |
{ |
uint32_t d = ((dataArray[i / 64] >> (i % 64)) & 1) ? 0xfffffff : 0x0000000; |
uint32_t crc_32 = ((crc >> 31)&1) ? 0xfffffff : 0x0000000; |
crc <<= 1; |
crc = crc ^ ((d ^ crc_32) & DBG_CRC32_POLY); |
} |
uint32_t crc = 0xffffffff; |
for (int i = offset; i < size + offset; i++) { |
uint32_t d = |
((dataArray[i / 64] >> (i % 64)) & 1) ? 0xfffffff : |
0x0000000; |
uint32_t crc_32 = ((crc >> 31) & 1) ? 0xfffffff : 0x0000000; |
crc <<= 1; |
crc = crc ^ ((d ^ crc_32) & DBG_CRC32_POLY); |
} |
|
return crc; |
return crc; |
} |
|
uint32_t |
DebugUnitSC::bit_reverse_swar_2(uint32_t x) |
uint32_t DebugUnitSC::bit_reverse_swar_2(uint32_t x) |
{ |
return (((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1)); |
return (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
} |
uint32_t |
DebugUnitSC::bit_reverse_swar_4(uint32_t x) |
|
uint32_t DebugUnitSC::bit_reverse_swar_4(uint32_t x) |
{ |
x=(((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1)); |
x=(((x&0xcccccccc)>>2)|((x&0x33333333)<<2)); |
return x; |
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); |
return x; |
} |
uint32_t |
DebugUnitSC::bit_reverse_swar_8(uint32_t x) |
|
uint32_t DebugUnitSC::bit_reverse_swar_8(uint32_t x) |
{ |
x=(((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1)); |
x=(((x&0xcccccccc)>>2)|((x&0x33333333)<<2)); |
x=(((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4)); |
return x; |
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); |
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); |
return x; |
} |
uint32_t |
DebugUnitSC::bit_reverse_swar_16(uint32_t x) |
|
uint32_t DebugUnitSC::bit_reverse_swar_16(uint32_t x) |
{ |
x=(((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1)); |
x=(((x&0xcccccccc)>>2)|((x&0x33333333)<<2)); |
x=(((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4)); |
x=(((x&0xff00ff00)>>8)|((x&0x00ff00ff)<<8)); |
return x; |
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); |
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); |
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); |
return x; |
} |
uint32_t |
DebugUnitSC::bit_reverse_swar_32(uint32_t x) |
|
uint32_t DebugUnitSC::bit_reverse_swar_32(uint32_t x) |
{ |
x=(((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1)); |
x=(((x&0xcccccccc)>>2)|((x&0x33333333)<<2)); |
x=(((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4)); |
x=(((x&0xff00ff00)>>8)|((x&0x00ff00ff)<<8)); |
x=(((x&0xffff0000)>>16)|((x&0x0000ffff)<<16)); // We could be on 64-bit arch! |
return x; |
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); |
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); |
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); |
x = (((x & 0xffff0000) >> 16) | ((x & 0x0000ffff) << 16)); // We could be on 64-bit arch! |
return x; |
} |
|
uint32_t |
DebugUnitSC::bit_reverse_data(uint32_t data, int length){ |
if (length == 2) return bit_reverse_swar_2(data); |
if (length == 4) return bit_reverse_swar_4(data); |
if (length == 8) return bit_reverse_swar_8(data); |
if (length == 16) return bit_reverse_swar_16(data); |
if (length == 32) return bit_reverse_swar_32(data); |
// Long and laborious way - hopefully never gets called anymore! |
uint32_t reverse=0; |
for (int i=0;i<length;i++) reverse |= (((data>>i)&1)<<(length-1-i)); |
return reverse; |
|
uint32_t DebugUnitSC::bit_reverse_data(uint32_t data, int length) |
{ |
if (length == 2) |
return bit_reverse_swar_2(data); |
if (length == 4) |
return bit_reverse_swar_4(data); |
if (length == 8) |
return bit_reverse_swar_8(data); |
if (length == 16) |
return bit_reverse_swar_16(data); |
if (length == 32) |
return bit_reverse_swar_32(data); |
// Long and laborious way - hopefully never gets called anymore! |
uint32_t reverse = 0; |
for (int i = 0; i < length; i++) |
reverse |= (((data >> i) & 1) << (length - 1 - i)); |
return reverse; |
} |
/sysc/src/TapActionDRScan.cpp
33,7 → 33,6
#include "TapActionDRScan.h" |
#include "TapStateMachine.h" |
|
|
//! Constructor for "large" DR registers |
|
//! Sets up the superclass with the SystemC completion event and initializes |
51,45 → 50,35
//! @param[in] _dRegInArray The register to shift in. |
//! @param[in] _dRegSize Size in bits of the register to shift in. |
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t *_dRegInArray, |
int _dRegSize |
) : |
TapAction (_doneEvent), |
dRegBitSize (_dRegSize), |
dRegWordSize ((_dRegSize + 63) / 64), |
goToPauseState(0), |
bitsBeforePause(0), |
bitsShifted (0), |
dRScanState (SHIFT_DR_PREPARING) |
TapActionDRScan::TapActionDRScan(sc_core::sc_event * _doneEvent, uint64_t * _dRegInArray, int _dRegSize): |
TapAction(_doneEvent), |
dRegBitSize(_dRegSize), |
dRegWordSize((_dRegSize + 63) / 64), |
goToPauseState(0), |
bitsBeforePause(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING) |
{ |
// Small registers are represented simply. Large registers are copied to a |
// local instance (since we destroy dRegIn when shifting it) |
// Small registers are represented simply. Large registers are copied to a |
// local instance (since we destroy dRegIn when shifting it) |
|
if (1 == dRegWordSize) |
{ |
dRegIn = _dRegInArray[0]; |
dRegOut = 0; |
} |
else |
{ |
dRegInArray = new uint64_t [dRegWordSize]; |
dRegOutArray = new uint64_t [dRegWordSize]; |
if (1 == dRegWordSize) { |
dRegIn = _dRegInArray[0]; |
dRegOut = 0; |
} else { |
dRegInArray = new uint64_t[dRegWordSize]; |
dRegOutArray = new uint64_t[dRegWordSize]; |
|
// Copy in the in array and zero the out array |
for (int i = 0; i < dRegWordSize; i++) |
{ |
dRegInArray[i] = _dRegInArray[i]; |
dRegOutArray[i] = 0; |
// Copy in the in array and zero the out array |
for (int i = 0; i < dRegWordSize; i++) { |
dRegInArray[i] = _dRegInArray[i]; |
dRegOutArray[i] = 0; |
} |
|
// Create a mask for the top word |
int maskBits = ((dRegBitSize - 1) % 64) + 1; |
topMask = (1ULL << maskBits) - 1ULL; |
} |
} // TapActionDRScan () |
|
// Create a mask for the top word |
int maskBits = ((dRegBitSize - 1) % 64) + 1; |
topMask = (1ULL << maskBits) - 1ULL; |
} |
} // TapActionDRScan () |
|
|
//! Constructor for small DR registers |
|
//! Sets up the superclass with the SystemC completion event and initializes |
104,30 → 93,25
//! greater than 64, or we give a rude message and set |
//! the value to 64 anyway. |
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegIn, |
int _dRegSize) : |
TapAction (_doneEvent), |
dRegBitSize (_dRegSize), |
dRegWordSize (1), |
goToPauseState(0), |
bitsBeforePause(0), |
bitsShifted (0), |
dRScanState (SHIFT_DR_PREPARING) |
TapActionDRScan::TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegIn, |
int _dRegSize):TapAction(_doneEvent), |
dRegBitSize(_dRegSize), |
dRegWordSize(1), |
goToPauseState(0), |
bitsBeforePause(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING) |
{ |
// Print a rude message if we are not small |
if (dRegBitSize > 64) |
{ |
std::cerr << "Simple DR size reduced to 64 bits" << std::endl; |
dRegBitSize = 64; |
} |
// Print a rude message if we are not small |
if (dRegBitSize > 64) { |
std::cerr << "Simple DR size reduced to 64 bits" << std::endl; |
dRegBitSize = 64; |
} |
// Simple representation |
dRegIn = _dRegIn; |
dRegOut = 0; |
|
// Simple representation |
dRegIn = _dRegIn; |
dRegOut = 0; |
} // TapActionDRScan () |
|
} // TapActionDRScan () |
|
//! Constructor for "large" DR registers using special PAUSE state |
|
//! Sets up the superclass with the SystemC completion event and initializes |
147,48 → 131,38
//! @param[in] _goToPauseState Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0 |
//! @param[in] _bitsBeforePauseState Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed |
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t *_dRegInArray, |
int _dRegSize, |
int _goToPauseState, |
int _bitsBeforePauseState |
) : |
TapAction (_doneEvent), |
dRegBitSize (_dRegSize), |
dRegWordSize ((_dRegSize + 63) / 64), |
goToPauseState(_goToPauseState), |
bitsBeforePause(_bitsBeforePauseState), |
pauseStateCount(0), |
bitsShifted (0), |
dRScanState (SHIFT_DR_PREPARING) |
TapActionDRScan::TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t * _dRegInArray, |
int _dRegSize, |
int _goToPauseState, |
int |
_bitsBeforePauseState):TapAction(_doneEvent), |
dRegBitSize(_dRegSize), dRegWordSize((_dRegSize + 63) / 64), |
goToPauseState(_goToPauseState), bitsBeforePause(_bitsBeforePauseState), |
pauseStateCount(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING) |
{ |
// Small registers are represented simply. Large registers are copied to a |
// local instance (since we destroy dRegIn when shifting it) |
// Small registers are represented simply. Large registers are copied to a |
// local instance (since we destroy dRegIn when shifting it) |
|
if (1 == dRegWordSize) |
{ |
dRegIn = _dRegInArray[0]; |
dRegOut = 0; |
} |
else |
{ |
dRegInArray = new uint64_t [dRegWordSize]; |
dRegOutArray = new uint64_t [dRegWordSize]; |
if (1 == dRegWordSize) { |
dRegIn = _dRegInArray[0]; |
dRegOut = 0; |
} else { |
dRegInArray = new uint64_t[dRegWordSize]; |
dRegOutArray = new uint64_t[dRegWordSize]; |
|
// Copy in the in array and zero the out array |
for (int i = 0; i < dRegWordSize; i++) |
{ |
dRegInArray[i] = _dRegInArray[i]; |
dRegOutArray[i] = 0; |
// Copy in the in array and zero the out array |
for (int i = 0; i < dRegWordSize; i++) { |
dRegInArray[i] = _dRegInArray[i]; |
dRegOutArray[i] = 0; |
} |
|
// Create a mask for the top word |
int maskBits = ((dRegBitSize - 1) % 64) + 1; |
topMask = (1ULL << maskBits) - 1ULL; |
} |
} // TapActionDRScan () |
|
// Create a mask for the top word |
int maskBits = ((dRegBitSize - 1) % 64) + 1; |
topMask = (1ULL << maskBits) - 1ULL; |
} |
} // TapActionDRScan () |
|
|
//! Constructor for small DR registers using special PAUSE state |
|
//! Sets up the superclass with the SystemC completion event and initializes |
205,52 → 179,39
//! @param[in] _goToPauseState Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0 |
//! @param[in] _bitsBeforePauseState Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed |
|
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent, |
uint64_t _dRegIn, |
int _dRegSize, |
int _goToPauseState, |
int _bitsBeforePauseState |
) : |
TapAction (_doneEvent), |
dRegBitSize (_dRegSize), |
dRegWordSize (1), |
goToPauseState(_goToPauseState), |
bitsBeforePause(_bitsBeforePauseState), |
pauseStateCount(0), |
bitsShifted (0), |
dRScanState (SHIFT_DR_PREPARING) |
TapActionDRScan::TapActionDRScan(sc_core::sc_event * _doneEvent, |
uint64_t _dRegIn, |
int _dRegSize, |
int _goToPauseState, |
int |
_bitsBeforePauseState):TapAction(_doneEvent), |
dRegBitSize(_dRegSize), dRegWordSize(1), goToPauseState(_goToPauseState), |
bitsBeforePause(_bitsBeforePauseState), pauseStateCount(0), bitsShifted(0), |
dRScanState(SHIFT_DR_PREPARING) |
{ |
// Print a rude message if we are not small |
if (dRegBitSize > 64) |
{ |
std::cerr << "Simple DR size reduced to 64 bits" << std::endl; |
dRegBitSize = 64; |
} |
// Print a rude message if we are not small |
if (dRegBitSize > 64) { |
std::cerr << "Simple DR size reduced to 64 bits" << std::endl; |
dRegBitSize = 64; |
} |
// Simple representation |
dRegIn = _dRegIn; |
dRegOut = 0; |
|
// Simple representation |
dRegIn = _dRegIn; |
dRegOut = 0; |
} // TapActionDRScan () |
|
} // TapActionDRScan () |
|
|
|
|
//! Destructor. |
|
//! If we allocated them, free the large registers |
|
TapActionDRScan::~TapActionDRScan () |
TapActionDRScan::~TapActionDRScan() |
{ |
if (dRegWordSize > 1) |
{ |
delete [] dRegInArray; |
delete [] dRegOutArray; |
} |
} // ~TapActionDRScan () |
if (dRegWordSize > 1) { |
delete[]dRegInArray; |
delete[]dRegOutArray; |
} |
} // ~TapActionDRScan () |
|
|
//! Process the Shift-DR action |
|
//! This drives the DR-Scan state. We can only do this if we have the TAP |
269,236 → 230,193
|
//! @return True if the action is complete |
|
bool |
TapActionDRScan::process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms) |
bool TapActionDRScan::process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms) |
{ |
// Ensure we are in a consistent state. If not then we'll have moved towards |
// it and can return with the given tms |
if (!checkResetDone (tapStateMachine, tms, true)) |
{ |
return false; |
} |
|
if (goToPauseState) |
{ |
switch (dRScanState) |
{ |
case SHIFT_DR_PREPARING: |
|
// Are we in the Shift-DR state yet? |
if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
else |
{ |
dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE; // Drop through |
} |
|
case SHIFT_DR_SHIFTING_BEFORE_PAUSE: |
|
// Are we still shifting stuff? |
if (bitsShifted < bitsBeforePause) |
{ |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut (); |
|
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) |
{ |
shiftDRegIn (tdo); |
} |
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == bitsBeforePause); |
|
// Not done until we've updated |
return false; |
} |
else |
{ |
// Capture the last TDO bit |
shiftDRegIn (tdo); |
|
// Now lower TMS to go to PAUSE_DR |
tms = false; |
|
dRScanState = SHIFT_DR_SHIFTING_PAUSE; |
|
} |
|
case SHIFT_DR_SHIFTING_PAUSE: |
{ |
if (!tapStateMachine->targetState (TAP_PAUSE_DR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
|
if ( pauseStateCount++ < 3) |
return false; |
// Sit in DR_PAUSE state and cycle until TDO is low |
// tms starts false, should get set to true on the cycle |
// tdo goes low, then the next cycle we go back to SHIFT_DR |
// and we return so tms isn't set again. |
if (!tdo) |
{ |
tms = true; |
dRScanState = SHIFT_DR_EXIT2; |
// Ensure we are in a consistent state. If not then we'll have moved towards |
// it and can return with the given tms |
if (!checkResetDone(tapStateMachine, tms, true)) { |
return false; |
} |
} |
|
case SHIFT_DR_EXIT2: |
{ |
tms = false; |
shiftDRegIn (0); |
dRScanState = SHIFT_DR_SHIFTING_AFTER_PAUSE; |
return false; |
|
} |
|
case SHIFT_DR_SHIFTING_AFTER_PAUSE: |
{ |
if (bitsShifted < dRegBitSize) |
{ |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut (); |
|
//printf("shifting after pause (%d+32=%d) %d of %d tdo=%d\n",bitsBeforePause,bitsBeforePause+32, bitsShifted, dRegBitSize,(tdo) ? 1 : 0); |
shiftDRegIn (tdo); |
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == dRegBitSize); |
|
// Not done until we've updated |
return false; |
} |
else |
{ |
// Capture the last TDO bit |
shiftDRegIn (tdo); |
|
dRScanState = SHIFT_DR_UPDATING; // Drop through |
} |
} |
|
|
case SHIFT_DR_UPDATING: |
|
// Are we still trying to update? |
if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
else |
{ |
return true; // All done |
} |
} |
} |
else |
{ |
switch (dRScanState) |
{ |
case SHIFT_DR_PREPARING: |
|
// Are we in the Shift-DR state yet? |
if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
else |
{ |
dRScanState = SHIFT_DR_SHIFTING; // Drop through |
} |
|
case SHIFT_DR_SHIFTING: |
|
// Are we still shifting stuff? |
if (bitsShifted < dRegBitSize) |
{ |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut (); |
|
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) |
{ |
shiftDRegIn (tdo); |
|
if (goToPauseState) { |
switch (dRScanState) { |
case SHIFT_DR_PREPARING: |
|
// Are we in the Shift-DR state yet? |
if (!tapStateMachine->targetState(TAP_SHIFT_DR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE; // Drop through |
} |
|
case SHIFT_DR_SHIFTING_BEFORE_PAUSE: |
|
// Are we still shifting stuff? |
if (bitsShifted < bitsBeforePause) { |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut(); |
|
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) { |
shiftDRegIn(tdo); |
} |
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == bitsBeforePause); |
|
// Not done until we've updated |
return false; |
} else { |
// Capture the last TDO bit |
shiftDRegIn(tdo); |
|
// Now lower TMS to go to PAUSE_DR |
tms = false; |
|
dRScanState = SHIFT_DR_SHIFTING_PAUSE; |
|
} |
|
case SHIFT_DR_SHIFTING_PAUSE: |
{ |
if (!tapStateMachine->targetState |
(TAP_PAUSE_DR, tms)) { |
return false; // Not there. Accept the TMS value |
} |
|
if (pauseStateCount++ < 3) |
return false; |
// Sit in DR_PAUSE state and cycle until TDO is low |
// tms starts false, should get set to true on the cycle |
// tdo goes low, then the next cycle we go back to SHIFT_DR |
// and we return so tms isn't set again. |
if (!tdo) { |
tms = true; |
dRScanState = SHIFT_DR_EXIT2; |
return false; |
} |
} |
|
case SHIFT_DR_EXIT2: |
{ |
tms = false; |
shiftDRegIn(0); |
dRScanState = SHIFT_DR_SHIFTING_AFTER_PAUSE; |
return false; |
|
} |
|
case SHIFT_DR_SHIFTING_AFTER_PAUSE: |
{ |
if (bitsShifted < dRegBitSize) { |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut(); |
|
//printf("shifting after pause (%d+32=%d) %d of %d tdo=%d\n",bitsBeforePause,bitsBeforePause+32, bitsShifted, dRegBitSize,(tdo) ? 1 : 0); |
shiftDRegIn(tdo); |
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == dRegBitSize); |
|
// Not done until we've updated |
return false; |
} else { |
// Capture the last TDO bit |
shiftDRegIn(tdo); |
|
dRScanState = SHIFT_DR_UPDATING; // Drop through |
} |
} |
|
case SHIFT_DR_UPDATING: |
|
// Are we still trying to update? |
if (!tapStateMachine->targetState(TAP_UPDATE_DR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
return true; // All done |
} |
} |
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == dRegBitSize); |
|
// Not done until we've updated |
return false; |
} |
else |
{ |
// Capture the last TDO bit |
shiftDRegIn (tdo); |
|
dRScanState = SHIFT_DR_UPDATING; // Drop through |
|
} |
|
case SHIFT_DR_UPDATING: |
|
// Are we still trying to update? |
if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
else |
{ |
return true; // All done |
} |
} else { |
switch (dRScanState) { |
case SHIFT_DR_PREPARING: |
|
// Are we in the Shift-DR state yet? |
if (!tapStateMachine->targetState(TAP_SHIFT_DR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
dRScanState = SHIFT_DR_SHIFTING; // Drop through |
} |
|
case SHIFT_DR_SHIFTING: |
|
// Are we still shifting stuff? |
if (bitsShifted < dRegBitSize) { |
// We are in the Shift-DR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Set the TDI value. In a routine to keep this tidy. |
tdi = shiftDRegOut(); |
|
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) { |
shiftDRegIn(tdo); |
} |
// TMS is 0 to keep us here UNLESS this is the last bit, in which case |
// it is 1 to move us into Exit1-DR. |
tms = (bitsShifted == dRegBitSize); |
|
// Not done until we've updated |
return false; |
} else { |
// Capture the last TDO bit |
shiftDRegIn(tdo); |
|
dRScanState = SHIFT_DR_UPDATING; // Drop through |
|
} |
|
case SHIFT_DR_UPDATING: |
|
// Are we still trying to update? |
if (!tapStateMachine->targetState(TAP_UPDATE_DR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
return true; // All done |
} |
} |
} |
} |
} // process () |
} // process () |
|
|
//! Get the shifted out value. |
|
//! This version works with large values. |
|
//! @param[out] dRegArray Array for the result |
void |
TapActionDRScan::getDRegOut (uint64_t dRegArray[]) |
void TapActionDRScan::getDRegOut(uint64_t dRegArray[]) |
{ |
if (1 == dRegWordSize) |
{ |
dRegArray[0] = dRegOut; |
} |
else |
{ |
for (int i = 0 ; i < dRegWordSize; i++) |
{ |
dRegArray[i] = dRegOutArray[i]; |
if (1 == dRegWordSize) { |
dRegArray[0] = dRegOut; |
} else { |
for (int i = 0; i < dRegWordSize; i++) { |
dRegArray[i] = dRegOutArray[i]; |
} |
} |
} |
} // getDRegOut () |
} // getDRegOut () |
|
|
//! Get the shifted out value. |
|
//! This version is for small values. For large values it silently returns the |
509,51 → 427,43
|
//! @return The value shifted out (or the bottom 64 bits thereof if the |
//! register is "large"). |
uint64_t |
TapActionDRScan::getDRegOut () |
uint64_t TapActionDRScan::getDRegOut() |
{ |
if (1 == dRegWordSize) |
{ |
return dRegOut; |
} |
else |
{ |
return dRegOutArray[0]; |
} |
} // getDRegOut () |
if (1 == dRegWordSize) { |
return dRegOut; |
} else { |
return dRegOutArray[0]; |
} |
} // getDRegOut () |
|
|
//! Utility to shift the bottom bit out of the dReg. |
|
//! Two flavours depending on whether we have a "small" register |
|
//! @return The bit shifted out. |
bool |
TapActionDRScan::shiftDRegOut () |
bool TapActionDRScan::shiftDRegOut() |
{ |
if (1 == dRegWordSize) // "Small" register |
{ |
bool res = dRegIn & 1; |
dRegIn >>= 1; |
return res; |
} |
else // "Large" register |
{ |
bool res = (dRegInArray[0] & 1) == 1; |
|
// Shift all but the first word along |
for (int i = 0; i < (dRegWordSize - 1); i++) |
if (1 == dRegWordSize) // "Small" register |
{ |
dRegInArray[i] = (dRegInArray[i] >> 1) | (dRegInArray[i+1] << 63); |
} |
bool res = dRegIn & 1; |
dRegIn >>= 1; |
return res; |
} else // "Large" register |
{ |
bool res = (dRegInArray[0] & 1) == 1; |
|
// Shift the first word |
dRegInArray[dRegWordSize - 1] >>= 1; |
// Shift all but the first word along |
for (int i = 0; i < (dRegWordSize - 1); i++) { |
dRegInArray[i] = |
(dRegInArray[i] >> 1) | (dRegInArray[i + 1] << 63); |
} |
|
return res; |
} |
} // shiftDRegOut () |
// Shift the first word |
dRegInArray[dRegWordSize - 1] >>= 1; |
|
return res; |
} |
} // shiftDRegOut () |
|
//! Utility to shift the top bit into the dReg. |
|
560,30 → 470,28
//! Two flavours depending on whether we have a "small" register |
|
//! @param bitIn The bit to shift in the top |
void |
TapActionDRScan::shiftDRegIn (bool bitIn) |
void TapActionDRScan::shiftDRegIn(bool bitIn) |
{ |
if (1 == dRegWordSize) // "Small" register |
{ |
dRegOut >>= 1; // Move all the existing bits right |
if (1 == dRegWordSize) // "Small" register |
{ |
dRegOut >>= 1; // Move all the existing bits right |
|
if (bitIn) // OR any new bit in |
if (bitIn) // OR any new bit in |
{ |
uint64_t tmpBit = 1ULL << (dRegBitSize - 1); |
dRegOut |= tmpBit; |
} |
} else // "Large" register |
{ |
uint64_t tmpBit = 1ULL << (dRegBitSize - 1); |
dRegOut |= tmpBit; |
// Shift all but the first word along |
for (int i = 0; i < (dRegWordSize - 1); i++) { |
dRegOutArray[i] >>= 1; |
dRegOutArray[i] |= dRegOutArray[i + 1] << 63; |
} |
|
// The first word is shifted and the new bit masked in |
dRegOutArray[dRegWordSize - 1] >>= 1; |
dRegOutArray[dRegWordSize - 1] |= |
bitIn ? (topMask + 1) >> 1 : 0; |
} |
} |
else // "Large" register |
{ |
// Shift all but the first word along |
for (int i = 0; i < (dRegWordSize - 1); i++) |
{ |
dRegOutArray[i] >>= 1; |
dRegOutArray[i] |= dRegOutArray[i+1] << 63; |
} |
|
// The first word is shifted and the new bit masked in |
dRegOutArray[dRegWordSize - 1] >>= 1; |
dRegOutArray[dRegWordSize - 1] |= bitIn ? (topMask + 1) >> 1 : 0; |
} |
} // shiftDRegIn () |
} // shiftDRegIn () |
/sysc/src/MpHash.cpp
30,35 → 30,31
|
#include "MpHash.h" |
|
|
//! Constructor |
|
//! Allocate the hash table |
//! @param[in] size Number of slots in the hash table. Defaults to |
//! DEFAULT_MP_HASH_SIZE. |
MpHash::MpHash (int _size) : |
size (_size) |
MpHash::MpHash(int _size): |
size(_size) |
{ |
// Allocate and clear the hash table |
hashTab = new MpEntry *[size]; |
// Allocate and clear the hash table |
hashTab = new MpEntry *[size]; |
|
for (int i = 0; i < size; i++) |
{ |
hashTab[i] = NULL; |
} |
} // MpHash () |
for (int i = 0; i < size; i++) { |
hashTab[i] = NULL; |
} |
} // MpHash () |
|
|
//! Destructor |
|
//! Free the hash table |
MpHash::~MpHash () |
MpHash::~MpHash() |
{ |
delete [] hashTab; |
delete[]hashTab; |
|
} // ~MpHash () |
} // ~MpHash () |
|
|
//! Add an entry to the hash table |
|
//! Add the entry if it wasn't already there. If it was there do nothing. The |
73,34 → 69,29
//! @param[in] addr The address of the matchpoint |
//! @para[in] instr The instruction to associate with the address |
void |
MpHash::add (MpType type, |
uint32_t addr, |
uint32_t instr) |
MpHash::add(MpType type, uint32_t addr, uint32_t instr) |
{ |
int hv = addr % size; |
MpEntry *curr; |
int hv = addr % size; |
MpEntry *curr; |
|
// See if we already have the entry |
for(curr = hashTab[hv]; NULL != curr; curr = curr->next) |
{ |
if ((type == curr->type) && (addr == curr->addr)) |
{ |
return; // We already have the entry |
// See if we already have the entry |
for (curr = hashTab[hv]; NULL != curr; curr = curr->next) { |
if ((type == curr->type) && (addr == curr->addr)) { |
return; // We already have the entry |
} |
} |
} |
|
// Insert the new entry at the head of the chain |
curr = new MpEntry (); |
|
curr->type = type; |
curr->addr = addr; |
curr->instr = instr; |
curr->next = hashTab[hv]; |
// Insert the new entry at the head of the chain |
curr = new MpEntry(); |
|
hashTab[hv] = curr; |
curr->type = type; |
curr->addr = addr; |
curr->instr = instr; |
curr->next = hashTab[hv]; |
|
} // add () |
hashTab[hv] = curr; |
|
} // add () |
|
//!Look up an entry in the matchpoint hash table |
|
110,25 → 101,20
//! @param[in] addr The address of the matchpoint |
|
//! @return The entry found, or NULL if the entry was not found |
MpEntry * |
MpHash::lookup (MpType type, |
uint32_t addr) |
MpEntry *MpHash::lookup(MpType type, uint32_t addr) |
{ |
int hv = addr % size; |
int hv = addr % size; |
|
// Search |
for (MpEntry *curr = hashTab[hv]; NULL != curr; curr = curr->next) |
{ |
if ((type == curr->type) && (addr == curr->addr)) |
{ |
return curr; // The entry found |
// Search |
for (MpEntry * curr = hashTab[hv]; NULL != curr; curr = curr->next) { |
if ((type == curr->type) && (addr == curr->addr)) { |
return curr; // The entry found |
} |
} |
} |
|
return NULL; // Not found |
|
} // lookup () |
return NULL; // Not found |
|
} // lookup () |
|
//! Delete an entry from the matchpoint hash table |
|
145,43 → 131,34
//! default) then the instruction is not written back. |
|
//! @return TRUE if an entry was found and deleted |
bool |
MpHash::remove (MpType type, |
uint32_t addr, |
uint32_t *instr) |
bool MpHash::remove(MpType type, uint32_t addr, uint32_t * instr) |
{ |
int hv = addr % size; |
MpEntry *prev = NULL; |
MpEntry *curr; |
int hv = addr % size; |
MpEntry *prev = NULL; |
MpEntry *curr; |
|
// Search |
for (curr = hashTab[hv]; NULL != curr; curr = curr->next) |
{ |
if ((type == curr->type) && (addr == curr->addr)) |
{ |
// Found - delete. Method depends on whether we are the head of |
// chain. |
if (NULL == prev) |
{ |
hashTab[hv] = curr->next; |
} |
else |
{ |
prev->next = curr->next; |
} |
// Search |
for (curr = hashTab[hv]; NULL != curr; curr = curr->next) { |
if ((type == curr->type) && (addr == curr->addr)) { |
// Found - delete. Method depends on whether we are the head of |
// chain. |
if (NULL == prev) { |
hashTab[hv] = curr->next; |
} else { |
prev->next = curr->next; |
} |
|
if (NULL != instr) |
{ |
*instr = curr->instr; // Return the found instruction |
} |
if (NULL != instr) { |
*instr = curr->instr; // Return the found instruction |
} |
|
delete curr; |
return true; // Success |
delete curr; |
return true; // Success |
} |
|
prev = curr; |
} |
|
prev = curr; |
} |
return false; // Not found |
|
return false; // Not found |
|
} // remove () |
} // remove () |
/sysc/src/Or1200MonitorSC.cpp
38,9 → 38,10
#include "OrpsocMain.h" |
|
#include <errno.h> |
int monitor_to_gdb_pipe[2][2]; // [0][] - monitor to gdb, [1][] - gdb to monitor, [][0] - read, [][1] - write |
int monitor_to_gdb_pipe[2][2]; // [0][] - monitor to gdb, [1][] - gdb to |
// monitor, [][0] - read, [][1] - write |
|
SC_HAS_PROCESS( Or1200MonitorSC ); |
SC_HAS_PROCESS(Or1200MonitorSC); |
|
//! Constructor for the OpenRISC 1200 monitor |
|
47,333 → 48,304
//! @param[in] name Name of this module, passed to the parent constructor. |
//! @param[in] accessor Accessor class for this Verilated ORPSoC model |
|
Or1200MonitorSC::Or1200MonitorSC (sc_core::sc_module_name name, |
OrpsocAccess *_accessor, |
MemoryLoad *_memoryload, |
int argc, |
char *argv[]) : |
sc_module (name), |
accessor (_accessor), |
memoryload(_memoryload) |
Or1200MonitorSC::Or1200MonitorSC(sc_core::sc_module_name name, |
OrpsocAccess * _accessor, |
MemoryLoad * _memoryload, |
int argc, |
char *argv[]):sc_module(name), |
accessor(_accessor), memoryload(_memoryload) |
{ |
string logfileDefault(DEFAULT_EXEC_LOG_FILE); |
string logfileNameString; |
logging_enabled = false; |
logfile_name_provided = false; |
profiling_enabled = false; |
string profileFileName(DEFAULT_PROF_FILE); |
memdumpFileName = (DEFAULT_MEMDUMP_FILE); |
int memdump_start = 0; int memdump_end = 0; |
do_memdump = false; // Default is not to do a dump of RAM at finish |
logging_regs = true; // Execution log includes register values by default |
bool rsp_server_enabled = false; |
wait_for_stall_cmd_response = false; // Default |
insn_count = insn_count_rst = 0; |
cycle_count = cycle_count_rst = 0; |
|
quiet = false; |
monitor_for_crash = false; |
lookslikewevecrashed_count = crash_monitor_buffer_head = 0; |
/* Assign defaults */ |
string logfileDefault(DEFAULT_EXEC_LOG_FILE); |
string logfileNameString; |
trace_enabled = false; |
logging_enabled = false; |
logfile_name_provided = false; |
profiling_enabled = false; |
string profileFileName(DEFAULT_PROF_FILE); |
memdumpFileName = (DEFAULT_MEMDUMP_FILE); |
int memdump_start = -1; |
int memdump_end = -1; |
do_memdump = false; // Default is not to do a dump of RAM at finish |
logging_regs = true; // Execution log has GPR values by default |
bool rsp_server_enabled = false; |
wait_for_stall_cmd_response = false; // Default |
insn_count = insn_count_rst = 0; |
cycle_count = cycle_count_rst = 0; |
|
bus_trans_log_enabled = bus_trans_log_name_provided = |
bus_trans_log_start_delay_enable = false; // Default |
string bus_trans_default_log_name(DEFAULT_BUS_LOG_FILE); |
string bus_trans_log_file; |
perf_summary = false; |
monitor_for_crash = false; |
lookslikewevecrashed_count = crash_monitor_buffer_head = 0; |
|
// Parse the command line options |
bool cmdline_name_found = false; |
if (argc > 1) |
{ |
// Search through the command line parameters for the "-log" option |
for(int i=1; i < argc; i++) |
{ |
if ((strcmp(argv[i], "-l")==0) || |
(strcmp(argv[i], "--log")==0)) |
{ |
logging_enabled = true; |
binary_log_format = false; |
if (i+1 < argc) |
if(argv[i+1][0] != '-') |
{ |
logfileNameString = (argv[i+1]); |
logfile_name_provided = true; |
} |
if (!logfile_name_provided) |
logfileNameString = logfileDefault; |
} |
else if ((strcmp(argv[i], "--log-noregs")==0)) |
{ |
logging_regs = false; |
} |
else if ((strcmp(argv[i], "-b")==0) || |
(strcmp(argv[i], "--binlog")==0)) |
{ |
logging_enabled = true; |
binary_log_format = true; |
if (i+1 < argc) |
if(argv[i+1][0] != '-') |
{ |
logfileNameString = (argv[i+1]); |
logfile_name_provided = true; |
} |
if (!logfile_name_provided) |
logfileNameString = logfileDefault; |
bus_trans_log_enabled = bus_trans_log_name_provided = bus_trans_log_start_delay_enable = false; // Default |
string bus_trans_default_log_name(DEFAULT_BUS_LOG_FILE); |
string bus_trans_log_file; |
|
} |
else if ((strcmp(argv[i], "-c")==0) || |
(strcmp(argv[i], "--crash-monitor")==0)) |
{ |
monitor_for_crash = true; |
} |
else if ((strcmp(argv[i], "-q")==0) || |
(strcmp(argv[i], "--quiet")==0)) |
{ |
quiet = true; |
} |
else if ((strcmp(argv[i], "-p")==0) || |
(strcmp(argv[i], "--profile")==0)) |
{ |
profiling_enabled = true; |
// Check for !end of command line and that next thing is not a |
// command |
if ((i+1 < argc)){ |
if(argv[i+1][0] != '-') |
profileFileName = (argv[i+1]); |
} |
} |
else if ( (strcmp(argv[i], "-r")==0) || |
(strcmp(argv[i], "--rsp")==0) ) |
{ |
// We need to detect this here too |
rsp_server_enabled = true; |
} |
|
else if ((strcmp(argv[i], "-m")==0) || |
(strcmp(argv[i], "--memdump")==0)) |
{ |
do_memdump = true; |
// Check for !end of command line and that next thing is not a |
// command or a memory address |
if (i+1 < argc) |
{ |
if((argv[i+1][0] != '-') && (strncmp("0x", argv[i+1],2) != 0)) |
{ |
// Hopefully this is the filename we want to use. |
// All addresses should have preceeding hex identifier 0x |
memdumpFileName = argv[i+1]; |
// We've used this next index, can safely increment i |
i++; |
} |
// Parse the command line options |
bool cmdline_name_found = false; |
|
/* Search through the command line parameters for the "-log" option */ |
for (int i = 1; i < argc && argc > 1; i++) { |
if ((strcmp(argv[i], "-l") == 0) || |
(strcmp(argv[i], "--log") == 0)) { |
logging_enabled = true; |
binary_log_format = false; |
if (i + 1 < argc) |
if (argv[i + 1][0] != '-') { |
logfileNameString = (argv[i + 1]); |
logfile_name_provided = true; |
} |
if (!logfile_name_provided) |
logfileNameString = logfileDefault; |
} else if ((strcmp(argv[i], "--log-noregs") == 0)) { |
logging_regs = false; |
} else if ((strcmp(argv[i], "--trace") == 0)) { |
trace_enabled = true; |
|
} else if ((strcmp(argv[i], "-b") == 0) || |
(strcmp(argv[i], "--binlog") == 0)) { |
logging_enabled = true; |
binary_log_format = true; |
if (i + 1 < argc) |
if (argv[i + 1][0] != '-') { |
logfileNameString = (argv[i + 1]); |
logfile_name_provided = true; |
} |
if (!logfile_name_provided) |
logfileNameString = logfileDefault; |
|
} else if ((strcmp(argv[i], "-c") == 0) || |
(strcmp(argv[i], "--crash-monitor") == 0)) { |
monitor_for_crash = true; |
} else if ((strcmp(argv[i], "-u") == 0) || |
(strcmp(argv[i], "--summary") == 0)) { |
perf_summary = true; |
} else if ((strcmp(argv[i], "-p") == 0) || |
(strcmp(argv[i], "--profile") == 0)) { |
profiling_enabled = true; |
// Check for !end of command line and that |
// next thing is not a command |
if ((i + 1 < argc)) { |
if (argv[i + 1][0] != '-') |
profileFileName = (argv[i + 1]); |
} |
} else if ((strcmp(argv[i], "-r") == 0) || |
(strcmp(argv[i], "--rsp") == 0)) { |
// We need to detect this here too |
rsp_server_enabled = true; |
} |
if (i+1 < argc) |
{ |
if((argv[i+1][0] != '-') && (strncmp("0x", argv[i+1],2) == 0)) |
{ |
// Hopefully this is is the start address |
// All addresses should have preceeding hex identifier 0x |
sscanf( argv[i+1], "0x%x", &memdump_start); |
i++; |
} |
|
else if ((strcmp(argv[i], "-m") == 0) || |
(strcmp(argv[i], "--memdump") == 0)) { |
do_memdump = true; |
/* Check for !end of command line and that next thing |
is not a command or a memory address. |
*/ |
if (i + 1 < argc) { |
if ((argv[i + 1][0] != '-') |
&& (strncmp("0x", argv[i + 1], 2) != 0)) { |
/* Hopefully this is the filename we |
want to use. All addresses should |
have preceeding hex identifier 0x |
*/ |
memdumpFileName = argv[i + 1]; |
/* We've used this next index, can |
safely increment i |
*/ |
i++; |
} |
} |
if (i + 1 < argc) { |
if ((argv[i + 1][0] != '-') |
&& (strncmp("0x", argv[i + 1], 2) == 0)) { |
sscanf(argv[i + 1], "0x%x", |
&memdump_start); |
i++; |
} |
} |
if (i + 1 < argc) { |
if ((argv[i + 1][0] != '-') |
&& (strncmp("0x", argv[i + 1], 2) == 0)) { |
sscanf(argv[i + 1], "0x%x", |
&memdump_end); |
i++; |
} |
} |
} |
if (i+1 < argc) |
{ |
if((argv[i+1][0] != '-') && (strncmp("0x", argv[i+1],2) == 0)) |
{ |
// Hopefully this is is the end address |
// All addresses should have preceeding hex identifier 0x |
sscanf( argv[i+1], "0x%x", &memdump_end); |
i++; |
} |
} |
} |
/* |
else if ((strcmp(argv[i], "-u")==0) || |
(strcmp(argv[i], "--bus-log")==0)) |
{ |
bus_trans_log_enabled = true; |
if (i+1 < argc) |
if(argv[i+1][0] != '-') |
{ |
bus_trans_log_file = (argv[i+1]); |
bus_trans_log_name_provided = true; |
} |
|
if (!bus_trans_log_name_provided) |
bus_trans_log_file = bus_trans_default_log_name; |
|
// check for a log start delay |
if (i+2 < argc) |
if(argv[i+2][0] != '-') |
{ |
// We have a bus transaction log start delay |
bus_trans_log_start_delay_enable = true; |
int time_val = atoi(argv[i+2]); |
sc_time log_start_time(time_val,SC_NS); |
bus_trans_log_start_delay = log_start_time; |
} |
} |
*/ |
} |
} |
#if 0 |
else if ((strcmp(argv[i], "-u") == 0) || |
(strcmp(argv[i], "--bus-log") == 0)) { |
bus_trans_log_enabled = true; |
if (i + 1 < argc) |
if (argv[i + 1][0] != '-') { |
bus_trans_log_file = (argv[i + 1]); |
bus_trans_log_name_provided = true; |
} |
|
|
if (!rsp_server_enabled) |
{ |
monitor_to_gdb_pipe[0][0] = monitor_to_gdb_pipe[0][1] = NULL; |
monitor_to_gdb_pipe[1][0] = monitor_to_gdb_pipe[1][1] = NULL; |
} |
if (!bus_trans_log_name_provided) |
bus_trans_log_file = bus_trans_default_log_name; |
|
|
// checkInstruction monitors the bus for special NOP instructionsl |
SC_METHOD (checkInstruction); |
sensitive << clk.pos(); |
dont_initialize(); |
/* check for a log start delay */ |
if (i + 2 < argc) |
if (argv[i + 2][0] != '-') { |
/* We have a bus transaction log start |
delay */ |
bus_trans_log_start_delay_enable = true; |
int time_val = atoi(argv[i + 2]); |
sc_time log_start_time(time_val, SC_NS); |
bus_trans_log_start_delay = |
log_start_time; |
} |
} |
#endif |
|
|
if (profiling_enabled) |
{ |
|
profileFile.open(profileFileName.c_str(), ios::out); // Open profiling log file |
if(profileFile.is_open()) |
{ |
// If the file was opened OK, then enabled logging and print a message. |
profiling_enabled = true; |
cout << "* Execution profiling enabled. Logging to " << profileFileName << endl; |
} |
|
// Setup profiling function |
SC_METHOD (callLog); |
sensitive << clk.pos(); |
dont_initialize(); |
start = clock(); |
} |
|
if(logging_enabled) |
{ |
|
/* Now open the file */ |
if (binary_log_format) |
statusFile.open(logfileNameString.c_str(), ios::out | ios::binary); |
else |
statusFile.open(logfileNameString.c_str(), ios::out ); |
|
/* Check the open() */ |
if(statusFile.is_open() && binary_log_format) |
{ |
cout << "* Processor execution logged in binary format to file: " << logfileNameString << endl; |
/* Write out a byte indicating whether there's register values too */ |
statusFile.write((char*)&logging_regs, 1); |
|
if (!rsp_server_enabled) { |
monitor_to_gdb_pipe[0][0] = monitor_to_gdb_pipe[0][1] = NULL; |
monitor_to_gdb_pipe[1][0] = monitor_to_gdb_pipe[1][1] = NULL; |
} |
else if (statusFile.is_open() && !binary_log_format) |
cout << "* Processor execution logged to file: " << logfileNameString << endl; |
else |
/* Couldn't open */ |
logging_enabled = false; |
|
} |
|
if (logging_enabled) |
{ |
if (binary_log_format) |
{ |
SC_METHOD (displayStateBinary); |
/* checkInstruction monitors the bus for special NOP instructionsl */ |
SC_METHOD(checkInstruction); |
sensitive << clk.pos(); |
dont_initialize(); |
|
if (profiling_enabled) { |
// Open profiling log file |
profileFile.open(profileFileName.c_str(), ios::out); |
if (profileFile.is_open()) { |
/* If the file was opened OK, then enabled logging and |
print a message. |
*/ |
profiling_enabled = true; |
cout << "* Execution profiling enabled. Logging to " << |
profileFileName << endl; |
} |
// Setup profiling function |
SC_METHOD(callLog); |
sensitive << clk.pos(); |
dont_initialize(); |
} |
else |
{ |
SC_METHOD (displayState); |
|
if (logging_enabled) { |
|
/* Now open the file */ |
if (binary_log_format) |
statusFile.open(logfileNameString.c_str(), |
ios::out | ios::binary); |
else |
statusFile.open(logfileNameString.c_str(), ios::out); |
|
/* Check the open() */ |
if (statusFile.is_open() && binary_log_format) { |
cout << |
"* Processor execution logged in binary format to file: " |
<< logfileNameString << endl; |
/* Write out a byte indicating whether there's register |
values too |
*/ |
statusFile.write((char *)&logging_regs, 1); |
|
} else if (statusFile.is_open() && !binary_log_format) |
cout << "* Processor execution logged to file: " << |
logfileNameString << endl; |
else |
/* Couldn't open */ |
logging_enabled = false; |
|
} |
sensitive << clk.pos(); |
dont_initialize(); |
start = clock(); |
|
} |
|
if (monitor_for_crash) |
{ |
cout << "* Crash monitor enabled" << endl; |
} |
if (logging_enabled) { |
if (binary_log_format) { |
SC_METHOD(displayStateBinary); |
} else { |
SC_METHOD(displayState); |
} |
sensitive << clk.pos(); |
dont_initialize(); |
start = clock(); |
|
// Check sizes we were given from memory dump command line options first |
if (do_memdump) |
{ |
if ((memdump_start > ORPSOC_SRAM_SIZE) || (memdump_end > ORPSOC_SRAM_SIZE) || |
((memdump_start > memdump_end) && (memdump_end != 0))) |
{ |
do_memdump = false; |
cout << "* Memory dump addresses range incorrect. Limit of memory is 0x" << hex << ORPSOC_SRAM_SIZE << ". Memory dumping disabled." << endl; |
} |
} |
|
if (do_memdump) |
{ |
// Were we given dump addresses? If not, we dump all of the memory |
// Size of memory isn't clearly defined in any one place. This could lead to |
// big problems when changing size of the RAM in simulation. |
|
if (memdump_start == 0 && memdump_end == 0) |
memdump_end = ORPSOC_SRAM_SIZE; |
|
if (memdump_start != 0 && memdump_end == 0) |
{ |
// Probably just got the single memorydump param |
// Interpet as a length from 0 |
memdump_end = memdump_start; |
memdump_start = 0; |
if (monitor_for_crash) { |
cout << "* Crash monitor enabled" << endl; |
} |
|
if (memdump_start & 0x3) memdump_start &= ~0x3; // word-align the start address |
if (memdump_end & 0x3) memdump_end = (memdump_end+4) & ~0x3; // word-align the start address |
|
memdump_start_addr = memdump_start; |
memdump_end_addr = memdump_end; |
} |
|
/* |
if (bus_trans_log_enabled) |
{ |
// Setup log file and register the bus monitoring function |
busTransLog.open(bus_trans_log_file.c_str(), ios::out ); |
if (do_memdump) { |
// Were we given dump addresses? If not, we dump all of the |
// memory. Size of memory isn't clearly defined in any one |
// place. This could lead to big problems when changing size of |
// the RAM in simulation. |
|
/* No memory dump beginning specified. Set to zero. */ |
if (memdump_start == -1) |
memdump_start = 0; |
|
/* No dump end specified, assign some token amount, probably |
useless, but then the user should have specified more. */ |
if (memdump_end == -1) |
memdump_end = memdump_start + 0x2000; |
|
if (busTransLog.is_open()) |
{ |
cout << "* System bus transactions logged to file: " << |
bus_trans_log_file; |
|
if (bus_trans_log_start_delay_enable) |
cout << ", on at " << bus_trans_log_start_delay.to_string(); |
cout << endl; |
if (memdump_start & 0x3) |
memdump_start &= ~0x3; // word-align the start address |
if (memdump_end & 0x3) |
memdump_end = (memdump_end + 4) & ~0x3; // word-align the start address |
|
memdump_start_addr = memdump_start; |
memdump_end_addr = memdump_end; |
} |
else |
// Couldn't open |
bus_trans_log_enabled = false; |
} |
#if 0 |
if (bus_trans_log_enabled) { |
// Setup log file and register the bus monitoring function |
busTransLog.open(bus_trans_log_file.c_str(), ios::out); |
|
if (busTransLog.is_open()) { |
cout << "* System bus transactions logged to file: " << |
bus_trans_log_file; |
|
if (bus_trans_log_enabled) |
{ |
// Setup profiling function |
SC_METHOD (busMonitor); |
sensitive << clk.pos(); |
dont_initialize(); |
} |
*/ |
|
} // Or1200MonitorSC () |
if (bus_trans_log_start_delay_enable) |
cout << ", on at " << |
bus_trans_log_start_delay.to_string(); |
cout << endl; |
} else |
// Couldn't open |
bus_trans_log_enabled = false; |
} |
|
if (bus_trans_log_enabled) { |
// Setup profiling function |
SC_METHOD(busMonitor); |
sensitive << clk.pos(); |
dont_initialize(); |
} |
#endif |
|
// Record roughly when we begin execution |
start = clock(); |
|
} // Or1200MonitorSC () |
|
//! Print usage for the options of this module |
void |
Or1200MonitorSC::printUsage() |
void |
Or1200MonitorSC::printUsage() |
{ |
printf("\nLogging and diagnostic options:\n"); |
printf(" -p, --profile [<file>]Enable execution profiling output to <file> (default is\n\t\t\t"DEFAULT_PROF_FILE")\n"); |
printf(" -l, --log <file>\tLog processor execution to <file>\n"); |
printf(" --log-noregs\tLog excludes register contents\n"); |
printf("\nLogging and diagnostic options:\n"); |
printf(" --trace\t\tEnable an execution trace to stdout during simulation\n"); |
printf(" -u, --summary\t\tEnable summary on exit\n"); |
printf |
(" -p, --profile [<file>]\n\t\t\tEnable execution profiling output to <file> (default is\n\t\t\t" |
DEFAULT_PROF_FILE ")\n"); |
printf(" -l, --log <file>\tLog processor execution to <file>\n"); |
printf(" --log-noregs\tLog excludes register contents\n"); |
|
printf(" -b, --binlog <file>\tGenerate binary format execution log (faster, smaller)\n"); |
printf |
(" -b, --binlog <file>\tGenerate binary format execution log (faster, smaller)\n"); |
|
printf(" -m, --memdump <file> <0xstartaddr> <0xendaddr>\n\t\t\tDump data between <0xstartaddr> and <0xendaddr> from\n\t\t\tthe system's RAM to <file> in binary format on exit\n"); |
printf(" -c, --crash-monitor\tDetect when the processor has crashed and exit\n"); |
printf |
(" -m, --memdump <file> <0xstartaddr> <0xendaddr>\n\t\t\tDump data between <0xstartaddr> and <0xendaddr> from\n\t\t\tthe system's RAM to <file> in binary format on exit\n"); |
printf |
(" -c, --crash-monitor\tDetect when the processor has crashed and exit\n"); |
/* |
printf(" -u, --bus-log <file> <val>\n\t\t\tLog the wishbone bus transactions to <file>, opt. start\n\t\t\tafter <val> ns\n\n"); |
*/ |
390,289 → 362,439
//! - l.nop 3 Printf the string with the arguments in R3, etc |
//! - l.nop 4 Print a character |
|
//#define OR1200_OR32_NOP_BITS_31_TO_26 6'b000101 |
#define OR1200_OR32_NOP 0x14000000 |
#define OR1200_OR32_NOP_INSN_TOP_BYTE 0x15 |
#define OR1200_OR32_NOP 0x14000000 |
|
extern int SIM_RUNNING; |
void |
|
void |
Or1200MonitorSC::checkInstruction() |
{ |
uint32_t r3; |
double ts; |
uint32_t current_WbInsn, current_WbPC; |
|
cycle_count++; |
uint32_t r3; |
double ts; |
uint32_t currentWbInsn, currentWbPC; |
clock_t now; |
double elapsedTime; |
int hertz, khertz; |
unsigned long long int psPeriod; |
char insnMSByte; |
uint32_t insnImm; |
|
/* Check if this counts as an "executed" instruction */ |
if (!accessor->getWbFreeze()) |
{ |
// Cache writeback stage instruction |
current_WbInsn = accessor->getWbInsn(); |
|
if ((((current_WbInsn & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(current_WbInsn & (1<<16))) && !(accessor->getExceptFlushpipe() && accessor->getExDslot())) |
insn_count++; |
else |
// Exception version |
if (accessor->getExceptFlushpipe()) |
insn_count++; |
} |
|
// Check the instruction when the freeze signal is low. |
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) |
{ |
// Do something if we have l.nop |
switch (current_WbInsn) |
{ |
case NOP_EXIT: |
r3 = accessor->getGpr (3); |
if (!quiet) |
{ |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
std::cout << std::fixed << std::setprecision (2) << ts; |
std::cout << " ns: Exiting (" << r3 << ")" << std::endl; |
perfSummary(); |
} |
if (logging_enabled) statusFile.close(); |
if (profiling_enabled) profileFile.close(); |
if (bus_trans_log_enabled) busTransLog.close(); |
memdump(); |
SIM_RUNNING=0; |
sc_stop(); |
break; |
cycle_count++; |
|
case NOP_REPORT: |
if (!quiet) |
{ |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
r3 = accessor->getGpr (3); |
std::cout << std::fixed << std::setprecision (2) << ts; |
std::cout << " ns: report (" << hex << r3 << ")" << std::endl; |
} |
break; |
/* Check if this counts as an "executed" instruction */ |
if (!accessor->getWbFreeze()) { |
// Memory writeback stage instruction |
currentWbInsn = accessor->getWbInsn(); |
|
case NOP_PRINTF: |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
std::cout << std::fixed << std::setprecision (2) << ts; |
std::cout << " ns: printf: "; |
simPrintf(accessor->getGpr (4), accessor->getGpr (3)); |
break; |
if (((((currentWbInsn & 0xfc000000) != |
(uint32_t) OR1200_OR32_NOP) |
|| !(currentWbInsn & (1 << 16))) |
&& !(accessor->getExceptFlushpipe() |
&& accessor->getExDslot())) || |
// Exception version |
accessor->getExceptFlushpipe()) |
{ |
|
insn_count++; |
if (trace_enabled) |
printTrace(); |
} |
|
case NOP_PUTC: |
r3 = accessor->getGpr (3); |
std::cout << (char)r3 << std::flush; |
break; |
} |
// Check the instruction when the freeze signal is low. |
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) { |
// Extract MSB of instruction |
insnMSByte = (currentWbInsn >> 24) & 0xff; |
|
if (insnMSByte == OR1200_OR32_NOP_INSN_TOP_BYTE) |
{ |
insnImm = currentWbInsn & 0xffff; |
|
case NOP_CNT_RESET: |
if (!quiet) |
{ |
std::cout << "****************** counters reset ******************" << endl; |
std::cout << "since last reset: cycles " << cycle_count - cycle_count_rst << ", insn #" << insn_count - insn_count_rst << endl; |
std::cout << "****************** counters reset ******************" << endl; |
cycle_count_rst = cycle_count; |
insn_count_rst = insn_count; |
/* 3 separate counters we'll use for various things */ |
} |
case NOP_CNT_RESET1: |
if (!quiet) |
{ |
std::cout << "**** counter1 cycles: " << std::setfill('0') << std::setw(10) << cycle_count - cycles_1 << " resetting ********" << endl; |
cycles_1 = cycle_count; |
} |
break; |
case NOP_CNT_RESET2: |
if (!quiet) |
{ |
std::cout << "**** counter2 cycles: " << std::setfill('0') << std::setw(10) << cycle_count - cycles_2 << " resetting ********" << endl; |
cycles_2 = cycle_count; |
} |
break; |
case NOP_CNT_RESET3: |
if (!quiet) |
{ |
std::cout << "**** counter3 cycles: " << std::setfill('0') << std::setw(10) << cycle_count - cycles_3 << " resetting ********" << endl; |
cycles_3 = cycle_count; |
} |
break; |
default: |
break; |
} |
|
if (monitor_for_crash) |
{ |
current_WbPC = accessor->getWbPC(); |
// Look at current instruction |
if (current_WbInsn == 0x00000000) |
{ |
// Looks like we've jumped somewhere incorrectly |
lookslikewevecrashed_count++; |
} |
#define CRASH_MONITOR_LOG_BAD_INSNS 1 |
// Do something if we have l.nop |
switch (insnImm) { |
|
case NOP_EXIT: |
r3 = accessor->getGpr(3); |
/* No timestamp with reports, so exit report is |
same format as from or1ksim */ |
/* |
ts = sc_time_stamp().to_seconds() * |
1000000000.0; |
std::cout << std::fixed << std:: |
setprecision(2) << ts; |
*/ |
std:: |
cout << "exit(" << r3 << ")" << |
std::endl; |
if (perf_summary) |
perfSummary(); |
|
if (logging_enabled) |
statusFile.close(); |
if (profiling_enabled) |
profileFile.close(); |
if (bus_trans_log_enabled) |
busTransLog.close(); |
memdump(); |
gSimRunning = 0; |
sc_stop(); |
break; |
|
case NOP_REPORT: |
/* No timestamp with reports, so reports are |
same format as from or1ksim */ |
/* |
ts = sc_time_stamp().to_seconds() * |
1000000000.0; |
|
std::cout << std::fixed << std:: |
setprecision(2) << ts; |
*/ |
r3 = accessor->getGpr(3); |
std::cout << "report(0x" << |
std::setfill('0') << hex << |
std::setw(8) << r3 << ");" << std::endl; |
break; |
|
case NOP_PRINTF: |
/* |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
std::cout << std::fixed << std::setprecision(2) << ts; |
*/ |
std::cout << "printf: "; |
simPrintf(accessor->getGpr(4), accessor->getGpr(3)); |
break; |
|
case NOP_PUTC: |
r3 = accessor->getGpr(3); |
std::cout << (char)r3 << std::flush; |
break; |
|
case NOP_GET_TICKS: |
// Put number of cycles so far into r11 and r12 |
accessor->setGpr(11, (uint32_t) cycle_count&0xffffffff); |
accessor->setGpr(12, (uint32_t) (cycle_count >> 32) & |
0xffffffff); |
/* |
std::cout << "NOP_GET_TICKS: " << dec << cycle_count << |
" r11:" << dec << accessor->getGpr(11) << |
" r12:" << dec << accessor->getGpr(12) << |
std::endl; |
*/ |
break; |
case NOP_GET_PS: |
// Put PS/cycle into r11 |
now = clock(); |
elapsedTime = |
(double (now) - double (start))/CLOCKS_PER_SEC; |
|
// Calculate execution rate so far |
khertz = (int)((cycle_count / elapsedTime) / 1000); |
|
psPeriod |
= (((unsigned long long int) 1000000000) / |
(unsigned long long int ) khertz); |
|
accessor->setGpr(11, (uint32_t) psPeriod); |
|
/* |
std::cout << "NOP_GET_PS: khertz: " << dec << khertz << |
" r11:" << dec << accessor->getGpr(11) << |
endl; |
*/ |
break; |
|
case NOP_CNT_RESET: |
if (!gQuiet) { |
std::cout << |
"****************** counters reset ******************" |
<< endl; |
std::cout << "since last reset: cycles " << |
cycle_count - |
cycle_count_rst << ", insn #" << insn_count |
- insn_count_rst << endl; |
std::cout << |
"****************** counters reset ******************" |
<< endl; |
cycle_count_rst = cycle_count; |
insn_count_rst = insn_count; |
/* 3 separate counters we'll use for various things */ |
} |
case NOP_CNT_RESET1: |
if (!gQuiet) { |
std::cout << "**** counter1 cycles: " << |
std::setfill('0') << std::setw(10) << |
cycle_count - |
cycles_1 << " resetting ********" << endl; |
cycles_1 = cycle_count; |
} |
break; |
case NOP_CNT_RESET2: |
if (!gQuiet) { |
std::cout << "**** counter2 cycles: " << |
std::setfill('0') << std::setw(10) << |
cycle_count - |
cycles_2 << " resetting ********" << endl; |
cycles_2 = cycle_count; |
} |
break; |
case NOP_CNT_RESET3: |
if (!gQuiet) { |
std::cout << "**** counter3 cycles: " << |
std::setfill('0') << std::setw(10) << |
cycle_count - |
cycles_3 << " resetting ********" << endl; |
cycles_3 = cycle_count; |
} |
break; |
default: |
break; |
} |
|
} |
|
if (monitor_for_crash) { |
currentWbPC = accessor->getWbPC(); |
// Look at current instruction |
if (currentWbInsn == 0x00000000) { |
// Looks like we've jumped somewhere incorrectly |
lookslikewevecrashed_count++; |
} |
#define CRASH_MONITOR_LOG_BAD_INSNS 0 |
#if CRASH_MONITOR_LOG_BAD_INSNS |
|
/* Log so-called "bad" instructions, or at least instructions we |
executed, no matter if they caused us to increment |
lookslikewevecrashed_count, this way we get them in our list too */ |
if (((current_WbInsn & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(current_WbInsn & (1<<16))) |
{ |
crash_monitor_buffer[crash_monitor_buffer_head][0] = current_WbPC; |
crash_monitor_buffer[crash_monitor_buffer_head][1] = current_WbInsn; |
/* Circular buffer */ |
if(crash_monitor_buffer_head < CRASH_MONITOR_BUFFER_SIZE-1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head = 0; |
|
} |
|
/* Log so-called "bad" instructions, or at least instructions we |
executed, no matter if they caused us to increment |
lookslikewevecrashed_count, this way we get them in our list too */ |
if ((insnMSByte != OR1200_OR32_NOP_INSN_TOP_BYTE) |
|| !(currentWbInsn & (1 << 16))) { |
crash_monitor_buffer[crash_monitor_buffer_head] |
[0] = currentWbPC; |
crash_monitor_buffer[crash_monitor_buffer_head] |
[1] = currentWbInsn; |
/* Circular buffer */ |
if (crash_monitor_buffer_head < |
CRASH_MONITOR_BUFFER_SIZE - 1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head = 0; |
|
} |
#else |
else if (((current_WbInsn & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(current_WbInsn & (1<<16))) |
{ |
else if (((insnMSByte != OR1200_OR32_NOP_INSN_TOP_BYTE)) |
|| !(currentWbInsn & (1 << 16))) { |
|
crash_monitor_buffer[crash_monitor_buffer_head][0] = current_WbPC; |
crash_monitor_buffer[crash_monitor_buffer_head][1] = current_WbInsn; |
/* Circular buffer */ |
if(crash_monitor_buffer_head < CRASH_MONITOR_BUFFER_SIZE-1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head = 0; |
|
/* Reset this */ |
lookslikewevecrashed_count = 0; |
} |
#endif |
if (wait_for_stall_cmd_response) |
{ |
// We've already crashed, and we're issued a command to stall the |
// processor to the system C debug unit interface, and we're |
// waiting for this debug unit to send back the message that we've |
// stalled. |
char readChar; |
int n = read(monitor_to_gdb_pipe[1][0], &readChar, sizeof(char)); |
if (!( ((n < 0) && (errno == EAGAIN)) || (n==0) )) |
wait_for_stall_cmd_response = false; // We got response |
lookslikewevecrashed_count = 0; |
|
} |
else if (lookslikewevecrashed_count > 0) |
{ |
|
if (lookslikewevecrashed_count >= CRASH_MONITOR_BUFFER_SIZE/4) |
{ |
/* Probably crashed. Bail out, print out buffer */ |
std::cout << "********************************************************************************"<< endl; |
std::cout << "* Looks like processor crashed. Printing last " << CRASH_MONITOR_BUFFER_SIZE << " instructions executed:" << endl; |
|
int crash_monitor_buffer_head_end = (crash_monitor_buffer_head > 0) ? crash_monitor_buffer_head - 1 : CRASH_MONITOR_BUFFER_SIZE-1; |
while (crash_monitor_buffer_head != crash_monitor_buffer_head_end) |
{ |
std::cout << "* PC: " << std::setfill('0') << hex << std::setw(8) << crash_monitor_buffer[crash_monitor_buffer_head][0] << " INSN: " << std::setfill('0') << hex << std::setw(8) << crash_monitor_buffer[crash_monitor_buffer_head][1] << endl; |
|
if(crash_monitor_buffer_head < CRASH_MONITOR_BUFFER_SIZE-1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head = 0; |
} |
std::cout << "********************************************************************************"<< endl; |
|
if ( (monitor_to_gdb_pipe[0][0] != NULL)) |
{ |
// If GDB server is running, we'll pass control back to |
// the debugger instead of just quitting. |
char interrupt = 0x3; // Arbitrary |
write(monitor_to_gdb_pipe[0][1],&interrupt,sizeof(char)); |
wait_for_stall_cmd_response = true; |
lookslikewevecrashed_count = 0; |
std::cout << "* Stalling processor and returning control to GDB"<< endl; |
// Problem: the debug unit interface's stalling the processor over the simulated JTAG bus takes a while, in the meantime this monitor will continue running and keep triggering the crash detection code. We must somehow wait until the processor is stalled, or circumvent this crash detection output until we detect that the processor is stalled. |
// Solution: Added another pipe, when we want to wait for preocssor to stall, we set wait_for_stall_cmd_response=true, then each time we get back to this monitor function we simply poll the pipe until we're stalled. (A blocking read didn't work - this function never yielded and the RSP server handling function never got called). |
wait_for_stall_cmd_response = true; |
|
} |
else |
{ |
// Close down sim end exit |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
std::cout << std::fixed << std::setprecision (2) << ts; |
std::cout << " ns: Exiting (" << r3 << ")" << std::endl; |
perfSummary(); |
if (logging_enabled) statusFile.close(); |
if (profiling_enabled) profileFile.close(); |
if (bus_trans_log_enabled) busTransLog.close(); |
memdump(); |
SIM_RUNNING=0; |
sc_stop(); |
} |
crash_monitor_buffer[crash_monitor_buffer_head] |
[0] = currentWbPC; |
crash_monitor_buffer[crash_monitor_buffer_head] |
[1] = currentWbInsn; |
/* Circular buffer */ |
if (crash_monitor_buffer_head < |
CRASH_MONITOR_BUFFER_SIZE - 1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head = 0; |
|
/* Reset this */ |
lookslikewevecrashed_count = 0; |
} |
#endif |
if (wait_for_stall_cmd_response) { |
// We've already crashed, and we're issued a command to stall the |
// processor to the system C debug unit interface, and we're |
// waiting for this debug unit to send back the message that we've |
// stalled. |
char readChar; |
int n = |
read(monitor_to_gdb_pipe[1][0], &readChar, |
sizeof(char)); |
if (!(((n < 0) && (errno == EAGAIN)) |
|| (n == 0))) |
wait_for_stall_cmd_response = false; // We got response |
lookslikewevecrashed_count = 0; |
|
} else if (lookslikewevecrashed_count > 0) { |
|
if (lookslikewevecrashed_count >= |
CRASH_MONITOR_BUFFER_SIZE / 4) { |
/* Probably crashed. Bail out, print out buffer */ |
std::cout << |
"********************************************************************************" |
<< endl; |
std::cout << |
"* Looks like processor crashed. Printing last " |
<< CRASH_MONITOR_BUFFER_SIZE << |
" instructions executed:" << endl; |
|
int crash_monitor_buffer_head_end = |
(crash_monitor_buffer_head > |
0) ? crash_monitor_buffer_head - |
1 : CRASH_MONITOR_BUFFER_SIZE - 1; |
while (crash_monitor_buffer_head != |
crash_monitor_buffer_head_end) { |
std::cout << "* PC: " << |
std::setfill('0') << hex << |
std::setw(8) << |
crash_monitor_buffer |
[crash_monitor_buffer_head] |
[0] << " INSN: " << |
std::setfill('0') << hex << |
std::setw(8) << |
crash_monitor_buffer |
[crash_monitor_buffer_head] |
[1] << endl; |
|
if (crash_monitor_buffer_head < |
CRASH_MONITOR_BUFFER_SIZE - |
1) |
crash_monitor_buffer_head++; |
else |
crash_monitor_buffer_head |
= 0; |
} |
std::cout << |
"********************************************************************************" |
<< endl; |
|
if ((monitor_to_gdb_pipe[0][0] != NULL)) { |
// If GDB server is running, we'll pass control back to |
// the debugger instead of just quitting. |
char interrupt = 0x3; // Arbitrary |
write(monitor_to_gdb_pipe[0][1], |
&interrupt, sizeof(char)); |
wait_for_stall_cmd_response = |
true; |
lookslikewevecrashed_count = 0; |
std::cout << |
"* Stalling processor and returning control to GDB" |
<< endl; |
// Problem: the debug unit interface's stalling the processor over the simulated JTAG bus takes a while, in the meantime this monitor will continue running and keep triggering the crash detection code. We must somehow wait until the processor is stalled, or circumvent this crash detection output until we detect that the processor is stalled. |
// Solution: Added another pipe, when we want to wait for preocssor to stall, we set wait_for_stall_cmd_response=true, then each time we get back to this monitor function we simply poll the pipe until we're stalled. (A blocking read didn't work - this function never yielded and the RSP server handling function never got called). |
wait_for_stall_cmd_response = |
true; |
|
} else { |
// Close down sim end exit |
ts = sc_time_stamp().to_seconds |
() * 1000000000.0; |
std::cout << std::fixed << |
std::setprecision(2) << ts; |
std::cout << " ns: Exiting (" << |
r3 << ")" << std::endl; |
if (perf_summary) |
perfSummary(); |
if (logging_enabled) |
statusFile.close(); |
if (profiling_enabled) |
profileFile.close(); |
if (bus_trans_log_enabled) |
busTransLog.close(); |
memdump(); |
gSimRunning = 0; |
sc_stop(); |
} |
} |
} |
} |
} |
} |
} |
} // checkInstruction() |
} |
} // checkInstruction() |
|
|
//! Method to log execution in terms of calls and returns |
|
void |
void |
Or1200MonitorSC::callLog() |
{ |
uint32_t exinsn, delaypc; |
uint32_t o_a; // operand a |
uint32_t o_b; // operand b |
struct label_entry *tmp; |
|
// Instructions should be valid when freeze is low and there are no exceptions |
//if (!accessor->getExFreeze()) |
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) |
{ |
//exinsn = accessor->getExInsn();// & 0x3ffffff; |
exinsn = accessor->getWbInsn(); |
// Check the instruction |
switch((exinsn >> 26) & 0x3f) { // Check Opcode - top 6 bits |
case 0x1: |
/* Instruction: l.jal */ |
o_a = (exinsn >> 0) & 0x3ffffff; |
if(o_a & 0x02000000) o_a |= 0xfe000000; |
|
//delaypc = accessor->getExPC() + (o_a * 4); // PC we're jumping to |
delaypc = accessor->getWbPC() + (o_a * 4); // PC we're jumping to |
// Now we have info about where we're jumping to. Output the info, with label if possible |
// We print the PC we're jumping from + 8 which is the return address |
if ( tmp = memoryload->get_label (delaypc) ) |
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl; |
else |
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl; |
|
break; |
case 0x11: |
/* Instruction: l.jr */ |
// Bits 15-11 contain register number |
o_b = (exinsn >> 11) & 0x1f; |
if (o_b == 9) // l.jr r9 is typical return |
{ |
// Now get the value in this register |
delaypc = accessor->getGpr(o_b); |
// Output this jump |
profileFile << "-" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << delaypc << endl; |
} |
break; |
case 0x12: |
/* Instruction: l.jalr */ |
o_b = (exinsn >> 11) & 0x1f; |
// Now get the value in this register |
delaypc = accessor->getGpr(o_b); |
// Now we have info about where we're jumping to. Output the info, with label if possible |
// We print the PC we're jumping from + 8 which is the return address |
if ( tmp = memoryload->get_label (delaypc) ) |
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl; |
else |
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl; |
|
break; |
uint32_t exinsn, delaypc; |
uint32_t o_a; // operand a |
uint32_t o_b; // operand b |
struct label_entry *tmp; |
|
} |
} |
} // callLog() |
// Instructions should be valid when freeze is low and there are no exceptions |
//if (!accessor->getExFreeze()) |
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0)) { |
//exinsn = accessor->getExInsn();// & 0x3ffffff; |
exinsn = accessor->getWbInsn(); |
// Check the instruction |
switch ((exinsn >> 26) & 0x3f) { // Check Opcode - top 6 bits |
case 0x1: |
/* Instruction: l.jal */ |
o_a = (exinsn >> 0) & 0x3ffffff; |
if (o_a & 0x02000000) |
o_a |= 0xfe000000; |
|
//delaypc = accessor->getExPC() + (o_a * 4); // PC we're jumping to |
delaypc = accessor->getWbPC() + (o_a * 4); // PC we're jumping to |
// Now we have info about where we're jumping to. Output the info, with label if possible |
// We print the PC we're jumping from + 8 which is the return address |
if (tmp = memoryload->get_label(delaypc)) |
profileFile << "+" << std::setfill('0') << hex |
<< std::setw(8) << cycle_count << " " << hex |
<< std::setw(8) << accessor->getWbPC() + |
8 << " " << hex << std::setw(8) << delaypc |
<< " " << tmp->name << endl; |
else |
profileFile << "+" << std::setfill('0') << hex |
<< std::setw(8) << cycle_count << " " << hex |
<< std::setw(8) << accessor->getWbPC() + |
8 << " " << hex << std::setw(8) << delaypc |
<< " @" << hex << std::setw(8) << delaypc << |
endl; |
|
break; |
case 0x11: |
/* Instruction: l.jr */ |
// Bits 15-11 contain register number |
o_b = (exinsn >> 11) & 0x1f; |
if (o_b == 9) // l.jr r9 is typical return |
{ |
// Now get the value in this register |
delaypc = accessor->getGpr(o_b); |
// Output this jump |
profileFile << "-" << std::setfill('0') << hex |
<< std::setw(8) << cycle_count << " " << hex |
<< std::setw(8) << delaypc << endl; |
} |
break; |
case 0x12: |
/* Instruction: l.jalr */ |
o_b = (exinsn >> 11) & 0x1f; |
// Now get the value in this register |
delaypc = accessor->getGpr(o_b); |
// Now we have info about where we're jumping to. Output the info, with label if possible |
// We print the PC we're jumping from + 8 which is the return address |
if (tmp = memoryload->get_label(delaypc)) |
profileFile << "+" << std::setfill('0') << hex |
<< std::setw(8) << cycle_count << " " << hex |
<< std::setw(8) << accessor->getWbPC() + |
8 << " " << hex << std::setw(8) << delaypc |
<< " " << tmp->name << endl; |
else |
profileFile << "+" << std::setfill('0') << hex |
<< std::setw(8) << cycle_count << " " << hex |
<< std::setw(8) << accessor->getWbPC() + |
8 << " " << hex << std::setw(8) << delaypc |
<< " @" << hex << std::setw(8) << delaypc << |
endl; |
|
break; |
|
} |
} |
} // callLog() |
|
void |
Or1200MonitorSC::printTrace() |
{ |
// TODO: Make this like or1ksim's trace, but for now print the basics |
//XXXXXXPC: XXXXINSN l.insn rA,rB,Imm etc... |
std::cout << |
std::setfill('0') << hex << std::setw(8) << |
accessor->getWbPC() << ": " << |
std::setfill('0') << hex << std::setw(8) << |
accessor->getWbInsn() << |
endl; |
} |
|
//! Method to output the state of the processor |
|
//! This function will output to a file, if enabled, the status of the processor |
680,187 → 802,208
//! process which calls the display_arch_state tasks. This is designed to be |
//! identical to that process, so the output is identical |
|
void |
void |
Or1200MonitorSC::displayState() |
{ |
// Output the state if we're not frozen and not flushing during a delay slot |
if (!accessor->getWbFreeze()) |
{ |
if ((((accessor->getWbInsn() & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(accessor->getWbInsn() & (1<<16))) && !(accessor->getExceptFlushpipe() && accessor->getExDslot())) |
{ |
// Print PC, instruction |
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << std::setw(8) << accessor->getWbInsn() << endl; |
// Output the state if we're not frozen and not flushing during a delay slot |
if (!accessor->getWbFreeze()) { |
if ((((accessor->getWbInsn() & 0xfc000000) != |
(uint32_t) OR1200_OR32_NOP) |
|| !(accessor->getWbInsn() & (1 << 16))) |
&& !(accessor->getExceptFlushpipe() |
&& accessor->getExDslot())) { |
// Print PC, instruction |
statusFile << "\nEXECUTED(" << std::setfill(' ') << |
std::setw(11) << dec << insn_count << "): " << |
std:: |
setfill('0') << hex << std::setw(8) << accessor-> |
getWbPC() << ": " << hex << std:: |
setw(8) << accessor->getWbInsn() << endl; |
} |
// Exception version |
else if (accessor->getExceptFlushpipe()) { |
// Print PC, instruction, indicate it caused an exception |
statusFile << "\nEXECUTED(" << std::setfill(' ') << |
std::setw(11) << dec << insn_count << "): " << |
std:: |
setfill('0') << hex << std::setw(8) << accessor-> |
getExPC() << ": " << hex << std:: |
setw(8) << accessor-> |
getExInsn() << " (exception)" << endl; |
} else |
return; |
} else |
return; |
|
if (logging_regs) { |
// Print general purpose register contents |
for (int i = 0; i < 32; i++) { |
if ((i % 4 == 0) && (i > 0)) |
statusFile << endl; |
statusFile << std::setfill('0'); |
statusFile << "GPR" << dec << std::setw(2) << i << ": " |
<< hex << std:: |
setw(8) << (uint32_t) accessor->getGpr(i) << " "; |
} |
statusFile << endl; |
|
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) |
accessor->getSprSr() << " "; |
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) |
accessor->getSprEpcr() << " "; |
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) |
accessor->getSprEear() << " "; |
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) |
accessor->getSprEsr() << endl; |
|
} |
// Exception version |
else if (accessor->getExceptFlushpipe()) |
{ |
// Print PC, instruction, indicate it caused an exception |
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getExPC() << ": " << hex << std::setw(8) << accessor->getExInsn() << " (exception)" << endl; |
} |
else |
|
return; |
} |
else |
return; |
|
if (logging_regs) |
{ |
// Print general purpose register contents |
for (int i=0; i<32; i++) |
{ |
if ((i%4 == 0)&&(i>0)) statusFile << endl; |
statusFile << std::setfill('0'); |
statusFile << "GPR" << dec << std::setw(2) << i << ": " << hex << std::setw(8) << (uint32_t) accessor->getGpr(i) << " "; |
} |
statusFile << endl; |
|
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) accessor->getSprSr() << " "; |
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " "; |
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " "; |
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl; |
|
} |
|
return; |
|
} // displayState() |
|
} // displayState() |
|
//! Method to output the state of the processor in binary format |
//! File format is simply first byte indicating whether register |
//! data is included, and then structs of the following type |
struct s_binary_output_buffer{ |
long long insn_count; |
uint32_t pc; |
uint32_t insn; |
char exception; |
uint32_t regs[32]; |
uint32_t sr; |
uint32_t epcr0; |
uint32_t eear0; |
uint32_t eser0; |
} __attribute__((__packed__)); |
struct s_binary_output_buffer { |
long long insn_count; |
uint32_t pc; |
uint32_t insn; |
char exception; |
uint32_t regs[32]; |
uint32_t sr; |
uint32_t epcr0; |
uint32_t eear0; |
uint32_t eser0; |
} __attribute__ ((__packed__)); |
|
struct s_binary_output_buffer_sans_regs{ |
long long insn_count; |
uint32_t pc; |
uint32_t insn; |
char exception; |
} __attribute__((__packed__)); |
|
void |
struct s_binary_output_buffer_sans_regs { |
long long insn_count; |
uint32_t pc; |
uint32_t insn; |
char exception; |
} __attribute__ ((__packed__)); |
|
void |
Or1200MonitorSC::displayStateBinary() |
{ |
struct s_binary_output_buffer outbuf; |
|
// Output the state if we're not frozen and not flushing during a delay slot |
if (!accessor->getWbFreeze()) |
{ |
if ((((accessor->getWbInsn() & 0xfc000000) != (uint32_t) OR1200_OR32_NOP) || !(accessor->getWbInsn() & (1<<16))) && !(accessor->getExceptFlushpipe() && accessor->getExDslot())) |
{ |
outbuf.insn_count = insn_count; |
outbuf.pc = (uint32_t) accessor->getWbPC(); |
outbuf.insn = (uint32_t) accessor->getWbInsn(); |
outbuf.exception = 0; |
} |
// Exception version |
else if (accessor->getExceptFlushpipe()) |
{ |
outbuf.insn_count = insn_count; |
outbuf.pc = (uint32_t) accessor->getExPC(); |
outbuf.insn = (uint32_t) accessor->getExInsn(); |
outbuf.exception = 1; |
} |
else |
struct s_binary_output_buffer outbuf; |
|
// Output the state if we're not frozen and not flushing during a delay slot |
if (!accessor->getWbFreeze()) { |
if ((((accessor->getWbInsn() & 0xfc000000) != |
(uint32_t) OR1200_OR32_NOP) |
|| !(accessor->getWbInsn() & (1 << 16))) |
&& !(accessor->getExceptFlushpipe() |
&& accessor->getExDslot())) { |
outbuf.insn_count = insn_count; |
outbuf.pc = (uint32_t) accessor->getWbPC(); |
outbuf.insn = (uint32_t) accessor->getWbInsn(); |
outbuf.exception = 0; |
} |
// Exception version |
else if (accessor->getExceptFlushpipe()) { |
outbuf.insn_count = insn_count; |
outbuf.pc = (uint32_t) accessor->getExPC(); |
outbuf.insn = (uint32_t) accessor->getExInsn(); |
outbuf.exception = 1; |
} else |
return; |
} else |
return; |
|
if (logging_regs) { |
// Print general purpose register contents |
for (int i = 0; i < 32; i++) |
outbuf.regs[i] = (uint32_t) accessor->getGpr(i); |
|
outbuf.sr = (uint32_t) accessor->getSprSr(); |
outbuf.epcr0 = (uint32_t) accessor->getSprEpcr(); |
outbuf.eear0 = (uint32_t) accessor->getSprEear(); |
outbuf.eser0 = (uint32_t) accessor->getSprEsr(); |
|
statusFile.write((char *)&outbuf, |
sizeof(struct s_binary_output_buffer)); |
|
} else |
statusFile.write((char *)&outbuf, |
sizeof(struct |
s_binary_output_buffer_sans_regs)); |
|
return; |
} |
else |
return; |
|
if (logging_regs) |
{ |
// Print general purpose register contents |
for (int i=0; i<32; i++) |
outbuf.regs[i] = (uint32_t) accessor->getGpr(i); |
|
outbuf.sr = (uint32_t) accessor->getSprSr(); |
outbuf.epcr0 = (uint32_t) accessor->getSprEpcr(); |
outbuf.eear0 = (uint32_t) accessor->getSprEear(); |
outbuf.eser0 = (uint32_t) accessor->getSprEsr(); |
|
statusFile.write((char*)&outbuf, sizeof(struct s_binary_output_buffer)); |
|
} |
else |
statusFile.write((char*)&outbuf, sizeof(struct s_binary_output_buffer_sans_regs)); |
|
|
|
return; |
|
} // displayStateBinary() |
} // displayStateBinary() |
|
//! Function to calculate the number of instructions performed and the time taken |
void |
Or1200MonitorSC::perfSummary() |
{ |
if (!quiet) |
{ |
double ts; |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had |
|
clock_t finish = clock(); |
double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC; |
// It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second. |
double ips = (insn_count/elapsed_time); |
double mips = (insn_count/elapsed_time)/1000000; |
int hertz = (int) ((cycles/elapsed_time)/1000); |
std::cout << "* Or1200Monitor: simulated " << sc_time_stamp() << ", time elapsed: " << elapsed_time << " seconds" << endl; |
std::cout << "* Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed at approx " << hertz << "kHz" << endl; |
std::cout << "* Or1200Monitor: simulated " << insn_count << " instructions, insn/sec. = " << ips /*<< ", mips = " << mips*/ << endl; |
} |
return; |
} // perfSummary |
double ts; |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
int cycles = ts / (BENCH_CLK_HALFPERIOD * 2); // Number of clock cycles we had |
|
clock_t finish = clock(); |
double elapsedTime = |
(double (finish) - double (start))/CLOCKS_PER_SEC; |
// It took elapsedTime seconds to do insn_count instructions. Divide |
// insn_count by the time to get instructions/second. |
double ips = (insn_count / elapsedTime); |
double kips = (insn_count / elapsedTime) /1000; |
double mips = (insn_count / elapsedTime) / 1000000; |
int hertz = (int)((cycles / elapsedTime) / 1000); |
std::cout << "* Or1200Monitor: simulator time at exit: " << ts |
<< " ns" << endl; |
std::cout << "* Or1200Monitor: system time elapsed: " << elapsedTime |
<< " seconds" << endl; |
std::cout << "* Or1200Monitor: simulated " << dec << cycles << |
" clock cycles, executed at approx " << hertz << "kHz" << |
endl; |
std::cout << "* Or1200Monitor: simulated " << insn_count << |
" instructions, 1000's insn/sec. = " << kips << endl; |
return; |
} // perfSummary |
|
|
//! Dump contents of simulation's RAM to file |
void |
Or1200MonitorSC::memdump() |
{ |
if (!do_memdump) return; |
uint32_t current_word; |
int size_words = (memdump_end_addr/4) - (memdump_start_addr/4); |
if (!(size_words > 0)) return; |
|
// First try opening the file |
memdumpFile.open(memdumpFileName.c_str(), ios::binary); // Open memorydump file |
if(memdumpFile.is_open()) |
{ |
// If we could open the file then turn on logging |
cout << "* Dumping system RAM from 0x" << hex << memdump_start_addr << "-0x" << hex << memdump_end_addr << " to file " << memdumpFileName << endl; |
|
while (size_words) |
{ |
// Read the data from the simulation memory |
current_word = accessor->get_mem32(memdump_start_addr); |
// Change from whatever endian the host is (most |
// cases little) to big endian |
current_word = htonl(current_word); |
memdumpFile.write((char*) ¤t_word, 4); |
memdump_start_addr+=4; size_words--; |
if (!do_memdump) |
return; |
uint32_t current_word; |
int size_words = (memdump_end_addr / 4) - (memdump_start_addr / 4); |
if (!(size_words > 0)) |
return; |
|
// First try opening the file |
memdumpFile.open(memdumpFileName.c_str(), ios::binary); // Open memorydump file |
if (memdumpFile.is_open()) { |
// If we could open the file then turn on logging |
cout << "* Dumping system RAM from 0x" << hex << |
memdump_start_addr << "-0x" << hex << memdump_end_addr << |
" to file " << memdumpFileName << endl; |
|
while (size_words) { |
// Read the data from the simulation memory |
current_word = accessor->get_mem32(memdump_start_addr); |
// Change from whatever endian the host is (most |
// cases little) to big endian |
current_word = htonl(current_word); |
memdumpFile.write((char *)¤t_word, 4); |
memdump_start_addr += 4; |
size_words--; |
} |
|
// Ideally we've now finished piping out the data |
// not 100% about the endianess of this. |
} |
|
// Ideally we've now finished piping out the data |
// not 100% about the endianess of this. |
} |
memdumpFile.close(); |
|
memdumpFile.close(); |
|
} |
|
/* |
void |
Or1200MonitorSC::busMonitor() |
{ |
void |
Or1200MonitorSC::busMonitor() |
{ |
|
// This is for the wb_conmax module. Presumably other Wishbone bus arbiters |
// will need this section of the code to be re-written appropriately, along |
874,192 → 1017,185
static int cyclesWaited = 0; |
|
if (bus_trans_log_start_delay_enable) |
{ |
if (sc_time_stamp() >= bus_trans_log_start_delay) |
{ |
// No longer waiting |
bus_trans_log_start_delay_enable = false; |
cout << "* System log now enabled (time = " << bus_trans_log_start_delay.to_string() << ")" << endl; |
} |
{ |
if (sc_time_stamp() >= bus_trans_log_start_delay) |
{ |
// No longer waiting |
bus_trans_log_start_delay_enable = false; |
cout << "* System log now enabled (time = " << bus_trans_log_start_delay.to_string() << ")" << endl; |
} |
|
if (bus_trans_log_start_delay_enable) |
return; |
} |
if (bus_trans_log_start_delay_enable) |
return; |
} |
|
switch ( busLogState ) |
{ |
case BUS_LOG_IDLE: |
{ |
// Check the current granted master's cyc and stb inputs |
uint32_t gnt = accessor->getWbArbGrant(); |
if (accessor->getWbArbMastCycI(gnt) && accessor->getWbArbMastStbI(gnt) && |
!accessor->getWbArbMastAckO(gnt)) |
{ |
currentAddr = accessor->getWbArbMastAdrI(gnt); |
currentDataIn = accessor->getWbArbMastDatI(gnt); |
currentSel = (uint32_t) accessor->getWbArbMastSelI(gnt); |
currentSlave = (uint32_t)accessor->getWbArbMastSlaveSelDecoded(gnt)-1; |
currentWe = accessor->getWbArbMastWeI(gnt); |
currentMaster = gnt; |
busLogState = BUS_LOG_WAIT_FOR_ACK; |
cyclesWaited = 0; |
} |
} |
{ |
case BUS_LOG_IDLE: |
{ |
// Check the current granted master's cyc and stb inputs |
uint32_t gnt = accessor->getWbArbGrant(); |
if (accessor->getWbArbMastCycI(gnt) && accessor->getWbArbMastStbI(gnt) && |
!accessor->getWbArbMastAckO(gnt)) |
{ |
currentAddr = accessor->getWbArbMastAdrI(gnt); |
currentDataIn = accessor->getWbArbMastDatI(gnt); |
currentSel = (uint32_t) accessor->getWbArbMastSelI(gnt); |
currentSlave = (uint32_t)accessor->getWbArbMastSlaveSelDecoded(gnt)-1; |
currentWe = accessor->getWbArbMastWeI(gnt); |
currentMaster = gnt; |
busLogState = BUS_LOG_WAIT_FOR_ACK; |
cyclesWaited = 0; |
} |
} |
|
break; |
break; |
|
case BUS_LOG_WAIT_FOR_ACK: |
case BUS_LOG_WAIT_FOR_ACK: |
|
cyclesWaited++; |
cyclesWaited++; |
|
// Check for ACK |
if (accessor->getWbArbMastAckO(currentMaster)) |
{ |
// Transaction completed |
busTransLog << sc_time_stamp() << " M" << currentMaster << " "; |
if (currentWe) |
busTransLog << " W " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec << currentSlave << " " << hex << std::setw(8) << currentDataIn << " " << dec << cyclesWaited << endl; |
else |
busTransLog << " R " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec << currentSlave << " " << hex << std::setw(8) << accessor->getWbArbMastDatO(currentMaster) << " " << dec << cyclesWaited << endl; |
// Check for ACK |
if (accessor->getWbArbMastAckO(currentMaster)) |
{ |
// Transaction completed |
busTransLog << sc_time_stamp() << " M" << currentMaster << " "; |
if (currentWe) |
busTransLog << " W " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec << currentSlave << " " << hex << std::setw(8) << currentDataIn << " " << dec << cyclesWaited << endl; |
else |
busTransLog << " R " << hex << currentSel << " " << hex << std::setfill('0') << std::setw(8) << currentAddr << " S" << dec << currentSlave << " " << hex << std::setw(8) << accessor->getWbArbMastDatO(currentMaster) << " " << dec << cyclesWaited << endl; |
|
busLogState = BUS_LOG_IDLE; |
} |
busLogState = BUS_LOG_IDLE; |
} |
|
break; |
break; |
|
} |
} |
|
return; |
|
} // busMonitor () |
} // busMonitor () |
*/ |
void |
void |
Or1200MonitorSC::simPrintf(uint32_t stackaddr, uint32_t regparam) |
{ |
|
//cerr << hex << stackaddr << " " << regparam << endl; |
//cerr << hex << stackaddr << " " << regparam << endl; |
#define FMTLEN 2000 |
char fmtstr[FMTLEN]; |
uint32_t arg; |
oraddr_t argaddr; |
char *fmtstrend; |
char *fmtstrpart = fmtstr; |
int tee_exe_log; |
char fmtstr[FMTLEN]; |
uint32_t arg; |
oraddr_t argaddr; |
char *fmtstrend; |
char *fmtstrpart = fmtstr; |
int tee_exe_log; |
|
/*simgetstr (stackaddr, regparam);*/ |
/* Get the format string*/ |
uint32_t fmtaddr; |
int i; |
fmtaddr = regparam; |
/*simgetstr (stackaddr, regparam); */ |
/* Get the format string */ |
uint32_t fmtaddr; |
int i; |
fmtaddr = regparam; |
|
i = 0; |
while (accessor->get_mem8(fmtaddr) != '\0') |
{ |
fmtstr[i++] = accessor->get_mem8(fmtaddr); |
fmtaddr++; |
if (i == FMTLEN - 1) |
break; |
} |
fmtstr[i] = '\0'; |
|
|
argaddr = stackaddr; |
int index, last_index; |
index = last_index = 0; |
char tmp_char; |
while (1) |
{ |
/* Look for the next format argument, or end of string */ |
while (!(fmtstrpart[index] == '\0' || fmtstrpart[index] == '%')) |
index++; |
|
if (fmtstrpart[index] == '\0' && index == last_index) |
/* We had something like "%d\0", so we're done*/ |
return; |
|
if (fmtstrpart[index] == '\0') |
{ |
/* Final printf */ |
printf("%s", (char*) fmtstrpart + last_index); |
return; |
i = 0; |
while (accessor->get_mem8(fmtaddr) != '\0') { |
fmtstr[i++] = accessor->get_mem8(fmtaddr); |
fmtaddr++; |
if (i == FMTLEN - 1) |
break; |
} |
else |
{ |
/* We have a section between last_index and index that we should print out*/ |
fmtstrpart[index] = '\0'; /* Replace % with \0 for now */ |
printf ("%s",fmtstrpart + last_index); |
fmtstrpart[index] = '%'; /* Replace the % */ |
} |
fmtstr[i] = '\0'; |
|
last_index = index; /* last_index now pointing at the % */ |
|
/* Now extract the part that requires formatting */ |
/* Look for the end of the format argument*/ |
while (!(fmtstrpart[index] == 'd' || fmtstrpart[index] == 'i' |
|| fmtstrpart[index] == 'o' || fmtstrpart[index] == 'u' |
|| fmtstrpart[index] == 'x' || fmtstrpart[index] == 'X' |
|| fmtstrpart[index] == 'f' || fmtstrpart[index] == 'e' |
|| fmtstrpart[index] == 'E' || fmtstrpart[index] == 'g' |
|| fmtstrpart[index] == 'G' || fmtstrpart[index] == 'c' |
|| fmtstrpart[index] == 's' || fmtstrpart[index] == '\0' |
|| fmtstrpart[index+1] == '%')) |
index++; |
|
if (fmtstrpart[index] == '\0') |
{ |
// Error |
return; |
argaddr = stackaddr; |
int index, last_index; |
index = last_index = 0; |
char tmp_char; |
while (1) { |
/* Look for the next format argument, or end of string */ |
while (!(fmtstrpart[index] == '\0' || fmtstrpart[index] == '%')) |
index++; |
|
if (fmtstrpart[index] == '\0' && index == last_index) |
/* We had something like "%d\0", so we're done */ |
return; |
|
if (fmtstrpart[index] == '\0') { |
/* Final printf */ |
printf("%s", (char *)fmtstrpart + last_index); |
return; |
} else { |
/* We have a section between last_index and index that we should print out */ |
fmtstrpart[index] = '\0'; /* Replace % with \0 for now */ |
printf("%s", fmtstrpart + last_index); |
fmtstrpart[index] = '%'; /* Replace the % */ |
} |
|
last_index = index; /* last_index now pointing at the % */ |
|
/* Now extract the part that requires formatting */ |
/* Look for the end of the format argument */ |
while (!(fmtstrpart[index] == 'd' || fmtstrpart[index] == 'i' |
|| fmtstrpart[index] == 'o' || fmtstrpart[index] == 'u' |
|| fmtstrpart[index] == 'x' || fmtstrpart[index] == 'X' |
|| fmtstrpart[index] == 'f' || fmtstrpart[index] == 'e' |
|| fmtstrpart[index] == 'E' || fmtstrpart[index] == 'g' |
|| fmtstrpart[index] == 'G' || fmtstrpart[index] == 'c' |
|| fmtstrpart[index] == 's' |
|| fmtstrpart[index] == '\0' |
|| fmtstrpart[index + 1] == '%')) |
index++; |
|
if (fmtstrpart[index] == '\0') { |
// Error |
return; |
} else if (fmtstrpart[index] == '%' |
&& fmtstrpart[index + 1] == '%') { |
/* Deal with the %% case to print a single % */ |
index++; |
printf("%%"); |
} else { |
/* We now will print the part that requires the next argument */ |
/* Same trick, but this time remember what the char was */ |
tmp_char = fmtstrpart[index + 1]; |
fmtstrpart[index + 1] = '\0'; /* Replace % with \0 for now */ |
/* Check what we're printing */ |
if (fmtstrpart[index] == 's') { |
/* It's a string, so pull it out of memory into a local char* |
and pass it to printf() */ |
int tmp_string_len, z; |
/* Assume stackaddr already pointing at appropriate value */ |
oraddr_t ormem_str_ptr = |
accessor->get_mem32(argaddr); |
|
while (accessor->get_mem8(ormem_str_ptr++) != |
'\0') |
tmp_string_len++; |
tmp_string_len++; /* One for terminating char */ |
|
char *str = (char *)malloc(tmp_string_len); |
if (str == NULL) |
return; /* Malloc failed, bigger issues than printf'ing out of sim */ |
ormem_str_ptr = accessor->get_mem32(argaddr); /* Reset start pointer value */ |
for (z = 0; z < tmp_string_len; z++) |
str[z] = |
accessor->get_mem8(ormem_str_ptr + |
z); |
|
printf(fmtstrpart + last_index, str); |
free(str); |
} else { |
/* |
Some other kind of variable, pull it off the stack and print |
it out. Assume stackaddr already pointing at appropriate |
value |
*/ |
arg = accessor->get_mem32(argaddr); |
printf(fmtstrpart + last_index, arg); |
} |
argaddr += 4; /* Increment argument pointer in stack */ |
fmtstrpart[index + 1] = tmp_char; /* Replace the char we took out */ |
} |
index++; |
last_index = index; |
} |
else if (fmtstrpart[index] == '%' && fmtstrpart[index+1] == '%') |
{ |
/* Deal with the %% case to print a single % */ |
index++; |
printf("%%"); |
} |
else |
{ |
/* We now will print the part that requires the next argument */ |
/* Same trick, but this time remember what the char was */ |
tmp_char = fmtstrpart[index+1]; |
fmtstrpart[index+1] = '\0'; /* Replace % with \0 for now */ |
/* Check what we're printing*/ |
if (fmtstrpart[index] == 's') |
{ |
/* It's a string, so pull it out of memory into a local char* |
and pass it to printf() */ |
int tmp_string_len, z; |
/* Assume stackaddr already pointing at appropriate value*/ |
oraddr_t ormem_str_ptr = accessor->get_mem32(argaddr); |
|
while (accessor->get_mem8(ormem_str_ptr++) != '\0') |
tmp_string_len++; |
tmp_string_len++; /* One for terminating char */ |
|
char* str = (char *) malloc (tmp_string_len); |
if (str == NULL) return; /* Malloc failed, bigger issues than printf'ing out of sim */ |
ormem_str_ptr = accessor->get_mem32(argaddr); /* Reset start pointer value*/ |
for (z=0;z<tmp_string_len;z++) |
str[z] = accessor->get_mem8(ormem_str_ptr+z); |
|
printf (fmtstrpart + last_index, str); |
free (str); |
} |
else |
{ |
/* |
Some other kind of variable, pull it off the stack and print |
it out. Assume stackaddr already pointing at appropriate |
value |
*/ |
arg = accessor->get_mem32(argaddr); |
printf (fmtstrpart + last_index, arg); |
} |
argaddr+= 4; /* Increment argument pointer in stack */ |
fmtstrpart[index+1] = tmp_char; /* Replace the char we took out */ |
} |
index++; |
last_index = index; |
} |
|
return; |
} // simPrintf () |
return; |
} // simPrintf () |
/sysc/src/TapActionIRScan.cpp
28,11 → 28,9
|
// $Id$ |
|
|
#include "TapActionIRScan.h" |
#include "TapStateMachine.h" |
|
|
//! Constructor |
|
//! Sets up the superclass with the SystemC completion event and initializes |
43,20 → 41,15
//! @param[in] _iRegIn The register to shift in. |
//! @param[in] _iRegSize Size in bits of the register to shift in. |
|
TapActionIRScan::TapActionIRScan (sc_core::sc_event *_doneEvent, |
uint32_t _iRegIn, |
int _iRegSize) : |
TapAction (_doneEvent), |
iRegIn (_iRegIn), |
iRegSize (_iRegSize), |
iRegOut (0), |
bitsShifted (0), |
iRScanState (SHIFT_IR_PREPARING) |
TapActionIRScan::TapActionIRScan(sc_core::sc_event * _doneEvent, |
uint32_t _iRegIn, |
int _iRegSize):TapAction(_doneEvent), |
iRegIn(_iRegIn), |
iRegSize(_iRegSize), iRegOut(0), bitsShifted(0), iRScanState(SHIFT_IR_PREPARING) |
{ |
|
} // TapActionIRScan () |
} // TapActionIRScan () |
|
|
//! Process the Shift-IR action |
|
//! This drives the IR-Scan state. We can only do this if we have the TAP |
75,104 → 68,83
|
//! @return True if the action is complete |
|
bool |
TapActionIRScan::process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms) |
bool TapActionIRScan::process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms) |
{ |
// Ensure we are in a consistent state. If not then we'll have moved towards |
// it and can return with the given tms |
if (!checkResetDone (tapStateMachine, tms, true)) |
{ |
return false; |
} |
// Ensure we are in a consistent state. If not then we'll have moved towards |
// it and can return with the given tms |
if (!checkResetDone(tapStateMachine, tms, true)) { |
return false; |
} |
// We are consistent, so work through the IR-Scan process |
switch (iRScanState) { |
case SHIFT_IR_PREPARING: |
|
// We are consistent, so work through the IR-Scan process |
switch (iRScanState) |
{ |
case SHIFT_IR_PREPARING: |
// Are we in the Shift-IR state yet? |
if (!tapStateMachine->targetState(TAP_SHIFT_IR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
iRScanState = SHIFT_IR_SHIFTING; // Drop through |
} |
|
// Are we in the Shift-IR state yet? |
if (!tapStateMachine->targetState (TAP_SHIFT_IR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
} |
else |
{ |
iRScanState = SHIFT_IR_SHIFTING; // Drop through |
} |
case SHIFT_IR_SHIFTING: |
|
case SHIFT_IR_SHIFTING: |
// Are we still shifting stuff? |
if (bitsShifted < iRegSize) { |
// We are in the Shift-IR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
|
// Are we still shifting stuff? |
if (bitsShifted < iRegSize) |
{ |
// We are in the Shift-IR state. Another bit about to be done, so |
// increment the count |
bitsShifted++; |
// Shift out the TDI value from the bottom of the register |
tdi = iRegIn & 1; |
iRegIn >>= 1; |
|
// Shift out the TDI value from the bottom of the register |
tdi = iRegIn & 1; |
iRegIn >>= 1; |
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) { |
iRegOut >>= 1; // Move all the existing bits right |
|
// Record the TDO value. This is always a cycle late, so we ignore |
// it the first time. The value shifts in from the top. |
if (bitsShifted > 1) |
{ |
iRegOut >>= 1; // Move all the existing bits right |
|
if (tdo) // OR any new bit in |
{ |
uint32_t tmpBit = 1 << (iRegSize - 1); |
iRegOut |= tmpBit; |
} |
} |
if (tdo) // OR any new bit in |
{ |
uint32_t tmpBit = 1 << (iRegSize - 1); |
iRegOut |= tmpBit; |
} |
} |
// TMS is 0 to keep us here UNLESS this is the last bit, in which |
// case it is 1 to move us into Exit1-IR. |
tms = (bitsShifted == iRegSize); |
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which |
// case it is 1 to move us into Exit1-IR. |
tms = (bitsShifted == iRegSize); |
return false; |
} else { |
// Capture the last TDO bit |
iRegOut >>= 1; // Move all the existing bits right |
|
return false; |
} |
else |
{ |
// Capture the last TDO bit |
iRegOut >>= 1; // Move all the existing bits right |
if (tdo) // OR any new bit in |
{ |
uint32_t tmpBit = 1 << (iRegSize - 1); |
iRegOut |= tmpBit; |
} |
|
if (tdo) // OR any new bit in |
{ |
uint32_t tmpBit = 1 << (iRegSize - 1); |
iRegOut |= tmpBit; |
} |
iRScanState = SHIFT_IR_UPDATING; // Drop through |
} |
|
iRScanState = SHIFT_IR_UPDATING; // Drop through |
} |
case SHIFT_IR_UPDATING: |
|
case SHIFT_IR_UPDATING: |
|
// Are we still trying to update? |
if (!tapStateMachine->targetState (TAP_UPDATE_IR, tms)) |
{ |
return false; // Not there. Accept the TMS value |
// Are we still trying to update? |
if (!tapStateMachine->targetState(TAP_UPDATE_IR, tms)) { |
return false; // Not there. Accept the TMS value |
} else { |
return true; // All done |
} |
} |
else |
{ |
return true; // All done |
} |
} |
} // process () |
} // process () |
|
|
//! Get the shifted out register |
|
//! @return The value of the shifted our register |
|
uint32_t |
TapActionIRScan::getIRegOut () |
uint32_t TapActionIRScan::getIRegOut() |
{ |
return iRegOut; |
return iRegOut; |
|
} // getIRegOut () |
|
|
} // getIRegOut () |
/sysc/src/TapAction.cpp
32,9 → 32,8
|
#include "TapAction.h" |
|
class sc_event; |
class sc_event; |
|
|
//! Constructor |
|
//! Records the SystemC event used to notify completion and sets the |
42,26 → 41,22
|
//! @param _actionType The action type |
|
TapAction::TapAction (sc_core::sc_event *_doneEvent) : |
doneEvent (_doneEvent), |
resetCounter (0) |
TapAction::TapAction(sc_core::sc_event * _doneEvent): |
doneEvent(_doneEvent), resetCounter(0) |
{ |
|
} // TapAction () |
} // TapAction () |
|
|
//! Accessor to get the SystemC completion event |
|
//! @return The SystemC completion event |
|
sc_core::sc_event * |
TapAction::getDoneEvent () |
sc_core::sc_event * TapAction::getDoneEvent() |
{ |
return doneEvent; |
return doneEvent; |
|
} // getDoneEvent () |
} // getDoneEvent () |
|
|
//! Function to check the TAP is in a consistent state, optionally with a |
//! warning. |
|
82,38 → 77,30
|
//! @return TRUE if the TAP state machine was already in a consistent state. |
|
bool |
TapAction::checkResetDone (TapStateMachine *tapStateMachine, |
bool &tms, |
bool warn) |
bool TapAction::checkResetDone(TapStateMachine * tapStateMachine, |
bool & tms, bool warn) |
{ |
// Nothing more to do if we are consistent |
if (tapStateMachine->getResetDone ()) |
{ |
return true; |
} |
// Nothing more to do if we are consistent |
if (tapStateMachine->getResetDone()) { |
return true; |
} |
// Need to reset. If requested and this is the first cycle of reset, give a |
// warning. |
if (warn && (0 == resetCounter)) { |
std::cerr << "JTAG TAP state inconsistent: resetting" << |
std::endl; |
} |
// Drive towards reset |
resetCounter++; |
tms = 1; |
|
// Need to reset. If requested and this is the first cycle of reset, give a |
// warning. |
if (warn && (0 == resetCounter)) |
{ |
std::cerr << "JTAG TAP state inconsistent: resetting" << std::endl; |
} |
|
// Drive towards reset |
resetCounter++; |
tms = 1; |
|
// If we have got to the end of the reset sequence we can clear the |
// tapStateMachine and report we are consistent. However we will not return |
// true until the next call. |
if (tapStateMachine->TAP_RESET_CYCLES == resetCounter) |
{ |
tapStateMachine->setResetDone (true); |
resetCounter = 0; // Ready for next time |
} |
else |
{ |
return false; |
} |
} // checkResetDone () |
// If we have got to the end of the reset sequence we can clear the |
// tapStateMachine and report we are consistent. However we will not return |
// true until the next call. |
if (tapStateMachine->TAP_RESET_CYCLES == resetCounter) { |
tapStateMachine->setResetDone(true); |
resetCounter = 0; // Ready for next time |
} else { |
return false; |
} |
} // checkResetDone () |
/sysc/src/RspConnection.cpp
57,7 → 57,6
// Define RSP_TRACE to turn on tracing of packets sent and received |
// #define RSP_TRACE |
|
|
//----------------------------------------------------------------------------- |
//! Constructor when using a port number |
|
65,13 → 64,12
|
//! @param[in] _portNum The port number to connect to |
//----------------------------------------------------------------------------- |
RspConnection::RspConnection (int _portNum) |
RspConnection::RspConnection(int _portNum) |
{ |
rspInit (_portNum, DEFAULT_RSP_SERVICE); |
rspInit(_portNum, DEFAULT_RSP_SERVICE); |
|
} // RspConnection () |
} // RspConnection () |
|
|
//----------------------------------------------------------------------------- |
//! Constructor when using a service |
|
80,25 → 78,23
//! @param[in] _serviceName The service name to use. Defaults to |
//! DEFAULT_RSP_SERVER |
//----------------------------------------------------------------------------- |
RspConnection::RspConnection (const char *_serviceName) |
RspConnection::RspConnection(const char *_serviceName) |
{ |
rspInit (0, _serviceName); |
rspInit(0, _serviceName); |
|
} // RspConnection () |
} // RspConnection () |
|
|
//----------------------------------------------------------------------------- |
//! Destructor |
|
//! Close the connection if it is still open |
//----------------------------------------------------------------------------- |
RspConnection::~RspConnection () |
RspConnection::~RspConnection() |
{ |
this->rspClose (); // Don't confuse with any other close () |
this->rspClose(); // Don't confuse with any other close () |
|
} // ~RspConnection () |
} // ~RspConnection () |
|
|
//----------------------------------------------------------------------------- |
//! Generic initialization routine specifying both port number and service |
//! name. |
115,16 → 111,14
//! @param[in] _serviceName The service name to use (if PortNum == 0). |
//----------------------------------------------------------------------------- |
void |
RspConnection::rspInit (int _portNum, |
const char *_serviceName) |
RspConnection::rspInit(int _portNum, const char *_serviceName) |
{ |
portNum = _portNum; |
serviceName = _serviceName; |
clientFd = -1; |
portNum = _portNum; |
serviceName = _serviceName; |
clientFd = -1; |
|
} // init () |
} // init () |
|
|
//----------------------------------------------------------------------------- |
//! Get a new client connection. |
|
148,197 → 142,176
//! @return TRUE if the connection was established or can be retried. FALSE |
//! if the error was so serious the program must be aborted. |
//----------------------------------------------------------------------------- |
bool |
RspConnection::rspConnect () |
bool RspConnection::rspConnect() |
{ |
// 0 is used as the RSP port number to indicate that we should use the |
// service name instead. |
if (0 == portNum) |
{ |
struct servent *service = getservbyname (serviceName, "tcp"); |
// 0 is used as the RSP port number to indicate that we should use the |
// service name instead. |
if (0 == portNum) { |
struct servent *service = getservbyname(serviceName, "tcp"); |
|
if (NULL == service) |
{ |
cerr << "ERROR: RSP unable to find service \"" << serviceName |
<< "\": " << strerror (errno) << endl; |
return false; |
if (NULL == service) { |
cerr << "ERROR: RSP unable to find service \"" << |
serviceName << "\": " << strerror(errno) << endl; |
return false; |
} |
|
portNum = ntohs(service->s_port); |
} |
// Open a socket on which we'll listen for clients |
int tmpFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
if (tmpFd < 0) { |
cerr << "ERROR: Cannot open RSP socket" << endl; |
return false; |
} |
// Allow rapid reuse of the port on this socket |
int optval = 1; |
setsockopt(tmpFd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, |
sizeof(optval)); |
|
portNum = ntohs (service->s_port); |
} |
// Bind the port to the socket |
struct sockaddr_in sockAddr; |
sockAddr.sin_family = PF_INET; |
sockAddr.sin_port = htons(portNum); |
sockAddr.sin_addr.s_addr = INADDR_ANY; |
|
// Open a socket on which we'll listen for clients |
int tmpFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); |
if (tmpFd < 0) |
{ |
cerr << "ERROR: Cannot open RSP socket" << endl; |
return false; |
} |
if (bind(tmpFd, (struct sockaddr *)&sockAddr, sizeof(sockAddr))) { |
cerr << "ERROR: Cannot bind to RSP socket" << endl; |
return false; |
} |
// Listen for (at most one) client |
if (listen(tmpFd, 1)) { |
cerr << "ERROR: Cannot listen on RSP socket" << endl; |
return false; |
} |
|
// Allow rapid reuse of the port on this socket |
int optval = 1; |
setsockopt (tmpFd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, |
sizeof (optval)); |
cout << "Listening for RSP on port " << portNum << endl << flush; |
|
// Accept a client which connects |
socklen_t len; // Size of the socket address |
clientFd = accept(tmpFd, (struct sockaddr *)&sockAddr, &len); |
|
if (-1 == clientFd) { |
cerr << "Warning: Failed to accept RSP client" << endl; |
return true; // OK to retry |
} |
// Enable TCP keep alive process |
optval = 1; |
setsockopt(clientFd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, |
sizeof(optval)); |
|
// Bind the port to the socket |
struct sockaddr_in sockAddr; |
sockAddr.sin_family = PF_INET; |
sockAddr.sin_port = htons (portNum); |
sockAddr.sin_addr.s_addr = INADDR_ANY; |
int flags; |
|
if (bind (tmpFd, (struct sockaddr *) &sockAddr, sizeof (sockAddr))) |
{ |
cerr << "ERROR: Cannot bind to RSP socket" << endl; |
return false; |
} |
|
// Listen for (at most one) client |
if (listen (tmpFd, 1)) |
{ |
cerr << "ERROR: Cannot listen on RSP socket" << endl; |
return false; |
} |
|
cout << "Listening for RSP on port " << portNum << endl << flush; |
/* If they have O_NONBLOCK, use the Posix way to do it */ |
|
// Accept a client which connects |
socklen_t len; // Size of the socket address |
clientFd = accept (tmpFd, (struct sockaddr *)&sockAddr, &len); |
#if defined(O_NONBLOCK) |
/* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */ |
if (-1 == (flags = fcntl(clientFd, F_GETFL, 0))) |
flags = 0; |
|
if (-1 == clientFd) |
{ |
cerr << "Warning: Failed to accept RSP client" << endl; |
return true; // OK to retry |
} |
|
// Enable TCP keep alive process |
optval = 1; |
setsockopt (clientFd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, |
sizeof (optval)); |
|
int flags; |
|
/* If they have O_NONBLOCK, use the Posix way to do it */ |
|
#if defined(O_NONBLOCK) |
/* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */ |
if (-1 == (flags = fcntl(clientFd, F_GETFL, 0))) |
flags = 0; |
|
fcntl(clientFd, F_SETFL, flags | O_NONBLOCK); |
fcntl(clientFd, F_SETFL, flags | O_NONBLOCK); |
#else |
/* Otherwise, use the old way of doing it */ |
flags = 1; |
ioctl(clientFd, FIOBIO, &flags); |
/* Otherwise, use the old way of doing it */ |
flags = 1; |
ioctl(clientFd, FIOBIO, &flags); |
#endif |
|
/* Set socket to be non-blocking */ |
/* Set socket to be non-blocking */ |
|
/* We do this because when we're given a continue, or step |
instruction,command we set the processor stall off, then instantly check |
if it's stopped. If it hasn't then we drop through and wait for input |
from GDB. Obviously this will cause problems when it will stop after we |
do the check. So now, rspSocketPeek() been implemented to simply check if |
there's an incoming command from GDB (although, mainly interested in |
int. commands), otherwise it returns back to poll the processor's |
stall bit. It can only do this if the socket is non-blocking. |
/* We do this because when we're given a continue, or step |
instruction,command we set the processor stall off, then instantly check |
if it's stopped. If it hasn't then we drop through and wait for input |
from GDB. Obviously this will cause problems when it will stop after we |
do the check. So now, rspSocketPeek() been implemented to simply check if |
there's an incoming command from GDB (although, mainly interested in |
int. commands), otherwise it returns back to poll the processor's |
stall bit. It can only do this if the socket is non-blocking. |
|
At first test, simply adding this line appeared to give no problems with |
the existing code. No "simulation" of blocking behaviour on the |
non-blocking socket was required (in the event that a read/write throws |
back a EWOULDBLOCK error, as was looked to be the case in the previous |
GDB handling code) -- Julius |
*/ |
if (ioctl(clientFd, FIONBIO, (char *)&optval) > 0 ) |
{ |
cerr << "RspConnect: ioctl failed, line "<< __LINE__ << endl; |
close(clientFd); |
close(tmpFd); |
return false; |
} |
At first test, simply adding this line appeared to give no problems with |
the existing code. No "simulation" of blocking behaviour on the |
non-blocking socket was required (in the event that a read/write throws |
back a EWOULDBLOCK error, as was looked to be the case in the previous |
GDB handling code) -- Julius |
*/ |
if (ioctl(clientFd, FIONBIO, (char *)&optval) > 0) { |
cerr << "RspConnect: ioctl failed, line " << __LINE__ << endl; |
close(clientFd); |
close(tmpFd); |
return false; |
} |
// Don't delay small packets, for better interactive response (disable |
// Nagel's algorithm) |
optval = 1; |
setsockopt(clientFd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, |
sizeof(optval)); |
|
// Don't delay small packets, for better interactive response (disable |
// Nagel's algorithm) |
optval = 1; |
setsockopt (clientFd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, |
sizeof (optval)); |
// Socket is no longer needed |
close(tmpFd); // No longer need this |
signal(SIGPIPE, SIG_IGN); // So we don't exit if client dies |
|
// Socket is no longer needed |
close (tmpFd); // No longer need this |
signal (SIGPIPE, SIG_IGN); // So we don't exit if client dies |
cout << "Remote debugging from host " << inet_ntoa(sockAddr.sin_addr) |
<< endl; |
return true; |
|
cout << "Remote debugging from host " << inet_ntoa (sockAddr.sin_addr) |
<< endl; |
return true; |
} // rspConnect () |
|
} // rspConnect () |
|
|
//----------------------------------------------------------------------------- |
//! Close a client connection if it is open |
//----------------------------------------------------------------------------- |
void |
RspConnection::rspClose () |
void RspConnection::rspClose() |
{ |
if (isConnected ()) |
{ |
cout << "Closing connection" << endl; |
close (clientFd); |
clientFd = -1; |
} |
} // rspClose () |
if (isConnected()) { |
cout << "Closing connection" << endl; |
close(clientFd); |
clientFd = -1; |
} |
} // rspClose () |
|
|
//----------------------------------------------------------------------------- |
//! Report if we are connected to a client. |
|
//! @return TRUE if we are connected, FALSE otherwise |
//----------------------------------------------------------------------------- |
bool |
RspConnection::isConnected () |
bool RspConnection::isConnected() |
{ |
return -1 != clientFd; |
return -1 != clientFd; |
|
} // isConnected () |
} // isConnected () |
|
//----------------------------------------------------------------------------- |
//! Peek at data coming into server from GDB |
|
|
//! Useful for polling for ETX (0x3) chars being sent when GDB wants to |
//! interrupt |
|
|
//! @return the char we peeked, 0 otherwise |
//----------------------------------------------------------------------------- |
char |
RspConnection::rspSocketPeek() |
char RspConnection::rspSocketPeek() |
{ |
char c; |
int n; |
// Using recv here instead of read becuase we can pass the MSG_PEEK |
// flag, which lets us look at what's on the socket, without actually |
// taking it off |
char c; |
int n; |
// Using recv here instead of read becuase we can pass the MSG_PEEK |
// flag, which lets us look at what's on the socket, without actually |
// taking it off |
|
//if (DEBUG_GDB) |
// printf("peeking at GDB socket...\n"); |
|
n = recv (clientFd, &c, sizeof (c), MSG_PEEK); |
|
//if (DEBUG_GDB) |
// printf("peeked, got n=%d, c=0x%x\n",n, c); |
|
if (n>0) |
return c; |
else |
return -1; |
/* |
if (n > 0) |
return c; |
else |
return '\0'; |
*/ |
//if (DEBUG_GDB) |
// printf("peeking at GDB socket...\n"); |
|
n = recv(clientFd, &c, sizeof(c), MSG_PEEK); |
|
//if (DEBUG_GDB) |
// printf("peeked, got n=%d, c=0x%x\n",n, c); |
|
if (n > 0) |
return c; |
else |
return -1; |
/* |
if (n > 0) |
return c; |
else |
return '\0'; |
*/ |
|
} |
|
//----------------------------------------------------------------------------- |
361,129 → 334,104
//! @return TRUE to indicate success, FALSE otherwise (means a communications |
//! failure) |
//----------------------------------------------------------------------------- |
bool |
RspConnection::getPkt (RspPacket *pkt) |
bool RspConnection::getPkt(RspPacket * pkt) |
{ |
// Keep getting packets, until one is found with a valid checksum |
while (true) |
{ |
int bufSize = pkt->getBufSize (); |
unsigned char checksum; // The checksum we have computed |
int count; // Index into the buffer |
int ch; // Current character |
// Keep getting packets, until one is found with a valid checksum |
while (true) { |
int bufSize = pkt->getBufSize(); |
unsigned char checksum; // The checksum we have computed |
int count; // Index into the buffer |
int ch; // Current character |
|
// Wait around for the start character ('$'). Ignore all other |
// characters |
ch = getRspChar(); |
while (ch != '$') { |
if (-1 == ch) { |
return false; // Connection failed |
} else { |
ch = getRspChar(); |
} |
} |
|
// Wait around for the start character ('$'). Ignore all other |
// characters |
ch = getRspChar (); |
while (ch != '$') |
{ |
if (-1 == ch) |
{ |
return false; // Connection failed |
} |
else |
{ |
ch = getRspChar (); |
} |
} |
// Read until a '#' or end of buffer is found |
checksum = 0; |
count = 0; |
while (count < bufSize - 1) { |
ch = getRspChar(); |
|
// Read until a '#' or end of buffer is found |
checksum = 0; |
count = 0; |
while (count < bufSize - 1) |
{ |
ch = getRspChar (); |
if (-1 == ch) { |
return false; // Connection failed |
} |
// If we hit a start of line char begin all over again |
if ('$' == ch) { |
checksum = 0; |
count = 0; |
|
if (-1 == ch) |
{ |
return false; // Connection failed |
} |
continue; |
} |
// Break out if we get the end of line char |
if ('#' == ch) { |
break; |
} |
// Update the checksum and add the char to the buffer |
checksum = checksum + (unsigned char)ch; |
pkt->data[count] = (char)ch; |
count++; |
} |
|
// If we hit a start of line char begin all over again |
if ('$' == ch) |
{ |
checksum = 0; |
count = 0; |
// Mark the end of the buffer with EOS - it's convenient for non-binary |
// data to be valid strings. |
pkt->data[count] = 0; |
pkt->setLen(count); |
|
continue; |
} |
// If we have a valid end of packet char, validate the checksum. If we |
// don't it's because we ran out of buffer in the previous loop. |
if ('#' == ch) { |
unsigned char xmitcsum; // The checksum in the packet |
|
// Break out if we get the end of line char |
if ('#' == ch) |
{ |
break; |
} |
ch = getRspChar(); |
if (-1 == ch) { |
return false; // Connection failed |
} |
xmitcsum = Utils::char2Hex(ch) << 4; |
|
// Update the checksum and add the char to the buffer |
checksum = checksum + (unsigned char)ch; |
pkt->data[count] = (char)ch; |
count++; |
} |
ch = getRspChar(); |
if (-1 == ch) { |
return false; // Connection failed |
} |
|
// Mark the end of the buffer with EOS - it's convenient for non-binary |
// data to be valid strings. |
pkt->data[count] = 0; |
pkt->setLen (count); |
xmitcsum += Utils::char2Hex(ch); |
|
// If we have a valid end of packet char, validate the checksum. If we |
// don't it's because we ran out of buffer in the previous loop. |
if ('#' == ch) |
{ |
unsigned char xmitcsum; // The checksum in the packet |
|
ch = getRspChar (); |
if (-1 == ch) |
{ |
return false; // Connection failed |
} |
xmitcsum = Utils::char2Hex (ch) << 4; |
|
ch = getRspChar (); |
if (-1 == ch) |
{ |
return false; // Connection failed |
} |
|
xmitcsum += Utils::char2Hex (ch); |
|
// If the checksums don't match print a warning, and put the |
// negative ack back to the client. Otherwise put a positive ack. |
if (checksum != xmitcsum) |
{ |
cerr << "Warning: Bad RSP checksum: Computed 0x" |
<< setw (2) << setfill ('0') << hex |
<< checksum << ", received 0x" << xmitcsum |
<< setfill (' ') << dec << endl; |
if (!putRspChar ('-')) // Failed checksum |
{ |
return false; // Comms failure |
} |
} |
else |
{ |
if (!putRspChar ('+')) // successful transfer |
{ |
return false; // Comms failure |
} |
else |
{ |
// If the checksums don't match print a warning, and put the |
// negative ack back to the client. Otherwise put a positive ack. |
if (checksum != xmitcsum) { |
cerr << "Warning: Bad RSP checksum: Computed 0x" |
<< setw(2) << setfill('0') << hex |
<< checksum << ", received 0x" << xmitcsum |
<< setfill(' ') << dec << endl; |
if (!putRspChar('-')) // Failed checksum |
{ |
return false; // Comms failure |
} |
} else { |
if (!putRspChar('+')) // successful transfer |
{ |
return false; // Comms failure |
} else { |
#ifdef RSP_TRACE |
cout << "getPkt: " << *pkt << endl; |
cout << "getPkt: " << *pkt << endl; |
#endif |
return true; // Success |
return true; // Success |
} |
} |
} else { |
cerr << "Warning: RSP packet overran buffer" << endl; |
} |
} |
} |
else |
{ |
cerr << "Warning: RSP packet overran buffer" << endl; |
} |
} |
|
} // getPkt () |
} // getPkt () |
|
|
//----------------------------------------------------------------------------- |
//! Put the packet out on the RSP connection |
|
500,81 → 448,68
//! @return TRUE to indicate success, FALSE otherwise (means a communications |
//! failure). |
//----------------------------------------------------------------------------- |
bool |
RspConnection::putPkt (RspPacket *pkt) |
bool RspConnection::putPkt(RspPacket * pkt) |
{ |
int len = pkt->getLen (); |
int ch; // Ack char |
int len = pkt->getLen(); |
int ch; // Ack char |
|
// Construct $<packet info>#<checksum>. Repeat until the GDB client |
// acknowledges satisfactory receipt. |
do |
{ |
unsigned char checksum = 0; // Computed checksum |
int count = 0; // Index into the buffer |
// Construct $<packet info>#<checksum>. Repeat until the GDB client |
// acknowledges satisfactory receipt. |
do { |
unsigned char checksum = 0; // Computed checksum |
int count = 0; // Index into the buffer |
|
if (!putRspChar ('$')) // Start char |
{ |
return false; // Comms failure |
} |
|
|
// Body of the packet |
for (count = 0; count < len; count++) |
{ |
unsigned char ch = pkt->data[count]; |
|
// Check for escaped chars |
if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch)) |
{ |
ch ^= 0x20; |
checksum += (unsigned char)'}'; |
if (!putRspChar ('}')) |
if (!putRspChar('$')) // Start char |
{ |
return false; // Comms failure |
return false; // Comms failure |
} |
// Body of the packet |
for (count = 0; count < len; count++) { |
unsigned char ch = pkt->data[count]; |
|
} |
// Check for escaped chars |
if (('$' == ch) || ('#' == ch) || ('*' == ch) |
|| ('}' == ch)) { |
ch ^= 0x20; |
checksum += (unsigned char)'}'; |
if (!putRspChar('}')) { |
return false; // Comms failure |
} |
|
checksum += ch; |
if (!putRspChar (ch)) |
{ |
return false; // Comms failure |
} |
} |
} |
|
if (!putRspChar ('#')) // End char |
{ |
return false; // Comms failure |
} |
checksum += ch; |
if (!putRspChar(ch)) { |
return false; // Comms failure |
} |
} |
|
// Computed checksum |
if (!putRspChar (Utils::hex2Char (checksum >> 4))) |
{ |
return false; // Comms failure |
if (!putRspChar('#')) // End char |
{ |
return false; // Comms failure |
} |
// Computed checksum |
if (!putRspChar(Utils::hex2Char(checksum >> 4))) { |
return false; // Comms failure |
} |
if (!putRspChar(Utils::hex2Char(checksum % 16))) { |
return false; // Comms failure |
} |
// Check for ack of connection failure |
ch = getRspChar(); |
if (-1 == ch) { |
return false; // Comms failure |
} |
} |
if (!putRspChar (Utils::hex2Char (checksum % 16))) |
{ |
return false; // Comms failure |
} |
while ('+' != ch); |
|
// Check for ack of connection failure |
ch = getRspChar (); |
if (-1 == ch) |
{ |
return false; // Comms failure |
} |
} |
while ('+' != ch); |
|
#ifdef RSP_TRACE |
cout << "putPkt: " << *pkt << endl; |
cout << "putPkt: " << *pkt << endl; |
#endif |
return true; |
return true; |
|
} // putPkt () |
} // putPkt () |
|
|
//----------------------------------------------------------------------------- |
//! Put a single character out on the RSP connection |
|
585,44 → 520,38
|
//! @return TRUE if char sent OK, FALSE if not (communications failure) |
//----------------------------------------------------------------------------- |
bool |
RspConnection::putRspChar (char c) |
bool RspConnection::putRspChar(char c) |
{ |
if (-1 == clientFd) |
{ |
cerr << "Warning: Attempt to write '" << c |
<< "' to unopened RSP client: Ignored" << endl; |
return false; |
} |
if (-1 == clientFd) { |
cerr << "Warning: Attempt to write '" << c |
<< "' to unopened RSP client: Ignored" << endl; |
return false; |
} |
// Write until successful (we retry after interrupts) or catastrophic |
// failure. |
while (true) { |
switch (write(clientFd, &c, sizeof(c))) { |
case -1: |
// Error: only allow interrupts or would block |
if ((EAGAIN != errno) && (EINTR != errno)) { |
cerr << |
"Warning: Failed to write to RSP client: " |
<< "Closing client connection: " << |
strerror(errno) << endl; |
return false; |
} |
|
// Write until successful (we retry after interrupts) or catastrophic |
// failure. |
while (true) |
{ |
switch (write (clientFd, &c, sizeof (c))) |
{ |
case -1: |
// Error: only allow interrupts or would block |
if ((EAGAIN != errno) && (EINTR != errno)) |
{ |
cerr << "Warning: Failed to write to RSP client: " |
<< "Closing client connection: " |
<< strerror (errno) << endl; |
return false; |
} |
|
break; |
break; |
|
case 0: |
break; // Nothing written! Try again |
case 0: |
break; // Nothing written! Try again |
|
default: |
return true; // Success, we can return |
default: |
return true; // Success, we can return |
} |
} |
} |
} // putRspChar () |
} // putRspChar () |
|
|
//----------------------------------------------------------------------------- |
//! Get a single character from the RSP connection |
|
631,43 → 560,38
|
//! @return The character received or -1 on failure |
//----------------------------------------------------------------------------- |
int |
RspConnection::getRspChar () |
int RspConnection::getRspChar() |
{ |
if (-1 == clientFd) |
{ |
cerr << "Warning: Attempt to read from " |
<< "unopened RSP client: Ignored" << endl; |
return -1; |
} |
if (-1 == clientFd) { |
cerr << "Warning: Attempt to read from " |
<< "unopened RSP client: Ignored" << endl; |
return -1; |
} |
// Blocking read until successful (we retry after interrupts) or |
// catastrophic failure. |
while (true) { |
unsigned char c; |
|
// Blocking read until successful (we retry after interrupts) or |
// catastrophic failure. |
while (true) |
{ |
unsigned char c; |
switch (read(clientFd, &c, sizeof(c))) { |
case -1: |
if (errno == EAGAIN || errno == EWOULDBLOCK) |
continue; |
// Error: only allow interrupts |
if (EINTR != errno) { |
cerr << |
"Warning: Failed to read from RSP client: " |
<< "Closing client connection: " << |
strerror(errno) << endl; |
return -1; |
} |
break; |
|
switch (read (clientFd, &c, sizeof (c))) |
{ |
case -1: |
if (errno == EAGAIN || errno == EWOULDBLOCK) |
continue; |
// Error: only allow interrupts |
if (EINTR != errno) |
{ |
cerr << "Warning: Failed to read from RSP client: " |
<< "Closing client connection: " |
<< strerror (errno) << endl; |
return -1; |
} |
break; |
case 0: |
return -1; |
|
case 0: |
return -1; |
|
default: |
return c & 0xff; // Success, we can return (no sign extend!) |
default: |
return c & 0xff; // Success, we can return (no sign extend!) |
} |
} |
} |
|
} // getRspChar () |
} // getRspChar () |
/sysc/src/TraceSC.cpp
33,7 → 33,7
|
#define DEBUG_TRACESC 1 |
|
SC_HAS_PROCESS( TraceSC ); |
SC_HAS_PROCESS(TraceSC); |
|
//! Constructor for the trace module |
|
41,150 → 41,138
//! constructor. |
//! @param _trace_target ORPSoC module to trace |
|
TraceSC::TraceSC (sc_core::sc_module_name name, |
Vorpsoc_top *_traceTarget, |
int argc, |
char *argv[]) : |
sc_module (name), |
traceTarget (_traceTarget) |
TraceSC::TraceSC(sc_core::sc_module_name name, Vorpsoc_top * _traceTarget, int argc, char *argv[]): |
sc_module(name), |
traceTarget(_traceTarget) |
{ |
#if VM_TRACE |
|
// Setup the name of the VCD dump file |
string dumpNameDefault("vlt-dump.vcd"); |
string testNameString; |
string vcdDumpFile; |
// Setup the name of the VCD dump file |
string dumpNameDefault("vlt-dump.vcd"); |
string testNameString; |
string vcdDumpFile; |
|
// Search through the command line parameters for VCD dump options |
dump_start_delay = 0; |
dump_stop_set = 0; |
int time_val; |
int cmdline_name_found=0; |
if (argc > 1) |
{ |
for(int i=1; i<argc; i++) |
{ |
if ((strcmp(argv[i], "-vcd")==0) || |
(strcmp(argv[i], "--vcd")==0)) |
{ |
testNameString = (argv[i+1]); |
vcdDumpFile = testNameString; |
cmdline_name_found=1; |
} |
else if ( (strcmp(argv[i], "-vcdstart")==0) || |
(strcmp(argv[i], "--vcdstart")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_start_time(time_val,SC_NS); |
dump_start = dump_start_time; |
if (DEBUG_TRACESC) cout << "TraceSC(): Dump start time set at " << dump_start.to_string() << endl; |
dump_start_delay = 1; |
break; |
} |
else if ( (strcmp(argv[i], "-vcdstop")==0) || |
(strcmp(argv[i], "--vcdstop")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_stop_time(time_val,SC_NS); |
dump_stop = dump_stop_time; |
if (DEBUG_TRACESC) cout << "TraceSC(): Dump stop time set at " << dump_stop.to_string() << endl; |
dump_stop_set = 1; |
break; |
// Search through the command line parameters for VCD dump options |
dump_start_delay = 0; |
dump_stop_set = 0; |
int time_val; |
int cmdline_name_found = 0; |
if (argc > 1) { |
for (int i = 1; i < argc; i++) { |
if ((strcmp(argv[i], "-vcd") == 0) || |
(strcmp(argv[i], "--vcd") == 0)) { |
testNameString = (argv[i + 1]); |
vcdDumpFile = testNameString; |
cmdline_name_found = 1; |
} else if ((strcmp(argv[i], "-vcdstart") == 0) || |
(strcmp(argv[i], "--vcdstart") == 0)) { |
time_val = atoi(argv[i + 1]); |
sc_time dump_start_time(time_val, SC_NS); |
dump_start = dump_start_time; |
if (DEBUG_TRACESC) |
cout << |
"TraceSC(): Dump start time set at " |
<< dump_start.to_string() << endl; |
dump_start_delay = 1; |
break; |
} else if ((strcmp(argv[i], "-vcdstop") == 0) || |
(strcmp(argv[i], "--vcdstop") == 0)) { |
time_val = atoi(argv[i + 1]); |
sc_time dump_stop_time(time_val, SC_NS); |
dump_stop = dump_stop_time; |
if (DEBUG_TRACESC) |
cout << |
"TraceSC(): Dump stop time set at " |
<< dump_stop.to_string() << endl; |
dump_stop_set = 1; |
break; |
} |
} |
} |
} |
} |
|
if(cmdline_name_found==0) // otherwise use our default VCD dump file name |
vcdDumpFile = dumpNameDefault; |
|
Verilated::traceEverOn (true); |
|
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
|
cout << endl; |
|
if (cmdline_name_found == 0) // otherwise use our default VCD dump file name |
vcdDumpFile = dumpNameDefault; |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
Verilated::traceEverOn(true); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
spTraceFile = new SpTraceVcdCFile (); |
setSpTimeResolution (sc_get_time_resolution ()); |
traceTarget->trace (spTraceFile, 99); |
spTraceFile->open (vcdDumpFile.c_str()); |
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay == 1) |
dumping_now = 0; // We'll wait for the time to dump |
else |
dumping_now = 1; // Begin with dumping turned on |
if (dump_start_delay) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
|
cout << endl; |
|
// Method to drive the dump on each clock edge |
//SC_METHOD (driveTrace); |
//sensitive << clk; |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
spTraceFile = new SpTraceVcdCFile(); |
setSpTimeResolution(sc_get_time_resolution()); |
traceTarget->trace(spTraceFile, 99); |
spTraceFile->open(vcdDumpFile.c_str()); |
|
if (dump_start_delay == 1) |
dumping_now = 0; // We'll wait for the time to dump |
else |
dumping_now = 1; // Begin with dumping turned on |
|
// Method to drive the dump on each clock edge |
//SC_METHOD (driveTrace); |
//sensitive << clk; |
|
#endif |
|
} // TraceSC () |
|
} // TraceSC () |
|
//! Destructor for the trace module. |
|
//! Used to close the tracefile |
|
TraceSC::~TraceSC () |
TraceSC::~TraceSC() |
{ |
#if VM_TRACE |
spTraceFile->close (); |
spTraceFile->close(); |
#endif |
|
} // ~TraceSC () |
|
} // ~TraceSC () |
|
//! Method to drive the trace. We're called on every clock edge, and also at |
//! initialization (to get initial values into the dump). |
void |
TraceSC::driveTrace() |
TraceSC::driveTrace() |
{ |
#if VM_TRACE |
|
if (DEBUG_TRACESC) cout << "TraceSC(): " << endl; |
if (dumping_now == 0) |
{ |
// Check the time, see if we should enable dumping |
if (sc_time_stamp() >= dump_start) |
{ |
// Give a message |
cout << "* VCD tracing turned on at time " << dump_start.to_string() << endl; |
dumping_now = 1; |
if (DEBUG_TRACESC) |
cout << "TraceSC(): " << endl; |
if (dumping_now == 0) { |
// Check the time, see if we should enable dumping |
if (sc_time_stamp() >= dump_start) { |
// Give a message |
cout << "* VCD tracing turned on at time " << |
dump_start.to_string() << endl; |
dumping_now = 1; |
} |
} |
} |
|
if (dumping_now == 1) |
spTraceFile->dump (sc_time_stamp().to_double()); |
if (dumping_now == 1) |
spTraceFile->dump(sc_time_stamp().to_double()); |
|
|
// Should we turn off tracing? |
if ((dumping_now == 1) && (dump_stop_set == 1)) |
{ |
if (sc_time_stamp() >= dump_stop) |
{ |
// Give a message |
cout << "* VCD tracing turned off at time " << dump_stop.to_string() << endl; |
dumping_now = 0; // Turn off the dump |
// Should we turn off tracing? |
if ((dumping_now == 1) && (dump_stop_set == 1)) { |
if (sc_time_stamp() >= dump_stop) { |
// Give a message |
cout << "* VCD tracing turned off at time " << |
dump_stop.to_string() << endl; |
dumping_now = 0; // Turn off the dump |
} |
} |
} |
|
#endif |
|
} // driveTrace() |
} // driveTrace() |
|
|
//! Utility method to set the SystemPerl trace time resolution. |
|
//! This should be automatic, but is missed in Verilator 3.700. |
191,79 → 179,64
|
//! @param t The desired time resolution (as a SC time) |
|
void |
TraceSC::setSpTimeResolution (sc_time t) |
void TraceSC::setSpTimeResolution(sc_time t) |
{ |
#if VM_TRACE |
|
double secs = t.to_seconds(); |
int val; // Integral value of the precision |
const char *units; // Units as text |
double secs = t.to_seconds(); |
int val; // Integral value of the precision |
const char *units; // Units as text |
|
if (secs < 1.0e-15) |
{ |
cerr << "* VCD time resolution " << secs << " too small: ignored" << endl; |
return; |
} |
else if (secs < 1.0e-12) |
{ |
val = secs / 1.0e-15; |
units = "f"; |
} |
else if (secs < 1.0e-9) |
{ |
val = secs / 1.0e-12; |
units = "p"; |
} |
else if (secs < 1.0e-6) |
{ |
val = secs / 1.0e-9; |
units = "n"; |
} |
else if (secs < 1.0e-3) |
{ |
val = secs / 1.0e-6; |
units = "u"; |
} |
else if (secs < 1.0) |
{ |
val = secs / 1.0e-3; |
units = "m"; |
} |
else |
{ |
val = secs; |
units = "s"; |
} |
if (secs < 1.0e-15) { |
cerr << "* VCD time resolution " << secs << |
" too small: ignored" << endl; |
return; |
} else if (secs < 1.0e-12) { |
val = secs / 1.0e-15; |
units = "f"; |
} else if (secs < 1.0e-9) { |
val = secs / 1.0e-12; |
units = "p"; |
} else if (secs < 1.0e-6) { |
val = secs / 1.0e-9; |
units = "n"; |
} else if (secs < 1.0e-3) { |
val = secs / 1.0e-6; |
units = "u"; |
} else if (secs < 1.0) { |
val = secs / 1.0e-3; |
units = "m"; |
} else { |
val = secs; |
units = "s"; |
} |
|
// Val must be a power of 10 |
switch (val) |
{ |
case 1: |
case 10: |
case 100: |
case 1000: |
case 10000: |
case 100000: |
case 1000000: |
case 10000000: |
case 100000000: |
case 1000000000: |
// Val must be a power of 10 |
switch (val) { |
case 1: |
case 10: |
case 100: |
case 1000: |
case 10000: |
case 100000: |
case 1000000: |
case 10000000: |
case 100000000: |
case 1000000000: |
|
break; // OK |
break; // OK |
|
default: |
cerr << "VCD time resolution " << secs << " not power of 10: ignored" |
<< endl; |
return; |
} |
default: |
cerr << "VCD time resolution " << secs << |
" not power of 10: ignored" << endl; |
return; |
} |
|
// Set the time resolution for the trace file |
char str[32]; |
sprintf (str, "%d %s", val, units); |
spTraceFile->spTrace()->set_time_resolution (str); |
// Set the time resolution for the trace file |
char str[32]; |
sprintf(str, "%d %s", val, units); |
spTraceFile->spTrace()->set_time_resolution(str); |
|
#endif |
|
} // setSpTimeResolution() |
|
} // setSpTimeResolution() |
/sysc/src/TapActionReset.cpp
28,10 → 28,8
|
// $Id$ |
|
|
#include "TapActionReset.h" |
|
|
//! Constructor |
|
//! Records the SystemC completion event with the parent. Sets the ::firstTime |
40,14 → 38,12
|
//! @param[in] _doneEvent The SystemC completion event |
|
TapActionReset::TapActionReset (sc_core::sc_event *_doneEvent) : |
TapAction (_doneEvent), |
firstTime (true) |
TapActionReset::TapActionReset(sc_core::sc_event * _doneEvent): |
TapAction(_doneEvent), firstTime(true) |
{ |
|
} // TapActionReset () |
} // TapActionReset () |
|
|
//! Process the reset action |
|
//! This reuses the parent class ::checkResetDone() method. The first time we |
68,22 → 64,17
|
//! @return True if the action is complete |
|
bool |
TapActionReset::process (TapStateMachine *tapStateMachine, |
bool &tdi, |
bool tdo, |
bool &tms) |
bool TapActionReset::process(TapStateMachine * tapStateMachine, |
bool & tdi, bool tdo, bool & tms) |
{ |
if (firstTime) |
{ |
tapStateMachine->setResetDone (false); |
firstTime = false; |
} |
if (firstTime) { |
tapStateMachine->setResetDone(false); |
firstTime = false; |
} |
// Parent does the work (no warning message). Our result draws on the value |
// set in the tapStateMachine, to avoid an extra cycle. |
checkResetDone(tapStateMachine, tms, false); |
|
// Parent does the work (no warning message). Our result draws on the value |
// set in the tapStateMachine, to avoid an extra cycle. |
checkResetDone (tapStateMachine, tms, false); |
return tapStateMachine->getResetDone(); |
|
return tapStateMachine->getResetDone (); |
|
} // process () |
} // process () |
/sysc/src/OrpsocAccess.cpp
51,220 → 51,198
|
//! @param[in] orpsoc The SystemC Verilated ORPSoC instance |
|
OrpsocAccess::OrpsocAccess (Vorpsoc_top *orpsoc_top) |
OrpsocAccess::OrpsocAccess(Vorpsoc_top * orpsoc_top) |
{ |
// Assign processor accessor objects |
or1200_ctrl = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_ctrl; |
or1200_except = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_except; |
or1200_sprs = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_sprs; |
rf_a = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_rf->rf_a; |
// Assign main memory accessor objects |
// For old ram_wb: ram_wb_sc_sw = orpsoc_top->v->ram_wb0->ram0; |
//ram_wb_sc_sw = orpsoc_top->v->wb_ram_b3_0; |
wishbone_ram = orpsoc_top->v->ram_wb0->ram_wb_b3_0; |
// Assign processor accessor objects |
or1200_ctrl = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_ctrl; |
or1200_except = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_except; |
or1200_sprs = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_sprs; |
rf_a = orpsoc_top->v->or1200_top0->or1200_cpu->or1200_rf->rf_a; |
// Assign main memory accessor objects |
// For old ram_wb: ram_wb_sc_sw = orpsoc_top->v->ram_wb0->ram0; |
//ram_wb_sc_sw = orpsoc_top->v->wb_ram_b3_0; |
wishbone_ram = orpsoc_top->v->ram_wb0->ram_wb_b3_0; |
|
// Assign arbiter accessor object |
//wb_arbiter = orpsoc_top->v->wb_conbus; |
// Assign arbiter accessor object |
//wb_arbiter = orpsoc_top->v->wb_conbus; |
|
} // OrpsocAccess () |
} // OrpsocAccess () |
|
//! Access for the ex_freeze signal |
|
//! @return The value of the or1200_ctrl.ex_freeze signal |
|
bool |
OrpsocAccess::getExFreeze () |
bool OrpsocAccess::getExFreeze() |
{ |
return or1200_ctrl->ex_freeze; |
return or1200_ctrl->ex_freeze; |
|
} // getExFreeze () |
} // getExFreeze () |
|
//! Access for the wb_freeze signal |
|
//! @return The value of the or1200_ctrl.wb_freeze signal |
|
bool |
OrpsocAccess::getWbFreeze () |
bool OrpsocAccess::getWbFreeze() |
{ |
return or1200_ctrl->wb_freeze; |
return or1200_ctrl->wb_freeze; |
|
} // getWbFreeze () |
} // getWbFreeze () |
|
//! Access for the except_flushpipe signal |
|
//! @return The value of the or1200_except.except_flushpipe signal |
|
bool |
OrpsocAccess::getExceptFlushpipe () |
bool OrpsocAccess::getExceptFlushpipe() |
{ |
return or1200_except->except_flushpipe; |
return or1200_except->except_flushpipe; |
|
} // getExceptFlushpipe () |
} // getExceptFlushpipe () |
|
//! Access for the ex_dslot signal |
|
//! @return The value of the or1200_except.ex_dslot signalfac |
|
bool |
OrpsocAccess::getExDslot () |
bool OrpsocAccess::getExDslot() |
{ |
return or1200_except->ex_dslot; |
return or1200_except->ex_dslot; |
|
} // getExDslot () |
} // getExDslot () |
|
//! Access for the except_type value |
|
//! @return The value of the or1200_except.except_type register |
|
uint32_t |
OrpsocAccess::getExceptType () |
uint32_t OrpsocAccess::getExceptType() |
{ |
return (or1200_except->get_except_type) (); |
return (or1200_except->get_except_type) (); |
|
} // getExceptType () |
} // getExceptType () |
|
|
//! Access for the id_pc register |
|
//! @return The value of the or1200_except.id_pc register |
|
uint32_t |
OrpsocAccess::getIdPC () |
uint32_t OrpsocAccess::getIdPC() |
{ |
return (or1200_except->get_id_pc) (); |
return (or1200_except->get_id_pc) (); |
|
} // getIdPC () |
} // getIdPC () |
|
//! Access for the ex_pc register |
|
//! @return The value of the or1200_except.id_ex register |
|
uint32_t |
OrpsocAccess::getExPC () |
uint32_t OrpsocAccess::getExPC() |
{ |
return (or1200_except->get_ex_pc) (); |
return (or1200_except->get_ex_pc) (); |
|
} // getExPC () |
} // getExPC () |
|
//! Access for the wb_pc register |
|
//! @return The value of the or1200_except.wb_pc register |
|
uint32_t |
OrpsocAccess::getWbPC () |
uint32_t OrpsocAccess::getWbPC() |
{ |
return (or1200_except->get_wb_pc) (); |
return (or1200_except->get_wb_pc) (); |
|
} // getWbPC () |
} // getWbPC () |
|
//! Access for the id_insn register |
|
//! @return The value of the or1200_ctrl.wb_insn register |
|
uint32_t |
OrpsocAccess::getIdInsn () |
uint32_t OrpsocAccess::getIdInsn() |
{ |
return (or1200_ctrl->get_id_insn) (); |
return (or1200_ctrl->get_id_insn) (); |
|
} // getIdInsn () |
} // getIdInsn () |
|
//! Access for the ex_insn register |
|
//! @return The value of the or1200_ctrl.ex_insn register |
|
uint32_t |
OrpsocAccess::getExInsn () |
uint32_t OrpsocAccess::getExInsn() |
{ |
return (or1200_ctrl->get_ex_insn) (); |
return (or1200_ctrl->get_ex_insn) (); |
|
} // getExInsn () |
} // getExInsn () |
|
|
//! Access for the wb_insn register |
|
//! @return The value of the or1200_ctrl.wb_insn register |
|
uint32_t |
OrpsocAccess::getWbInsn () |
uint32_t OrpsocAccess::getWbInsn() |
{ |
return (or1200_ctrl->get_wb_insn) (); |
return (or1200_ctrl->get_wb_insn) (); |
|
} // getWbInsn () |
} // getWbInsn () |
|
//! Access the Wishbone SRAM memory |
|
//! @return The value of the 32-bit memory word at addr |
|
uint32_t |
OrpsocAccess::get_mem32 (uint32_t addr) |
uint32_t OrpsocAccess::get_mem32(uint32_t addr) |
{ |
return (wishbone_ram->get_mem) (addr/4); |
return (wishbone_ram->get_mem32) (addr / 4); |
|
} // get_mem32 () |
} // get_mem32 () |
|
|
//! Access a byte from the Wishbone SRAM memory |
|
//! @return The value of the memory byte at addr |
|
uint8_t |
OrpsocAccess::get_mem8 (uint32_t addr) |
uint8_t OrpsocAccess::get_mem8(uint32_t addr) |
{ |
|
uint32_t word; |
static uint32_t cached_word; |
static uint32_t cached_word_addr = 0xffffffff; |
int sel = addr & 0x3; // Remember which byte we want |
addr = addr / 4; |
if (addr != cached_word_addr) |
{ |
cached_word_addr = addr; |
// Convert address to word number here |
word = (wishbone_ram->get_mem) (addr); |
cached_word = word; |
} |
else |
word = cached_word; |
uint32_t word; |
static uint32_t cached_word; |
static uint32_t cached_word_addr = 0xffffffff; |
int sel = addr & 0x3; // Remember which byte we want |
addr = addr / 4; |
if (addr != cached_word_addr) { |
cached_word_addr = addr; |
// Convert address to word number here |
word = (wishbone_ram->get_mem8) (addr); |
cached_word = word; |
} else |
word = cached_word; |
|
switch(sel) |
{ |
/* Big endian word expected */ |
case 0: |
return ((word >> 24) & 0xff); |
break; |
case 1: |
return ((word >> 16) & 0xff); |
break; |
case 2: |
return ((word >> 8) & 0xff); |
break; |
case 3: |
return ((word >> 0) & 0xff); |
break; |
default: |
return 0; |
} |
switch (sel) { |
/* Big endian word expected */ |
case 0: |
return ((word >> 24) & 0xff); |
break; |
case 1: |
return ((word >> 16) & 0xff); |
break; |
case 2: |
return ((word >> 8) & 0xff); |
break; |
case 3: |
return ((word >> 0) & 0xff); |
break; |
default: |
return 0; |
} |
|
} // get_mem8 () |
} // get_mem8 () |
|
|
//! Write value to the Wishbone SRAM memory |
|
void |
OrpsocAccess::set_mem32 (uint32_t addr, uint32_t data) |
void OrpsocAccess::set_mem32(uint32_t addr, uint32_t data) |
{ |
(wishbone_ram->set_mem) (addr/4, data); |
(wishbone_ram->set_mem32) (addr / 4, data); |
|
} // set_mem32 () |
} // set_mem32 () |
|
//! Trigger the $readmemh() system call |
|
void |
OrpsocAccess::do_ram_readmemh (void) |
void OrpsocAccess::do_ram_readmemh(void) |
{ |
(wishbone_ram->do_readmemh) (); |
(wishbone_ram->do_readmemh) (); |
|
} // do_ram_readmemh () |
} // do_ram_readmemh () |
|
//! Access for the OR1200 GPRs |
|
274,57 → 252,64
|
//! @return The value of the GPR |
|
uint32_t |
OrpsocAccess::getGpr (uint32_t regNum) |
uint32_t OrpsocAccess::getGpr(uint32_t regNum) |
{ |
return (rf_a->get_gpr) (regNum); |
return (rf_a->get_gpr) (regNum); |
|
} // getGpr () |
} // getGpr () |
|
//! Access for the OR1200 GPRs |
|
//! These are extracted from memory using the Verilog function |
|
//! @param[in] regNum The GPR whose value is wanted |
//! @param[in] value The value of GPR to write |
|
void OrpsocAccess::setGpr(uint32_t regNum, uint32_t value) |
{ |
(rf_a->set_gpr) (regNum, value); |
|
} // getGpr () |
|
//! Access for the sr register |
|
//! @return The value of the or1200_sprs.sr register |
|
uint32_t |
OrpsocAccess::getSprSr () |
uint32_t OrpsocAccess::getSprSr() |
{ |
return (or1200_sprs->get_sr) (); |
return (or1200_sprs->get_sr) (); |
|
} // getSprSr () |
} // getSprSr () |
|
//! Access for the epcr register |
|
//! @return The value of the or1200_sprs.epcr register |
|
uint32_t |
OrpsocAccess::getSprEpcr () |
uint32_t OrpsocAccess::getSprEpcr() |
{ |
return (or1200_sprs->get_epcr) (); |
return (or1200_sprs->get_epcr) (); |
|
} // getSprEpcr () |
} // getSprEpcr () |
|
//! Access for the eear register |
|
//! @return The value of the or1200_sprs.eear register |
|
uint32_t |
OrpsocAccess::getSprEear () |
uint32_t OrpsocAccess::getSprEear() |
{ |
return (or1200_sprs->get_eear) (); |
return (or1200_sprs->get_eear) (); |
|
} // getSprEear () |
} // getSprEear () |
|
//! Access for the esr register |
|
//! @return The value of the or1200_sprs.esr register |
|
uint32_t |
OrpsocAccess::getSprEsr () |
uint32_t OrpsocAccess::getSprEsr() |
{ |
return (or1200_sprs->get_esr) (); |
return (or1200_sprs->get_esr) (); |
|
} // getSprEsr () |
} // getSprEsr () |
|
/* |
//! Access for the arbiter's grant signal |
338,7 → 323,6
|
} // getWbArbGrant () |
|
|
//! Arbiter master[mast_num] access functions |
|
//! Access for the arbiter's master[mast_num] data in signal |
374,7 → 358,6
|
} // getWbArbMastAdrI () |
|
|
//! Access for the arbiter's master[mast_num] select signal |
|
//! @return The value of the wb_conmax_top.m_sel_i[mast_num] |
/sysc/src/JtagDriverSC.cpp
31,9 → 31,8
|
#include "JtagDriverSC.h" |
|
SC_HAS_PROCESS(JtagDriverSC); |
|
SC_HAS_PROCESS (JtagDriverSC); |
|
//! Constructor for the JTAG driver. |
|
//! We create a SC_THREAD in which we can spit out some actions. Must be a |
43,93 → 42,84
//! constructor. |
//! @param[in] _tapActionQueue Pointer to fifo of actions to perform |
|
JtagDriverSC::JtagDriverSC (sc_core::sc_module_name name, |
sc_core::sc_fifo<TapAction *> *_tapActionQueue) : |
sc_module (name), |
tapActionQueue (_tapActionQueue), |
currentScanChain (OR1K_SC_UNDEF) |
JtagDriverSC::JtagDriverSC(sc_core::sc_module_name name, sc_core::sc_fifo < TapAction * >*_tapActionQueue): |
sc_module(name), |
tapActionQueue(_tapActionQueue), currentScanChain(OR1K_SC_UNDEF) |
{ |
SC_THREAD (queueActions); |
SC_THREAD(queueActions); |
|
} // JtagDriverSC () |
} // JtagDriverSC () |
|
|
//! SystemC thread to queue some actions |
|
//! Have to use a thread, since we will end up waiting for actions to |
//! complete. |
|
void |
JtagDriverSC::queueActions () |
void JtagDriverSC::queueActions() |
{ |
uint32_t res; // General result variable |
uint32_t res; // General result variable |
|
// Reset the JTAG |
reset (); |
// Reset the JTAG |
reset(); |
|
// Select the register scan chain to stall the processor, stall the |
// processor and check it has stalled |
selectChain (OR1K_SC_REGISTER); |
writeReg (OR1K_RSC_RISCOP, RISCOP_STALL); |
// Select the register scan chain to stall the processor, stall the |
// processor and check it has stalled |
selectChain(OR1K_SC_REGISTER); |
writeReg(OR1K_RSC_RISCOP, RISCOP_STALL); |
|
do |
{ |
res = readReg (OR1K_RSC_RISCOP); |
std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000 |
<< "us: RISCOP = " << std::hex << res << std::endl; |
} |
while ((res & RISCOP_STALL) != RISCOP_STALL); |
do { |
res = readReg(OR1K_RSC_RISCOP); |
std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000 |
<< "us: RISCOP = " << std::hex << res << std::endl; |
} |
while ((res & RISCOP_STALL) != RISCOP_STALL); |
|
// Write the NPC SPR. Select the RISC_DEBUG scan chain, read the |
// register, write the register and read it back. |
selectChain (OR1K_SC_RISC_DEBUG); |
// Write the NPC SPR. Select the RISC_DEBUG scan chain, read the |
// register, write the register and read it back. |
selectChain(OR1K_SC_RISC_DEBUG); |
|
res = readReg (0x10); // NPC |
std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000 |
res = readReg(0x10); // NPC |
std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000 |
<< "us: Old NPC = " << std::hex << res << std::endl; |
|
writeReg (0x10, 0x4000100); |
writeReg(0x10, 0x4000100); |
|
res = readReg (0x10); // NPC |
std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000 |
res = readReg(0x10); // NPC |
std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000 |
<< "us: New NPC = " << std::hex << res << std::endl; |
|
// Unstall and check it has unstalled |
selectChain (OR1K_SC_REGISTER); |
writeReg (OR1K_RSC_RISCOP, 0); |
// Unstall and check it has unstalled |
selectChain(OR1K_SC_REGISTER); |
writeReg(OR1K_RSC_RISCOP, 0); |
|
do |
{ |
res = readReg (OR1K_RSC_RISCOP); |
std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000 |
<< "us: RISCOP = " << std::hex << res << std::endl; |
} |
while ((res & RISCOP_STALL) == RISCOP_STALL); |
do { |
res = readReg(OR1K_RSC_RISCOP); |
std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000 |
<< "us: RISCOP = " << std::hex << res << std::endl; |
} |
while ((res & RISCOP_STALL) == RISCOP_STALL); |
|
} // queueActions () |
} // queueActions () |
|
|
//! Reset the JTAG |
|
//! @note Must be called from a SystemC thread, because of the use of wait() |
|
void |
JtagDriverSC::reset () |
void JtagDriverSC::reset() |
{ |
sc_core::sc_event *actionDone = new sc_core::sc_event(); |
TapActionReset *resetAction; |
sc_core::sc_event * actionDone = new sc_core::sc_event(); |
TapActionReset *resetAction; |
|
// Create and queue the reset action and wait for it to complete |
resetAction = new TapActionReset (actionDone); |
tapActionQueue->write (resetAction); |
wait (*actionDone); |
// Create and queue the reset action and wait for it to complete |
resetAction = new TapActionReset(actionDone); |
tapActionQueue->write(resetAction); |
wait(*actionDone); |
|
delete resetAction; |
delete actionDone; |
delete resetAction; |
delete actionDone; |
|
} // reset () |
} // reset () |
|
|
//! Select an OpenRISC 1000 scan chain |
|
//! Built on top of the JTAG commands to shift registers |
142,49 → 132,44
|
//! @param[in] chain The desired scan chain |
|
|
void |
JtagDriverSC::selectChain (int chain) |
void JtagDriverSC::selectChain(int chain) |
{ |
if (chain == currentScanChain) |
{ |
return; |
} |
else |
{ |
currentScanChain = chain; |
} |
if (chain == currentScanChain) { |
return; |
} else { |
currentScanChain = chain; |
} |
|
sc_core::sc_event *actionDone = new sc_core::sc_event(); |
TapActionIRScan *iRScan; |
TapActionDRScan *dRScan; |
sc_core::sc_event * actionDone = new sc_core::sc_event(); |
TapActionIRScan *iRScan; |
TapActionDRScan *dRScan; |
|
// Create and queue the IR-Scan action for CHAIN_SELECT (no CRC) |
iRScan = new TapActionIRScan (actionDone, CHAIN_SELECT_IR, JTAG_IR_LEN); |
tapActionQueue->write (iRScan); |
wait (*actionDone); |
// Create and queue the IR-Scan action for CHAIN_SELECT (no CRC) |
iRScan = new TapActionIRScan(actionDone, CHAIN_SELECT_IR, JTAG_IR_LEN); |
tapActionQueue->write(iRScan); |
wait(*actionDone); |
|
delete iRScan; |
delete iRScan; |
|
// Create and queue the DR-Scan action for the specified chain (which we |
// know will fit into 64 bits) |
uint64_t chainReg = crc8 (chain, CHAIN_DR_LEN) << (CHAIN_DR_LEN) | chain; |
dRScan = new TapActionDRScan (actionDone, chainReg, CHAIN_DR_LEN + CRC_LEN); |
tapActionQueue->write (dRScan); |
wait (*actionDone); |
// Create and queue the DR-Scan action for the specified chain (which we |
// know will fit into 64 bits) |
uint64_t chainReg = crc8(chain, CHAIN_DR_LEN) << (CHAIN_DR_LEN) | chain; |
dRScan = |
new TapActionDRScan(actionDone, chainReg, CHAIN_DR_LEN + CRC_LEN); |
tapActionQueue->write(dRScan); |
wait(*actionDone); |
|
delete dRScan; |
delete dRScan; |
|
// Create and queue the IR-Scan action for DEBUG (no CRC) |
iRScan = new TapActionIRScan (actionDone, DEBUG_IR, JTAG_IR_LEN); |
tapActionQueue->write (iRScan); |
wait (*actionDone); |
// Create and queue the IR-Scan action for DEBUG (no CRC) |
iRScan = new TapActionIRScan(actionDone, DEBUG_IR, JTAG_IR_LEN); |
tapActionQueue->write(iRScan); |
wait(*actionDone); |
|
delete iRScan; |
delete actionDone; |
delete iRScan; |
delete actionDone; |
|
} // selectChain() |
|
} // selectChain() |
|
//! Read an OpenRISC 1000 JTAG register |
|
219,47 → 204,42
|
//! @return The register value read |
|
uint32_t |
JtagDriverSC::readReg (uint32_t addr) |
uint32_t JtagDriverSC::readReg(uint32_t addr) |
{ |
bool firstTime = true; |
int bitSizeNoCrc; // Size of reg w/o its CRC field |
|
// Determine the size of register to read. |
switch (currentScanChain) |
{ |
case OR1K_SC_RISC_DEBUG: |
bitSizeNoCrc = RISC_DEBUG_DR_LEN; |
break; |
|
case OR1K_SC_REGISTER: |
bitSizeNoCrc = REGISTER_DR_LEN; |
break; |
|
case OR1K_SC_WISHBONE: |
bitSizeNoCrc = WISHBONE_DR_LEN; |
break; |
} |
bool firstTime = true; |
int bitSizeNoCrc; // Size of reg w/o its CRC field |
|
// Read the register twice. Use an optimized version if the register is |
// "small". |
if ((bitSizeNoCrc + CRC_LEN) < 64) |
{ |
(void)readReg1 (addr, bitSizeNoCrc); |
return readReg1 (addr, bitSizeNoCrc); |
} |
else |
{ |
uint64_t *dReg = new uint64_t [(bitSizeNoCrc + CRC_LEN + 63) / 64]; |
(void)readReg1 (dReg, addr, bitSizeNoCrc); |
uint32_t res = readReg1 (dReg, addr, bitSizeNoCrc); |
delete [] dReg; |
// Determine the size of register to read. |
switch (currentScanChain) { |
case OR1K_SC_RISC_DEBUG: |
bitSizeNoCrc = RISC_DEBUG_DR_LEN; |
break; |
|
return res; |
} |
} // readReg () |
case OR1K_SC_REGISTER: |
bitSizeNoCrc = REGISTER_DR_LEN; |
break; |
|
case OR1K_SC_WISHBONE: |
bitSizeNoCrc = WISHBONE_DR_LEN; |
break; |
} |
|
// Read the register twice. Use an optimized version if the register is |
// "small". |
if ((bitSizeNoCrc + CRC_LEN) < 64) { |
(void)readReg1(addr, bitSizeNoCrc); |
return readReg1(addr, bitSizeNoCrc); |
} else { |
uint64_t *dReg = |
new uint64_t[(bitSizeNoCrc + CRC_LEN + 63) / 64]; |
(void)readReg1(dReg, addr, bitSizeNoCrc); |
uint32_t res = readReg1(dReg, addr, bitSizeNoCrc); |
delete[]dReg; |
|
return res; |
} |
} // readReg () |
|
//! Single read of an OpenRISC 1000 JTAG register |
|
//! Built on top of the JTAG commands to shift registers |
275,49 → 255,45
|
//! @return The register value read |
|
uint32_t |
JtagDriverSC::readReg1 (uint32_t addr, |
int bitSizeNoCrc) |
uint32_t JtagDriverSC::readReg1(uint32_t addr, int bitSizeNoCrc) |
{ |
// Useful fields and sizes and the register itself |
int fullBitSize = bitSizeNoCrc + CRC_LEN; |
int dataOffset = bitSizeNoCrc - DR_DATA_LEN; |
uint64_t dReg; |
// Useful fields and sizes and the register itself |
int fullBitSize = bitSizeNoCrc + CRC_LEN; |
int dataOffset = bitSizeNoCrc - DR_DATA_LEN; |
uint64_t dReg; |
|
// Allocate space for the shifted reg and a SystemC completion event |
sc_core::sc_event *actionDone = new sc_core::sc_event(); |
// Allocate space for the shifted reg and a SystemC completion event |
sc_core::sc_event * actionDone = new sc_core::sc_event(); |
|
// Loop until CRCs match |
while (true) |
{ |
// Create the data to shift in |
dReg = 0ULL; |
dReg |= addr; |
uint8_t crc_in = crc8 (dReg, bitSizeNoCrc); |
dReg |= (uint64_t)crc_in << bitSizeNoCrc; |
// Loop until CRCs match |
while (true) { |
// Create the data to shift in |
dReg = 0ULL; |
dReg |= addr; |
uint8_t crc_in = crc8(dReg, bitSizeNoCrc); |
dReg |= (uint64_t) crc_in << bitSizeNoCrc; |
|
// Prepare the action, queue it and wait for it to complete |
TapActionDRScan *dRScan = new TapActionDRScan (actionDone, dReg, |
fullBitSize); |
tapActionQueue->write (dRScan); |
wait (*actionDone); |
dReg = dRScan->getDRegOut (); |
delete dRScan; |
// Prepare the action, queue it and wait for it to complete |
TapActionDRScan *dRScan = new TapActionDRScan(actionDone, dReg, |
fullBitSize); |
tapActionQueue->write(dRScan); |
wait(*actionDone); |
dReg = dRScan->getDRegOut(); |
delete dRScan; |
|
// Check CRCs |
uint8_t crc_out = dReg >> bitSizeNoCrc; |
uint8_t crc_calc = crc8 (dReg, bitSizeNoCrc); |
// Check CRCs |
uint8_t crc_out = dReg >> bitSizeNoCrc; |
uint8_t crc_calc = crc8(dReg, bitSizeNoCrc); |
|
// All done if CRC matches |
if (crc_out == crc_calc) |
{ |
delete actionDone; |
return (dReg >> dataOffset) & ((1ULL << DR_DATA_LEN) - 1); |
// All done if CRC matches |
if (crc_out == crc_calc) { |
delete actionDone; |
return (dReg >> dataOffset) & ((1ULL << DR_DATA_LEN) - |
1); |
} |
} |
} |
} // readReg1 () |
} // readReg1 () |
|
|
//! Single read of an OpenRISC 1000 JTAG register |
|
//! Built on top of the JTAG commands to shift registers |
335,48 → 311,45
//! @return The register value read |
|
uint32_t |
JtagDriverSC::readReg1 (uint64_t *dRegArray, |
uint32_t addr, |
int bitSizeNoCrc) |
JtagDriverSC::readReg1(uint64_t * dRegArray, |
uint32_t addr, int bitSizeNoCrc) |
{ |
// Useful fields and sizes |
int fullBitSize = bitSizeNoCrc + CRC_LEN; |
int dataOffset = bitSizeNoCrc - DR_DATA_LEN; |
// Useful fields and sizes |
int fullBitSize = bitSizeNoCrc + CRC_LEN; |
int dataOffset = bitSizeNoCrc - DR_DATA_LEN; |
|
// Allocate a SystemC completion event |
sc_core::sc_event *actionDone = new sc_core::sc_event(); |
// Allocate a SystemC completion event |
sc_core::sc_event * actionDone = new sc_core::sc_event(); |
|
// Loop until CRCs match |
while (true) |
{ |
// Create the data to shift in |
memset (dRegArray, 0, fullBitSize / 8); |
dRegArray[0] |= addr; |
uint8_t crc_in = crc8 (dRegArray, bitSizeNoCrc); |
insertBits (crc_in, CRC_LEN, dRegArray, bitSizeNoCrc); |
// Loop until CRCs match |
while (true) { |
// Create the data to shift in |
memset(dRegArray, 0, fullBitSize / 8); |
dRegArray[0] |= addr; |
uint8_t crc_in = crc8(dRegArray, bitSizeNoCrc); |
insertBits(crc_in, CRC_LEN, dRegArray, bitSizeNoCrc); |
|
// Prepare the action, queue it and wait for it to complete |
TapActionDRScan *dRScan = new TapActionDRScan (actionDone, dRegArray, |
fullBitSize); |
tapActionQueue->write (dRScan); |
wait (*actionDone); |
dRScan->getDRegOut (dRegArray); |
delete dRScan; |
// Prepare the action, queue it and wait for it to complete |
TapActionDRScan *dRScan = |
new TapActionDRScan(actionDone, dRegArray, |
fullBitSize); |
tapActionQueue->write(dRScan); |
wait(*actionDone); |
dRScan->getDRegOut(dRegArray); |
delete dRScan; |
|
// Check CRCs |
uint8_t crc_out = extractBits (dRegArray, bitSizeNoCrc, CRC_LEN); |
uint8_t crc_calc = crc8 (dRegArray, bitSizeNoCrc); |
// Check CRCs |
uint8_t crc_out = extractBits(dRegArray, bitSizeNoCrc, CRC_LEN); |
uint8_t crc_calc = crc8(dRegArray, bitSizeNoCrc); |
|
// All done if CRC matches |
if (crc_out == crc_calc) |
{ |
delete actionDone; |
return extractBits (dRegArray, dataOffset, DR_DATA_LEN); |
// All done if CRC matches |
if (crc_out == crc_calc) { |
delete actionDone; |
return extractBits(dRegArray, dataOffset, DR_DATA_LEN); |
} |
} |
} |
} // readReg1 () |
} // readReg1 () |
|
|
//! Write an OpenRISC 1000 JTAG register |
|
//! Built on top of the JTAG commands to shift registers |
400,56 → 373,53
//! @param[in] data The register data to write |
|
void |
JtagDriverSC::writeReg (uint32_t addr, |
uint32_t data) |
JtagDriverSC::writeReg(uint32_t addr, uint32_t data) |
{ |
int bitSizeNoCrc; // Size of reg w/o its CRC field |
uint64_t writeBit; // Mask for the write enable bit |
int bitSizeNoCrc; // Size of reg w/o its CRC field |
uint64_t writeBit; // Mask for the write enable bit |
|
// Determine the size of register to write. |
switch (currentScanChain) |
{ |
case OR1K_SC_RISC_DEBUG: |
bitSizeNoCrc = RISC_DEBUG_DR_LEN; |
writeBit = RISC_DEBUG_RW; |
break; |
// Determine the size of register to write. |
switch (currentScanChain) { |
case OR1K_SC_RISC_DEBUG: |
bitSizeNoCrc = RISC_DEBUG_DR_LEN; |
writeBit = RISC_DEBUG_RW; |
break; |
|
case OR1K_SC_REGISTER: |
bitSizeNoCrc = REGISTER_DR_LEN; |
writeBit = REGISTER_RW; |
break; |
case OR1K_SC_REGISTER: |
bitSizeNoCrc = REGISTER_DR_LEN; |
writeBit = REGISTER_RW; |
break; |
|
case OR1K_SC_WISHBONE: |
bitSizeNoCrc = WISHBONE_DR_LEN; |
writeBit = WISHBONE_RW; |
break; |
} |
case OR1K_SC_WISHBONE: |
bitSizeNoCrc = WISHBONE_DR_LEN; |
writeBit = WISHBONE_RW; |
break; |
} |
|
// Create the register in an array |
int wordSize = (bitSizeNoCrc + CRC_LEN + 63) / 64; |
uint64_t *dReg = new uint64_t [wordSize]; |
// Create the register in an array |
int wordSize = (bitSizeNoCrc + CRC_LEN + 63) / 64; |
uint64_t *dReg = new uint64_t[wordSize]; |
|
// Create the data to shift in |
memset (dReg, 0, wordSize * 8); |
dReg[0] |= writeBit | addr; |
insertBits (data, DR_DATA_LEN, dReg, bitSizeNoCrc - DR_DATA_LEN); |
insertBits (crc8 (dReg, bitSizeNoCrc), CRC_LEN, dReg, bitSizeNoCrc); |
// Create the data to shift in |
memset(dReg, 0, wordSize * 8); |
dReg[0] |= writeBit | addr; |
insertBits(data, DR_DATA_LEN, dReg, bitSizeNoCrc - DR_DATA_LEN); |
insertBits(crc8(dReg, bitSizeNoCrc), CRC_LEN, dReg, bitSizeNoCrc); |
|
// Prepare the action, queue it and wait for it to complete |
sc_core::sc_event *actionDone = new sc_core::sc_event(); |
TapActionDRScan *dRScan = new TapActionDRScan (actionDone, dReg, |
bitSizeNoCrc + CRC_LEN); |
// Prepare the action, queue it and wait for it to complete |
sc_core::sc_event * actionDone = new sc_core::sc_event(); |
TapActionDRScan *dRScan = new TapActionDRScan(actionDone, dReg, |
bitSizeNoCrc + CRC_LEN); |
|
tapActionQueue->write (dRScan); |
wait (*actionDone); |
tapActionQueue->write(dRScan); |
wait(*actionDone); |
|
delete [] dReg; |
delete dRScan; |
delete actionDone; |
delete[]dReg; |
delete dRScan; |
delete actionDone; |
|
} // writeReg () |
} // writeReg () |
|
|
//! Compute CRC-8-ATM |
|
//! The data is in a uint64_t, for which we use the first size bits to compute |
465,32 → 435,30
//! @param data The data whose CRC is desired |
//! @param size The number of bits in the data |
|
uint8_t |
JtagDriverSC::crc8 (uint64_t data, |
int size) |
uint8_t JtagDriverSC::crc8(uint64_t data, int size) |
{ |
uint8_t crc = 0; |
uint8_t crc = 0; |
|
for (int i = 0; i < size; i++) |
{ |
uint8_t d = data & 1; // Latest data bit |
data >>= 1; |
for (int i = 0; i < size; i++) { |
uint8_t d = data & 1; // Latest data bit |
data >>= 1; |
|
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
|
crc = ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | newCrc0; |
} |
crc = |
((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | |
newCrc0; |
} |
|
return crc; |
return crc; |
|
} // crc8 () |
} // crc8 () |
|
|
//! Compute CRC-8-ATM |
|
//! The data is in an array of uint64_t, for which we use the first size bits |
506,30 → 474,28
//! @param dataArray The array of data whose CRC is desired |
//! @param size The number of bits in the data |
|
uint8_t |
JtagDriverSC::crc8 (uint64_t dataArray[], |
int size) |
uint8_t JtagDriverSC::crc8(uint64_t dataArray[], int size) |
{ |
uint8_t crc = 0; |
uint8_t crc = 0; |
|
for (int i = 0; i < size; i++) |
{ |
uint8_t d = (dataArray[i / 64] >> (i % 64)) & 1; |
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
for (int i = 0; i < size; i++) { |
uint8_t d = (dataArray[i / 64] >> (i % 64)) & 1; |
uint8_t oldCrc7 = (crc >> 7) & 1; |
uint8_t oldCrc1 = (crc >> 1) & 1; |
uint8_t oldCrc0 = (crc >> 0) & 1; |
uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7; // Why d? |
uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7; // Why d? |
uint8_t newCrc0 = d ^ oldCrc7; |
|
crc = ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | newCrc0; |
} |
crc = |
((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | |
newCrc0; |
} |
|
return crc; |
return crc; |
|
} // crc8 () |
} // crc8 () |
|
|
//! Utility to insert a string of bits into array |
|
//! This is a simple overwriting |
539,42 → 505,36
//! @param array Array into which to insert |
//! @param startBit Offset at which to insert bits |
|
void |
JtagDriverSC::insertBits (uint64_t str, |
int strLen, |
uint64_t *array, |
int startBit) |
void JtagDriverSC::insertBits(uint64_t str, |
int strLen, uint64_t * array, int startBit) |
{ |
int startWord = startBit / 64; |
int endWord = (startBit + strLen - 1) / 64; |
int startWord = startBit / 64; |
int endWord = (startBit + strLen - 1) / 64; |
|
startBit = startBit % 64; |
startBit = startBit % 64; |
|
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit; |
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit; |
|
array[startWord] &= ~startMask; |
array[startWord] |= str << startBit; |
array[startWord] &= ~startMask; |
array[startWord] |= str << startBit; |
|
// If we were all in one word, we can give up now. |
if (startWord == endWord) |
{ |
return; |
} |
// If we were all in one word, we can give up now. |
if (startWord == endWord) { |
return; |
} |
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (startBit + strLen) % 64; |
|
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (startBit + strLen) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
|
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
array[endWord] &= ~endMask; |
array[endWord] |= str >> (strLen - bitsToDo); |
|
array[endWord] &= ~endMask; |
array[endWord] |= str >> (strLen - bitsToDo); |
} // insertBits() |
|
} // insertBits() |
|
|
//! Utility to extract a string of bits from an array |
|
//! @param array Array from which to extract |
583,32 → 543,27
|
//! @return Extracted bits |
|
uint64_t |
JtagDriverSC::extractBits (uint64_t *array, |
int startBit, |
int strLen) |
uint64_t JtagDriverSC::extractBits(uint64_t * array, int startBit, int strLen) |
{ |
int startWord = startBit / 64; |
int endWord = (startBit + strLen - 1) / 64; |
int startWord = startBit / 64; |
int endWord = (startBit + strLen - 1) / 64; |
|
startBit = startBit % 64; |
startBit = startBit % 64; |
|
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit; |
uint64_t res = (array[startWord] & startMask) >> startBit; |
// Deal with the startWord. Get enough bits for the mask and put them in the |
// right place |
uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit; |
uint64_t res = (array[startWord] & startMask) >> startBit; |
|
// If we were all in one word, we can give up now. |
if (startWord == endWord) |
{ |
return res; |
} |
// If we were all in one word, we can give up now. |
if (startWord == endWord) { |
return res; |
} |
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (startBit + strLen) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
|
// Deal with the endWord. Get enough bits for the mask. No need to shift |
// these up - they're always at the bottom of the word |
int bitsToDo = (startBit + strLen) % 64; |
uint64_t endMask = (1ULL << bitsToDo) - 1ULL; |
return res | ((array[endWord] & endMask) << (strLen - bitsToDo)); |
|
return res | ((array[endWord] & endMask) << (strLen - bitsToDo)); |
|
} // extractBits () |
} // extractBits () |
/sysc/src/SprCache.cpp
31,7 → 31,6
|
#include "SprCache.h" |
|
|
//----------------------------------------------------------------------------- |
//! Constructor |
|
40,46 → 39,43
//! @param[in] _tableSize The desire hash table size. A prime number is |
//! recommended. |
//----------------------------------------------------------------------------- |
SprCache::SprCache (int _tableSize) : |
tableSize (_tableSize) |
SprCache::SprCache(int _tableSize): |
tableSize(_tableSize) |
{ |
sprIsValid = new bool [tableSize]; |
sprKeyNum = new uint16_t [tableSize]; |
sprValue = new uint32_t [tableSize]; |
sprIsValid = new bool[tableSize]; |
sprKeyNum = new uint16_t[tableSize]; |
sprValue = new uint32_t[tableSize]; |
|
clear (); |
clear(); |
|
} // SprCache () |
} // SprCache () |
|
|
//----------------------------------------------------------------------------- |
//! Destructor |
|
//! Free up the tables |
//----------------------------------------------------------------------------- |
SprCache::~SprCache () |
SprCache::~SprCache() |
{ |
delete [] sprValue; |
delete [] sprKeyNum; |
delete [] sprIsValid; |
delete[]sprValue; |
delete[]sprKeyNum; |
delete[]sprIsValid; |
|
} // ~SprCache () |
} // ~SprCache () |
|
|
//! Empty the hash table |
|
//! Only need to worry about the validity field |
void |
SprCache::clear () |
SprCache::clear() |
{ |
memset (sprIsValid, false, tableSize); |
memset(sprIsValid, false, tableSize); |
|
// No more than 70% full |
maxToUse = tableSize * 7 / 10; |
// No more than 70% full |
maxToUse = tableSize * 7 / 10; |
|
} // clear () |
} // clear () |
|
|
//----------------------------------------------------------------------------- |
//! Write a new value into the cache |
|
93,33 → 89,27
//! @param[in] force If TRUE the value will be written to the hash table, |
//! even if it is too full. |
//----------------------------------------------------------------------------- |
void |
SprCache::write (uint16_t sprNum, |
uint32_t value, |
bool force) |
void SprCache::write(uint16_t sprNum, uint32_t value, bool force) |
{ |
if (maxToUse <= 0) |
{ |
return; // Table is full |
} |
if (maxToUse <= 0) { |
return; // Table is full |
} |
|
int hv = sprNum % tableSize; |
int hv = sprNum % tableSize; |
|
// We can use the slot if either it is empty, or it is full and the key |
// number matches. |
while (sprIsValid[hv] && (sprKeyNum[hv] != sprNum)) |
{ |
hv = (hv + 1) % tableSize; |
} |
// We can use the slot if either it is empty, or it is full and the key |
// number matches. |
while (sprIsValid[hv] && (sprKeyNum[hv] != sprNum)) { |
hv = (hv + 1) % tableSize; |
} |
|
sprIsValid[hv] = true; |
sprKeyNum[hv] = sprNum; |
sprValue[hv] = value; |
maxToUse--; |
sprIsValid[hv] = true; |
sprKeyNum[hv] = sprNum; |
sprValue[hv] = value; |
maxToUse--; |
|
} // write () |
} // write () |
|
|
//----------------------------------------------------------------------------- |
//! Try to read a value from the cache |
|
131,20 → 121,17
|
//! @return True if the value was found in the hash table |
//----------------------------------------------------------------------------- |
bool |
SprCache::read (uint16_t sprNum, |
uint32_t &value) |
bool SprCache::read(uint16_t sprNum, uint32_t & value) |
{ |
int hv = sprNum % tableSize; |
int hv = sprNum % tableSize; |
|
// Look for either an empty slot (we are not there) or a matching key (we |
// are there) |
while (sprIsValid[hv] && (sprKeyNum[hv] != sprNum)) |
{ |
hv = (hv + 1) % tableSize; |
} |
// Look for either an empty slot (we are not there) or a matching key (we |
// are there) |
while (sprIsValid[hv] && (sprKeyNum[hv] != sprNum)) { |
hv = (hv + 1) % tableSize; |
} |
|
value = sprValue[hv]; |
return sprIsValid[hv]; |
value = sprValue[hv]; |
return sprIsValid[hv]; |
|
} // read () |
} // read () |
/sysc/src/RspPacket.cpp
35,7 → 35,6
#include "RspPacket.h" |
#include "Utils.h" |
|
|
using std::ostream; |
using std::cerr; |
using std::dec; |
44,7 → 43,6
using std::setfill; |
using std::setw; |
|
|
//----------------------------------------------------------------------------- |
//! Constructor |
|
53,26 → 51,24
//! @param[in] _rspConnection The RSP connection we will use |
//! @param[in] _bufSize Size of data buffer to allocate |
//----------------------------------------------------------------------------- |
RspPacket::RspPacket (int _bufSize) : |
bufSize (_bufSize) |
RspPacket::RspPacket(int _bufSize): |
bufSize(_bufSize) |
{ |
data = new char [_bufSize]; |
data = new char[_bufSize]; |
|
} // RspPacket (); |
} // RspPacket (); |
|
|
//----------------------------------------------------------------------------- |
//! Destructor |
|
//! Give back the data buffer |
//----------------------------------------------------------------------------- |
RspPacket::~RspPacket () |
RspPacket::~RspPacket() |
{ |
delete [] data; |
delete[]data; |
|
} // ~RspPacket () |
} // ~RspPacket () |
|
|
//----------------------------------------------------------------------------- |
//! Pack a string into a packet. |
|
81,25 → 77,23
//! @param str The string to copy into the data packet before sending |
//----------------------------------------------------------------------------- |
void |
RspPacket::packStr (const char *str) |
RspPacket::packStr(const char *str) |
{ |
int slen = strlen (str); |
int slen = strlen(str); |
|
// Construct the packet to send, so long as string is not too big, otherwise |
// truncate. Add EOS at the end for convenient debug printout |
if (slen >= bufSize) |
{ |
cerr << "Warning: String \"" << str |
<< "\" too large for RSP packet: truncated\n" << endl; |
slen = bufSize - 1; |
} |
// Construct the packet to send, so long as string is not too big, otherwise |
// truncate. Add EOS at the end for convenient debug printout |
if (slen >= bufSize) { |
cerr << "Warning: String \"" << str |
<< "\" too large for RSP packet: truncated\n" << endl; |
slen = bufSize - 1; |
} |
|
strncpy (data, str, slen); |
data[slen] = 0; |
len = slen; |
strncpy(data, str, slen); |
data[slen] = 0; |
len = slen; |
|
} // packStr () |
|
} // packStr () |
|
//----------------------------------------------------------------------------- |
//! Get the data buffer size |
106,40 → 100,34
|
//! @return The data buffer size |
//----------------------------------------------------------------------------- |
int |
RspPacket::getBufSize () |
int RspPacket::getBufSize() |
{ |
return bufSize; |
return bufSize; |
|
} // getBufSize () |
} // getBufSize () |
|
|
//----------------------------------------------------------------------------- |
//! Get the current number of chars in the data buffer |
|
//! @return The number of chars in the data buffer |
//----------------------------------------------------------------------------- |
int |
RspPacket::getLen () |
int RspPacket::getLen() |
{ |
return len; |
return len; |
|
} // getLen () |
} // getLen () |
|
|
//----------------------------------------------------------------------------- |
//! Set the number of chars in the data buffer |
|
//! @param[in] _len The number of chars to be set |
//----------------------------------------------------------------------------- |
void |
RspPacket::setLen (int _len) |
void RspPacket::setLen(int _len) |
{ |
len = _len; |
len = _len; |
|
} // setLen () |
} // setLen () |
|
|
//----------------------------------------------------------------------------- |
//! Output stream operator |
|
146,11 → 134,9
//! @param[out] s Stream to output to |
//! @param[in] p Packet to output |
//----------------------------------------------------------------------------- |
ostream & |
operator<< (ostream &s, |
RspPacket &p) |
ostream & operator<<(ostream & s, RspPacket & p) |
{ |
return s << "RSP packet: " << std::dec << std::setw (3) << p.getLen() |
<< std::setw (0) << " chars, \"" << p.data << "\""; |
return s << "RSP packet: " << std::dec << std::setw(3) << p.getLen() |
<< std::setw(0) << " chars, \"" << p.data << "\""; |
|
} // operator<< () |
} // operator<< () |