Skip to content

Commit

Permalink
Added DMA Control Support
Browse files Browse the repository at this point in the history
Added:
* DMA Control Support
* Migration to New Range System
* New Range System
  • Loading branch information
Cherrytree56567 committed Oct 23, 2023
1 parent e5ac91f commit a376d38
Show file tree
Hide file tree
Showing 24 changed files with 118 additions and 70 deletions.
133 changes: 74 additions & 59 deletions PSEMU/Bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Bios.h"
#include "Range.h"
#include "RAM.h"
#include "DMA.h"

class Bus {
public:
Expand All @@ -20,33 +21,37 @@ class Bus {
const Range EXPANSION_1 = Range(0x1f000000, 512 * 1024);
const Range IRQ_CONTROL = Range(0x1f801070, 8);
const Range TIMERS = Range(0x1f801100, 0x30);
const Range DMA = Range(0x1f801080, 0x80);
const Range _DMA = Range(0x1f801080, 0x80);
const Range GPU = Range(0x1f801810, 8);
const Range MEM_CONTROL = Range(0x1f801000, 36);

uint32_t mask_region(uint32_t addr) {
// Index address space in 512MB chunks
uint32_t index = (addr >> 29);

return addr & region_mask[index];
return (addr & region_mask[index]);
}

// Load and Store functions
uint32_t load32(uint32_t addr) {

if (addr % 4 != 0) {
throw std::runtime_error("[Bus] ERROR: Unaligned load32 address " + std::to_string(addr));
}

uint32_t abs_addr = mask_region(addr);
if (RAM_.contains(abs_addr)) {
return ram.load32(RAM_.offset(abs_addr));
} else if (BIOS.contains(abs_addr)) {
return bios.load32(BIOS.offset(abs_addr));
} else if (IRQ_CONTROL.contains(abs_addr)) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << "\n";
return 0;
} else if (DMA.contains(abs_addr)) {
std::cout << "[BUS] WARNING: DMA NOT IMPLEMENTED. DMA read: " << std::to_string(DMA.offset(abs_addr)) << "\n";
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
return ram.load32(offset.value());
} else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) {
return bios.load32(offset.value());
} else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(offset.value()) << "\n";
return 0;
} else if (GPU.contains(abs_addr)) {
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(GPU.offset(abs_addr)) << "\n";
switch (GPU.offset(abs_addr)) {
} else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
dma_reg(offset.value());
} else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(offset.value()) << "\n";
switch (offset.value()) {
case 4:
return 0x1c000000;
break;
Expand All @@ -56,38 +61,34 @@ class Bus {
}
}

if (addr % 4 != 0) {
throw std::runtime_error("[Bus] ERROR: Unaligned load32 address " + std::to_string(addr));
}

throw std::runtime_error("[Bus] ERROR: Unhandled fetch32 at address " + std::to_string(addr));
}

void store32(uint32_t addr, uint32_t value) {
uint32_t abs_addr = mask_region(addr);
if (RAM_.contains(abs_addr)) {
ram.store32(RAM_.offset(abs_addr), value);
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
ram.store32(offset.value(), value);
return;
} else if (BIOS.contains(abs_addr)) {
bios.store32(BIOS.offset(abs_addr), value);
} else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) {
bios.store32(offset.value(), value);
return;
} else if (IRQ_CONTROL.contains(abs_addr)) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control: " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n";
} else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control: " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
return;
} else if (DMA.contains(abs_addr)) {
} else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: DMA NOT IMPLEMENTED. DMA write: " << std::to_string(abs_addr) << std::to_string(value) << "\n";
return;
} else if (GPU.contains(abs_addr)) {
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU write " << std::to_string(GPU.offset(abs_addr)) << " " << std::to_string(value) << "\n";
} else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU write " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
return;
} else if (TIMERS.contains(abs_addr)) {
std::cout << "[BUS] WARNING: Timer NOT IMPLEMENTED. Timer write register" << std::to_string(TIMERS.offset(abs_addr)) << " " << std::to_string(value) << "\n";
} else if (auto offset = TIMERS.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: Timer NOT IMPLEMENTED. Timer write register" << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
return;
} else if (CACHE_CONTROL.contains(abs_addr)) {
std::cout << "[Bus] WARNING: Cache Control not implemented. Cache Control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n";
} else if (auto offset = CACHE_CONTROL.contains(abs_addr); offset.has_value()) {
std::cout << "[Bus] WARNING: Cache Control not implemented. Cache Control read " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
return;
} else if (MEM_CONTROL.contains(abs_addr)) {
switch (MEM_CONTROL.offset(abs_addr)) {
} else if (auto offset = MEM_CONTROL.contains(abs_addr); offset.has_value()) {
switch (offset.value()) {
case 0:
if (value != 0x1f000000) {
std::cout << "[Bus] ERROR: Bad Expansion 1 base address: " << std::to_string(value) << "\n";
Expand All @@ -99,11 +100,11 @@ class Bus {
}
break;
default:
std::cout << "[Bus] ERROR: Unhandled write to MEM Control " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n";
std::cout << "[Bus] ERROR: Unhandled write to MEM Control " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
break;
}
return;
} else if (RAM_SIZE.contains(abs_addr)) {
} else if (auto offset = RAM_SIZE.contains(abs_addr); offset.has_value()) {
return;
}

Expand All @@ -117,17 +118,17 @@ class Bus {

void store16(uint32_t addr, uint16_t value) {
uint32_t abs_addr = mask_region(addr);
if (RAM_.contains(abs_addr)) {
ram.store16(RAM_.offset(abs_addr), value);
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
ram.store16(offset.value(), value);
return;
} else if (SPU.contains(abs_addr)) {
std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU write register " << std::to_string(SPU.offset(abs_addr)) << "\n";
} else if (auto offset = SPU.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU write register " << std::to_string(offset.value()) << "\n";
return;
} else if (TIMERS.contains(abs_addr)) {
std::cout << "[BUS] WARNING: TIMER NOT IMPLEMENTED. Timer write register " << std::to_string(TIMERS.offset(abs_addr)) << "\n";
} else if (auto offset = TIMERS.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: TIMER NOT IMPLEMENTED. Timer write register " << std::to_string(offset.value()) << "\n";
return;
} else if (IRQ_CONTROL.contains(abs_addr)) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control write " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n";
} else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control write " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n";
return;
}

Expand All @@ -141,11 +142,11 @@ class Bus {

void store8(uint32_t addr, uint8_t value) {
uint32_t abs_addr = mask_region(addr);
if (RAM_.contains(abs_addr)) {
ram.store8(RAM_.offset(abs_addr), value);
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
ram.store8(offset.value(), value);
return;
} else if (EXPANSION_2.contains(abs_addr)) {
std::cout << "[BUS] WARNING: Expansion 2 NOT IMPLEMENTED. Expansion 2 read register " << std::to_string(EXPANSION_2.offset(abs_addr)) << "\n";
} else if (auto offset = EXPANSION_2.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: Expansion 2 NOT IMPLEMENTED. Expansion 2 read register " << std::to_string(offset.value()) << "\n";
return;
}

Expand All @@ -160,12 +161,12 @@ class Bus {
uint8_t load8(uint32_t addr) {
uint32_t abs_addr = mask_region(addr);

if (RAM_.contains(abs_addr)) {
return ram.load8(RAM_.offset(abs_addr));
} else if (BIOS.contains(abs_addr)) {
return bios.load8(BIOS.offset(abs_addr));
} else if (EXPANSION_1.contains(abs_addr)) {
std::cout << "[BUS] WARNING: Expansion 1 NOT IMPLEMENTED. Expansion 1 read register " << std::to_string(EXPANSION_1.offset(abs_addr)) << "\n";
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
return ram.load8(offset.value());
} else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) {
return bios.load8(offset.value());
} else if (auto offset = EXPANSION_1.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: Expansion 1 NOT IMPLEMENTED. Expansion 1 read register " << std::to_string(offset.value()) << "\n";
return 0;
}

Expand All @@ -175,21 +176,35 @@ class Bus {
uint16_t load16(uint8_t addr) {
uint32_t abs_addr = mask_region(addr);

if (RAM_.contains(abs_addr)) {
return ram.load16(RAM_.offset(abs_addr));
} else if (SPU.contains(abs_addr)) {
std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU read register " << std::to_string(SPU.offset(abs_addr)) << "\n";
if (auto offset = RAM_.contains(abs_addr); offset.has_value()) {
return ram.load16(offset.value());
} else if (auto offset = SPU.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU read register " << std::to_string(offset.value()) << "\n";
return 0;
} else if (IRQ_CONTROL.contains(abs_addr)) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << "\n";
} else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(offset.value()) << "\n";
return 0;
}

throw std::runtime_error("[Bus] ERROR: Unhandled load16 into address " + std::to_string(addr));
}

uint32_t dma_reg(uint32_t offset) {
switch (offset){
case 0x70:
return dma.get_control();
break;

default:
std::cout << "[BUS] Unhandled DMA access\n";
return 0;
break;
}
}

Bios bios;
RAM ram;
DMA dma;

const uint32_t region_mask[8] = {
0xffffffff, 0xffffffff,
Expand Down
4 changes: 3 additions & 1 deletion PSEMU/CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ void CPU::reset() {
regs[i] = 0xdeadbeef;
out_regs[i] = 0xdeadbeef;
}
out_regs[0] = 0;
regs[0] = 0;
load = std::make_tuple(0, 0);
sr = 0;
cause = 0;
Expand Down Expand Up @@ -50,7 +52,7 @@ void CPU::fetch() {
}

void CPU::decode_execute(Instruction instruction) {
std::cout << "instruction: " << instruction.instruction << "\n";
std::cout << "PC: " << pc << "\n";
switch (instruction.opcode()) {
case (0b000000):
switch (instruction.function()) {
Expand Down
1 change: 1 addition & 0 deletions PSEMU/DMA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "DMA.h"
15 changes: 15 additions & 0 deletions PSEMU/DMA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include <cstdint>

class DMA {
public:
DMA() {
control = 0x07654321;
}

uint32_t get_control() { return control; }

private:
uint32_t control;
};

3 changes: 3 additions & 0 deletions PSEMU/PSEMU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ int main() {
while (true) {
cpu.tick();
}
for (int i = 0; i < 2 * 1024 * 1024; i++) {
std::cout << bus.ram.load32(i) << "\n";
}
return 0;
}
2 changes: 2 additions & 0 deletions PSEMU/PSEMU.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
<ClCompile Include="Bios.cpp" />
<ClCompile Include="Bus.cpp" />
<ClCompile Include="CPU.cpp" />
<ClCompile Include="DMA.cpp" />
<ClCompile Include="PSEMU.cpp" />
<ClCompile Include="RAM.cpp" />
</ItemGroup>
Expand All @@ -144,6 +145,7 @@
<ClInclude Include="Bios.h" />
<ClInclude Include="Bus.h" />
<ClInclude Include="CPU.h" />
<ClInclude Include="DMA.h" />
<ClInclude Include="Instruction.h" />
<ClInclude Include="RAM.h" />
<ClInclude Include="Range.h" />
Expand Down
9 changes: 9 additions & 0 deletions PSEMU/PSEMU.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<Filter Include="Source Files\Bus\RAM">
<UniqueIdentifier>{8524c40f-742d-4742-baa0-fa4732042965}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Bus\DMA">
<UniqueIdentifier>{3dcc3f34-d96f-4c55-abea-df2abfcfccee}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="PSEMU.cpp">
Expand All @@ -45,6 +48,9 @@
<ClCompile Include="RAM.cpp">
<Filter>Source Files\Bus\RAM</Filter>
</ClCompile>
<ClCompile Include="DMA.cpp">
<Filter>Source Files\Bus\DMA</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Testing\OP_ADD\ADD_TEST.asm">
Expand All @@ -70,5 +76,8 @@
<ClInclude Include="RAM.h">
<Filter>Source Files\Bus\RAM</Filter>
</ClInclude>
<ClInclude Include="DMA.h">
<Filter>Source Files\Bus\DMA</Filter>
</ClInclude>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion PSEMU/RAM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

void RAM::newl() {
for (int i = 0; i < (2 * 1024 * 1024); i++) {
ram[i] = 0x0;
ram[i] = 0xca;
}
}

Expand Down
11 changes: 5 additions & 6 deletions PSEMU/Range.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ struct Range {

Range(uint32_t s, uint32_t l) : start(s), length(l) {}

inline bool contains(uint32_t addr) const {
return (addr >= start && addr < start + length);
}

inline uint32_t offset(uint32_t addr) const {
return addr - start;
std::optional<uint32_t> contains(uint32_t addr) const {
if (addr >= start && addr < start + length)
return (addr - start);
else
return std::nullopt;
}
};
Binary file modified PSEMU/x64/Debug/CPU.obj
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.ilk
Binary file not shown.
7 changes: 4 additions & 3 deletions PSEMU/x64/Debug/PSEMU.log
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(132,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(826,53): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1102,16): warning C4244: 'initializing': conversion from 'uint64_t' to 'uint32_t', possible loss of data
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1104,23): warning C4293: '>>': shift count negative or too big, undefined behavior
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(828,53): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1104,16): warning C4244: 'initializing': conversion from 'uint64_t' to 'uint32_t', possible loss of data
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1106,23): warning C4293: '>>': shift count negative or too big, undefined behavior
DMA.cpp
PSEMU.cpp
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
Expand Down
Binary file modified PSEMU/x64/Debug/PSEMU.obj
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog
Binary file not shown.
1 change: 1 addition & 0 deletions PSEMU/x64/Debug/PSEMU.tlog/Cl.items.tlog
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
C:\Users\ronit\Desktop\PSEMU\PSEMU\Bios.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\Bios.obj
C:\Users\ronit\Desktop\PSEMU\PSEMU\Bus.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\Bus.obj
C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\CPU.obj
C:\Users\ronit\Desktop\PSEMU\PSEMU\DMA.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\DMA.obj
C:\Users\ronit\Desktop\PSEMU\PSEMU\PSEMU.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\PSEMU.obj
C:\Users\ronit\Desktop\PSEMU\PSEMU\RAM.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\RAM.obj
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/link.command.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/link.write.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/vc143.idb
Binary file not shown.
Binary file modified PSEMU/x64/Debug/vc143.pdb
Binary file not shown.
Binary file modified x64/Debug/PSEMU.exe
Binary file not shown.
Binary file modified x64/Debug/PSEMU.pdb
Binary file not shown.

0 comments on commit a376d38

Please sign in to comment.