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.
28 * Authors: Nathan Binkert
35 * Alpha Console Definition
41 #include "arch/alpha/system.hh"
42 #include "base/inifile.hh"
43 #include "base/str.hh"
44 #include "base/trace.hh"
45 #include "cpu/base.hh"
46 #include "cpu/thread_context.hh"
47 #include "dev/alpha_console.hh"
48 #include "dev/platform.hh"
49 #include "dev/simconsole.hh"
50 #include "dev/simple_disk.hh"
51 #include "mem/physical.hh"
52 #include "sim/builder.hh"
53 #include "sim/sim_object.hh"
56 using namespace AlphaISA
;
58 AlphaConsole::AlphaConsole(Params
*p
)
59 : BasicPioDevice(p
), disk(p
->disk
),
60 console(params()->cons
), system(params()->alpha_sys
), cpu(params()->cpu
)
63 pioSize
= sizeof(struct AlphaAccess
);
65 alphaAccess
= new Access();
66 alphaAccess
->last_offset
= pioSize
- 1;
68 alphaAccess
->version
= ALPHA_ACCESS_VERSION
;
69 alphaAccess
->diskUnit
= 1;
71 alphaAccess
->diskCount
= 0;
72 alphaAccess
->diskPAddr
= 0;
73 alphaAccess
->diskBlock
= 0;
74 alphaAccess
->diskOperation
= 0;
75 alphaAccess
->outputChar
= 0;
76 alphaAccess
->inputChar
= 0;
77 bzero(alphaAccess
->cpuStack
, sizeof(alphaAccess
->cpuStack
));
82 AlphaConsole::startup()
84 system
->setAlphaAccess(pioAddr
);
85 alphaAccess
->numCPUs
= system
->getNumCPUs();
86 alphaAccess
->kernStart
= system
->getKernelStart();
87 alphaAccess
->kernEnd
= system
->getKernelEnd();
88 alphaAccess
->entryPoint
= system
->getKernelEntry();
89 alphaAccess
->mem_size
= system
->physmem
->size();
90 alphaAccess
->cpuClock
= cpu
->frequency() / 1000000; // In MHz
91 alphaAccess
->intrClockFrequency
= params()->platform
->intrFrequency();
95 AlphaConsole::read(Packet
*pkt
)
98 /** XXX Do we want to push the addr munging to a bus brige or something? So
99 * the device has it's physical address and then the bridge adds on whatever
100 * machine dependent address swizzle is required?
103 assert(pkt
->result
== Packet::Unknown
);
104 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
106 Addr daddr
= pkt
->getAddr() - pioAddr
;
110 switch (pkt
->getSize())
112 case sizeof(uint32_t):
115 case offsetof(AlphaAccess
, last_offset
):
116 pkt
->set(alphaAccess
->last_offset
);
118 case offsetof(AlphaAccess
, version
):
119 pkt
->set(alphaAccess
->version
);
121 case offsetof(AlphaAccess
, numCPUs
):
122 pkt
->set(alphaAccess
->numCPUs
);
124 case offsetof(AlphaAccess
, intrClockFrequency
):
125 pkt
->set(alphaAccess
->intrClockFrequency
);
128 /* Old console code read in everyting as a 32bit int
129 * we now break that for better error checking.
131 pkt
->result
= Packet::BadAddress
;
133 DPRINTF(AlphaConsole
, "read: offset=%#x val=%#x\n", daddr
,
134 pkt
->get
<uint32_t>());
136 case sizeof(uint64_t):
139 case offsetof(AlphaAccess
, inputChar
):
140 pkt
->set(console
->console_in());
142 case offsetof(AlphaAccess
, cpuClock
):
143 pkt
->set(alphaAccess
->cpuClock
);
145 case offsetof(AlphaAccess
, mem_size
):
146 pkt
->set(alphaAccess
->mem_size
);
148 case offsetof(AlphaAccess
, kernStart
):
149 pkt
->set(alphaAccess
->kernStart
);
151 case offsetof(AlphaAccess
, kernEnd
):
152 pkt
->set(alphaAccess
->kernEnd
);
154 case offsetof(AlphaAccess
, entryPoint
):
155 pkt
->set(alphaAccess
->entryPoint
);
157 case offsetof(AlphaAccess
, diskUnit
):
158 pkt
->set(alphaAccess
->diskUnit
);
160 case offsetof(AlphaAccess
, diskCount
):
161 pkt
->set(alphaAccess
->diskCount
);
163 case offsetof(AlphaAccess
, diskPAddr
):
164 pkt
->set(alphaAccess
->diskPAddr
);
166 case offsetof(AlphaAccess
, diskBlock
):
167 pkt
->set(alphaAccess
->diskBlock
);
169 case offsetof(AlphaAccess
, diskOperation
):
170 pkt
->set(alphaAccess
->diskOperation
);
172 case offsetof(AlphaAccess
, outputChar
):
173 pkt
->set(alphaAccess
->outputChar
);
176 int cpunum
= (daddr
- offsetof(AlphaAccess
, cpuStack
)) /
177 sizeof(alphaAccess
->cpuStack
[0]);
179 if (cpunum
>= 0 && cpunum
< 64)
180 pkt
->set(alphaAccess
->cpuStack
[cpunum
]);
182 panic("Unknown 64bit access, %#x\n", daddr
);
184 DPRINTF(AlphaConsole
, "read: offset=%#x val=%#x\n", daddr
,
185 pkt
->get
<uint64_t>());
188 pkt
->result
= Packet::BadAddress
;
190 if (pkt
->result
== Packet::Unknown
)
191 pkt
->result
= Packet::Success
;
196 AlphaConsole::write(Packet
*pkt
)
198 assert(pkt
->result
== Packet::Unknown
);
199 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
200 Addr daddr
= pkt
->getAddr() - pioAddr
;
202 uint64_t val
= pkt
->get
<uint64_t>();
203 assert(pkt
->getSize() == sizeof(uint64_t));
206 case offsetof(AlphaAccess
, diskUnit
):
207 alphaAccess
->diskUnit
= val
;
210 case offsetof(AlphaAccess
, diskCount
):
211 alphaAccess
->diskCount
= val
;
214 case offsetof(AlphaAccess
, diskPAddr
):
215 alphaAccess
->diskPAddr
= val
;
218 case offsetof(AlphaAccess
, diskBlock
):
219 alphaAccess
->diskBlock
= val
;
222 case offsetof(AlphaAccess
, diskOperation
):
224 disk
->read(alphaAccess
->diskPAddr
, alphaAccess
->diskBlock
,
225 alphaAccess
->diskCount
);
227 panic("Invalid disk operation!");
231 case offsetof(AlphaAccess
, outputChar
):
232 console
->out((char)(val
& 0xff));
236 int cpunum
= (daddr
- offsetof(AlphaAccess
, cpuStack
)) /
237 sizeof(alphaAccess
->cpuStack
[0]);
238 warn("%d: Trying to launch CPU number %d!", curTick
, cpunum
);
239 assert(val
> 0 && "Must not access primary cpu");
240 if (cpunum
>= 0 && cpunum
< 64)
241 alphaAccess
->cpuStack
[cpunum
] = val
;
243 panic("Unknown 64bit access, %#x\n", daddr
);
246 pkt
->result
= Packet::Success
;
252 AlphaConsole::Access::serialize(ostream
&os
)
254 SERIALIZE_SCALAR(last_offset
);
255 SERIALIZE_SCALAR(version
);
256 SERIALIZE_SCALAR(numCPUs
);
257 SERIALIZE_SCALAR(mem_size
);
258 SERIALIZE_SCALAR(cpuClock
);
259 SERIALIZE_SCALAR(intrClockFrequency
);
260 SERIALIZE_SCALAR(kernStart
);
261 SERIALIZE_SCALAR(kernEnd
);
262 SERIALIZE_SCALAR(entryPoint
);
263 SERIALIZE_SCALAR(diskUnit
);
264 SERIALIZE_SCALAR(diskCount
);
265 SERIALIZE_SCALAR(diskPAddr
);
266 SERIALIZE_SCALAR(diskBlock
);
267 SERIALIZE_SCALAR(diskOperation
);
268 SERIALIZE_SCALAR(outputChar
);
269 SERIALIZE_SCALAR(inputChar
);
270 SERIALIZE_ARRAY(cpuStack
,64);
274 AlphaConsole::Access::unserialize(Checkpoint
*cp
, const std::string
§ion
)
276 UNSERIALIZE_SCALAR(last_offset
);
277 UNSERIALIZE_SCALAR(version
);
278 UNSERIALIZE_SCALAR(numCPUs
);
279 UNSERIALIZE_SCALAR(mem_size
);
280 UNSERIALIZE_SCALAR(cpuClock
);
281 UNSERIALIZE_SCALAR(intrClockFrequency
);
282 UNSERIALIZE_SCALAR(kernStart
);
283 UNSERIALIZE_SCALAR(kernEnd
);
284 UNSERIALIZE_SCALAR(entryPoint
);
285 UNSERIALIZE_SCALAR(diskUnit
);
286 UNSERIALIZE_SCALAR(diskCount
);
287 UNSERIALIZE_SCALAR(diskPAddr
);
288 UNSERIALIZE_SCALAR(diskBlock
);
289 UNSERIALIZE_SCALAR(diskOperation
);
290 UNSERIALIZE_SCALAR(outputChar
);
291 UNSERIALIZE_SCALAR(inputChar
);
292 UNSERIALIZE_ARRAY(cpuStack
, 64);
296 AlphaConsole::serialize(ostream
&os
)
298 alphaAccess
->serialize(os
);
302 AlphaConsole::unserialize(Checkpoint
*cp
, const std::string
§ion
)
304 alphaAccess
->unserialize(cp
, section
);
307 BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole
)
309 SimObjectParam
<SimConsole
*> sim_console
;
310 SimObjectParam
<SimpleDisk
*> disk
;
311 Param
<Addr
> pio_addr
;
312 SimObjectParam
<AlphaSystem
*> system
;
313 SimObjectParam
<BaseCPU
*> cpu
;
314 SimObjectParam
<Platform
*> platform
;
315 Param
<Tick
> pio_latency
;
317 END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole
)
319 BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole
)
321 INIT_PARAM(sim_console
, "The Simulator Console"),
322 INIT_PARAM(disk
, "Simple Disk"),
323 INIT_PARAM(pio_addr
, "Device Address"),
324 INIT_PARAM(system
, "system object"),
325 INIT_PARAM(cpu
, "Processor"),
326 INIT_PARAM(platform
, "platform"),
327 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000)
329 END_INIT_SIM_OBJECT_PARAMS(AlphaConsole
)
331 CREATE_SIM_OBJECT(AlphaConsole
)
333 AlphaConsole::Params
*p
= new AlphaConsole::Params
;
334 p
->name
= getInstanceName();
335 p
->platform
= platform
;
336 p
->pio_addr
= pio_addr
;
337 p
->pio_delay
= pio_latency
;
338 p
->cons
= sim_console
;
340 p
->alpha_sys
= system
;
343 return new AlphaConsole(p
);
346 REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole
)