tsunami_io.cc revision 2107
110923SN/A/* 210923SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 310923SN/A * All rights reserved. 410923SN/A * 510923SN/A * Redistribution and use in source and binary forms, with or without 610923SN/A * modification, are permitted provided that the following conditions are 710923SN/A * met: redistributions of source code must retain the above copyright 810923SN/A * notice, this list of conditions and the following disclaimer; 910923SN/A * redistributions in binary form must reproduce the above copyright 1010923SN/A * notice, this list of conditions and the following disclaimer in the 1110923SN/A * documentation and/or other materials provided with the distribution; 1210923SN/A * neither the name of the copyright holders nor the names of its 1310923SN/A * contributors may be used to endorse or promote products derived from 1410923SN/A * this software without specific prior written permission. 1510923SN/A * 1610923SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710923SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810923SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910923SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010923SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110923SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210923SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310923SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410923SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510923SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610923SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710923SN/A */ 2810923SN/A 2910923SN/A/** @file 3010923SN/A * Tsunami I/O including PIC, PIT, RTC, DMA 3110923SN/A */ 3210923SN/A 3310923SN/A#include <sys/time.h> 3410923SN/A 3510923SN/A#include <deque> 3610923SN/A#include <string> 3710923SN/A#include <vector> 3810923SN/A 3910923SN/A#include "base/trace.hh" 4010923SN/A#include "dev/tsunami_io.hh" 4111290Sgabor.dozsa@arm.com#include "dev/tsunami.hh" 4210923SN/A#include "dev/pitreg.h" 4311290Sgabor.dozsa@arm.com#include "mem/bus/bus.hh" 4411290Sgabor.dozsa@arm.com#include "mem/bus/pio_interface.hh" 4510923SN/A#include "mem/bus/pio_interface_impl.hh" 4611290Sgabor.dozsa@arm.com#include "sim/builder.hh" 4711290Sgabor.dozsa@arm.com#include "dev/tsunami_cchip.hh" 4810923SN/A#include "dev/tsunamireg.h" 4910923SN/A#include "dev/rtcreg.h" 5010923SN/A#include "mem/functional/memory_control.hh" 5110923SN/A 5210923SN/Ausing namespace std; 5311290Sgabor.dozsa@arm.com//Should this be AlphaISA? 5411290Sgabor.dozsa@arm.comusing namespace TheISA; 5510923SN/A 5610923SN/ATsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i) 5710923SN/A : _name(name), event(t, i), addr(0) 5810923SN/A{ 5910923SN/A memset(clock_data, 0, sizeof(clock_data)); 6011290Sgabor.dozsa@arm.com stat_regA = RTCA_32768HZ | RTCA_1024HZ; 6110923SN/A stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 6210923SN/A} 6311290Sgabor.dozsa@arm.com 6411290Sgabor.dozsa@arm.comvoid 6510923SN/ATsunamiIO::RTC::set_time(time_t t) 6610923SN/A{ 6711290Sgabor.dozsa@arm.com struct tm tm; 6810923SN/A gmtime_r(&t, &tm); 6911290Sgabor.dozsa@arm.com 7010923SN/A sec = tm.tm_sec; 7110923SN/A min = tm.tm_min; 7210923SN/A hour = tm.tm_hour; 7310923SN/A wday = tm.tm_wday + 1; 7411290Sgabor.dozsa@arm.com mday = tm.tm_mday; 7511290Sgabor.dozsa@arm.com mon = tm.tm_mon + 1; 7610923SN/A year = tm.tm_year; 7710923SN/A 7810923SN/A DPRINTFN("Real-time clock set to %s", asctime(&tm)); 7910923SN/A} 8010923SN/A 8110923SN/Avoid 8211290Sgabor.dozsa@arm.comTsunamiIO::RTC::writeAddr(const uint8_t *data) 8311290Sgabor.dozsa@arm.com{ 8411290Sgabor.dozsa@arm.com if (*data <= RTC_STAT_REGD) 8511290Sgabor.dozsa@arm.com addr = *data; 8610923SN/A else 8710923SN/A panic("RTC addresses over 0xD are not implemented.\n"); 8810923SN/A} 8911701Smichael.lebeane@amd.com 9011701Smichael.lebeane@amd.comvoid 9111701Smichael.lebeane@amd.comTsunamiIO::RTC::writeData(const uint8_t *data) 9211701Smichael.lebeane@amd.com{ 9311701Smichael.lebeane@amd.com if (addr < RTC_STAT_REGA) 9411290Sgabor.dozsa@arm.com clock_data[addr] = *data; 9511290Sgabor.dozsa@arm.com else { 9611290Sgabor.dozsa@arm.com switch (addr) { 9711290Sgabor.dozsa@arm.com case RTC_STAT_REGA: 9811290Sgabor.dozsa@arm.com if (*data != (RTCA_32768HZ | RTCA_1024HZ)) 9911290Sgabor.dozsa@arm.com panic("Unimplemented RTC register A value write!\n"); 10011290Sgabor.dozsa@arm.com stat_regA = *data; 10111701Smichael.lebeane@amd.com break; 10211290Sgabor.dozsa@arm.com case RTC_STAT_REGB: 10311290Sgabor.dozsa@arm.com if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 10411290Sgabor.dozsa@arm.com panic("Write to RTC reg B bits that are not implemented!\n"); 10511290Sgabor.dozsa@arm.com 10611703Smichael.lebeane@amd.com if (*data & RTCB_PRDC_IE) { 10711290Sgabor.dozsa@arm.com if (!event.scheduled()) 10811290Sgabor.dozsa@arm.com event.scheduleIntr(); 10911290Sgabor.dozsa@arm.com } else { 11010923SN/A if (event.scheduled()) 11110923SN/A event.deschedule(); 11210923SN/A } 11311290Sgabor.dozsa@arm.com 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