mirror of
https://github.com/hch12907/orbum.git
synced 2024-05-20 05:00:48 -04:00
VIF: Implement microprogram-related instructions
This commit is contained in:
parent
7dc76e4c80
commit
b3676c2232
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue