1
0
mirror of synced 2026-01-28 04:17:15 +00:00
Files
andrastantos.cray-sim/simulator/sim_lib/sim_iop.h
2020-09-09 15:11:45 -07:00

294 lines
12 KiB
C++

#ifndef __SIM_IOP_H__
#define __SIM_IOP_H__
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <boost/asio.hpp>
#include "utils.h"
#include "cray_types.h"
#include "cray_logger.h"
#include "cray_channels.h"
#include "debug_events.h"
#include <stdint.h>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/timer/timer.hpp>
#include "config_file.h"
#include "ui.h"
#include "cray_mainframe.h"
#include <queue>
#include "iop_cluster_if.h"
#include "sim_iop_disk.h"
#include "sim_iop_con.h"
#include "sim_iop_eth.h"
#include "sim_iop_periph.h"
enum class DeviceTypes_e {
DD00 = 0, // Invalid entry (???)
DD19 = 1, // DD19 disk drive
DD29 = 2, // DD29 disk drive
DD49 = 3, // DD49 disk drive
DD39 = 4, // DD39 disk drive
DD10 = 5, // DD10 disk drive
DD40 = 6, // DD40 disk drive
DD50 = 7, // DD50 disk drive
DD11 = 8, // DD11 disk drive
DD41 = 9, // DD41 disk drive
DD60 = 10, // DD60 disk drive
DD61 = 11, // DD61 disk drive
DD62 = 12, // DD62 disk drive
DD42 = 13, // DD42 disk drive
DA62 = 14, // DA62 disk drive
DA60 = 15, // DA60 disk drive
DD301 = 16, // DD301 disk drive
DA301 = 17, // DA301 disk drive
DD302 = 18, // DD302 disk drive
DA302 = 19, // DA302 disk drive
DDESDI = 64, // old esdi drive
DD3 = 65, // new esdi drive
DDLDAS = 66, // old DAS
DDAS2 = 67, // new DAS
DD4 = 68, // ipi + sabre 7
RD1 = 69, // removable esdi
DDIMEM = 70, // ironics+memory vme boards
DD5S = 71, // DD5S SCSI drive
DD5I = 72, // DD5I IPI drive
DD_U = 73, // DD_U Generic SCSI drive
DD6S = 74, // DD6S SCSI drive
DD7S = 75, // DD7S SCSI drive
DD318 = 76, // DD318 SCSI drive
DD501 = 77, // DD501 SCSI drive
};
inline uint64_t GetBitsReverse(uint64_t aData, const BitRange_s aRange) {
return GetBitsReverse(aData, aRange.Start, aRange.End);
}
inline void SetBitsReverse(uint64_t &aData, const BitRange_s aRange, uint64_t aValue) {
aData = SetBitsReverse(aData, aRange.Start, aRange.End, aValue);
}
inline void SetBits(uint64_t &aData, const BitRange_s aRange, uint64_t aValue) {
aData = SetBits(aData, aRange.Start, aRange.End, aValue);
}
inline uint64_t GetBits(uint64_t aData, const BitRange_s aRange) {
return GetBits(aData, aRange.Start, aRange.End);
}
inline void SetBitsInPlace(uint64_t &aData, const BitRange_s aRange, uint64_t aValue) {
aData = SetBits(aData, aRange.Start, aRange.End, aValue);
}
//enum class MachineTypes_e : int;
class IopEPacket_c {
public:
explicit IopEPacket_c(const std::vector<CInt_t> &aPacket) : mPacket(aPacket) {}
IopEPacket_c(const std::vector<CInt_t>::const_iterator &aPacketBegin,const std::vector<CInt_t>::const_iterator &aPacketEnd): mPacket(aPacketBegin, aPacketEnd) {}
IopEPacket_c(const IopEPacket_c &aOri) : mPacket(aOri.mPacket) {}
IopEPacket_c() {}
void SetSize(size_t aSize) {
mPacket.resize(aSize + 1, 0);
SetLength(uint16_t(aSize + 1));
}
static const uint8_t cMagic = 45;
static const uint8_t cFlagRet = 0200; // Retransmit packet request
static const uint8_t cFlagAck = 0100; // Acknowledge packet
static const uint8_t cFlagIni = 040; // Restart IOP sequence numbers at 1
bool IsValid() const;
std::vector<CInt_t> &Finalize();
std::vector<CInt_t> &GetRawData() { return mPacket; }
const std::vector<CInt_t> &GetRawData() const { return mPacket; }
uint8_t GetMagic() const { return uint8_t(GetBits(mPacket[0], 58, 63)); }
uint16_t GetLength() const { return uint16_t(GetBits(mPacket[0], 48, 57)); }
uint8_t GetKernelId() const { return uint8_t(GetBits(mPacket[0], 45, 47)); }
uint8_t GetSource() const { return uint8_t(GetBits(mPacket[0], 41, 44)); }
uint8_t GetCluster() const { return uint8_t(GetBits(mPacket[0], 37, 40)); }
uint8_t GetProcess() const { return uint8_t(GetBits(mPacket[0], 32, 36)); }
uint8_t GetFlags() const { return uint8_t(GetBits(mPacket[0], 24, 31)); }
uint8_t GetLogicalPath() const { return uint8_t(GetBits(mPacket[0], 16, 23)); }
uint8_t GetSeq() const { return uint8_t(GetBits(mPacket[0], 8, 15)); }
uint8_t GetAckSeq() const { return uint8_t(GetBits(mPacket[0], 0, 7)); }
void SetMagic(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 58, 63, aValue); }
void SetLength(uint16_t aValue) { mPacket[0] = SetBits(mPacket[0], 48, 57, aValue); }
void SetKernelId(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 45, 47, aValue); }
void SetSource(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 41, 44, aValue); }
void SetCluster(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 37, 40, aValue); }
void SetProcess(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 32, 36, aValue); }
void SetFlags(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 24, 31, aValue); }
void SetLogicalPath(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 16, 23, aValue); }
void SetSeq(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 8, 15, aValue); }
void SetAckSeq(uint8_t aValue) { mPacket[0] = SetBits(mPacket[0], 0, 7, aValue); }
CInt_t &Data(size_t aIdx) { return mPacket[aIdx + 1]; }
CInt_t Data(size_t aIdx) const { return mPacket[aIdx + 1]; }
protected:
std::vector<CInt_t> mPacket;
};
// Simulated I/O processor class
inline void ReversePacket(std::vector<CInt_t> &aPacket) {
const BitRange_s DIDRange(0, 15);
const BitRange_s SIDRange(16, 31);
// Swap source and destination
uint16_t DID = uint16_t(GetBitsReverse(aPacket[0], DIDRange));
uint16_t SID = uint16_t(GetBitsReverse(aPacket[0], SIDRange));
SetBitsReverse(aPacket[0], DIDRange, SID);
SetBitsReverse(aPacket[0], SIDRange, DID);
}
class SimIopCluster_c: public IopClusterBase_i {
protected:
class ChannelIToC_c : public Channel_i {
public:
ChannelIToC_c(const Configuration_c &aConfig, size_t aChannelId, Mainframe_c &aMainframe, class SimIopCluster_c &aParent);
~ChannelIToC_c() {}
virtual void ChannelTick() override;
virtual bool NeedsChannelTick() const override { return true; }
virtual CLogger_c &GetLogger() const override { return mLogger; }
bool ReadyToSend() const;
void QueuePacket(const std::vector<CInt_t> &aPacket);
virtual void HandleActivation() override {
mLogger << setloglevel(LogLevel_IoActivity) << " primed to transmit " << DecPrinter(BufferLeft()) << " words at address " << HexPrinter(GetAddress()) << std::endl;
}
virtual void HandleDeactivation() override {
mLogger << setloglevel(LogLevel_IoActivity) << " went inactive" << std::endl;
}
size_t GetQueueLength() const { return mPacketQueue.size(); }
virtual void SetAddress(CAddr_t aAddress) override {
mLogger << setloglevel(LogLevel_IoTrace) << "======== Channel address is set to " << HexPrinter(aAddress) << std::endl;
Channel_i::SetAddress(aAddress);
}
protected:
void SendPacket(const std::vector<CInt_t> &aPacket, bool aReplace = false);
std::queue<std::vector<CInt_t>> mPacketQueue;
std::vector<CInt_t> mPacket;
size_t mPacketIdx;
bool mPacketValid;
mutable CLogger_c mLogger;
SimIopCluster_c &mParent;
};
class ChannelCToI_c : public Channel_i {
public:
ChannelCToI_c(const Configuration_c &aConfig, size_t aChannelId, Mainframe_c &aMainframe, class SimIopCluster_c &aParent);
~ChannelCToI_c() {}
virtual void ChannelTick() override;
virtual bool NeedsChannelTick() const override { return true; }
virtual CLogger_c &GetLogger() const override { return mLogger; }
bool HasPacket();
std::vector<CInt_t> GetPacket();
virtual void HandleActivation() override {
mLogger << setloglevel(LogLevel_IoActivity) << " primed to transmit " << DecPrinter(BufferLeft()) << " words at address " << HexPrinter(GetAddress()) << std::endl;
}
virtual void HandleDeactivation() override {
mLogger << setloglevel(LogLevel_IoActivity) << " went inactive" << std::endl;
}
virtual void SetAddress(CAddr_t aAddress) override {
mLogger << setloglevel(LogLevel_IoTrace) << "======== Channel address is set to " << HexPrinter(aAddress) << std::endl;
Channel_i::SetAddress(aAddress);
}
protected:
std::vector<CInt_t> mPacket;
size_t mPacketIdx;
bool mPacketValid;
mutable CLogger_c mLogger;
SimIopCluster_c &mParent;
};
public:
typedef std::unique_ptr<ChannelIToC_c> (*IToCChannelCreator_t)(SimIopCluster_c *aThis, const Configuration_c &aConfig);
typedef std::unique_ptr<ChannelCToI_c> (*CToIChannelCreator_t)(SimIopCluster_c *aThis, const Configuration_c &aConfig);
explicit SimIopCluster_c(const Configuration_c &aConfig, size_t aIopId, class Mainframe_c &aMainframe, IToCChannelCreator_t aIToCChannelCreator = CreateIToCChannel, CToIChannelCreator_t aCToIChannelCreator = CreateCToIChannel);
virtual void RegisterCommands(CommandHooks_t &aHooks) override;
virtual void GetPeripheralStatus(StatusReport_c &aStatus, PeripheralType_e aFilter, boost::timer::nanosecond_type aElapsedTime, bool aLongFormat) const override;
virtual void GetCpuStatus(StatusReport_c &aStatus, boost::timer::nanosecond_type aElapsedTime, bool aLongFormat) const override {}
virtual std::string GetName() const override;
virtual std::string GetLongName() const override;
CLogger_c &GetLogger() const { return mLogger; }
class Mainframe_c &GetMainframe() { return *mMainframe; }
virtual void MasterClear() override;
virtual void Tick() override;
ChannelIToC_c &GetIToCChannel() { return *mIToCChannel; }
ChannelCToI_c &GetCToIChannel() { return *mCToIChannel; }
IopEPacket_c GenerateResponse(IopEPacket_c &aRequest) const;
IopEPacket_c GenerateResponse() const;
void SendPacket(IopEPacket_c &aPacket);
void SendPacket(std::vector<CInt_t> &aPacket);
MachineTypes_e GetMachineType() const;
IopRevision_e GetIopRevision() const { return mIopRevision; }
size_t GetId() const { return mIopId; }
virtual void Dump(size_t aIdent = 0) const override {}
virtual void DeadStart() override {}
protected:
static std::unique_ptr<ChannelIToC_c> CreateIToCChannel(SimIopCluster_c *aThis, const Configuration_c &aConfig);
static std::unique_ptr<ChannelCToI_c> CreateCToIChannel(SimIopCluster_c *aThis, const Configuration_c &aConfig);
enum class States_e {
Reset,
WaitTimeSent,
WaitISent,
WaitJSent,
RunningJ90,
RunningYEL,
KernelPanic
} mState;
IopRevision_e mIopRevision;
bool mMasterCluster;
mutable CLogger_c mLogger;
class Mainframe_c *mMainframe;
size_t mIopId;
uint8_t mSeqSent;
uint8_t mSeqReceived;
size_t mPacketsReceived;
size_t mPacketsSent;
std::vector<std::unique_ptr<class SimIopDisk_c>> mDisks;
std::vector<std::unique_ptr<class SimIopConsole_c>> mConsoles;
boost::property_tree::ptree mDefaultConsoleConfig;
std::vector<std::unique_ptr<class SimIopEth_c>> mEthInterfaces;
std::unique_ptr<class SimIopPeripheral_c> mIopPeripheral;
std::unique_ptr<ChannelIToC_c> mIToCChannel;
std::unique_ptr<ChannelCToI_c> mCToIChannel;
void HandleTPacket(std::vector<CInt_t> &aPacket);
void HandleAPacket(std::vector<CInt_t> &aPacket);
void HandleKPacket(std::vector<CInt_t> &aPacket);
void HandleIosEOPacket(IopEPacket_c &aPacket);
void HandleIosEZPacket(IopEPacket_c &aPacket);
void HandleIosEDPacket(IopEPacket_c &aPacket);
void HandleIosEPPacket(IopEPacket_c &aPacket);
void MakeConsoles(size_t aMaxConsoleId);
boost::optional<std::string> mKernelFileName;
size_t mKernelPreamble;
boost::optional<std::string> mParameterFileName;
boost::optional<std::string> mRamFsFileName;
uint32_t mBootCluster;
uint32_t mBootChannel;
uint8_t mLogicalMainframeNumber;
uint8_t mOWSProtocolLevel;
boost::optional<std::string> mRunLevel;
bool mDontTouchExchangePacket;
};
#endif // __SIM_IOP_H__