OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

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", &regNum))
{
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", &regNum)) {
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", &regNum, 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", &regNum, 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*) &current_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 *)&current_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<< ()

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.