⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 koala.hh

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 HH
📖 第 1 页 / 共 2 页
字号:
#ifndef koala_hh_included#define koala_hh_included#include <setjmp.h>#include <mips64/bus.hh>#include <mips64/cache.hh>#include <mips64/cpu.hh>#include <mips64/types.hh>#include <checkpoint.hh>#include <clock.hh>#include <cpu.hh>#include <inttypes.hh>#include <serial.hh>class Koala    : public virtual Serializable, public MIPS64Cpu{    private:    static SerialType<Koala> type;public:    // The usual interfaces.    Koala(const SimArgs& args);    Koala(Checkpoint& cp);    ~Koala();    void reset(bool warm);    void checkpoint(Checkpoint& cp, bool parent = false) const;    // The fetch-execute loop.    void run(ClockValue timeslice);    // Interrupt delivery functions:    void deliver_cold_reset();    void deliver_soft_reset();    void deliver_nmi();    void deliver_interrupt(unsigned int n);    void clear_interrupt(unsigned int n);    void dump_state();public:    // Register names, for debugging.    static const char* regname[32];    // 16 bit implementation and revision fields.  The upper 8 bits are 0x20    // for R4600, 0x21 for R4700. The lower 8 bits should distinguish the    // simulator.    static const UInt32 ImpRev = 0x2070;    // A system coprocessor timer interrupt.    class Timer	: public Event, public virtual Serializable    {    private:	static SerialType<Timer> type;	Koala* cpu;    public:	Timer(Koala* c, ClockValue w)	    : Event(w, 0), cpu(c) { }	explicit Timer(const SimArgs& args)	    : Event(args) { assert(UNREACHABLE); }	explicit Timer(Checkpoint& cp);	void invoke();	void checkpoint(Checkpoint& cp, bool parent = false) const;    };    // Fundamental parameters.    static const int vaddr_width 	= 40;    static const int log2_icache_assoc 	=  1;    static const int log2_icache_size  	= 14;    static const int log2_icache_line  	=  5;    static const int log2_dcache_assoc 	=  1;    static const int log2_dcache_size  	= 14;    static const int log2_dcache_line  	=  5;    static const size_t write_buffers  	=  0;    static const size_t tlb_size       	= 48;    static const VA  xkseg_end		= VA(C000,00FF,8000,0000);    // Some instruction latencies. These are for R4600. On R4700, both all    // four multiplication latencies are decreased by four cycles.    static const int mult_latency	= 10;    static const int multu_latency	= 10;    static const int div_latency	= 42;    static const int divu_latency	= 42;    static const int dmult_latency	= 12;    static const int dmultu_latency	= 12;    static const int ddiv_latency	= 74;    static const int ddivu_latency	= 74;    // Asynchronous event constants. Each interrupt source corresponds to a    // single bit of the (events) word. Bits 8 through 16 correspond to    // interrupts 0 through 7. Other bits represent the three reset exceptions    // as follows:    enum {	cold_reset_event	= 1 << 0,	soft_reset_event	= 1 << 1,	nmi_event		= 1 << 2    };    // Cache of some strategic CPU mode bits. This shortcut is used to avoid    // parsing of the somewhat convoluted Status register during address    // translation and instruction decoding.    enum {	xmode = 1 << 0,	// 64 bit mode ([USK]X & [usk]mode)	cmode = 1 << 1, // 32 bit (compatibility) mode (!xmode)	bmode = 1 << 2,	// big-endian-cpu (big_endian_mem() ^ reverse_endian())	rmode = 1 << 3, // reverse-endian (RE && umode)	umode = 1 << 4,	// user mode	smode = 1 << 5,	// supervisor mode	kmode = 1 << 6	// kernel mode    };    // Pipeline information. This is fairly ad hoc, but it is still useful.    enum {	nothing_special,	// nothing special	branch_delay,		// current instruction in the branch-delay slot	instr_addr_error 	// instruction address error    };    // A TLB Entry structure.    struct TLBEntry {	TLBEntry* next;	// the hash chain	TLBEntry* prev;	// the hash chain	UInt64 hi;	// VPN/2 << 13	UInt64 mask;	// ~((oddbit << 1) - 1)	UInt64 oddbit;	// the odd bit of VPN	UInt32 lo[2];	// EntryLo0/1	Int16 asid;	// the ASID, sign bit set for global entries.	UInt16 index;	// TLB index	UInt16 hash;	// TLB map index    };    // An invalid ASID bit used to mark unused TLB entries.    static const Int16 invalid_asid = (1 << 8);    // An global ASID bit.    static const Int16 global_asid = (Int16)(1 << 15);    // Geometry of the TLB lookup map (see below.)    static const int log2_tlb_map_size = 8;    static const int tlb_map_size = 1 << log2_tlb_map_size;     // Cache structures. See <mips64/cache.hh> for details.    typedef MIPS64Cache<log2_icache_size,log2_icache_line,log2_icache_assoc>	ICache;    typedef MIPS64Cache<log2_dcache_size,log2_dcache_line,log2_dcache_assoc>	DCache;     // An invalid cache tag used to mark unused cache lines.    static const UInt32 bad_tag = ~UInt32(0);    // An invalid ibuf tag used to marked unused icache buffers.    static const VA bad_ibuf_tag = ~(VA)(0);    // An invalid physical address returned by translate_vaddr() on cache    // operations that specify an invalid address.    static const PA bad_pa = ~PA(0);    // TLB access types, used to select the appropriate TLB miss handler.    enum {	instr_fetch,	// instruction fetch	data_load,	// data load	data_store,	// data store	cache_op	// cache operations (ignore errors)    };    // The two-entry ITLB. Each entry maps a 4KB page.    struct ITLBEntry {	VA vpn;		// virtual address page number (va / 4KB)	PA pa;		// physical address and the caching algorithm	Int16 asid;	// ASID and the global bit.    };    // Although not in real hardware, we also cache the two most recent    // I-cache accesses, as simulating cache lookups is slow, and as many as 8    // instructions can be fetched from one cache line.    struct ICacheBuffer {	VA tag;		// address of the cache shifted by log2_icache_line	UInt64* line;	// pointer to the ICache line.	// Extract a doubleword given a PC.	UInt64 operator[] (VA pc) const	    { return line[bits(pc, Koala::log2_icache_line - 1, 3)]; }    };    // CPU state.    Int16 asid;		// same as the ASID field in EntryHi    UInt16 events;	// external events: this also replaces Cause[15:8].    UInt8  pipeline;	// current instruction in the branch-delay slot    UInt8  mode;	// CPU mode    bool   sync_bit;	// true after executing the SYNC instruction.    VA branch_target;	// next PC when in the branch delay slot    // cp0[Random] is not updated on each clock cycle. Instead, its value is    // updated when either cp0[Random] or cp0[Wired] is set, and the current    // value is computed using the time elapsed since then.    ClockValue random_seed;    // Similary, we lazily compute the value of the Count register.    ClockValue count_seed;    // ITLB data. (lru_itlb) stores the index of the least-recently used entry.    ITLBEntry itlb[2];    bool lru_itlb;    // I-cache buffer data (lru_ibuf) stores the index of the least-recently    // used entry (0 or 1).    ICacheBuffer ibuf[2];    bool lru_ibuf;    // There's at most one timer interrupt pending at any given time.        Timer* timer;    // The longjmp buffer used for handling exceptions.    jmp_buf env;    // The TLB and L1 caches.    TLBEntry tlb[tlb_size];    ICache icache;    DCache dcache;    // The TLB map used to simulate the direct-mapped TLB lookup.  There's an    // extra entry at the end that contains the hash chain of all unused TLB    // entries (that way, there is always exactly (tlb_size) mappings in the    // hash table).    TLBEntry* tlb_map[tlb_map_size + 1];    // The trace mode flag.    enum {	no_tracing,	report_interrupts,	report_exceptions,	print_instructions,	dump_gprs    };    // The NOP guard.    static const UInt32 catch_nops = 128;    size_t nop_count;    // (mode) operations.    void enter_kernel_mode()    {	mode = kmode | (bit(cp0[SR], SR_KX) ? xmode : cmode);	if (big_endian_mem())	    mode |= bmode;    }    void leave_kernel_mode()    {	switch (bits(cp0[SR], SR_KSU_Last, SR_EXL) << 1) {	case 1 << SR_KSU_Last: // user	    mode = umode | (bit(cp0[SR], SR_UX) ? xmode : cmode);	    if (bit(cp0[SR], SR_RE))		mode |= rmode;	    if (big_endian_mem() != bool(reverse_endian()))		mode |= bmode;	    break;	case 1 << SR_KSU_First: // supervisor	    mode = smode | (bit(cp0[SR], SR_SX) ? xmode : cmode);	    if (big_endian_mem())		mode |= bmode;	    break;	default: // kernel (or undefined, but I ignore that bit ;)	    mode = kmode | (bit(cp0[SR], SR_KX) ? xmode : cmode);	    if (big_endian_mem())		mode |= bmode;	    break;	}    }    // Compute the current value of the Random register.    int get_random() const    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -