Basic DMA, MFC, channel changes

Added new consts, thread-safe locks for critical resources, removed some
warnings. Modified git-version.h
This commit is contained in:
Nekotekina 2013-12-11 02:58:11 +04:00
parent bba9ea830f
commit c9fc99c388
5 changed files with 93 additions and 71 deletions

View File

@ -3,21 +3,22 @@
enum
{
MFC_PUT_CMD = 0x20,
MFC_GET_CMD = 0x40,
MFC_PUTL_CMD = 0x24,
MFC_GETL_CMD = 0x44,
MFC_GETLLAR_CMD = 0xD0,
MFC_PUTLLC_CMD = 0xB4,
MFC_PUTLLUC_CMD = 0xB0,
MFC_PUTQLLUC_CMD= 0xB8,
MFC_SNDSIG_CMD = 0xA0,
MFC_BARRIER_CMD = 0xC0,
MFC_EIEIO_CMD = 0xC8,
MFC_SYNC_CMD = 0xCC,
MFC_BARRIER_MASK= 0x01,
MFC_FENCE_MASK = 0x02,
MFC_MASK_CMD = 0xffff,
MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22,
MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42,
MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26,
MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46,
MFC_GETLLAR_CMD = 0xD0,
MFC_PUTLLC_CMD = 0xB4,
MFC_PUTLLUC_CMD = 0xB0,
MFC_PUTQLLUC_CMD = 0xB8,
MFC_SNDSIG_CMD = 0xA0, MFC_SNDSIGB_CMD = 0xA1, MFC_SNDSIGF_CMD = 0xA2,
MFC_BARRIER_CMD = 0xC0,
MFC_EIEIO_CMD = 0xC8,
MFC_SYNC_CMD = 0xCC,
MFC_BARRIER_MASK = 0x01,
MFC_FENCE_MASK = 0x02,
MFC_MASK_CMD = 0xffff,
};
enum
@ -142,11 +143,13 @@ public:
struct DMAC
{
DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE];
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE];
//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
u64 ls_offset;
std::atomic<u32> queue_pos;
std::atomic<u32> proxy_pos;
u32 queue_pos;
u32 proxy_pos;
u32 queue_lock;
u32 proxy_lock;
u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
@ -160,31 +163,42 @@ struct DMAC
return MFC_PPU_DMA_QUEUE_FULL;
}
DMAC_Proxy& p = proxy[proxy_pos++];
while (_InterlockedCompareExchange(&proxy_lock, 1, 0));
DMAC_Proxy& p = proxy[proxy_pos];
p.cmd = cmd;
p.tag = tag;
p.lsa = lsa;
p.ea = ea;
p.size = size;
proxy_pos++;
proxy_lock = 0;
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
}
void ClearCmd()
{
while (_InterlockedCompareExchange(&proxy_lock, 1, 0));
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
proxy_lock = 0; //release lock
}
void DoCmd()
{
if(proxy_pos)
{
DMAC_Proxy p = proxy[0];
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
const DMAC_Proxy& p = proxy[0];
switch(p.cmd)
switch(p.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) //barrier/fence ignored
{
case MFC_PUT_CMD:
memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size);
ClearCmd();
break;
case MFC_GET_CMD:
memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size);
ClearCmd();
break;
default:

View File

@ -57,12 +57,12 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); *value = MFC.QStatus.GetValue(); break;
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: *value = MFC2.QStatus.GetValue(); break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
@ -151,16 +151,15 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_LSA, 0x%x)", m_index, value); MFC.LSA.SetValue(value); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAH, 0x%x)", m_index, value); MFC.EAH.SetValue(value); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break;
case MFC_LSA_offs: MFC2.LSA.SetValue(value); break;
case MFC_EAH_offs: MFC2.EAH.SetValue(value); break;
case MFC_EAL_offs: MFC2.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: MFC2.Size_Tag.SetValue(value); break;
case MFC_CMDStatus_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value);
MFC.CMDStatus.SetValue(value);
DoMfcCmd();
MFC2.CMDStatus.SetValue(value);
EnqMfcCmd(MFC2);
break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break;
case Prxy_QueryType_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
@ -178,7 +177,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
}
Prxy.QueryType.SetValue(0);
MFC.QStatus.SetValue(Prxy.QueryMask.GetValue());
MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue());
}
break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;

View File

@ -46,11 +46,14 @@ void SPUThread::InitRegs()
dmac.ls_offset = m_offset;
dmac.proxy_pos = 0;
dmac.queue_pos = 0;
dmac.proxy_lock = 0;
dmac.queue_lock = 0;
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
SPU.Status.SetValue(SPU_STATUS_RUNNING);
Prxy.QueryType.SetValue(0);
MFC.CMDStatus.SetValue(0);
MFC1.CMDStatus.SetValue(0);
MFC2.CMDStatus.SetValue(0);
//PC = SPU.NPC.GetValue();
}

View File

@ -265,6 +265,7 @@ public:
private:
u32 m_value[max_count];
u32 m_index;
u32 m_lock;
public:
@ -276,19 +277,32 @@ public:
void Init()
{
m_index = 0;
m_lock = 0; //simple lock
}
__forceinline bool Pop(u32& res)
{
if(!m_index) return false;
while (_InterlockedCompareExchange(&m_lock, 1, 0));
if(!m_index)
{
m_lock = 0; //release lock
return false;
}
res = m_value[--m_index];
m_lock = 0;
return true;
}
__forceinline bool Push(u32 value)
{
if(m_index >= max_count) return false;
while (_InterlockedCompareExchange(&m_lock, 1, 0));
if(m_index >= max_count)
{
m_lock = 0; //release lock
return false;
}
m_value[m_index++] = value;
m_lock = 0;
return true;
}
@ -313,7 +327,7 @@ public:
}
};
struct
struct MFCReg
{
Channel<1> LSA;
Channel<1> EAH;
@ -321,7 +335,7 @@ public:
Channel<1> Size_Tag;
Channel<1> CMDStatus;
Channel<1> QStatus;
} MFC;
} MFC1, MFC2;
struct
{
@ -353,9 +367,9 @@ public:
DMAC dmac;
void DoMfcCmd()
void EnqMfcCmd(MFCReg& MFCArgs)
{
u32 cmd = MFC.CMDStatus.GetValue();
u32 cmd = MFCArgs.CMDStatus.GetValue();
u16 op = cmd & MFC_MASK_CMD;
switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
@ -363,21 +377,13 @@ public:
case MFC_PUT_CMD:
case MFC_GET_CMD:
{
u32 lsa = MFC.LSA.GetValue();
u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32);
u32 size_tag = MFC.Size_Tag.GetValue();
u32 lsa = MFCArgs.LSA.GetValue();
u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32);
u32 size_tag = MFCArgs.Size_Tag.GetValue();
u16 tag = (u16)size_tag;
u16 size = size_tag >> 16;
ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET");
ConLog.Warning("*** lsa = 0x%x", lsa);
ConLog.Warning("*** ea = 0x%llx", ea);
ConLog.Warning("*** tag = 0x%x", tag);
ConLog.Warning("*** size = 0x%x", size);
ConLog.Warning("*** cmd = 0x%x", cmd);
ConLog.SkipLn();
MFC.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
}
break;
@ -401,20 +407,20 @@ public:
return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
case MFC_LSA:
return MFC.LSA.max_count;
return MFC1.LSA.max_count;
case MFC_EAH:
return MFC.EAH.max_count;
return MFC1.EAH.max_count;
case MFC_EAL:
return MFC.EAL.max_count;
return MFC1.EAL.max_count;
case MFC_Size:
case MFC_TagID:
return MFC.Size_Tag.max_count;
return MFC1.Size_Tag.max_count;
case MFC_Cmd:
return MFC.CMDStatus.max_count;
return MFC1.CMDStatus.max_count;
default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
@ -455,28 +461,28 @@ public:
break;
case MFC_LSA:
MFC.LSA.SetValue(v);
MFC1.LSA.SetValue(v);
break;
case MFC_EAH:
MFC.EAH.SetValue(v);
MFC1.EAH.SetValue(v);
break;
case MFC_EAL:
MFC.EAL.SetValue(v);
MFC1.EAL.SetValue(v);
break;
case MFC_Size:
MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & 0xffff) | (v << 16));
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16));
break;
case MFC_TagID:
MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff));
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff));
break;
case MFC_Cmd:
MFC.CMDStatus.SetValue(v);
DoMfcCmd();
MFC1.CMDStatus.SetValue(v);
EnqMfcCmd(MFC1);
break;
default:

View File

@ -1,6 +1,6 @@
// This is a generated file.
#define RPCS3_GIT_VERSION "d83a9b1"
#define RPCS3_GIT_VERSION "unknown"
// If you don't want this file to update/recompile, change to 1.
#define RPCS3_GIT_VERSION_NO_UPDATE 0
#define RPCS3_GIT_VERSION_NO_UPDATE 1