// Cray-XMP I/O Processor simulator class #include "sim_iop_disk.h" #include "sim_iop.h" #if defined(PARTIAL_DEBUG) && defined(_MSC_VER) #pragma optimize ("", off) #endif // SimIopCluster_c::IopDisk_c ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct DiskGeometry_s { const char *Name; DeviceTypes_e DeviceType; uint32_t SectorSize; std::streamoff Sectors; std::streamoff Heads; std::streamoff Cylinders; uint32_t StripeFactor; }; const DiskGeometry_s cDiskGeometry[] = { {"DD00", DeviceTypes_e::DD00, 512, 42, 8, 890, 1}, {"DD19", DeviceTypes_e::DD19, 512, 18, 10, 411, 0}, {"DD29", DeviceTypes_e::DD29, 512, 18, 10, 823, 0}, {"DD49", DeviceTypes_e::DD49, 512, 42, 8, 890, 8}, {"DD39", DeviceTypes_e::DD39, 512, 24, 5, 842, 0}, {"DD10", DeviceTypes_e::DD10, 512, 12, 19, 1420, 0}, {"DD40", DeviceTypes_e::DD40, 512, 48, 19, 1420, 8}, {"DD50", DeviceTypes_e::DD50, 512, 42, 16, 890, 8}, {"DD11", DeviceTypes_e::DD11, 512, 12, 15, 1635, 0}, {"DD41", DeviceTypes_e::DD41, 512, 48, 15, 1635, 8}, {"DD60", DeviceTypes_e::DD60, 2048, 23, 2, 2611, 2}, {"DD61", DeviceTypes_e::DD61, 512, 11, 19, 2611,11}, {"DD62", DeviceTypes_e::DD62, 512, 28, 9, 2655, 6}, {"DD42", DeviceTypes_e::DD42, 512, 48, 19, 2611, 8}, {"DA62", DeviceTypes_e::DA62, 2048, 28, 9, 2655, 6}, {"DA60", DeviceTypes_e::DA60, 8192, 23, 2, 2611, 2}, {"DD301", DeviceTypes_e::DD301, 512, 25, 7, 1930, 5}, {"DA301", DeviceTypes_e::DA301, 2048, 25, 7, 1930, 5}, {"DD302", DeviceTypes_e::DD302, 512, 28, 7, 2251, 4}, {"DA302", DeviceTypes_e::DA302, 2048, 28, 7, 2251, 4}, {"DDESDI", DeviceTypes_e::DDESDI, 512, 1, 1, 170100, 1}, {"DD3", DeviceTypes_e::DD3, 512, 1, 1, 334200, 1}, {"DDLDAS", DeviceTypes_e::DDLDAS, 512, 1, 1, 1269114, 1}, {"DDAS2", DeviceTypes_e::DDAS2, 512, 1, 1, 2502000, 1}, {"DD4", DeviceTypes_e::DD4, 512, 1, 1, 653000, 1}, {"RD-1", DeviceTypes_e::RD1, 512, 1, 1, 334200, 1}, {"DDIMEM", DeviceTypes_e::DDIMEM, 512, 1, 1, 32768, 1}, {"DD5S", DeviceTypes_e::DD5S, 512, 1, 1, 781000, 1}, {"DD5I", DeviceTypes_e::DD5I, 512, 1, 1, 723000, 1}, {"DD_U", DeviceTypes_e::DD_U, 512, 1, 1, 0xfffffff, 1}, {"DD6S", DeviceTypes_e::DD6S, 512, 1, 1, 2389000, 1}, {"DD314", DeviceTypes_e::DD7S, 512, 1, 1, 1102000, 1}, {"DD318", DeviceTypes_e::DD318, 512, 1, 1, 2342634, 1}, {"DD501", DeviceTypes_e::DD501, 512, 1, 1, 6019481, 1} }; SimIopDisk_c::SimIopDisk_c(const Configuration_c &aConfig, const std::string &aDiskId, SimIopCluster_c &aParent): mDiskId(aDiskId), mLogger(aConfig, std::string("DSK_").append(aDiskId).c_str()), mParent(aParent), mCurrentHead(0), mCurrentSector(0), mCurrentCylinder(0), mReads(0), mWrites(0) { mLogger.SetParent(aParent.GetLogger()); mImageFileName = aConfig.get("ImageFileName"); mPysicalDeviceId = aConfig.get("PysicalDeviceId"); mIopNumber = aConfig.get("IopNumber"); mUnit = aConfig.get("Unit"); boost::optional DeviceType = aConfig.get_optional("DeviceType"); boost::optional SectorCnt = aConfig.get_optional("SectorCnt"); if (DeviceType.is_initialized()) { bool Found = false; for (auto &DiskGeometry : cDiskGeometry) { if (DeviceType.get() == DiskGeometry.Name) { Found = true; mNumHeads = DiskGeometry.Heads; mNumSectors = DiskGeometry.Sectors; mNumCylinders = DiskGeometry.Cylinders; mSectorSize = DiskGeometry.SectorSize * sizeof(CInt_t); break; } } if (!Found) throw InvalidParameter_x("Unknown DeviceType"); } else if (SectorCnt.is_initialized()) { mNumHeads = 1; mNumSectors = 1; mNumCylinders = SectorCnt.get(); if (mNumCylinders == std::streamoff(0)) throw InvalidParameter_x("Cylinders must be greater than 0"); mSectorSize = aConfig.get("SectorSize", 4096); if (mSectorSize == 0) throw InvalidParameter_x("SectorSize must be greater than 0"); if (mSectorSize % 1024 != 0) throw InvalidParameter_x("SectorSize must be a multiple of 1024"); } else { mNumHeads = aConfig.get("Heads"); if (mNumHeads == std::streamoff(0)) throw InvalidParameter_x("Heads must be greater than 0"); mNumSectors = aConfig.get("Sectors"); if (mNumSectors == std::streamoff(0)) throw InvalidParameter_x("Sectors must be greater than 0"); mNumCylinders = aConfig.get("Cylinders"); if (mNumCylinders == std::streamoff(0)) throw InvalidParameter_x("Cylinders must be greater than 0"); mSectorSize = aConfig.get("SectorSize", 4096); if (mSectorSize == 0) throw InvalidParameter_x("SectorSize must be greater than 0"); if (mSectorSize % 1024 != 0) throw InvalidParameter_x("SectorSize must be a multiple of 1024"); } MasterClear(); if (!boost::filesystem::exists(mImageFileName)) { std::fstream File; std::cout << "Creating disk image file: " << mImageFileName << "..." << std::flush; File.open(mImageFileName, std::ios::out | std::ios::binary); CRAY_ASSERT(!File.bad()); //size_t DiskSize = mNumHeads * mNumSectors * mNumCylinders * mSectorSize; //File.seekp(DiskSize - 1); CRAY_ASSERT(!File.bad()); char Data = 0; File.write(&Data, sizeof(Data)); CRAY_ASSERT(!File.bad()); File.close(); std::cout << " done" << std::endl; } } void SimIopDisk_c::Read(std::streamoff aCylinder, std::streamoff aHead, std::streamoff aSector, uint32_t aSectorCnt, CAddr_t aMainframeAddr) { mCurrentCylinder = aCylinder; mCurrentHead = aHead; mCurrentSector = aSector; std::streamoff ImageOffset = mSectorSize * (aCylinder * mNumHeads * mNumSectors + aHead * mNumSectors + aSector); mReads += mSectorSize / 1024 * aSectorCnt; std::stringstream EventStr; EventStr << "Reading sector " << "CHS:" << DecPrinter(aCylinder) << "-" << DecPrinter(aHead) << "-" << DecPrinter(aSector) << " (offset: " << HexPrinter(ImageOffset) << ") " << " to memory address " << HexPrinter(aMainframeAddr, 4) << " sector count: " << DecPrinter(aSectorCnt); mLogger << setloglevel(LogLevel_IoActivity) << EventStr.str() << std::endl; mParent.GetMainframe().GetEventDispatcher().Fire(EventStr.str()); std::fstream File(mImageFileName, std::ios::in | std::ios::binary); CRAY_ASSERT(!File.bad()); File.seekg(ImageOffset); CRAY_ASSERT(!File.bad()); LogLine_c TraceLine = mLogger << setloglevel(LogLevel_IoTrace); std::streamoff AccessSize = std::streamoff(mSectorSize) * std::streamoff(aSectorCnt) / sizeof(CInt_t); const size_t cLineSize = 4; CRAY_ASSERT(AccessSize % cLineSize == 0); AccessSize = AccessSize / cLineSize; for (std::streamoff i = 0; i < AccessSize; ++i) { CInt_t Data[cLineSize]; if (!File.eof()) { File.read((char*)(&Data), sizeof(Data)); CRAY_ASSERT(!File.bad()); } else { // If we're at EOF, simply 0-fill the data std::fill(Data, Data + cLineSize, 0); } if (TraceLine.good()) { TraceLine << HexPrinter(aMainframeAddr + i * cLineSize) << " : "; for (size_t j = 0; j < cLineSize; ++j) { TraceLine << HexPrinter(SwapBytes(Data[j])) << " "; } TraceLine << " - "; for (size_t j = 0; j < cLineSize; ++j) { TraceLine << AsciiDumpPrinter(SwapBytes(Data[j])) << " "; } TraceLine << std::endl; } for (size_t j = 0; j < cLineSize; ++j) { mParent.GetMainframe().MemWrite(CAddr_t(aMainframeAddr + i * cLineSize + j), Data[j]); } } TraceLine << std::endl; File.close(); } void SimIopDisk_c::Read(std::streamoff aSectorIdx, uint32_t aSectorCnt, CAddr_t aMainframeAddr) { std::streamoff Sector = aSectorIdx % mNumSectors; aSectorIdx = aSectorIdx / mNumSectors; std::streamoff Head = aSectorIdx % mNumHeads; aSectorIdx = aSectorIdx / mNumHeads; std::streamoff Cylinder = aSectorIdx; mLogger << setloglevel(LogLevel_IoActivity) << "Reading sector " << DecPrinter(aSectorIdx) << " CHS:" << DecPrinter(Cylinder) << "-" << DecPrinter(Head) << "-" << DecPrinter(Sector) << " mNumCylinder: " << DecPrinter(mNumCylinders) << " to memory address " << HexPrinter(aMainframeAddr, 4) << " sector count: " << DecPrinter(aSectorCnt) << std::endl; CRAY_ASSERT(Cylinder < mNumCylinders); Read(Cylinder, Head, Sector, aSectorCnt, aMainframeAddr); } void SimIopDisk_c::Write(std::streamoff aCylinder, std::streamoff aHead, std::streamoff aSector, uint32_t aSectorCnt, CAddr_t aMainframeAddr) { mCurrentCylinder = aCylinder; mCurrentHead = aHead; mCurrentSector = aSector; std::streamoff ImageOffset = mSectorSize * (aCylinder * mNumHeads * mNumSectors + aHead * mNumSectors + aSector); mWrites += mSectorSize / 1024 * aSectorCnt; std::stringstream EventStr; EventStr << "Writing sector " << "CHS:" << DecPrinter(aCylinder) << "-" << DecPrinter(aHead) << "-" << DecPrinter(aSector) << " (offset: " << HexPrinter(ImageOffset) << ") " << " from memory address " << HexPrinter(aMainframeAddr, 4) << " sector count: " << DecPrinter(aSectorCnt); mLogger << setloglevel(LogLevel_IoActivity) << EventStr.str() << std::endl; mParent.GetMainframe().GetEventDispatcher().Fire(EventStr.str()); std::fstream File; if (boost::filesystem::exists(mImageFileName)) { File.open(mImageFileName, std::ios::out | std::ios::in | std::ios::binary); } else { File.open(mImageFileName, std::ios::out | std::ios::binary); } CRAY_ASSERT(!File.bad()); File.seekp(ImageOffset); CRAY_ASSERT(File.good()); CRAY_ASSERT(!File.bad()); LogLine_c TraceLine = mLogger << setloglevel(LogLevel_IoTrace); std::streamoff AccessSize = std::streamoff(mSectorSize) * std::streamoff(aSectorCnt) / sizeof(CInt_t); const size_t cLineSize = 4; CRAY_ASSERT(AccessSize % cLineSize == 0); AccessSize = AccessSize / cLineSize; for (std::streamoff i = 0; i < AccessSize; ++i) { CInt_t Data[cLineSize]; for (size_t j = 0; j < cLineSize; ++j) { Data[j] = mParent.GetMainframe().MemRead(CAddr_t(aMainframeAddr + i * cLineSize + j)); } File.write((char*)(&Data), sizeof(Data)); CRAY_ASSERT(!File.bad()); if (TraceLine.good()) { TraceLine << HexPrinter(aMainframeAddr + i * cLineSize) << " : "; for (size_t j = 0; j < cLineSize; ++j) { TraceLine << HexPrinter(SwapBytes(Data[j])) << " "; } TraceLine << " - "; for (size_t j = 0; j < cLineSize; ++j) { TraceLine << AsciiDumpPrinter(SwapBytes(Data[j])) << " "; } TraceLine << std::endl; } } TraceLine << std::endl; File.close(); } void SimIopDisk_c::Write(std::streamoff aSectorIdx, uint32_t aSectorCnt, CAddr_t aMainframeAddr) { std::streamoff Sector = aSectorIdx % mNumSectors; aSectorIdx = aSectorIdx / mNumSectors; std::streamoff Head = aSectorIdx % mNumHeads; aSectorIdx = aSectorIdx / mNumHeads; std::streamoff Cylinder = aSectorIdx; CRAY_ASSERT(Cylinder < mNumCylinders); Write(Cylinder, Head, Sector, aSectorCnt, aMainframeAddr); } void SimIopDisk_c::GetStatus(StatusReport_c &aStatus, boost::timer::nanosecond_type aElapsedTime, bool aLongFormat) const { aStatus.put(aLongFormat ? "Cylinder" : "C", mCurrentCylinder); aStatus.put(aLongFormat ? "Head" : "H", mCurrentHead); aStatus.put(aLongFormat ? "Sector" : "S", mCurrentSector); aStatus.put(aLongFormat ? "Reads" : "R", mReads); aStatus.put(aLongFormat ? "Writes" : "W", mWrites); } std::string SimIopDisk_c::GetName() const { std::stringstream Name; Name << "DSK_" << mDiskId; return Name.str(); } void SimIopDisk_c::RegisterCommands(CommandHooks_t &aHooks) {} void SimIopDisk_c::MasterClear() {} #if defined(PARTIAL_DEBUG) && defined(_MSC_VER) #pragma optimize ("", on) #endif