Skip to content

Commit a4c1477

Browse files
committed
mips: Add DSPRAM
The optional Data Scratch Pad RAM (DSPRAM) block provides a general scratch pad RAM used for temporary storage of data. The DSPRAM provides a connection to on-chip memory or memory-mapped registers, which are accessed in parallel with the L1 data cache to minimize access latency Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
1 parent d086bb1 commit a4c1477

File tree

11 files changed

+259
-1
lines changed

11 files changed

+259
-1
lines changed

default-configs/mips-softmmu-common.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ CONFIG_ISA_TESTDEV=y
3333
CONFIG_EMPTY_SLOT=y
3434
CONFIG_MIPS_CPS=y
3535
CONFIG_MIPS_ITU=y
36+
CONFIG_MIPS_DSPRAM=y

hw/mips/cps.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
106106
object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present",
107107
&err);
108108
if (saar_present) {
109-
qdev_prop_set_ptr(DEVICE(&s->itu), "saar", (void *) &env->CP0_SAAR);
109+
qdev_prop_set_ptr(DEVICE(&s->itu), "saar",
110+
(void *) &env->CP0_SAAR[0]);
110111
}
111112
object_property_set_bool(OBJECT(&s->itu), true, "realized", &err);
112113
if (err != NULL) {

hw/mips/mips_malta.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,36 @@ static void create_cps(MaltaState *s, const char *cpu_model,
970970
*cbus_irq = NULL;
971971
}
972972

973+
static void create_dspram(void)
974+
{
975+
MIPSCPU *cpu = MIPS_CPU(first_cpu);
976+
CPUMIPSState *env = &cpu->env;
977+
bool dspram_present = (bool) env->dspramp;
978+
Error *err = NULL;
979+
980+
env->dspram = g_new0(MIPSDSPRAMState, 1);
981+
982+
/* DSPRAM */
983+
if (dspram_present) {
984+
if (!(bool) env->saarp) {
985+
error_report("%s: DSPRAM requires SAAR registers", __func__);
986+
exit(1);
987+
}
988+
object_initialize(env->dspram, sizeof(MIPSDSPRAMState),
989+
TYPE_MIPS_DSPRAM);
990+
qdev_set_parent_bus(DEVICE(env->dspram), sysbus_get_default());
991+
qdev_prop_set_ptr(DEVICE(env->dspram), "saar",
992+
(void *) &env->CP0_SAAR[1]);
993+
object_property_set_bool(OBJECT(env->dspram), true, "realized", &err);
994+
if (err != NULL) {
995+
error_report("%s: DSPRAM initialisation failed", __func__);
996+
exit(1);
997+
}
998+
memory_region_add_subregion(get_system_memory(), 0,
999+
sysbus_mmio_get_region(SYS_BUS_DEVICE(env->dspram), 0));
1000+
}
1001+
}
1002+
9731003
static void create_cpu(MaltaState *s, const char *cpu_model,
9741004
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
9751005
{
@@ -986,6 +1016,7 @@ static void create_cpu(MaltaState *s, const char *cpu_model,
9861016
} else {
9871017
create_cpu_without_cps(cpu_model, cbus_irq, i8259_irq);
9881018
}
1019+
create_dspram();
9891020
}
9901021

9911022
static

hw/misc/Makefile.objs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
4747
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
4848
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
4949
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
50+
obj-$(CONFIG_MIPS_DSPRAM) += mips_dspram.o
5051

5152
obj-$(CONFIG_PVPANIC) += pvpanic.o
5253
obj-$(CONFIG_EDU) += edu.o

hw/misc/mips_dspram.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Data Scratch Pad RAM
3+
*
4+
* Copyright (c) 2017 Imagination Technologies
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "qemu/osdep.h"
21+
#include "qapi/error.h"
22+
#include "cpu.h"
23+
#include "qemu/log.h"
24+
#include "exec/exec-all.h"
25+
#include "hw/hw.h"
26+
#include "hw/sysbus.h"
27+
#include "sysemu/sysemu.h"
28+
#include "hw/misc/mips_dspram.h"
29+
30+
static void raise_exception(int excp)
31+
{
32+
current_cpu->exception_index = excp;
33+
cpu_loop_exit(current_cpu);
34+
}
35+
36+
static uint64_t dspram_read(void *opaque, hwaddr addr, unsigned size)
37+
{
38+
MIPSDSPRAMState *s = (MIPSDSPRAMState *)opaque;
39+
40+
switch (size) {
41+
case 1:
42+
case 2:
43+
raise_exception(EXCP_AdEL);
44+
return 0;
45+
case 4:
46+
return *(uint32_t *) &s->ramblock[addr % (2 << s->size)];
47+
case 8:
48+
return *(uint64_t *) &s->ramblock[addr % (2 << s->size)];
49+
}
50+
return 0;
51+
}
52+
53+
static void dspram_write(void *opaque, hwaddr addr, uint64_t data,
54+
unsigned size)
55+
{
56+
MIPSDSPRAMState *s = (MIPSDSPRAMState *)opaque;
57+
58+
switch (size) {
59+
case 1:
60+
case 2:
61+
raise_exception(EXCP_AdES);
62+
return;
63+
case 4:
64+
*(uint32_t *) &s->ramblock[addr % (2 << s->size)] = (uint32_t) data;
65+
break;
66+
case 8:
67+
*(uint64_t *) &s->ramblock[addr % (2 << s->size)] = data;
68+
break;
69+
}
70+
}
71+
72+
void dspram_reconfigure(MIPSDSPRAMState *dspram)
73+
{
74+
MemoryRegion *mr = &dspram->mr;
75+
hwaddr address;
76+
bool is_enabled;
77+
78+
address = ((*(uint64_t *) dspram->saar) & 0xFFFFFFFFE000ULL) << 4;
79+
is_enabled = *(uint64_t *) dspram->saar & 1;
80+
81+
memory_region_transaction_begin();
82+
memory_region_set_size(mr, (2 << dspram->size));
83+
memory_region_set_address(mr, address);
84+
memory_region_set_enabled(mr, is_enabled);
85+
memory_region_transaction_commit();
86+
}
87+
88+
static const MemoryRegionOps dspram_ops = {
89+
.read = dspram_read,
90+
.write = dspram_write,
91+
.endianness = DEVICE_NATIVE_ENDIAN,
92+
.valid = {
93+
.unaligned = false,
94+
}
95+
};
96+
97+
static void mips_dspram_init(Object *obj)
98+
{
99+
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
100+
MIPSDSPRAMState *s = MIPS_DSPRAM(obj);
101+
102+
memory_region_init_io(&s->mr, OBJECT(s), &dspram_ops, s,
103+
"mips-dspram", (2 << s->size));
104+
sysbus_init_mmio(sbd, &s->mr);
105+
}
106+
107+
static void mips_dspram_realize(DeviceState *dev, Error **errp)
108+
{
109+
MIPSDSPRAMState *s = MIPS_DSPRAM(dev);
110+
111+
/* some error handling here */
112+
113+
s->ramblock = g_malloc0(2 << s->size);
114+
}
115+
116+
static void mips_dspram_reset(DeviceState *dev)
117+
{
118+
MIPSDSPRAMState *s = MIPS_DSPRAM(dev);
119+
120+
*(uint64_t *) s->saar = s->size << 1;
121+
memset(s->ramblock, 0, (2 << s->size));
122+
}
123+
124+
static Property mips_dspram_properties[] = {
125+
DEFINE_PROP_PTR("saar", MIPSDSPRAMState, saar),
126+
/* default DSPRAM size is 64 KB */
127+
DEFINE_PROP_SIZE("size", MIPSDSPRAMState, size, 0x10),
128+
DEFINE_PROP_END_OF_LIST(),
129+
};
130+
131+
static void mips_dspram_class_init(ObjectClass *klass, void *data)
132+
{
133+
DeviceClass *dc = DEVICE_CLASS(klass);
134+
135+
dc->props = mips_dspram_properties;
136+
dc->realize = mips_dspram_realize;
137+
dc->reset = mips_dspram_reset;
138+
}
139+
140+
static const TypeInfo mips_dspram_info = {
141+
.name = TYPE_MIPS_DSPRAM,
142+
.parent = TYPE_SYS_BUS_DEVICE,
143+
.instance_size = sizeof(MIPSDSPRAMState),
144+
.instance_init = mips_dspram_init,
145+
.class_init = mips_dspram_class_init,
146+
};
147+
148+
static void mips_dspram_register_types(void)
149+
{
150+
type_register_static(&mips_dspram_info);
151+
}
152+
153+
type_init(mips_dspram_register_types)
154+

include/hw/mips/cps.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "hw/intc/mips_gic.h"
2626
#include "hw/misc/mips_cpc.h"
2727
#include "hw/misc/mips_itu.h"
28+
#include "hw/misc/mips_dspram.h"
2829

2930
#define TYPE_MIPS_CPS "mips-cps"
3031
#define MIPS_CPS(obj) OBJECT_CHECK(MIPSCPSState, (obj), TYPE_MIPS_CPS)
@@ -41,6 +42,7 @@ typedef struct MIPSCPSState {
4142
MIPSGICState gic;
4243
MIPSCPCState cpc;
4344
MIPSITUState itu;
45+
MIPSDSPRAMState dspram;
4446
} MIPSCPSState;
4547

4648
qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number);

include/hw/misc/mips_dspram.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Data Scratch Pad RAM
3+
*
4+
* Copyright (c) 2017 Imagination Technologies
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#ifndef MIPS_DSPRAM_H
21+
#define MIPS_DSPRAM_H
22+
23+
#define TYPE_MIPS_DSPRAM "mips-dspram"
24+
#define MIPS_DSPRAM(obj) OBJECT_CHECK(MIPSDSPRAMState, (obj), TYPE_MIPS_DSPRAM)
25+
26+
typedef struct MIPSDSPRAMState {
27+
/*< private >*/
28+
SysBusDevice parent_obj;
29+
/*< public >*/
30+
31+
/* 2 ^ SIZE */
32+
uint64_t size;
33+
34+
MemoryRegion mr;
35+
36+
/* SAAR */
37+
bool saar_present;
38+
void *saar;
39+
40+
/* ramblock */
41+
uint8_t *ramblock;
42+
} MIPSDSPRAMState;
43+
44+
#endif /* MIPS_DSPRAM_H */

target-mips/cpu.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ struct CPUMIPSState {
648648
uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
649649
int insn_flags; /* Supported instruction set */
650650
int saarp;
651+
int dspramp;
651652

652653
CPU_COMMON
653654

@@ -662,6 +663,7 @@ struct CPUMIPSState {
662663
QEMUTimer *timer; /* Internal timer */
663664
struct MIPSITUState *itu;
664665
MemoryRegion *itc_tag; /* ITC Configuration Tags */
666+
struct MIPSDSPRAMState *dspram;
665667
target_ulong exception_base; /* ExceptionBase input to the core */
666668
};
667669

@@ -874,6 +876,9 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
874876
/* mips_itu.c */
875877
void itc_reconfigure(struct MIPSITUState *tag);
876878

879+
/* mips_dspram.c */
880+
void dspram_reconfigure(struct MIPSDSPRAMState *dspram);
881+
877882
/* helper.c */
878883
int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
879884
int mmu_idx);

target-mips/op_helper.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,11 @@ void helper_mtc0_saar(CPUMIPSState *env, target_ulong arg1)
15291529
itc_reconfigure(env->itu);
15301530
}
15311531
break;
1532+
case 1:
1533+
if (env->dspram) {
1534+
dspram_reconfigure(env->dspram);
1535+
}
1536+
break;
15321537
}
15331538
}
15341539
}
@@ -1546,6 +1551,11 @@ void helper_mthc0_saar(CPUMIPSState *env, target_ulong arg1)
15461551
itc_reconfigure(env->itu);
15471552
}
15481553
break;
1554+
case 1:
1555+
if (env->dspram) {
1556+
dspram_reconfigure(env->dspram);
1557+
}
1558+
break;
15491559
}
15501560
}
15511561
}

target-mips/translate.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20558,6 +20558,7 @@ void cpu_state_reset(CPUMIPSState *env)
2055820558
env->msair = env->cpu_model->MSAIR;
2055920559
env->insn_flags = env->cpu_model->insn_flags;
2056020560
env->saarp = env->cpu_model->SAARP;
20561+
env->dspramp = env->cpu_model->DSPRAMP;
2056120562

2056220563
#if defined(CONFIG_USER_ONLY)
2056320564
env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
@@ -20677,6 +20678,12 @@ void cpu_state_reset(CPUMIPSState *env)
2067720678
#endif
2067820679
}
2067920680

20681+
/* DSPRAM */
20682+
if (env->dspramp) {
20683+
/* Fixed DSPRAM size with Default Value */
20684+
env->CP0_SAAR[1] = 0x10 << 1;
20685+
}
20686+
2068020687
compute_hflags(env);
2068120688
restore_fp_status(env);
2068220689
restore_pamask(env);

0 commit comments

Comments
 (0)