Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[gem5.git] / dev / alpha_console.cc
1 /*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /** @file
30 * Alpha Console Definition
31 */
32
33 #include <cstddef>
34 #include <cstdio>
35 #include <string>
36
37 #include "base/inifile.hh"
38 #include "base/str.hh"
39 #include "base/trace.hh"
40 #include "cpu/base.hh"
41 #include "cpu/exec_context.hh"
42 #include "dev/alpha_console.hh"
43 #include "dev/simconsole.hh"
44 #include "dev/simple_disk.hh"
45 #include "dev/tsunami_io.hh"
46 #include "mem/bus/bus.hh"
47 #include "mem/bus/pio_interface.hh"
48 #include "mem/bus/pio_interface_impl.hh"
49 #include "mem/functional/memory_control.hh"
50 #include "mem/functional/physical.hh"
51 #include "sim/builder.hh"
52 #include "sim/sim_object.hh"
53 #include "sim/system.hh"
54
55 using namespace std;
56 using namespace AlphaISA;
57
58 AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
59 System *s, BaseCPU *c, Platform *p,
60 MemoryController *mmu, Addr a,
61 HierParams *hier, Bus *pio_bus)
62 : PioDevice(name, p), disk(d), console(cons), system(s), cpu(c), addr(a)
63 {
64 mmu->add_child(this, RangeSize(addr, size));
65
66 if (pio_bus) {
67 pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
68 &AlphaConsole::cacheAccess);
69 pioInterface->addAddrRange(RangeSize(addr, size));
70 }
71
72 alphaAccess = new Access;
73 alphaAccess->last_offset = size - 1;
74
75 alphaAccess->version = ALPHA_ACCESS_VERSION;
76 alphaAccess->diskUnit = 1;
77
78 alphaAccess->diskCount = 0;
79 alphaAccess->diskPAddr = 0;
80 alphaAccess->diskBlock = 0;
81 alphaAccess->diskOperation = 0;
82 alphaAccess->outputChar = 0;
83 alphaAccess->inputChar = 0;
84 bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
85
86 system->setAlphaAccess(addr);
87 }
88
89 void
90 AlphaConsole::startup()
91 {
92 alphaAccess->numCPUs = system->getNumCPUs();
93 alphaAccess->kernStart = system->getKernelStart();
94 alphaAccess->kernEnd = system->getKernelEnd();
95 alphaAccess->entryPoint = system->getKernelEntry();
96 alphaAccess->mem_size = system->physmem->size();
97 alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
98 alphaAccess->intrClockFrequency = platform->intrFrequency();
99 }
100
101 Fault
102 AlphaConsole::read(MemReqPtr &req, uint8_t *data)
103 {
104 memset(data, 0, req->size);
105
106 Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
107
108 switch (req->size)
109 {
110 case sizeof(uint32_t):
111 DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
112 *(uint32_t*)data);
113 switch (daddr)
114 {
115 case offsetof(AlphaAccess, last_offset):
116 *(uint32_t*)data = alphaAccess->last_offset;
117 break;
118 case offsetof(AlphaAccess, version):
119 *(uint32_t*)data = alphaAccess->version;
120 break;
121 case offsetof(AlphaAccess, numCPUs):
122 *(uint32_t*)data = alphaAccess->numCPUs;
123 break;
124 case offsetof(AlphaAccess, intrClockFrequency):
125 *(uint32_t*)data = alphaAccess->intrClockFrequency;
126 break;
127 default:
128 // Old console code read in everyting as a 32bit int
129 *(uint32_t*)data = *(uint32_t*)(consoleData + daddr);
130
131 }
132 break;
133 case sizeof(uint64_t):
134 DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
135 *(uint64_t*)data);
136 switch (daddr)
137 {
138 case offsetof(AlphaAccess, inputChar):
139 *(uint64_t*)data = console->console_in();
140 break;
141 case offsetof(AlphaAccess, cpuClock):
142 *(uint64_t*)data = alphaAccess->cpuClock;
143 break;
144 case offsetof(AlphaAccess, mem_size):
145 *(uint64_t*)data = alphaAccess->mem_size;
146 break;
147 case offsetof(AlphaAccess, kernStart):
148 *(uint64_t*)data = alphaAccess->kernStart;
149 break;
150 case offsetof(AlphaAccess, kernEnd):
151 *(uint64_t*)data = alphaAccess->kernEnd;
152 break;
153 case offsetof(AlphaAccess, entryPoint):
154 *(uint64_t*)data = alphaAccess->entryPoint;
155 break;
156 case offsetof(AlphaAccess, diskUnit):
157 *(uint64_t*)data = alphaAccess->diskUnit;
158 break;
159 case offsetof(AlphaAccess, diskCount):
160 *(uint64_t*)data = alphaAccess->diskCount;
161 break;
162 case offsetof(AlphaAccess, diskPAddr):
163 *(uint64_t*)data = alphaAccess->diskPAddr;
164 break;
165 case offsetof(AlphaAccess, diskBlock):
166 *(uint64_t*)data = alphaAccess->diskBlock;
167 break;
168 case offsetof(AlphaAccess, diskOperation):
169 *(uint64_t*)data = alphaAccess->diskOperation;
170 break;
171 case offsetof(AlphaAccess, outputChar):
172 *(uint64_t*)data = alphaAccess->outputChar;
173 break;
174 default:
175 int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
176 sizeof(alphaAccess->cpuStack[0]);
177
178 if (cpunum >= 0 && cpunum < 64)
179 *(uint64_t*)data = alphaAccess->cpuStack[cpunum];
180 else
181 panic("Unknown 64bit access, %#x\n", daddr);
182 }
183 break;
184 default:
185 return MachineCheckFault;
186 }
187
188 return NoFault;
189 }
190
191 Fault
192 AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
193 {
194 uint64_t val;
195
196 switch (req->size) {
197 case sizeof(uint32_t):
198 val = *(uint32_t *)data;
199 break;
200
201 case sizeof(uint64_t):
202 val = *(uint64_t *)data;
203 break;
204 default:
205 return MachineCheckFault;
206 }
207
208 Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
209 ExecContext *other_xc;
210
211 switch (daddr) {
212 case offsetof(AlphaAccess, diskUnit):
213 alphaAccess->diskUnit = val;
214 break;
215
216 case offsetof(AlphaAccess, diskCount):
217 alphaAccess->diskCount = val;
218 break;
219
220 case offsetof(AlphaAccess, diskPAddr):
221 alphaAccess->diskPAddr = val;
222 break;
223
224 case offsetof(AlphaAccess, diskBlock):
225 alphaAccess->diskBlock = val;
226 break;
227
228 case offsetof(AlphaAccess, diskOperation):
229 if (val == 0x13)
230 disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
231 alphaAccess->diskCount);
232 else
233 panic("Invalid disk operation!");
234
235 break;
236
237 case offsetof(AlphaAccess, outputChar):
238 console->out((char)(val & 0xff));
239 break;
240
241 other_xc->activate(); //Start the cpu
242 break;
243
244 default:
245 int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
246 sizeof(alphaAccess->cpuStack[0]);
247 warn("%d: Trying to launch CPU number %d!", curTick, cpunum);
248 assert(val > 0 && "Must not access primary cpu");
249 if (cpunum >= 0 && cpunum < 64)
250 alphaAccess->cpuStack[cpunum] = val;
251 else
252 panic("Unknown 64bit access, %#x\n", daddr);
253 }
254
255 return NoFault;
256 }
257
258 Tick
259 AlphaConsole::cacheAccess(MemReqPtr &req)
260 {
261 return curTick + 1000;
262 }
263
264 void
265 AlphaConsole::Access::serialize(ostream &os)
266 {
267 SERIALIZE_SCALAR(last_offset);
268 SERIALIZE_SCALAR(version);
269 SERIALIZE_SCALAR(numCPUs);
270 SERIALIZE_SCALAR(mem_size);
271 SERIALIZE_SCALAR(cpuClock);
272 SERIALIZE_SCALAR(intrClockFrequency);
273 SERIALIZE_SCALAR(kernStart);
274 SERIALIZE_SCALAR(kernEnd);
275 SERIALIZE_SCALAR(entryPoint);
276 SERIALIZE_SCALAR(diskUnit);
277 SERIALIZE_SCALAR(diskCount);
278 SERIALIZE_SCALAR(diskPAddr);
279 SERIALIZE_SCALAR(diskBlock);
280 SERIALIZE_SCALAR(diskOperation);
281 SERIALIZE_SCALAR(outputChar);
282 SERIALIZE_SCALAR(inputChar);
283 SERIALIZE_ARRAY(cpuStack,64);
284 }
285
286 void
287 AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
288 {
289 UNSERIALIZE_SCALAR(last_offset);
290 UNSERIALIZE_SCALAR(version);
291 UNSERIALIZE_SCALAR(numCPUs);
292 UNSERIALIZE_SCALAR(mem_size);
293 UNSERIALIZE_SCALAR(cpuClock);
294 UNSERIALIZE_SCALAR(intrClockFrequency);
295 UNSERIALIZE_SCALAR(kernStart);
296 UNSERIALIZE_SCALAR(kernEnd);
297 UNSERIALIZE_SCALAR(entryPoint);
298 UNSERIALIZE_SCALAR(diskUnit);
299 UNSERIALIZE_SCALAR(diskCount);
300 UNSERIALIZE_SCALAR(diskPAddr);
301 UNSERIALIZE_SCALAR(diskBlock);
302 UNSERIALIZE_SCALAR(diskOperation);
303 UNSERIALIZE_SCALAR(outputChar);
304 UNSERIALIZE_SCALAR(inputChar);
305 UNSERIALIZE_ARRAY(cpuStack, 64);
306 }
307
308 void
309 AlphaConsole::serialize(ostream &os)
310 {
311 alphaAccess->serialize(os);
312 }
313
314 void
315 AlphaConsole::unserialize(Checkpoint *cp, const std::string &section)
316 {
317 alphaAccess->unserialize(cp, section);
318 }
319
320 BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
321
322 SimObjectParam<SimConsole *> sim_console;
323 SimObjectParam<SimpleDisk *> disk;
324 SimObjectParam<MemoryController *> mmu;
325 Param<Addr> addr;
326 SimObjectParam<System *> system;
327 SimObjectParam<BaseCPU *> cpu;
328 SimObjectParam<Platform *> platform;
329 SimObjectParam<Bus*> pio_bus;
330 Param<Tick> pio_latency;
331 SimObjectParam<HierParams *> hier;
332
333 END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
334
335 BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
336
337 INIT_PARAM(sim_console, "The Simulator Console"),
338 INIT_PARAM(disk, "Simple Disk"),
339 INIT_PARAM(mmu, "Memory Controller"),
340 INIT_PARAM(addr, "Device Address"),
341 INIT_PARAM(system, "system object"),
342 INIT_PARAM(cpu, "Processor"),
343 INIT_PARAM(platform, "platform"),
344 INIT_PARAM(pio_bus, "The IO Bus to attach to"),
345 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
346 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
347
348 END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
349
350 CREATE_SIM_OBJECT(AlphaConsole)
351 {
352 return new AlphaConsole(getInstanceName(), sim_console, disk,
353 system, cpu, platform, mmu, addr, hier, pio_bus);
354 }
355
356 REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)