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