iob.cc (4130:a611c874376e) iob.cc (4194:af4f6022394b)
1/*
2 * Copyright (c) 2006 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 * Authors: Ali Saidi
29 */
30
31/** @file
32 * This device implemetns the niagara I/O bridge chip. It manages incomming
33 * interrupts and posts them to the CPU when needed. It holds mask registers and
34 * various status registers for CPUs to check what interrupts are pending as
35 * well as facilities to send IPIs to other cpus.
36 */
37
38#include <cstring>
39
40#include "arch/sparc/isa_traits.hh"
1/*
2 * Copyright (c) 2006 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 * Authors: Ali Saidi
29 */
30
31/** @file
32 * This device implemetns the niagara I/O bridge chip. It manages incomming
33 * interrupts and posts them to the CPU when needed. It holds mask registers and
34 * various status registers for CPUs to check what interrupts are pending as
35 * well as facilities to send IPIs to other cpus.
36 */
37
38#include <cstring>
39
40#include "arch/sparc/isa_traits.hh"
41#include "arch/sparc/faults.hh"
41#include "base/trace.hh"
42#include "cpu/intr_control.hh"
43#include "dev/sparc/iob.hh"
44#include "dev/platform.hh"
45#include "mem/port.hh"
46#include "mem/packet_access.hh"
47#include "sim/builder.hh"
42#include "base/trace.hh"
43#include "cpu/intr_control.hh"
44#include "dev/sparc/iob.hh"
45#include "dev/platform.hh"
46#include "mem/port.hh"
47#include "mem/packet_access.hh"
48#include "sim/builder.hh"
49#include "sim/faults.hh"
48#include "sim/system.hh"
49
50Iob::Iob(Params *p)
51 : PioDevice(p), ic(p->platform->intrctrl)
52{
53 iobManAddr = ULL(0x9800000000);
54 iobManSize = ULL(0x0100000000);
55 iobJBusAddr = ULL(0x9F00000000);
56 iobJBusSize = ULL(0x0100000000);
57 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
58 // Get the interrupt controller from the platform
59 ic = platform->intrctrl;
60
61 for (int x = 0; x < NumDeviceIds; ++x) {
62 intMan[x].cpu = 0;
63 intMan[x].vector = 0;
64 intCtl[x].mask = true;
65 intCtl[x].pend = false;
66 }
67
68}
69
70Tick
71Iob::read(PacketPtr pkt)
72{
73 assert(pkt->result == Packet::Unknown);
74
75 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
76 readIob(pkt);
77 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
78 readJBus(pkt);
79 else
80 panic("Invalid address reached Iob\n");
81
82 pkt->result = Packet::Success;
83 return pioDelay;
84}
85
86void
87Iob::readIob(PacketPtr pkt)
88{
89 Addr accessAddr = pkt->getAddr() - iobManAddr;
90 int index;
91 uint64_t data;
92
93 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
94 index = (accessAddr - IntManAddr) >> 3;
95 data = intMan[index].cpu << 8 | intMan[index].vector << 0;
96 pkt->set(data);
97 return;
98 }
99
100 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
101 index = (accessAddr - IntManAddr) >> 3;
102 data = intCtl[index].mask ? 1 << 2 : 0 |
103 intCtl[index].pend ? 1 << 0 : 0;
104 pkt->set(data);
105 return;
106 }
107
108 if (accessAddr == JIntVecAddr) {
109 pkt->set(jIntVec);
110 return;
111 }
112
113 panic("Read to unknown IOB offset 0x%x\n", accessAddr);
114}
115
116void
117Iob::readJBus(PacketPtr pkt)
118{
119 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
120 int cpuid = pkt->req->getCpuNum();
121 int index;
122 uint64_t data;
123
124
125
126
127 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
128 index = (accessAddr - JIntData0Addr) >> 3;
129 pkt->set(jBusData0[index]);
130 return;
131 }
132
133 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
134 index = (accessAddr - JIntData1Addr) >> 3;
135 pkt->set(jBusData1[index]);
136 return;
137 }
138
139 if (accessAddr == JIntDataA0Addr) {
140 pkt->set(jBusData0[cpuid]);
141 return;
142 }
143
144 if (accessAddr == JIntDataA1Addr) {
145 pkt->set(jBusData1[cpuid]);
146 return;
147 }
148
149 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
150 index = (accessAddr - JIntBusyAddr) >> 3;
151 data = jIntBusy[index].busy ? 1 << 5 : 0 |
152 jIntBusy[index].source;
153 pkt->set(data);
154 return;
155 }
156 if (accessAddr == JIntABusyAddr) {
157 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
158 jIntBusy[cpuid].source;
159 pkt->set(data);
160 return;
161 };
162
163 panic("Read to unknown JBus offset 0x%x\n", accessAddr);
164}
165
166Tick
167Iob::write(PacketPtr pkt)
168{
169 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
170 writeIob(pkt);
171 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
172 writeJBus(pkt);
173 else
174 panic("Invalid address reached Iob\n");
175
176
177 pkt->result = Packet::Success;
178 return pioDelay;
179}
180
181void
182Iob::writeIob(PacketPtr pkt)
183{
184 Addr accessAddr = pkt->getAddr() - iobManAddr;
185 int index;
186 uint64_t data;
187
188 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
189 index = (accessAddr - IntManAddr) >> 3;
190 data = pkt->get<uint64_t>();
191 intMan[index].cpu = bits(data,12,8);
192 intMan[index].vector = bits(data,5,0);
193 return;
194 }
195
196 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
197 index = (accessAddr - IntManAddr) >> 3;
198 data = pkt->get<uint64_t>();
199 intCtl[index].mask = bits(data,2,2);
200 if (bits(data,1,1))
201 intCtl[index].pend = false;
202 return;
203 }
204
205 if (accessAddr == JIntVecAddr) {
206 jIntVec = bits(pkt->get<uint64_t>(), 5,0);
207 return;
208 }
209
210 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
211 Type type;
212 int cpu_id;
213 int vector;
214 index = (accessAddr - IntManAddr) >> 3;
215 data = pkt->get<uint64_t>();
216 type = (Type)bits(data,17,16);
217 cpu_id = bits(data, 12,8);
218 vector = bits(data,5,0);
219 generateIpi(type,cpu_id, vector);
220 return;
221 }
222
223 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
224}
225
226void
227Iob::writeJBus(PacketPtr pkt)
228{
229 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
230 int cpuid = pkt->req->getCpuNum();
231 int index;
232 uint64_t data;
233
234 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
235 index = (accessAddr - JIntBusyAddr) >> 3;
236 data = pkt->get<uint64_t>();
237 jIntBusy[index].busy = bits(data,5,5);
238 return;
239 }
240 if (accessAddr == JIntABusyAddr) {
241 data = pkt->get<uint64_t>();
242 jIntBusy[cpuid].busy = bits(data,5,5);
243 return;
244 };
245
246 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
247}
248
249void
250Iob::receiveDeviceInterrupt(DeviceId devid)
251{
252 assert(devid < NumDeviceIds);
253 if (intCtl[devid].mask)
254 return;
255 intCtl[devid].mask = true;
256 intCtl[devid].pend = true;
257 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
258}
259
260
261void
262Iob::generateIpi(Type type, int cpu_id, int vector)
263{
50#include "sim/system.hh"
51
52Iob::Iob(Params *p)
53 : PioDevice(p), ic(p->platform->intrctrl)
54{
55 iobManAddr = ULL(0x9800000000);
56 iobManSize = ULL(0x0100000000);
57 iobJBusAddr = ULL(0x9F00000000);
58 iobJBusSize = ULL(0x0100000000);
59 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
60 // Get the interrupt controller from the platform
61 ic = platform->intrctrl;
62
63 for (int x = 0; x < NumDeviceIds; ++x) {
64 intMan[x].cpu = 0;
65 intMan[x].vector = 0;
66 intCtl[x].mask = true;
67 intCtl[x].pend = false;
68 }
69
70}
71
72Tick
73Iob::read(PacketPtr pkt)
74{
75 assert(pkt->result == Packet::Unknown);
76
77 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
78 readIob(pkt);
79 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
80 readJBus(pkt);
81 else
82 panic("Invalid address reached Iob\n");
83
84 pkt->result = Packet::Success;
85 return pioDelay;
86}
87
88void
89Iob::readIob(PacketPtr pkt)
90{
91 Addr accessAddr = pkt->getAddr() - iobManAddr;
92 int index;
93 uint64_t data;
94
95 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
96 index = (accessAddr - IntManAddr) >> 3;
97 data = intMan[index].cpu << 8 | intMan[index].vector << 0;
98 pkt->set(data);
99 return;
100 }
101
102 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
103 index = (accessAddr - IntManAddr) >> 3;
104 data = intCtl[index].mask ? 1 << 2 : 0 |
105 intCtl[index].pend ? 1 << 0 : 0;
106 pkt->set(data);
107 return;
108 }
109
110 if (accessAddr == JIntVecAddr) {
111 pkt->set(jIntVec);
112 return;
113 }
114
115 panic("Read to unknown IOB offset 0x%x\n", accessAddr);
116}
117
118void
119Iob::readJBus(PacketPtr pkt)
120{
121 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
122 int cpuid = pkt->req->getCpuNum();
123 int index;
124 uint64_t data;
125
126
127
128
129 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
130 index = (accessAddr - JIntData0Addr) >> 3;
131 pkt->set(jBusData0[index]);
132 return;
133 }
134
135 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
136 index = (accessAddr - JIntData1Addr) >> 3;
137 pkt->set(jBusData1[index]);
138 return;
139 }
140
141 if (accessAddr == JIntDataA0Addr) {
142 pkt->set(jBusData0[cpuid]);
143 return;
144 }
145
146 if (accessAddr == JIntDataA1Addr) {
147 pkt->set(jBusData1[cpuid]);
148 return;
149 }
150
151 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
152 index = (accessAddr - JIntBusyAddr) >> 3;
153 data = jIntBusy[index].busy ? 1 << 5 : 0 |
154 jIntBusy[index].source;
155 pkt->set(data);
156 return;
157 }
158 if (accessAddr == JIntABusyAddr) {
159 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
160 jIntBusy[cpuid].source;
161 pkt->set(data);
162 return;
163 };
164
165 panic("Read to unknown JBus offset 0x%x\n", accessAddr);
166}
167
168Tick
169Iob::write(PacketPtr pkt)
170{
171 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
172 writeIob(pkt);
173 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
174 writeJBus(pkt);
175 else
176 panic("Invalid address reached Iob\n");
177
178
179 pkt->result = Packet::Success;
180 return pioDelay;
181}
182
183void
184Iob::writeIob(PacketPtr pkt)
185{
186 Addr accessAddr = pkt->getAddr() - iobManAddr;
187 int index;
188 uint64_t data;
189
190 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
191 index = (accessAddr - IntManAddr) >> 3;
192 data = pkt->get<uint64_t>();
193 intMan[index].cpu = bits(data,12,8);
194 intMan[index].vector = bits(data,5,0);
195 return;
196 }
197
198 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
199 index = (accessAddr - IntManAddr) >> 3;
200 data = pkt->get<uint64_t>();
201 intCtl[index].mask = bits(data,2,2);
202 if (bits(data,1,1))
203 intCtl[index].pend = false;
204 return;
205 }
206
207 if (accessAddr == JIntVecAddr) {
208 jIntVec = bits(pkt->get<uint64_t>(), 5,0);
209 return;
210 }
211
212 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
213 Type type;
214 int cpu_id;
215 int vector;
216 index = (accessAddr - IntManAddr) >> 3;
217 data = pkt->get<uint64_t>();
218 type = (Type)bits(data,17,16);
219 cpu_id = bits(data, 12,8);
220 vector = bits(data,5,0);
221 generateIpi(type,cpu_id, vector);
222 return;
223 }
224
225 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
226}
227
228void
229Iob::writeJBus(PacketPtr pkt)
230{
231 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
232 int cpuid = pkt->req->getCpuNum();
233 int index;
234 uint64_t data;
235
236 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
237 index = (accessAddr - JIntBusyAddr) >> 3;
238 data = pkt->get<uint64_t>();
239 jIntBusy[index].busy = bits(data,5,5);
240 return;
241 }
242 if (accessAddr == JIntABusyAddr) {
243 data = pkt->get<uint64_t>();
244 jIntBusy[cpuid].busy = bits(data,5,5);
245 return;
246 };
247
248 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
249}
250
251void
252Iob::receiveDeviceInterrupt(DeviceId devid)
253{
254 assert(devid < NumDeviceIds);
255 if (intCtl[devid].mask)
256 return;
257 intCtl[devid].mask = true;
258 intCtl[devid].pend = true;
259 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
260}
261
262
263void
264Iob::generateIpi(Type type, int cpu_id, int vector)
265{
264 // Only handle interrupts for the moment... Cpu Idle/reset/resume will be
265 // later
266 if (type != 0)
266 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
267 if (cpu_id >= sys->getNumCPUs())
267 return;
268
268 return;
269
269 assert(type == 0);
270 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
270 switch (type) {
271 case 0: // interrupt
272 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
273 break;
274 case 1: // reset
275 warn("Sending reset to CPU: %d\n", cpu_id);
276 if (vector != por->trapType())
277 panic("Don't know how to set non-POR reset to cpu\n");
278 por->invoke(sys->threadContexts[cpu_id]);
279 sys->threadContexts[cpu_id]->activate();
280 break;
281 case 2: // idle -- this means stop executing and don't wake on interrupts
282 sys->threadContexts[cpu_id]->halt();
283 break;
284 case 3: // resume
285 sys->threadContexts[cpu_id]->activate();
286 break;
287 default:
288 panic("Invalid type to generate ipi\n");
289 }
271}
272
273bool
274Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
275{
276 // If we are already dealing with an interrupt for that cpu we can't deal
277 // with another one right now... come back later
278 if (jIntBusy[cpu_id].busy)
279 return false;
280
281 jIntBusy[cpu_id].busy = true;
282 jIntBusy[cpu_id].source = source;
283 jBusData0[cpu_id] = d0;
284 jBusData1[cpu_id] = d1;
285
286 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
287 return true;
288}
289
290void
291Iob::addressRanges(AddrRangeList &range_list)
292{
293 range_list.clear();
294 range_list.push_back(RangeSize(iobManAddr, iobManSize));
295 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
296}
297
298
299void
300Iob::serialize(std::ostream &os)
301{
302
303 SERIALIZE_SCALAR(jIntVec);
304 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
305 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
306 for (int x = 0; x < NumDeviceIds; x++) {
307 nameOut(os, csprintf("%s.Int%d", name(), x));
308 paramOut(os, "cpu", intMan[x].cpu);
309 paramOut(os, "vector", intMan[x].vector);
310 paramOut(os, "mask", intCtl[x].mask);
311 paramOut(os, "pend", intCtl[x].pend);
312 };
313 for (int x = 0; x < MaxNiagaraProcs; x++) {
314 nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
315 paramOut(os, "busy", jIntBusy[x].busy);
316 paramOut(os, "source", jIntBusy[x].source);
317 };
318}
319
320void
321Iob::unserialize(Checkpoint *cp, const std::string &section)
322{
323 UNSERIALIZE_SCALAR(jIntVec);
324 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
325 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
326 for (int x = 0; x < NumDeviceIds; x++) {
327 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
328 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
329 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
330 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
331 };
332 for (int x = 0; x < MaxNiagaraProcs; x++) {
333 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
334 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
335 };
336}
337
338
339
340
341BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob)
342 Param<Tick> pio_latency;
343 SimObjectParam<Platform *> platform;
344 SimObjectParam<System *> system;
345END_DECLARE_SIM_OBJECT_PARAMS(Iob)
346
347BEGIN_INIT_SIM_OBJECT_PARAMS(Iob)
348
349 INIT_PARAM(pio_latency, "Programmed IO latency"),
350 INIT_PARAM(platform, "platform"),
351 INIT_PARAM(system, "system object")
352
353END_INIT_SIM_OBJECT_PARAMS(Iob)
354
355CREATE_SIM_OBJECT(Iob)
356{
357 Iob::Params *p = new Iob::Params;
358 p->name = getInstanceName();
359 p->pio_delay = pio_latency;
360 p->platform = platform;
361 p->system = system;
362 return new Iob(p);
363}
364
365REGISTER_SIM_OBJECT("Iob", Iob)
290}
291
292bool
293Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
294{
295 // If we are already dealing with an interrupt for that cpu we can't deal
296 // with another one right now... come back later
297 if (jIntBusy[cpu_id].busy)
298 return false;
299
300 jIntBusy[cpu_id].busy = true;
301 jIntBusy[cpu_id].source = source;
302 jBusData0[cpu_id] = d0;
303 jBusData1[cpu_id] = d1;
304
305 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
306 return true;
307}
308
309void
310Iob::addressRanges(AddrRangeList &range_list)
311{
312 range_list.clear();
313 range_list.push_back(RangeSize(iobManAddr, iobManSize));
314 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
315}
316
317
318void
319Iob::serialize(std::ostream &os)
320{
321
322 SERIALIZE_SCALAR(jIntVec);
323 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
324 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
325 for (int x = 0; x < NumDeviceIds; x++) {
326 nameOut(os, csprintf("%s.Int%d", name(), x));
327 paramOut(os, "cpu", intMan[x].cpu);
328 paramOut(os, "vector", intMan[x].vector);
329 paramOut(os, "mask", intCtl[x].mask);
330 paramOut(os, "pend", intCtl[x].pend);
331 };
332 for (int x = 0; x < MaxNiagaraProcs; x++) {
333 nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
334 paramOut(os, "busy", jIntBusy[x].busy);
335 paramOut(os, "source", jIntBusy[x].source);
336 };
337}
338
339void
340Iob::unserialize(Checkpoint *cp, const std::string &section)
341{
342 UNSERIALIZE_SCALAR(jIntVec);
343 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
344 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
345 for (int x = 0; x < NumDeviceIds; x++) {
346 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
347 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
348 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
349 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
350 };
351 for (int x = 0; x < MaxNiagaraProcs; x++) {
352 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
353 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
354 };
355}
356
357
358
359
360BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob)
361 Param<Tick> pio_latency;
362 SimObjectParam<Platform *> platform;
363 SimObjectParam<System *> system;
364END_DECLARE_SIM_OBJECT_PARAMS(Iob)
365
366BEGIN_INIT_SIM_OBJECT_PARAMS(Iob)
367
368 INIT_PARAM(pio_latency, "Programmed IO latency"),
369 INIT_PARAM(platform, "platform"),
370 INIT_PARAM(system, "system object")
371
372END_INIT_SIM_OBJECT_PARAMS(Iob)
373
374CREATE_SIM_OBJECT(Iob)
375{
376 Iob::Params *p = new Iob::Params;
377 p->name = getInstanceName();
378 p->pio_delay = pio_latency;
379 p->platform = platform;
380 p->system = system;
381 return new Iob(p);
382}
383
384REGISTER_SIM_OBJECT("Iob", Iob)