VR4300: Start adding data cache support.

This commit is contained in:
Tyler Stachecki 2014-05-06 19:49:03 -04:00
parent 49cbfc8994
commit 656103920b
4 changed files with 180 additions and 0 deletions

View file

@ -33,6 +33,7 @@ int vr4300_init(struct vr4300 *vr4300, struct bus_controller *bus) {
vr4300_connect_bus(vr4300, bus);
vr4300_cp0_init(vr4300);
vr4300_dcache_init(&vr4300->dcache);
vr4300_icache_init(&vr4300->icache);
vr4300_pipeline_init(&vr4300->pipeline);

View file

@ -12,6 +12,7 @@
#define __vr4300_cpu_h__
#include "common.h"
#include "vr4300/cp0.h"
#include "vr4300/dcache.h"
#include "vr4300/icache.h"
#include "vr4300/pipeline.h"
@ -81,6 +82,7 @@ struct vr4300 {
uint64_t regs[NUM_VR4300_REGISTERS];
uint32_t mi_regs[NUM_MI_REGISTERS];
struct vr4300_dcache dcache;
struct vr4300_icache icache;
struct vr4300_pipeline pipeline;

138
vr4300/dcache.c Normal file
View file

@ -0,0 +1,138 @@
//
// vr4300/dcache.c: VR4300 instruction cache.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#include "common.h"
#include "vr4300/dcache.h"
static inline struct vr4300_dcache_line* get_line(
struct vr4300_dcache *dcache, uint64_t vaddr);
static inline const struct vr4300_dcache_line* get_line_const(
const struct vr4300_dcache *dcache, uint64_t vaddr);
static inline uint32_t get_tag(const struct vr4300_dcache_line *line);
static void invalidate_line(struct vr4300_dcache_line *line);
static bool is_dirty(const struct vr4300_dcache_line *line);
static bool is_valid(const struct vr4300_dcache_line *line);
static void set_clean(struct vr4300_dcache_line *line);
static void set_dirty(struct vr4300_dcache_line *line);
static void set_tag(struct vr4300_dcache_line *line, uint32_t tag);
static void validate_line(struct vr4300_dcache_line *line, uint32_t tag);
// Returns the line for a given virtual address.
struct vr4300_dcache_line* get_line(
struct vr4300_dcache *dcache, uint64_t vaddr) {
return dcache->lines + (vaddr >> 4 & 0x1FF);
}
// Returns the line for a given virtual address.
const struct vr4300_dcache_line* get_line_const(
const struct vr4300_dcache *dcache, uint64_t vaddr) {
return dcache->lines + (vaddr >> 4 & 0x1FF);
}
// Returns the physical tag associated with the line.
uint32_t get_tag(const struct vr4300_dcache_line *line) {
return line->metadata >> 12;
}
// Invalidates the line, but leaves the physical tag untouched.
void invalidate_line(struct vr4300_dcache_line *line) {
line->metadata &= ~0x1;
}
// Returns true if the line is valid, otherwise returns false.
bool is_dirty(const struct vr4300_dcache_line *line) {
return (line->metadata & 0x2) == 0x2;
}
// Returns true if the line is valid, otherwise returns false.
bool is_valid(const struct vr4300_dcache_line *line) {
return (line->metadata & 0x1) == 0x1;
}
// Sets the state of the line to clean.
void set_clean(struct vr4300_dcache_line *line) {
line->metadata &= ~0x2;
}
// Sets the state of the line to dirty.
void set_dirty(struct vr4300_dcache_line *line) {
line->metadata |= 0x2;
}
// Sets the tag of the specified line, retaining current valid bit.
void set_tag(struct vr4300_dcache_line *line, uint32_t tag) {
line->metadata = (tag << 12) | (line->metadata & 0x1);
}
// Sets the line's physical tag and validates the line.
static void validate_line(struct vr4300_dcache_line *line, uint32_t tag) {
line->metadata = (tag << 12) | 0x1;
}
// Fills an instruction cache line with data.
void vr4300_dcache_fill(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t paddr, const void *data) {
struct vr4300_dcache_line *line = get_line(dcache, vaddr);
memcpy(line->data, data, sizeof(line->data));
validate_line(line, paddr >> 4);
}
// Returns the tag of the line associated with vaddr.
uint32_t vr4300_dcache_get_tag(const struct vr4300_dcache *dcache,
uint64_t vaddr) {
const struct vr4300_dcache_line *line = get_line_const(dcache, vaddr);
return get_tag(line);
}
// Initializes the instruction cache.
void vr4300_dcache_init(struct vr4300_dcache *dcache) {
memset(dcache->lines, 0, sizeof(dcache->lines));
}
// Invalidates an instruction cache line (regardless if hit or miss).
void vr4300_dcache_invalidate(struct vr4300_dcache *dcache, uint64_t vaddr) {
struct vr4300_dcache_line *line = get_line(dcache, vaddr);
invalidate_line(line);
}
// Invalidates an instruction cache line (only on a hit).
void vr4300_dcache_invalidate_hit(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t paddr) {
struct vr4300_dcache_line *line = get_line(dcache, vaddr);
uint32_t ptag = get_tag(line);
if (ptag == (paddr >> 4) && is_valid(line))
invalidate_line(line);
}
// Probes the instruction cache for a matching line.
const struct vr4300_dcache_line* vr4300_dcache_probe(
const struct vr4300_dcache *dcache, uint64_t vaddr, uint32_t paddr) {
const struct vr4300_dcache_line *line = get_line_const(dcache, vaddr);
uint32_t ptag = get_tag(line);
// Virtually index, and physically tagged.
return (ptag == (paddr >> 4) && is_valid(line))
? line
: NULL;
}
// Sets the physical tag associated with the line.
void vr4300_dcache_set_tag(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t tag) {
struct vr4300_dcache_line *line = get_line(dcache, vaddr);
set_tag(line, tag);
}

39
vr4300/dcache.h Normal file
View file

@ -0,0 +1,39 @@
//
// vr4300/dcache.h: VR4300 instruction cache.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef __vr4300_dcache_h__
#define __vr4300_dcache_h__
#include "common.h"
struct vr4300_dcache_line {
uint8_t data[4 * 4];
uint32_t metadata;
};
struct vr4300_dcache {
struct vr4300_dcache_line lines[512];
};
void vr4300_dcache_init(struct vr4300_dcache *dcache);
void vr4300_dcache_fill(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t paddr, const void *data);
uint32_t vr4300_dcache_get_tag(const struct vr4300_dcache *dcache,
uint64_t vaddr);
void vr4300_dcache_invalidate(struct vr4300_dcache *dcache, uint64_t vaddr);
void vr4300_dcache_invalidate_hit(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t paddr);
const struct vr4300_dcache_line* vr4300_dcache_probe(
const struct vr4300_dcache *dcache, uint64_t vaddr, uint32_t paddr);
void vr4300_dcache_set_tag(struct vr4300_dcache *dcache,
uint64_t vaddr, uint32_t tag);
#endif