2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
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.
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.
30 * Alpha Console Definition
37 #include "arch/alpha/system.hh"
38 #include "base/inifile.hh"
39 #include "base/str.hh"
40 #include "base/trace.hh"
41 #include "cpu/base.hh"
42 #include "cpu/exec_context.hh"
43 #include "dev/alpha_console.hh"
44 #include "dev/platform.hh"
45 #include "dev/simconsole.hh"
46 #include "dev/simple_disk.hh"
47 #include "mem/physical.hh"
48 #include "sim/builder.hh"
49 #include "sim/sim_object.hh"
52 using namespace AlphaISA
;
54 AlphaConsole::AlphaConsole(Params
*p
)
55 : BasicPioDevice(p
), disk(p
->disk
),
56 console(params()->cons
), system(params()->alpha_sys
), cpu(params()->cpu
)
59 pioSize
= sizeof(struct AlphaAccess
);
61 alphaAccess
= new Access();
62 alphaAccess
->last_offset
= pioSize
- 1;
64 alphaAccess
->version
= ALPHA_ACCESS_VERSION
;
65 alphaAccess
->diskUnit
= 1;
67 alphaAccess
->diskCount
= 0;
68 alphaAccess
->diskPAddr
= 0;
69 alphaAccess
->diskBlock
= 0;
70 alphaAccess
->diskOperation
= 0;
71 alphaAccess
->outputChar
= 0;
72 alphaAccess
->inputChar
= 0;
73 bzero(alphaAccess
->cpuStack
, sizeof(alphaAccess
->cpuStack
));
75 system
->setAlphaAccess(pioAddr
);
79 AlphaConsole::startup()
81 alphaAccess
->numCPUs
= system
->getNumCPUs();
82 alphaAccess
->kernStart
= system
->getKernelStart();
83 alphaAccess
->kernEnd
= system
->getKernelEnd();
84 alphaAccess
->entryPoint
= system
->getKernelEntry();
85 alphaAccess
->mem_size
= system
->physmem
->size();
86 alphaAccess
->cpuClock
= cpu
->frequency() / 1000000; // In MHz
87 alphaAccess
->intrClockFrequency
= params()->platform
->intrFrequency();
91 AlphaConsole::addressRanges(AddrRangeList
&range_list
)
95 range_list
.push_back(RangeSize(pioAddr
, sizeof(struct AlphaAccess
)));
100 AlphaConsole::read(Packet
&pkt
)
103 /** XXX Do we want to push the addr munging to a bus brige or something? So
104 * the device has it's physical address and then the bridge adds on whatever
105 * machine dependent address swizzle is required?
108 assert(pkt
.result
== Unknown
);
109 assert(pkt
.addr
>= pioAddr
&& pkt
.addr
< pioAddr
+ pioSize
);
111 pkt
.time
= curTick
+ pioDelay
;
112 Addr daddr
= pkt
.addr
- pioAddr
;
119 case sizeof(uint32_t):
121 data32
= new uint32_t;
122 pkt
.data
= (uint8_t*)data32
;
124 data32
= (uint32_t*)pkt
.data
;
128 case offsetof(AlphaAccess
, last_offset
):
129 *data32
= alphaAccess
->last_offset
;
131 case offsetof(AlphaAccess
, version
):
132 *data32
= alphaAccess
->version
;
134 case offsetof(AlphaAccess
, numCPUs
):
135 *data32
= alphaAccess
->numCPUs
;
137 case offsetof(AlphaAccess
, intrClockFrequency
):
138 *data32
= alphaAccess
->intrClockFrequency
;
141 /* Old console code read in everyting as a 32bit int
142 * we now break that for better error checking.
144 pkt
.result
= BadAddress
;
146 DPRINTF(AlphaConsole
, "read: offset=%#x val=%#x\n", daddr
, *data32
);
148 case sizeof(uint64_t):
150 data64
= new uint64_t;
151 pkt
.data
= (uint8_t*)data64
;
153 data64
= (uint64_t*)pkt
.data
;
156 case offsetof(AlphaAccess
, inputChar
):
157 *data64
= console
->console_in();
159 case offsetof(AlphaAccess
, cpuClock
):
160 *data64
= alphaAccess
->cpuClock
;
162 case offsetof(AlphaAccess
, mem_size
):
163 *data64
= alphaAccess
->mem_size
;
165 case offsetof(AlphaAccess
, kernStart
):
166 *data64
= alphaAccess
->kernStart
;
168 case offsetof(AlphaAccess
, kernEnd
):
169 *data64
= alphaAccess
->kernEnd
;
171 case offsetof(AlphaAccess
, entryPoint
):
172 *data64
= alphaAccess
->entryPoint
;
174 case offsetof(AlphaAccess
, diskUnit
):
175 *data64
= alphaAccess
->diskUnit
;
177 case offsetof(AlphaAccess
, diskCount
):
178 *data64
= alphaAccess
->diskCount
;
180 case offsetof(AlphaAccess
, diskPAddr
):
181 *data64
= alphaAccess
->diskPAddr
;
183 case offsetof(AlphaAccess
, diskBlock
):
184 *data64
= alphaAccess
->diskBlock
;
186 case offsetof(AlphaAccess
, diskOperation
):
187 *data64
= alphaAccess
->diskOperation
;
189 case offsetof(AlphaAccess
, outputChar
):
190 *data64
= alphaAccess
->outputChar
;
193 int cpunum
= (daddr
- offsetof(AlphaAccess
, cpuStack
)) /
194 sizeof(alphaAccess
->cpuStack
[0]);
196 if (cpunum
>= 0 && cpunum
< 64)
197 *data64
= alphaAccess
->cpuStack
[cpunum
];
199 panic("Unknown 64bit access, %#x\n", daddr
);
201 DPRINTF(AlphaConsole
, "read: offset=%#x val=%#x\n", daddr
, *data64
);
204 pkt
.result
= BadAddress
;
206 if (pkt
.result
== Unknown
) pkt
.result
= Success
;
211 AlphaConsole::write(Packet
&pkt
)
213 pkt
.time
= curTick
+ pioDelay
;
215 assert(pkt
.result
== Unknown
);
216 assert(pkt
.addr
>= pioAddr
&& pkt
.addr
< pioAddr
+ pioSize
);
217 Addr daddr
= pkt
.addr
- pioAddr
;
219 uint64_t val
= *(uint64_t *)pkt
.data
;
220 assert(pkt
.size
== sizeof(uint64_t));
223 case offsetof(AlphaAccess
, diskUnit
):
224 alphaAccess
->diskUnit
= val
;
227 case offsetof(AlphaAccess
, diskCount
):
228 alphaAccess
->diskCount
= val
;
231 case offsetof(AlphaAccess
, diskPAddr
):
232 alphaAccess
->diskPAddr
= val
;
235 case offsetof(AlphaAccess
, diskBlock
):
236 alphaAccess
->diskBlock
= val
;
239 case offsetof(AlphaAccess
, diskOperation
):
241 disk
->read(alphaAccess
->diskPAddr
, alphaAccess
->diskBlock
,
242 alphaAccess
->diskCount
);
244 panic("Invalid disk operation!");
248 case offsetof(AlphaAccess
, outputChar
):
249 console
->out((char)(val
& 0xff));
253 int cpunum
= (daddr
- offsetof(AlphaAccess
, cpuStack
)) /
254 sizeof(alphaAccess
->cpuStack
[0]);
255 warn("%d: Trying to launch CPU number %d!", curTick
, cpunum
);
256 assert(val
> 0 && "Must not access primary cpu");
257 if (cpunum
>= 0 && cpunum
< 64)
258 alphaAccess
->cpuStack
[cpunum
] = val
;
260 panic("Unknown 64bit access, %#x\n", daddr
);
263 pkt
.result
= Success
;
269 AlphaConsole::Access::serialize(ostream
&os
)
271 SERIALIZE_SCALAR(last_offset
);
272 SERIALIZE_SCALAR(version
);
273 SERIALIZE_SCALAR(numCPUs
);
274 SERIALIZE_SCALAR(mem_size
);
275 SERIALIZE_SCALAR(cpuClock
);
276 SERIALIZE_SCALAR(intrClockFrequency
);
277 SERIALIZE_SCALAR(kernStart
);
278 SERIALIZE_SCALAR(kernEnd
);
279 SERIALIZE_SCALAR(entryPoint
);
280 SERIALIZE_SCALAR(diskUnit
);
281 SERIALIZE_SCALAR(diskCount
);
282 SERIALIZE_SCALAR(diskPAddr
);
283 SERIALIZE_SCALAR(diskBlock
);
284 SERIALIZE_SCALAR(diskOperation
);
285 SERIALIZE_SCALAR(outputChar
);
286 SERIALIZE_SCALAR(inputChar
);
287 SERIALIZE_ARRAY(cpuStack
,64);
291 AlphaConsole::Access::unserialize(Checkpoint
*cp
, const std::string
§ion
)
293 UNSERIALIZE_SCALAR(last_offset
);
294 UNSERIALIZE_SCALAR(version
);
295 UNSERIALIZE_SCALAR(numCPUs
);
296 UNSERIALIZE_SCALAR(mem_size
);
297 UNSERIALIZE_SCALAR(cpuClock
);
298 UNSERIALIZE_SCALAR(intrClockFrequency
);
299 UNSERIALIZE_SCALAR(kernStart
);
300 UNSERIALIZE_SCALAR(kernEnd
);
301 UNSERIALIZE_SCALAR(entryPoint
);
302 UNSERIALIZE_SCALAR(diskUnit
);
303 UNSERIALIZE_SCALAR(diskCount
);
304 UNSERIALIZE_SCALAR(diskPAddr
);
305 UNSERIALIZE_SCALAR(diskBlock
);
306 UNSERIALIZE_SCALAR(diskOperation
);
307 UNSERIALIZE_SCALAR(outputChar
);
308 UNSERIALIZE_SCALAR(inputChar
);
309 UNSERIALIZE_ARRAY(cpuStack
, 64);
313 AlphaConsole::serialize(ostream
&os
)
315 alphaAccess
->serialize(os
);
319 AlphaConsole::unserialize(Checkpoint
*cp
, const std::string
§ion
)
321 alphaAccess
->unserialize(cp
, section
);
324 BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole
)
326 SimObjectParam
<SimConsole
*> sim_console
;
327 SimObjectParam
<SimpleDisk
*> disk
;
329 SimObjectParam
<AlphaSystem
*> system
;
330 SimObjectParam
<BaseCPU
*> cpu
;
331 SimObjectParam
<Platform
*> platform
;
332 Param
<Tick
> pio_latency
;
334 END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole
)
336 BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole
)
338 INIT_PARAM(sim_console
, "The Simulator Console"),
339 INIT_PARAM(disk
, "Simple Disk"),
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_DFLT(pio_latency
, "Programmed IO latency", 1000)
346 END_INIT_SIM_OBJECT_PARAMS(AlphaConsole
)
348 CREATE_SIM_OBJECT(AlphaConsole
)
350 AlphaConsole::Params
*p
= new AlphaConsole::Params
;
351 p
->name
= getInstanceName();
352 p
->platform
= platform
;
354 p
->pio_delay
= pio_latency
;
355 p
->cons
= sim_console
;
357 p
->alpha_sys
= system
;
360 return new AlphaConsole(p
);
363 REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole
)