VIF: Implement microprogram-related instructions

This commit is contained in:
hch12907 2018-11-21 22:33:57 +08:00
parent 7dc76e4c80
commit b3676c2232
5 changed files with 134 additions and 20 deletions

View file

@ -54,19 +54,25 @@ int CVif::time_step(const int ticks_available)
if (unit->stat.is_stalled())
continue;
// If the VIF is waiting for the VU, run the current instruction and call it a day
if (unit->stat.extract_field(VifUnitRegister_Stat::VEW))
{
(this->*INSTRUCTION_TABLE[unit->inst->get_info()->impl_index])(unit, *unit->inst);
continue;
}
// Check the FIFO queue for incoming DMA packet. Exit early if there is nothing to process.
if (!unit->dma_fifo_queue->has_read_available(NUMBER_BYTES_IN_QWORD))
continue;
uqword raw_data;
unit->dma_fifo_queue->read(reinterpret_cast<ubyte*>(&raw_data), NUMBER_BYTES_IN_QWORD);
for (uword data : raw_data.uw)
for (int i = unit->packet_progress; i < NUMBER_WORDS_IN_QWORD; i++, unit->packet_progress = i)
{
unit->dma_fifo_queue->read(reinterpret_cast<ubyte*>(&unit->processing_data), NUMBER_BYTES_IN_WORD);
// Four VIF statuses: 0b00 Idle, 01 Waiting for data, 10 Decoding VIFcode, 11 Decompressing data
const ubyte status = unit->stat.extract_field(VifUnitRegister_Stat::VPS);
unit->processing_data = data;
const uword& data = unit->processing_data;
// If the VIF is idling, treat the data as a VIFcode
if (!status)
@ -74,18 +80,18 @@ int CVif::time_step(const int ticks_available)
unit->code.write_uword(data);
unit->inst = std::make_unique<VifcodeInstruction>(data);
unit->stat.insert_field(VifUnitRegister_Stat::VPS, 0b10);
unit->packets_left = obtain_required_words(*unit->inst);
unit->subpackets_left = obtain_required_words(*unit->inst);
continue;
}
else
{
unit->packets_left--;
unit->subpackets_left--;
(this->*INSTRUCTION_TABLE[unit->inst->get_info()->impl_index])(unit, *unit->inst);
// If there are no packets left, set the VIF status to idle
if (!unit->packets_left)
if (!unit->subpackets_left)
{
unit->stat.insert_field(VifUnitRegister_Stat::VPS, 0b00);
@ -100,6 +106,11 @@ int CVif::time_step(const int ticks_available)
}
}
}
if (unit->packet_progress >= NUMBER_WORDS_IN_QWORD)
{
unit->packet_progress = 0;
}
}
return 1;

View file

@ -5,6 +5,9 @@
void CVif::FLUSHE(VifUnit_Base* unit, const VifcodeInstruction inst)
{
const RResources& r = core->get_resources();
const VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
unit->stat.insert_field(VifUnitRegister_Stat::VEW, vu->operation_state == VuOperationState::Run);
}
void CVif::FLUSH(VifUnit_Base* unit, const VifcodeInstruction inst)
@ -16,7 +19,15 @@ void CVif::FLUSH(VifUnit_Base* unit, const VifcodeInstruction inst)
return;
}
// TODO: Implement this
const RResources& r = core->get_resources();
const VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
// TODO: Confirm behaviour.
const bool condition = vu->operation_state == VuOperationState::Run
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P1Q)
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P2Q);
unit->stat.insert_field(VifUnitRegister_Stat::VEW, condition);
}
void CVif::FLUSHA(VifUnit_Base* unit, const VifcodeInstruction inst)
@ -28,19 +39,62 @@ void CVif::FLUSHA(VifUnit_Base* unit, const VifcodeInstruction inst)
return;
}
// TODO: Implement this
const RResources& r = core->get_resources();
const VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
const bool condition = vu->operation_state == VuOperationState::Run
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P1Q)
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P2Q)
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P3Q);
unit->stat.insert_field(VifUnitRegister_Stat::VEW, condition);
}
void CVif::MSCAL(VifUnit_Base* unit, const VifcodeInstruction inst)
{
BOOST_LOG(Core::get_logger()) << "MSCAL called - dis gon b gud";
RResources& r = core->get_resources();
VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
const bool vu_is_running = vu->operation_state == VuOperationState::Run;
if (vu_is_running)
{
unit->stat.insert_field(VifUnitRegister_Stat::VEW, 1);
return;
}
// Set the VU state and its PC
vu->operation_state = VuOperationState::Run;
vu->pc.write_uword(inst.imm() * 8);
}
void CVif::MSCNT(VifUnit_Base* unit, const VifcodeInstruction inst)
{
BOOST_LOG(Core::get_logger()) << "MSCNT called - dis gon b gud";
RResources& r = core->get_resources();
VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
const bool vu_is_running = vu->operation_state == VuOperationState::Run;
if (vu_is_running)
{
unit->stat.insert_field(VifUnitRegister_Stat::VEW, 1);
return;
}
// Set the VU state
vu->operation_state = VuOperationState::Run;
}
void CVif::MSCALF(VifUnit_Base* unit, const VifcodeInstruction inst)
{
BOOST_LOG(Core::get_logger()) << "MSCALF called - dis gon b gud";
// VIF1 only
if (unit->core_id != 1)
{
@ -48,5 +102,21 @@ void CVif::MSCALF(VifUnit_Base* unit, const VifcodeInstruction inst)
return;
}
// TODO: Implement this
}
RResources& r = core->get_resources();
VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
const bool should_wait = vu->operation_state == VuOperationState::Run
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P1Q)
|| r.ee.gif.stat.extract_field(GifRegister_Stat::P2Q);
if (should_wait)
{
unit->stat.insert_field(VifUnitRegister_Stat::VEW, 1);
return;
}
// Set the VU state
vu->operation_state = VuOperationState::Run;
vu->pc.write_uword(inst.imm() * 8);
}

View file

@ -86,7 +86,7 @@ void CVif::MARK(VifUnit_Base* unit, const VifcodeInstruction inst)
void CVif::STMASK(VifUnit_Base* unit, const VifcodeInstruction inst)
{
if (unit->packets_left)
if (unit->subpackets_left)
return;
unit->mask.write_uword(unit->processing_data);
@ -94,20 +94,20 @@ void CVif::STMASK(VifUnit_Base* unit, const VifcodeInstruction inst)
void CVif::STROW(VifUnit_Base* unit, const VifcodeInstruction inst)
{
if (unit->packets_left >= 4)
if (unit->subpackets_left >= 4)
return;
SizedWordRegister* row_regs[4] = { &unit->r3, &unit->r2, &unit->r1, &unit->r0 };
SizedWordRegister *const row_regs[4] = { &unit->r3, &unit->r2, &unit->r1, &unit->r0 };
row_regs[unit->packets_left]->write_uword(unit->processing_data);
row_regs[unit->subpackets_left]->write_uword(unit->processing_data);
}
void CVif::STCOL(VifUnit_Base* unit, const VifcodeInstruction inst)
{
if (unit->packets_left >= 4)
if (unit->subpackets_left >= 4)
return;
SizedWordRegister* col_regs[4] = { &unit->c3, &unit->c2, &unit->c1, &unit->c0 };
SizedWordRegister *const col_regs[4] = { &unit->c3, &unit->c2, &unit->c1, &unit->c0 };
col_regs[unit->packets_left]->write_uword(unit->processing_data);
col_regs[unit->subpackets_left]->write_uword(unit->processing_data);
}

View file

@ -5,6 +5,36 @@
void CVif::MPG(VifUnit_Base* unit, const VifcodeInstruction inst)
{
RResources& r = core->get_resources();
VuUnit_Base *const vu = r.ee.vpu.vu.units[unit->core_id];
ArrayByteMemory* vu_micro_mem[2] = { &r.ee.vpu.vu.unit_0.memory_micro, &r.ee.vpu.vu.unit_1.memory_micro };
const bool vu_is_running = vu->operation_state == VuOperationState::Run;
if (vu_is_running)
{
unit->stat.insert_field(VifUnitRegister_Stat::VEW, 1);
return;
}
// First pass - decoding VIF code & obtaining the num
if (unit->subpackets_left == obtain_required_words(inst))
{
unit->num.write_uword(inst.num());
unit->stat.insert_field(VifUnitRegister_Stat::VFS, 0b11);
}
// Other passes - transfer data to VU mem
if (unit->subpackets_left < obtain_required_words(inst))
{
const uword starting_addr = inst.imm() * 8;
const uword offset = (inst.num() - unit->num.read_uword()) * 4 + unit->packet_progress;
vu_micro_mem[unit->core_id]->write_uword(starting_addr + offset, unit->processing_data);
unit->num.write_uword(unit->num.read_uword() - 1);
}
}
void CVif::DIRECT(VifUnit_Base* unit, const VifcodeInstruction inst)

View file

@ -23,8 +23,11 @@ public:
/// The data being processed by the VIF.
uword processing_data;
/// A packet has 4 subpackets. Which one are we processing now?
uword packet_progress;
/// The amount of packets that are needed for processing.
uword packets_left;
uword subpackets_left;
/// DMA FIFO queue.
DmaFifoQueue<>* dma_fifo_queue;