tsunami_io.cc revision 1854
1/* 2 * Copyright (c) 2004-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 * Tsunami I/O including PIC, PIT, RTC, DMA 31 */ 32 33#include <sys/time.h> 34 35#include <deque> 36#include <string> 37#include <vector> 38 39#include "base/trace.hh" 40#include "dev/tsunami_io.hh" 41#include "dev/tsunami.hh" 42#include "dev/pitreg.h" 43#include "mem/bus/bus.hh" 44#include "mem/bus/pio_interface.hh" 45#include "mem/bus/pio_interface_impl.hh" 46#include "sim/builder.hh" 47#include "dev/tsunami_cchip.hh" 48#include "dev/tsunamireg.h" 49#include "dev/rtcreg.h" 50#include "mem/functional/memory_control.hh" 51 52using namespace std; 53 54TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i) 55 : _name(name), event(t, i), addr(0) 56{ 57 memset(clock_data, 0, sizeof(clock_data)); 58 stat_regA = RTCA_32768HZ | RTCA_1024HZ; 59 stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 60} 61 62void 63TsunamiIO::RTC::set_time(time_t t) 64{ 65 struct tm tm; 66 gmtime_r(&t, &tm); 67 68 sec = tm.tm_sec; 69 min = tm.tm_min; 70 hour = tm.tm_hour; 71 wday = tm.tm_wday + 1; 72 mday = tm.tm_mday; 73 mon = tm.tm_mon + 1; 74 year = tm.tm_year; 75 76 DPRINTFN("Real-time clock set to %s", asctime(&tm)); 77} 78 79void 80TsunamiIO::RTC::writeAddr(const uint8_t *data) 81{ 82 if (*data <= RTC_STAT_REGD) 83 addr = *data; 84 else 85 panic("RTC addresses over 0xD are not implemented.\n"); 86} 87 88void 89TsunamiIO::RTC::writeData(const uint8_t *data) 90{ 91 if (addr < RTC_STAT_REGA) 92 clock_data[addr] = *data; 93 else { 94 switch (addr) { 95 case RTC_STAT_REGA: 96 if (*data != (RTCA_32768HZ | RTCA_1024HZ)) 97 panic("Unimplemented RTC register A value write!\n"); 98 stat_regA = *data; 99 break; 100 case RTC_STAT_REGB: 101 if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 102 panic("Write to RTC reg B bits that are not implemented!\n"); 103 104 if (*data & RTCB_PRDC_IE) { 105 if (!event.scheduled()) 106 event.scheduleIntr(); 107 } else { 108 if (event.scheduled()) 109 event.deschedule(); 110 } 111 stat_regB = *data; 112 break; 113 case RTC_STAT_REGC: 114 case RTC_STAT_REGD: 115 panic("RTC status registers C and D are not implemented.\n"); 116 break; 117 } 118 } 119} 120 121void 122TsunamiIO::RTC::readData(uint8_t *data) 123{ 124 if (addr < RTC_STAT_REGA) 125 *data = clock_data[addr]; 126 else { 127 switch (addr) { 128 case RTC_STAT_REGA: 129 // toggle UIP bit for linux 130 stat_regA ^= RTCA_UIP; 131 *data = stat_regA; 132 break; 133 case RTC_STAT_REGB: 134 *data = stat_regB; 135 break; 136 case RTC_STAT_REGC: 137 case RTC_STAT_REGD: 138 *data = 0x00; 139 break; 140 } 141 } 142} 143 144void 145TsunamiIO::RTC::serialize(const string &base, ostream &os) 146{ 147 paramOut(os, base + ".addr", addr); 148 arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 149 paramOut(os, base + ".stat_regA", stat_regA); 150 paramOut(os, base + ".stat_regB", stat_regB); 151} 152 153void 154TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 155 const string §ion) 156{ 157 paramIn(cp, section, base + ".addr", addr); 158 arrayParamIn(cp, section, base + ".clock_data", clock_data, 159 sizeof(clock_data)); 160 paramIn(cp, section, base + ".stat_regA", stat_regA); 161 paramIn(cp, section, base + ".stat_regB", stat_regB); 162 163 // We're not unserializing the event here, but we need to 164 // rescehedule the event since curTick was moved forward by the 165 // checkpoint 166 event.reschedule(curTick + event.interval); 167} 168 169TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 170 : Event(&mainEventQueue), tsunami(t), interval(i) 171{ 172 DPRINTF(MC146818, "RTC Event Initilizing\n"); 173 schedule(curTick + interval); 174} 175 176void 177TsunamiIO::RTC::RTCEvent::scheduleIntr() 178{ 179 schedule(curTick + interval); 180} 181 182void 183TsunamiIO::RTC::RTCEvent::process() 184{ 185 DPRINTF(MC146818, "RTC Timer Interrupt\n"); 186 schedule(curTick + interval); 187 //Actually interrupt the processor here 188 tsunami->cchip->postRTC(); 189} 190 191const char * 192TsunamiIO::RTC::RTCEvent::description() 193{ 194 return "tsunami RTC interrupt"; 195} 196 197TsunamiIO::PITimer::PITimer(const string &name) 198 : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 199 counter2(name + ".counter2") 200{ 201 counter[0] = &counter0; 202 counter[1] = &counter0; 203 counter[2] = &counter0; 204} 205 206void 207TsunamiIO::PITimer::writeControl(const uint8_t *data) 208{ 209 int rw; 210 int sel; 211 212 sel = GET_CTRL_SEL(*data); 213 214 if (sel == PIT_READ_BACK) 215 panic("PITimer Read-Back Command is not implemented.\n"); 216 217 rw = GET_CTRL_RW(*data); 218 219 if (rw == PIT_RW_LATCH_COMMAND) 220 counter[sel]->latchCount(); 221 else { 222 counter[sel]->setRW(rw); 223 counter[sel]->setMode(GET_CTRL_MODE(*data)); 224 counter[sel]->setBCD(GET_CTRL_BCD(*data)); 225 } 226} 227 228void 229TsunamiIO::PITimer::serialize(const string &base, ostream &os) 230{ 231 // serialize the counters 232 counter0.serialize(base + ".counter0", os); 233 counter1.serialize(base + ".counter1", os); 234 counter2.serialize(base + ".counter2", os); 235} 236 237void 238TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 239 const string §ion) 240{ 241 // unserialze the counters 242 counter0.unserialize(base + ".counter0", cp, section); 243 counter1.unserialize(base + ".counter1", cp, section); 244 counter2.unserialize(base + ".counter2", cp, section); 245} 246 247TsunamiIO::PITimer::Counter::Counter(const string &name) 248 : _name(name), event(this), count(0), latched_count(0), period(0), 249 mode(0), output_high(false), latch_on(false), read_byte(LSB), 250 write_byte(LSB) 251{ 252 253} 254 255void 256TsunamiIO::PITimer::Counter::latchCount() 257{ 258 // behave like a real latch 259 if(!latch_on) { 260 latch_on = true; 261 read_byte = LSB; 262 latched_count = count; 263 } 264} 265 266void 267TsunamiIO::PITimer::Counter::read(uint8_t *data) 268{ 269 if (latch_on) { 270 switch (read_byte) { 271 case LSB: 272 read_byte = MSB; 273 *data = (uint8_t)latched_count; 274 break; 275 case MSB: 276 read_byte = LSB; 277 latch_on = false; 278 *data = latched_count >> 8; 279 break; 280 } 281 } else { 282 switch (read_byte) { 283 case LSB: 284 read_byte = MSB; 285 *data = (uint8_t)count; 286 break; 287 case MSB: 288 read_byte = LSB; 289 *data = count >> 8; 290 break; 291 } 292 } 293} 294 295void 296TsunamiIO::PITimer::Counter::write(const uint8_t *data) 297{ 298 switch (write_byte) { 299 case LSB: 300 count = (count & 0xFF00) | *data; 301 302 if (event.scheduled()) 303 event.deschedule(); 304 output_high = false; 305 write_byte = MSB; 306 break; 307 308 case MSB: 309 count = (count & 0x00FF) | (*data << 8); 310 period = count; 311 312 if (period > 0) { 313 DPRINTF(Tsunami, "Timer set to curTick + %d\n", 314 count * event.interval); 315 event.schedule(curTick + count * event.interval); 316 } 317 write_byte = LSB; 318 break; 319 } 320} 321 322void 323TsunamiIO::PITimer::Counter::setRW(int rw_val) 324{ 325 if (rw_val != PIT_RW_16BIT) 326 panic("Only LSB/MSB read/write is implemented.\n"); 327} 328 329void 330TsunamiIO::PITimer::Counter::setMode(int mode_val) 331{ 332 if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 333 mode_val != PIT_MODE_SQWAVE) 334 panic("PIT mode %#x is not implemented: \n", mode_val); 335 336 mode = mode_val; 337} 338 339void 340TsunamiIO::PITimer::Counter::setBCD(int bcd_val) 341{ 342 if (bcd_val != PIT_BCD_FALSE) 343 panic("PITimer does not implement BCD counts.\n"); 344} 345 346bool 347TsunamiIO::PITimer::Counter::outputHigh() 348{ 349 return output_high; 350} 351 352void 353TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 354{ 355 paramOut(os, base + ".count", count); 356 paramOut(os, base + ".latched_count", latched_count); 357 paramOut(os, base + ".period", period); 358 paramOut(os, base + ".mode", mode); 359 paramOut(os, base + ".output_high", output_high); 360 paramOut(os, base + ".latch_on", latch_on); 361 paramOut(os, base + ".read_byte", read_byte); 362 paramOut(os, base + ".write_byte", write_byte); 363 364 Tick event_tick = 0; 365 if (event.scheduled()) 366 event_tick = event.when(); 367 paramOut(os, base + ".event_tick", event_tick); 368} 369 370void 371TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 372 const string §ion) 373{ 374 paramIn(cp, section, base + ".count", count); 375 paramIn(cp, section, base + ".latched_count", latched_count); 376 paramIn(cp, section, base + ".period", period); 377 paramIn(cp, section, base + ".mode", mode); 378 paramIn(cp, section, base + ".output_high", output_high); 379 paramIn(cp, section, base + ".latch_on", latch_on); 380 paramIn(cp, section, base + ".read_byte", read_byte); 381 paramIn(cp, section, base + ".write_byte", write_byte); 382 383 Tick event_tick; 384 paramIn(cp, section, base + ".event_tick", event_tick); 385 if (event_tick) 386 event.schedule(event_tick); 387} 388 389TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 390 : Event(&mainEventQueue) 391{ 392 interval = (Tick)(Clock::Float::s / 1193180.0); 393 counter = c_ptr; 394} 395 396void 397TsunamiIO::PITimer::Counter::CounterEvent::process() 398{ 399 DPRINTF(Tsunami, "Timer Interrupt\n"); 400 switch (counter->mode) { 401 case PIT_MODE_INTTC: 402 counter->output_high = true; 403 case PIT_MODE_RATEGEN: 404 case PIT_MODE_SQWAVE: 405 break; 406 default: 407 panic("Unimplemented PITimer mode.\n"); 408 } 409} 410 411const char * 412TsunamiIO::PITimer::Counter::CounterEvent::description() 413{ 414 return "tsunami 8254 Interval timer"; 415} 416 417TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, 418 Addr a, MemoryController *mmu, HierParams *hier, Bus *bus, 419 Tick pio_latency, Tick ci) 420 : PioDevice(name, t), addr(a), clockInterval(ci), tsunami(t), 421 pitimer(name + "pitimer"), rtc(name + ".rtc", t, ci) 422{ 423 mmu->add_child(this, RangeSize(addr, size)); 424 425 if (bus) { 426 pioInterface = newPioInterface(name + ".pio", hier, bus, this, 427 &TsunamiIO::cacheAccess); 428 pioInterface->addAddrRange(RangeSize(addr, size)); 429 pioLatency = pio_latency * bus->clockRate; 430 } 431 432 // set the back pointer from tsunami to myself 433 tsunami->io = this; 434 435 timerData = 0; 436 rtc.set_time(init_time == 0 ? time(NULL) : init_time); 437 picr = 0; 438 picInterrupting = false; 439} 440 441Tick 442TsunamiIO::frequency() const 443{ 444 return Clock::Frequency / clockInterval; 445} 446 447Fault 448TsunamiIO::read(MemReqPtr &req, uint8_t *data) 449{ 450 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", 451 req->vaddr, req->size, req->vaddr & 0xfff); 452 453 Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); 454 455 456 switch(req->size) { 457 case sizeof(uint8_t): 458 switch(daddr) { 459 // PIC1 mask read 460 case TSDEV_PIC1_MASK: 461 *(uint8_t*)data = ~mask1; 462 return No_Fault; 463 case TSDEV_PIC2_MASK: 464 *(uint8_t*)data = ~mask2; 465 return No_Fault; 466 case TSDEV_PIC1_ISR: 467 // !!! If this is modified 64bit case needs to be too 468 // Pal code has to do a 64 bit physical read because there is 469 // no load physical byte instruction 470 *(uint8_t*)data = picr; 471 return No_Fault; 472 case TSDEV_PIC2_ISR: 473 // PIC2 not implemnted... just return 0 474 *(uint8_t*)data = 0x00; 475 return No_Fault; 476 case TSDEV_TMR0_DATA: 477 pitimer.counter0.read(data); 478 return No_Fault; 479 case TSDEV_TMR1_DATA: 480 pitimer.counter1.read(data); 481 return No_Fault; 482 case TSDEV_TMR2_DATA: 483 pitimer.counter2.read(data); 484 return No_Fault; 485 case TSDEV_RTC_DATA: 486 rtc.readData(data); 487 return No_Fault; 488 case TSDEV_CTRL_PORTB: 489 if (pitimer.counter2.outputHigh()) 490 *data = PORTB_SPKR_HIGH; 491 else 492 *data = 0x00; 493 return No_Fault; 494 default: 495 panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); 496 } 497 case sizeof(uint16_t): 498 case sizeof(uint32_t): 499 panic("I/O Read - invalid size - va %#x size %d\n", 500 req->vaddr, req->size); 501 502 case sizeof(uint64_t): 503 switch(daddr) { 504 case TSDEV_PIC1_ISR: 505 // !!! If this is modified 8bit case needs to be too 506 // Pal code has to do a 64 bit physical read because there is 507 // no load physical byte instruction 508 *(uint64_t*)data = (uint64_t)picr; 509 return No_Fault; 510 default: 511 panic("I/O Read - invalid size - va %#x size %d\n", 512 req->vaddr, req->size); 513 } 514 515 default: 516 panic("I/O Read - invalid size - va %#x size %d\n", 517 req->vaddr, req->size); 518 } 519 panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); 520 521 return No_Fault; 522} 523 524Fault 525TsunamiIO::write(MemReqPtr &req, const uint8_t *data) 526{ 527 528#if TRACING_ON 529 uint8_t dt = *(uint8_t*)data; 530 uint64_t dt64 = dt; 531#endif 532 533 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 534 req->vaddr, req->size, req->vaddr & 0xfff, dt64); 535 536 Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); 537 538 switch(req->size) { 539 case sizeof(uint8_t): 540 switch(daddr) { 541 case TSDEV_PIC1_MASK: 542 mask1 = ~(*(uint8_t*)data); 543 if ((picr & mask1) && !picInterrupting) { 544 picInterrupting = true; 545 tsunami->cchip->postDRIR(55); 546 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 547 } 548 if ((!(picr & mask1)) && picInterrupting) { 549 picInterrupting = false; 550 tsunami->cchip->clearDRIR(55); 551 DPRINTF(Tsunami, "clearing pic interrupt\n"); 552 } 553 return No_Fault; 554 case TSDEV_PIC2_MASK: 555 mask2 = *(uint8_t*)data; 556 //PIC2 Not implemented to interrupt 557 return No_Fault; 558 case TSDEV_PIC1_ACK: 559 // clear the interrupt on the PIC 560 picr &= ~(1 << (*(uint8_t*)data & 0xF)); 561 if (!(picr & mask1)) 562 tsunami->cchip->clearDRIR(55); 563 return No_Fault; 564 case TSDEV_DMA1_CMND: 565 return No_Fault; 566 case TSDEV_DMA2_CMND: 567 return No_Fault; 568 case TSDEV_DMA1_MMASK: 569 return No_Fault; 570 case TSDEV_DMA2_MMASK: 571 return No_Fault; 572 case TSDEV_PIC2_ACK: 573 return No_Fault; 574 case TSDEV_DMA1_RESET: 575 return No_Fault; 576 case TSDEV_DMA2_RESET: 577 return No_Fault; 578 case TSDEV_DMA1_MODE: 579 mode1 = *(uint8_t*)data; 580 return No_Fault; 581 case TSDEV_DMA2_MODE: 582 mode2 = *(uint8_t*)data; 583 return No_Fault; 584 case TSDEV_DMA1_MASK: 585 case TSDEV_DMA2_MASK: 586 return No_Fault; 587 case TSDEV_TMR0_DATA: 588 pitimer.counter0.write(data); 589 return No_Fault; 590 case TSDEV_TMR1_DATA: 591 pitimer.counter1.write(data); 592 return No_Fault; 593 case TSDEV_TMR2_DATA: 594 pitimer.counter2.write(data); 595 return No_Fault; 596 case TSDEV_TMR_CTRL: 597 pitimer.writeControl(data); 598 return No_Fault; 599 case TSDEV_RTC_ADDR: 600 rtc.writeAddr(data); 601 return No_Fault; 602 case TSDEV_KBD: 603 return No_Fault; 604 case TSDEV_RTC_DATA: 605 rtc.writeData(data); 606 return No_Fault; 607 case TSDEV_CTRL_PORTB: 608 // System Control Port B not implemented 609 return No_Fault; 610 default: 611 panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data); 612 } 613 case sizeof(uint16_t): 614 case sizeof(uint32_t): 615 case sizeof(uint64_t): 616 default: 617 panic("I/O Write - invalid size - va %#x size %d\n", 618 req->vaddr, req->size); 619 } 620 621 622 return No_Fault; 623} 624 625void 626TsunamiIO::postPIC(uint8_t bitvector) 627{ 628 //PIC2 Is not implemented, because nothing of interest there 629 picr |= bitvector; 630 if (picr & mask1) { 631 tsunami->cchip->postDRIR(55); 632 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 633 } 634} 635 636void 637TsunamiIO::clearPIC(uint8_t bitvector) 638{ 639 //PIC2 Is not implemented, because nothing of interest there 640 picr &= ~bitvector; 641 if (!(picr & mask1)) { 642 tsunami->cchip->clearDRIR(55); 643 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 644 } 645} 646 647Tick 648TsunamiIO::cacheAccess(MemReqPtr &req) 649{ 650 return curTick + pioLatency; 651} 652 653void 654TsunamiIO::serialize(ostream &os) 655{ 656 SERIALIZE_SCALAR(timerData); 657 SERIALIZE_SCALAR(mask1); 658 SERIALIZE_SCALAR(mask2); 659 SERIALIZE_SCALAR(mode1); 660 SERIALIZE_SCALAR(mode2); 661 SERIALIZE_SCALAR(picr); 662 SERIALIZE_SCALAR(picInterrupting); 663 664 // Serialize the timers 665 pitimer.serialize("pitimer", os); 666 rtc.serialize("rtc", os); 667} 668 669void 670TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 671{ 672 UNSERIALIZE_SCALAR(timerData); 673 UNSERIALIZE_SCALAR(mask1); 674 UNSERIALIZE_SCALAR(mask2); 675 UNSERIALIZE_SCALAR(mode1); 676 UNSERIALIZE_SCALAR(mode2); 677 UNSERIALIZE_SCALAR(picr); 678 UNSERIALIZE_SCALAR(picInterrupting); 679 680 // Unserialize the timers 681 pitimer.unserialize("pitimer", cp, section); 682 rtc.unserialize("rtc", cp, section); 683} 684 685BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 686 687 SimObjectParam<Tsunami *> tsunami; 688 Param<time_t> time; 689 SimObjectParam<MemoryController *> mmu; 690 Param<Addr> addr; 691 SimObjectParam<Bus*> io_bus; 692 Param<Tick> pio_latency; 693 SimObjectParam<HierParams *> hier; 694 Param<Tick> frequency; 695 696END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 697 698BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 699 700 INIT_PARAM(tsunami, "Tsunami"), 701 INIT_PARAM(time, "System time to use (0 for actual time"), 702 INIT_PARAM(mmu, "Memory Controller"), 703 INIT_PARAM(addr, "Device Address"), 704 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), 705 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 706 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 707 INIT_PARAM(frequency, "clock interrupt frequency") 708 709END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 710 711CREATE_SIM_OBJECT(TsunamiIO) 712{ 713 return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier, 714 io_bus, pio_latency, frequency); 715} 716 717REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) 718