Merge pull request #10076 from lioncash/sibf

SI: Migrate bitfields to Common::BitField
This commit is contained in:
Léo Lam 2021-09-14 19:10:39 +02:00 committed by GitHub
commit 819a0a69ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 106 additions and 120 deletions

View File

@ -11,6 +11,7 @@
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include "Common/BitField.h"
#include "Common/ChunkFile.h" #include "Common/ChunkFile.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
@ -60,42 +61,36 @@ enum
// SI Channel Output // SI Channel Output
union USIChannelOut union USIChannelOut
{ {
u32 hex; u32 hex = 0;
struct
{ BitField<0, 8, u32> OUTPUT1;
u32 OUTPUT1 : 8; BitField<8, 8, u32> OUTPUT0;
u32 OUTPUT0 : 8; BitField<16, 8, u32> CMD;
u32 CMD : 8; BitField<24, 8, u32> reserved;
u32 : 8;
};
}; };
// SI Channel Input High u32 // SI Channel Input High u32
union USIChannelIn_Hi union USIChannelIn_Hi
{ {
u32 hex; u32 hex = 0;
struct
{ BitField<0, 8, u32> INPUT3;
u32 INPUT3 : 8; BitField<8, 8, u32> INPUT2;
u32 INPUT2 : 8; BitField<16, 8, u32> INPUT1;
u32 INPUT1 : 8; BitField<24, 6, u32> INPUT0;
u32 INPUT0 : 6; BitField<30, 1, u32> ERRLATCH; // 0: no error 1: Error latched. Check SISR.
u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR. BitField<31, 1, u32> ERRSTAT; // 0: no error 1: error on last transfer
u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
};
}; };
// SI Channel Input Low u32 // SI Channel Input Low u32
union USIChannelIn_Lo union USIChannelIn_Lo
{ {
u32 hex; u32 hex = 0;
struct
{ BitField<0, 8, u32> INPUT7;
u32 INPUT7 : 8; BitField<8, 8, u32> INPUT6;
u32 INPUT6 : 8; BitField<16, 8, u32> INPUT5;
u32 INPUT5 : 8; BitField<24, 8, u32> INPUT4;
u32 INPUT4 : 8;
};
}; };
// SI Channel // SI Channel
@ -106,105 +101,100 @@ struct SSIChannel
USIChannelIn_Lo in_lo; USIChannelIn_Lo in_lo;
std::unique_ptr<ISIDevice> device; std::unique_ptr<ISIDevice> device;
bool has_recent_device_change; bool has_recent_device_change = false;
}; };
// SI Poll: Controls how often a device is polled // SI Poll: Controls how often a device is polled
union USIPoll union USIPoll
{ {
u32 hex; u32 hex = 0;
struct
{ BitField<0, 1, u32> VBCPY3; // 1: write to output buffer only on vblank
u32 VBCPY3 : 1; // 1: write to output buffer only on vblank BitField<1, 1, u32> VBCPY2;
u32 VBCPY2 : 1; BitField<2, 1, u32> VBCPY1;
u32 VBCPY1 : 1; BitField<3, 1, u32> VBCPY0;
u32 VBCPY0 : 1; BitField<4, 1, u32> EN3; // Enable polling of channel
u32 EN3 : 1; // Enable polling of channel BitField<5, 1, u32> EN2; // does not affect communication RAM transfers
u32 EN2 : 1; // does not affect communication RAM transfers BitField<6, 1, u32> EN1;
u32 EN1 : 1; BitField<7, 1, u32> EN0;
u32 EN0 : 1; BitField<8, 8, u32> Y; // Polls per frame
u32 Y : 8; // Polls per frame BitField<16, 10, u32> X; // Polls per X lines. begins at vsync, min 7, max depends on video mode
u32 X : 10; // Polls per X lines. begins at vsync, min 7, max depends on video mode BitField<26, 6, u32> reserved;
u32 : 6;
};
}; };
// SI Communication Control Status Register // SI Communication Control Status Register
union USIComCSR union USIComCSR
{ {
u32 hex = 0; u32 hex = 0;
struct
{ BitField<0, 1, u32> TSTART; // write: start transfer read: transfer status
u32 TSTART : 1; // write: start transfer read: transfer status BitField<1, 2, u32> CHANNEL; // determines which SI channel will be
u32 CHANNEL : 2; // determines which SI channel will be used on the communication interface. // used on the communication interface.
u32 : 3; BitField<3, 3, u32> reserved_1;
u32 CALLBEN : 1; // Callback enable BitField<6, 1, u32> CALLBEN; // Callback enable
u32 CMDEN : 1; // Command enable? BitField<7, 1, u32> CMDEN; // Command enable?
u32 INLNGTH : 7; BitField<8, 7, u32> INLNGTH;
u32 : 1; BitField<15, 1, u32> reserved_2;
u32 OUTLNGTH : 7; // Communication Channel Output Length in bytes BitField<16, 7, u32> OUTLNGTH; // Communication Channel Output Length in bytes
u32 : 1; BitField<23, 1, u32> reserved_3;
u32 CHANEN : 1; // Channel enable? BitField<24, 1, u32> CHANEN; // Channel enable?
u32 CHANNUM : 2; // Channel number? BitField<25, 2, u32> CHANNUM; // Channel number?
u32 RDSTINTMSK : 1; // Read Status Interrupt Status Mask BitField<27, 1, u32> RDSTINTMSK; // Read Status Interrupt Status Mask
u32 RDSTINT : 1; // Read Status Interrupt Status BitField<28, 1, u32> RDSTINT; // Read Status Interrupt Status
u32 COMERR : 1; // Communication Error (set 0) BitField<29, 1, u32> COMERR; // Communication Error (set 0)
u32 TCINTMSK : 1; // Transfer Complete Interrupt Mask BitField<30, 1, u32> TCINTMSK; // Transfer Complete Interrupt Mask
u32 TCINT : 1; // Transfer Complete Interrupt BitField<31, 1, u32> TCINT; // Transfer Complete Interrupt
};
USIComCSR() = default; USIComCSR() = default;
USIComCSR(u32 value) : hex{value} {} explicit USIComCSR(u32 value) : hex{value} {}
}; };
// SI Status Register // SI Status Register
union USIStatusReg union USIStatusReg
{ {
u32 hex = 0; u32 hex = 0;
struct
{ BitField<0, 1, u32> UNRUN3; // (RWC) write 1: bit cleared read 1: main proc underrun error
u32 UNRUN3 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error BitField<1, 1, u32> OVRUN3; // (RWC) write 1: bit cleared read 1: overrun error
u32 OVRUN3 : 1; // (RWC) write 1: bit cleared read 1: overrun error BitField<2, 1, u32> COLL3; // (RWC) write 1: bit cleared read 1: collision error
u32 COLL3 : 1; // (RWC) write 1: bit cleared read 1: collision error BitField<3, 1, u32> NOREP3; // (RWC) write 1: bit cleared read 1: response error
u32 NOREP3 : 1; // (RWC) write 1: bit cleared read 1: response error BitField<4, 1, u32> WRST3; // (R) 1: buffer channel0 not copied
u32 WRST3 : 1; // (R) 1: buffer channel0 not copied BitField<5, 1, u32> RDST3; // (R) 1: new Data available
u32 RDST3 : 1; // (R) 1: new Data available BitField<6, 2, u32> reserved_1; // 7:6
u32 : 2; // 7:6 BitField<8, 1, u32> UNRUN2; // (RWC) write 1: bit cleared read 1: main proc underrun error
u32 UNRUN2 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error BitField<9, 1, u32> OVRUN2; // (RWC) write 1: bit cleared read 1: overrun error
u32 OVRUN2 : 1; // (RWC) write 1: bit cleared read 1: overrun error BitField<10, 1, u32> COLL2; // (RWC) write 1: bit cleared read 1: collision error
u32 COLL2 : 1; // (RWC) write 1: bit cleared read 1: collision error BitField<11, 1, u32> NOREP2; // (RWC) write 1: bit cleared read 1: response error
u32 NOREP2 : 1; // (RWC) write 1: bit cleared read 1: response error BitField<12, 1, u32> WRST2; // (R) 1: buffer channel0 not copied
u32 WRST2 : 1; // (R) 1: buffer channel0 not copied BitField<13, 1, u32> RDST2; // (R) 1: new Data available
u32 RDST2 : 1; // (R) 1: new Data available BitField<14, 2, u32> reserved_2; // 15:14
u32 : 2; // 15:14 BitField<16, 1, u32> UNRUN1; // (RWC) write 1: bit cleared read 1: main proc underrun error
u32 UNRUN1 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error BitField<17, 1, u32> OVRUN1; // (RWC) write 1: bit cleared read 1: overrun error
u32 OVRUN1 : 1; // (RWC) write 1: bit cleared read 1: overrun error BitField<18, 1, u32> COLL1; // (RWC) write 1: bit cleared read 1: collision error
u32 COLL1 : 1; // (RWC) write 1: bit cleared read 1: collision error BitField<19, 1, u32> NOREP1; // (RWC) write 1: bit cleared read 1: response error
u32 NOREP1 : 1; // (RWC) write 1: bit cleared read 1: response error BitField<20, 1, u32> WRST1; // (R) 1: buffer channel0 not copied
u32 WRST1 : 1; // (R) 1: buffer channel0 not copied BitField<21, 1, u32> RDST1; // (R) 1: new Data available
u32 RDST1 : 1; // (R) 1: new Data available BitField<22, 2, u32> reserved_3; // 23:22
u32 : 2; // 23:22 BitField<24, 1, u32> UNRUN0; // (RWC) write 1: bit cleared read 1: main proc underrun error
u32 UNRUN0 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error BitField<25, 1, u32> OVRUN0; // (RWC) write 1: bit cleared read 1: overrun error
u32 OVRUN0 : 1; // (RWC) write 1: bit cleared read 1: overrun error BitField<26, 1, u32> COLL0; // (RWC) write 1: bit cleared read 1: collision error
u32 COLL0 : 1; // (RWC) write 1: bit cleared read 1: collision error BitField<27, 1, u32> NOREP0; // (RWC) write 1: bit cleared read 1: response error
u32 NOREP0 : 1; // (RWC) write 1: bit cleared read 1: response error BitField<28, 1, u32> WRST0; // (R) 1: buffer channel0 not copied
u32 WRST0 : 1; // (R) 1: buffer channel0 not copied BitField<29, 1, u32> RDST0; // (R) 1: new Data available
u32 RDST0 : 1; // (R) 1: new Data available BitField<30, 1, u32> reserved_4;
u32 : 1; BitField<31, 1, u32> WR; // (RW) write 1 start copy, read 0 copy done
u32 WR : 1; // (RW) write 1 start copy, read 0 copy done
};
USIStatusReg() = default; USIStatusReg() = default;
USIStatusReg(u32 value) : hex{value} {} explicit USIStatusReg(u32 value) : hex{value} {}
}; };
// SI EXI Clock Count // SI EXI Clock Count
union USIEXIClockCount union USIEXIClockCount
{ {
u32 hex; u32 hex = 0;
struct
{ BitField<0, 1, u32> LOCK; // 1: prevents CPU from setting EXI clock to 32MHz
u32 LOCK : 1; // 1: prevents CPU from setting EXI clock to 32MHz BitField<1, 30, u32> reserved;
u32 : 0;
};
}; };
static CoreTiming::EventType* s_change_device_event; static CoreTiming::EventType* s_change_device_event;
@ -257,14 +247,10 @@ static void UpdateInterrupts()
s_com_csr.RDSTINT = 0; s_com_csr.RDSTINT = 0;
// check if we have to generate an interrupt // check if we have to generate an interrupt
if ((s_com_csr.RDSTINT & s_com_csr.RDSTINTMSK) || (s_com_csr.TCINT & s_com_csr.TCINTMSK)) const bool generate_interrupt = (s_com_csr.RDSTINT & s_com_csr.RDSTINTMSK) != 0 ||
{ (s_com_csr.TCINT & s_com_csr.TCINTMSK) != 0;
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, true);
} ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, generate_interrupt);
else
{
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, false);
}
} }
static void GenerateSIInterrupt(SIInterruptType type) static void GenerateSIInterrupt(SIInterruptType type)
@ -499,28 +485,28 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
// In and out for the 4 SI channels. // In and out for the 4 SI channels.
for (int i = 0; i < MAX_SI_CHANNELS; ++i) for (u32 i = 0; i < u32(MAX_SI_CHANNELS); ++i)
{ {
// We need to clear the RDST bit for the SI channel when reading. // We need to clear the RDST bit for the SI channel when reading.
// CH0 -> Bit 24 + 5 // CH0 -> Bit 24 + 5
// CH1 -> Bit 16 + 5 // CH1 -> Bit 16 + 5
// CH2 -> Bit 8 + 5 // CH2 -> Bit 8 + 5
// CH3 -> Bit 0 + 5 // CH3 -> Bit 0 + 5
int rdst_bit = 8 * (3 - i) + 5; const u32 rdst_bit = 8 * (3 - i) + 5;
mmio->Register(base | (SI_CHANNEL_0_OUT + 0xC * i), mmio->Register(base | (SI_CHANNEL_0_OUT + 0xC * i),
MMIO::DirectRead<u32>(&s_channel[i].out.hex), MMIO::DirectRead<u32>(&s_channel[i].out.hex),
MMIO::DirectWrite<u32>(&s_channel[i].out.hex)); MMIO::DirectWrite<u32>(&s_channel[i].out.hex));
mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i), mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i),
MMIO::ComplexRead<u32>([i, rdst_bit](u32) { MMIO::ComplexRead<u32>([i, rdst_bit](u32) {
s_status_reg.hex &= ~(1 << rdst_bit); s_status_reg.hex &= ~(1U << rdst_bit);
UpdateInterrupts(); UpdateInterrupts();
return s_channel[i].in_hi.hex; return s_channel[i].in_hi.hex;
}), }),
MMIO::DirectWrite<u32>(&s_channel[i].in_hi.hex)); MMIO::DirectWrite<u32>(&s_channel[i].in_hi.hex));
mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i), mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i),
MMIO::ComplexRead<u32>([i, rdst_bit](u32) { MMIO::ComplexRead<u32>([i, rdst_bit](u32) {
s_status_reg.hex &= ~(1 << rdst_bit); s_status_reg.hex &= ~(1U << rdst_bit);
UpdateInterrupts(); UpdateInterrupts();
return s_channel[i].in_lo.hex; return s_channel[i].in_lo.hex;
}), }),
@ -532,13 +518,13 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | SI_COM_CSR, MMIO::DirectRead<u32>(&s_com_csr.hex), mmio->Register(base | SI_COM_CSR, MMIO::DirectRead<u32>(&s_com_csr.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](u32, u32 val) {
USIComCSR tmp_com_csr(val); const USIComCSR tmp_com_csr(val);
s_com_csr.CHANNEL = tmp_com_csr.CHANNEL; s_com_csr.CHANNEL = tmp_com_csr.CHANNEL.Value();
s_com_csr.INLNGTH = tmp_com_csr.INLNGTH; s_com_csr.INLNGTH = tmp_com_csr.INLNGTH.Value();
s_com_csr.OUTLNGTH = tmp_com_csr.OUTLNGTH; s_com_csr.OUTLNGTH = tmp_com_csr.OUTLNGTH.Value();
s_com_csr.RDSTINTMSK = tmp_com_csr.RDSTINTMSK; s_com_csr.RDSTINTMSK = tmp_com_csr.RDSTINTMSK.Value();
s_com_csr.TCINTMSK = tmp_com_csr.TCINTMSK; s_com_csr.TCINTMSK = tmp_com_csr.TCINTMSK.Value();
if (tmp_com_csr.RDSTINT) if (tmp_com_csr.RDSTINT)
s_com_csr.RDSTINT = 0; s_com_csr.RDSTINT = 0;
@ -560,7 +546,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | SI_STATUS_REG, MMIO::DirectRead<u32>(&s_status_reg.hex), mmio->Register(base | SI_STATUS_REG, MMIO::DirectRead<u32>(&s_status_reg.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](u32, u32 val) {
USIStatusReg tmp_status(val); const USIStatusReg tmp_status(val);
// clear bits ( if (tmp.bit) SISR.bit=0 ) // clear bits ( if (tmp.bit) SISR.bit=0 )
if (tmp_status.NOREP0) if (tmp_status.NOREP0)