1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 03:29:45 +00:00

Expose full bus to IOC dependents; add notes.

This commit is contained in:
Thomas Harte 2024-03-25 11:07:44 -04:00
parent ae684edbe1
commit 521fca6089
4 changed files with 93 additions and 28 deletions

View File

@ -15,6 +15,20 @@
namespace InstructionSet::ARM {
/// Maps from a semantic ARM read of type @c SourceT to either the 8- or 32-bit value observed
/// by watching the low 8 bits or all 32 bits of the data bus.
template <typename DestinationT, typename SourceT>
DestinationT read_bus(SourceT value) {
if constexpr (std::is_same_v<DestinationT, SourceT>) {
return value;
}
if constexpr (std::is_same_v<DestinationT, uint8_t>) {
return uint8_t(value);
} else {
return value | (value << 8) | (value << 16) | (value << 24);
}
}
/// A class compatible with the @c OperationMapper definition of a scheduler which applies all actions
/// immediately, updating either a set of @c Registers or using the templated @c MemoryT to access
/// memory. No hooks are currently provided for applying realistic timing.

View File

@ -142,7 +142,7 @@ class ConcreteMachine:
return executor_.bus.video().crt().get_scaled_scan_status();
}
std::array<uint32_t, 750> pc_history;
std::array<uint32_t, 75> pc_history;
std::size_t pc_history_ptr = 0;
uint32_t instr_count = 0;
@ -168,7 +168,7 @@ class ConcreteMachine:
static bool log = false;
static bool accumulate = false;
// if(executor_.pc() == 0x03803400) {
// if(executor_.pc() == 0x03801ed8 || executor_.registers()[9] == 0x00ff'0000) {
// printf("At %08x; after last PC %08x and %zu ago was %08x\n", executor_.pc(), pc_history[(pc_history_ptr - 2 + pc_history.size()) % pc_history.size()], pc_history.size(), pc_history[pc_history_ptr]);
// }
@ -186,7 +186,7 @@ class ConcreteMachine:
}
// TODO: pipeline prefetch?
// log |= executor_.pc() == 0x3961244;
// log |= executor_.pc() == 0x03801ebc;
// log |= instr_count == 72766815;
// log &= executor_.pc() != 0x000000a0;

View File

@ -128,15 +128,16 @@ struct InputOutputController {
/// Access type.
enum class Type {
Sync = 0b00,
Fast = 0b01,
Medium = 0b10,
Fast = 0b10,
Medium = 0b01,
Slow = 0b11
} type;
};
bool read(uint32_t address, uint8_t &value) {
template <typename IntT>
bool read(uint32_t address, IntT &value) {
const Address target(address);
value = 0xff;
value = IntT(~0);
switch(target.bank) {
default:
@ -217,13 +218,22 @@ struct InputOutputController {
// logger.error().append("%02x: Counter %d high is %02x", target, (target >> 4) - 0x4, value);
break;
}
return true;
break;
}
// if constexpr (std::is_same_v<IntT, uint8_t>) {
// } else {
// // TODO: generalise this adaptation of an 8-bit device to the 32-bit bus, which probably isn't right anyway.
// uint8_t value;
// ioc_.read(address, value);
// source = value;
// }
return true;
}
bool write(uint32_t address, uint8_t value) {
template <typename IntT>
bool write(uint32_t address, IntT value) {
const Address target(address);
switch(target.bank) {
default:
@ -238,13 +248,21 @@ struct InputOutputController {
break;
case 0x00:
// TODO: does the rest of the control register relate to anything?
control_ = value;
control_ = static_cast<uint8_t>(value);
i2c_.set_clock_data(!(value & 2), !(value & 1));
// Per the A500 documentation:
// b7: vertical sync/test input bit, so should be programmed high;
// b6: input for printer acknowledgement, so should be programmed high;
// b5: speaker mute; 1 = muted;
// b4: "Available on the auxiliary I/O connector"
// b3: "Programmed HIGH, unless Reset Mask is required."
// b2: Used as the floppy disk (READY) input and must be programmed high;
// b1 and b0: I2C connections as above.
break;
case 0x04:
serial_.output(IOCParty, value);
serial_.output(IOCParty, static_cast<uint8_t>(value));
irq_b_.clear(IRQB::KeyboardTransmitEmpty);
observer_.update_interrupts();
break;
@ -260,9 +278,9 @@ struct InputOutputController {
break;
// Interrupts.
case 0x18: irq_a_.mask = value; break;
case 0x28: irq_b_.mask = value; break;
case 0x38: fiq_.mask = value; break;
case 0x18: irq_a_.mask = static_cast<uint8_t>(value); break;
case 0x28: irq_b_.mask = static_cast<uint8_t>(value); break;
case 0x38: fiq_.mask = static_cast<uint8_t>(value); break;
// Counters.
case 0x40: case 0x50: case 0x60: case 0x70:
@ -285,7 +303,48 @@ struct InputOutputController {
counters_[(target.offset >> 4) - 0x4].output = counters_[(target.offset >> 4) - 0x4].value;
break;
}
return true;
break;
// Bank 5: both the hard disk and the latches, depending on type.
case 5:
switch(target.type) {
default:
logger.error().append("Unrecognised IOC bank 5 type %d write; %02x to offset %02x", target.type, value, target.offset);
break;
case Address::Type::Fast:
switch(target.offset) {
default:
logger.error().append("Unrecognised IOC fast bank 5 write; %02x to offset %02x", value, target.offset);
break;
}
break;
// TODO, per the A500 documentation:
//
// Latch A:
// b0, b1, b2, b3 = drive selects;
// b4 = side select;
// b5 = motor on/off
// b6 = floppy in use (i.e. LED?);
// b7 = "Not used."
//
// Latch B:
// b0: ?
// b1: double/single density; 0 = double.
// b2: ?
// b3: floppy drive reset; 0 = reset.
// b4: printer strobe
// b5: ?
// b6: ?
// b7: HS3?
//
// Latch C:
// (probably not present on earlier machines?)
// b2/b3: sync polarity [b3 = V polarity, b2 = H?]
// b0/b1: VIDC master clock; 00 = 24Mhz, 01 = 25.175Mhz; 10 = 36Mhz; 11 = reserved.
}
break;
}
// case 0x327'0000 & AddressMask: // Bank 7

View File

@ -114,8 +114,7 @@ struct MemoryController {
} break;
case Zone::IOControllers:
// TODO: have I overrestricted the value type for the IOC area?
ioc_.write(address, uint8_t(source));
ioc_.template write<IntT>(address, source);
break;
case Zone::VideoController:
@ -172,16 +171,9 @@ struct MemoryController {
source = high_rom<IntT>(address);
break;
case Zone::IOControllers: {
if constexpr (std::is_same_v<IntT, uint8_t>) {
ioc_.read(address, source);
} else {
// TODO: generalise this adaptation of an 8-bit device to the 32-bit bus, which probably isn't right anyway.
uint8_t value;
ioc_.read(address, value);
source = value;
}
} break;
case Zone::IOControllers:
ioc_.template read<IntT>(address, source);
break;
default:
logger.error().append("TODO: read from %08x", address);