1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Starts sketching out the asynchronous bus.

This commit is contained in:
Thomas Harte 2019-04-29 13:45:53 -04:00
parent 97e118abfa
commit d9071ee9f1
5 changed files with 110 additions and 81 deletions

View File

@ -60,8 +60,8 @@ class QL: public CPU::MC68000::BusHandler {
// Check that the two coincide.
if(strcmp(correct_state, local_state)) {
fprintf(stderr, "Diverges at line %d\n", line_count);
fprintf(stderr, "Good: %s", correct_state);
fprintf(stderr, "Bad: %s", local_state);
fprintf(stderr, "Good: %s\n", correct_state);
fprintf(stderr, "Bad: %s\n", local_state);
assert(false);
}
}

View File

@ -220,6 +220,24 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform = false> cla
State get_state();
void set_state(const State &);
/// Sets the DTack line — @c true for active, @c false for inactive.
void set_dtack(bool);
/// Sets the VPA (valid peripheral address) line — @c true for active, @c false for inactive.
void set_is_peripheral_address(bool);
/// Sets the bus error line — @c true for active, @c false for inactive.
void set_bus_error(bool);
/// Sets the interrupt lines, IPL0, IPL1 and IPL2.
void set_interrupt_level(int);
/// Sets the bus request line.
void set_bus_request(bool);
/// Sets the bus acknowledge line.
void set_bus_acknowledge(bool);
private:
T &bus_handler_;
};

View File

@ -39,6 +39,75 @@
template <class T, bool dtack_is_implicit, bool signal_will_perform> void Processor<T, dtack_is_implicit, signal_will_perform>::run_for(HalfCycles duration) {
HalfCycles remaining_duration = duration + half_cycles_left_to_run_;
while(remaining_duration > HalfCycles(0)) {
/*
PERFORM THE CURRENT BUS STEP'S MICROCYCLE.
*/
// Check for DTack if this isn't being treated implicitly.
if(active_step_->microcycle.data_select_active()) {
if(!dtack_is_implicit) {
if(active_step_->microcycle.data_select_active() && !dtack_) {
// TODO: perform wait state.
continue;
}
}
// TODO: synchronous bus.
} else {
// TODO: check for bus error (but here, or when checking for DTACK?)
// if(active_step_->microcycle.operation & MicroCycle::NewAddress) {
// }
}
// Perform the microcycle.
remaining_duration -=
active_step_->microcycle.length +
bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_);
#ifdef LOG_TRACE
if(!(active_step_->microcycle.operation & Microcycle::IsProgram)) {
switch(active_step_->microcycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) {
default: break;
case Microcycle::SelectWord | Microcycle::Read:
printf("[%08x -> %04x] ", *active_step_->microcycle.address, active_step_->microcycle.value->full);
break;
case Microcycle::SelectByte | Microcycle::Read:
printf("[%08x -> %02x] ", *active_step_->microcycle.address, active_step_->microcycle.value->halves.low);
break;
case Microcycle::SelectWord:
printf("{%04x -> %08x} ", active_step_->microcycle.value->full, *active_step_->microcycle.address);
break;
case Microcycle::SelectByte:
printf("{%02x -> %08x} ", active_step_->microcycle.value->halves.low, *active_step_->microcycle.address);
break;
}
}
#endif
/*
PERFORM THE BUS STEP'S ACTION.
*/
switch(active_step_->action) {
default:
std::cerr << "Unimplemented 68000 bus step action: " << int(active_step_->action) << std::endl;
return;
break;
case BusStep::Action::None: break;
case BusStep::Action::IncrementEffectiveAddress0: effective_address_[0].full += 2; break;
case BusStep::Action::IncrementEffectiveAddress1: effective_address_[1].full += 2; break;
case BusStep::Action::DecrementEffectiveAddress0: effective_address_[0].full -= 2; break;
case BusStep::Action::DecrementEffectiveAddress1: effective_address_[1].full -= 2; break;
case BusStep::Action::IncrementProgramCounter: program_counter_.full += 2; break;
case BusStep::Action::AdvancePrefetch:
prefetch_queue_.halves.high = prefetch_queue_.halves.low;
break;
}
// Move to the next bus step.
++ active_step_;
/*
FIND THE NEXT MICRO-OP IF UNKNOWN.
*/
@ -67,22 +136,29 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
#endif
decoded_instruction_ = prefetch_queue_.halves.high.full;
if(!instructions[decoded_instruction_].micro_operations) {
// TODO: once all instructions are implemnted, this should be an instruction error.
std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl;
return;
} else {
#ifdef LOG_TRACE
std::cout << std::hex << (program_counter_.full - 4) << ": " << std::setw(4) << decoded_instruction_ << '\t';
std::cout << std::hex << (program_counter_.full - 4) << ": " << std::setw(4) << decoded_instruction_ << '\t';
#endif
}
if(signal_will_perform) {
bus_handler_.will_perform(program_counter_.full - 4, decoded_instruction_);
}
active_program_ = &instructions[decoded_instruction_];
active_micro_op_ = active_program_->micro_operations;
if(instructions[decoded_instruction_].micro_operations) {
active_program_ = &instructions[decoded_instruction_];
active_micro_op_ = active_program_->micro_operations;
} else {
active_program_ = nullptr;
active_micro_op_ = exception_micro_ops_; // TODO.
// The vector used dependds on whether this is a vanilla unrecognised instruction, or
// one on the A or F lines.
switch(decoded_instruction_ >> 12) {
default: populate_trap_steps(get_status(), 4); break;
case 0xa: populate_trap_steps(get_status(), 10); break;
case 0xf: populate_trap_steps(get_status(), 11); break;
}
}
}
auto bus_program = active_micro_op_->bus_program;
@ -1775,73 +1851,6 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
}
}
}
/*
PERFORM THE CURRENT BUS STEP'S MICROCYCLE.
*/
// Check for DTack if this isn't being treated implicitly.
if(!dtack_is_implicit) {
if(active_step_->microcycle.data_select_active() && !dtack_) {
// TODO: perform wait state.
continue;
}
}
// TODO: synchronous bus.
// TODO: check for bus error.
// Perform the microcycle.
remaining_duration -=
active_step_->microcycle.length +
bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_);
#ifdef LOG_TRACE
if(!(active_step_->microcycle.operation & Microcycle::IsProgram)) {
switch(active_step_->microcycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) {
default: break;
case Microcycle::SelectWord | Microcycle::Read:
printf("[%08x -> %04x] ", *active_step_->microcycle.address, active_step_->microcycle.value->full);
break;
case Microcycle::SelectByte | Microcycle::Read:
printf("[%08x -> %02x] ", *active_step_->microcycle.address, active_step_->microcycle.value->halves.low);
break;
case Microcycle::SelectWord:
printf("{%04x -> %08x} ", active_step_->microcycle.value->full, *active_step_->microcycle.address);
break;
case Microcycle::SelectByte:
printf("{%02x -> %08x} ", active_step_->microcycle.value->halves.low, *active_step_->microcycle.address);
break;
}
}
#endif
/*
PERFORM THE BUS STEP'S ACTION.
*/
switch(active_step_->action) {
default:
std::cerr << "Unimplemented 68000 bus step action: " << int(active_step_->action) << std::endl;
return;
break;
case BusStep::Action::None: break;
case BusStep::Action::IncrementEffectiveAddress0: effective_address_[0].full += 2; break;
case BusStep::Action::IncrementEffectiveAddress1: effective_address_[1].full += 2; break;
case BusStep::Action::DecrementEffectiveAddress0: effective_address_[0].full -= 2; break;
case BusStep::Action::DecrementEffectiveAddress1: effective_address_[1].full -= 2; break;
case BusStep::Action::IncrementProgramCounter: program_counter_.full += 2; break;
case BusStep::Action::AdvancePrefetch:
prefetch_queue_.halves.high = prefetch_queue_.halves.low;
break;
}
// Move to the next bus step.
++ active_step_;
}
half_cycles_left_to_run_ = remaining_duration;

View File

@ -3535,7 +3535,7 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
steps[4].microcycle.value = steps[5].microcycle.value = &program_counter_.halves.low;
}
// Set initial state. Largely TODO.
// Set initial state.
active_step_ = reset_bus_steps_;
effective_address_[0] = 0;
is_supervisor_ = 1;

View File

@ -326,8 +326,9 @@ class ProcessorStorage {
// A lookup table from instructions to implementations.
Program instructions[65536];
// Special steps for exception handlers.
// Special steps and programs for exception handlers.
BusStep *reset_bus_steps_;
MicroOp *exception_micro_ops_;
// Special micro-op sequences and storage for conditionals.
BusStep *branch_taken_bus_steps_;
@ -397,8 +398,9 @@ class ProcessorStorage {
// Fill in the status word value.
destination_bus_data_[0].full = status;
// Switch to supervisor mode.
// Switch to supervisor mode, disable the trace bit.
set_is_supervisor(true);
trace_flag_ = 0;
// Pick a vector.
effective_address_[0].full = vector << 2;