1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-26 15:32:04 +00:00

Eliminates unexpected bottleneck created by ACIA.

This commit is contained in:
Thomas Harte 2019-11-09 15:00:12 -05:00
parent cc7ff1ec9e
commit 8c736a639a
4 changed files with 30 additions and 34 deletions

View File

@ -91,29 +91,6 @@ void ACIA::write(int address, uint8_t value) {
update_clocking_observer();
}
void ACIA::run_for(HalfCycles length) {
if(transmit.transmission_data_time_remaining() > HalfCycles(0)) {
const auto write_data_time_remaining = transmit.write_data_time_remaining();
// There's at most one further byte available to enqueue, so a single 'if'
// rather than a 'while' is correct here. It's the responsibilit of the caller
// to ensure run_for lengths are appropriate for longer sequences.
if(length >= write_data_time_remaining) {
if(next_transmission_ != NoValueMask) {
transmit.advance_writer(write_data_time_remaining);
consider_transmission();
transmit.advance_writer(length - write_data_time_remaining);
} else {
transmit.advance_writer(length);
update_clocking_observer();
if(transmit_interrupt_enabled_) add_interrupt_cause(TransmitNeedsWrite);
}
} else {
transmit.advance_writer(length);
}
}
}
void ACIA::consider_transmission() {
if(next_transmission_ != NoValueMask && !transmit.write_data_time_remaining()) {
// Establish start bit and [7 or 8] data bits.

View File

@ -11,6 +11,7 @@
#include <cstdint>
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../ClockReceiver/ForceInline.hpp"
#include "../../ClockReceiver/ClockingHintSource.hpp"
#include "../SerialPort/SerialPort.hpp"
@ -49,7 +50,28 @@ class ACIA: public ClockingHint::Source, private Serial::Line::ReadDelegate {
Advances @c transmission_cycles in time, which should be
counted relative to the @c transmit_clock_rate.
*/
void run_for(HalfCycles transmission_cycles);
forceinline void run_for(HalfCycles transmission_cycles) {
if(transmit.transmission_data_time_remaining() > HalfCycles(0)) {
const auto write_data_time_remaining = transmit.write_data_time_remaining();
// There's at most one further byte available to enqueue, so a single 'if'
// rather than a 'while' is correct here. It's the responsibilit of the caller
// to ensure run_for lengths are appropriate for longer sequences.
if(transmission_cycles >= write_data_time_remaining) {
if(next_transmission_ != NoValueMask) {
transmit.advance_writer(write_data_time_remaining);
consider_transmission();
transmit.advance_writer(transmission_cycles - write_data_time_remaining);
} else {
transmit.advance_writer(transmission_cycles);
update_clocking_observer();
if(transmit_interrupt_enabled_) add_interrupt_cause(TransmitNeedsWrite);
}
} else {
transmit.advance_writer(transmission_cycles);
}
}
}
bool get_interrupt_line() const;

View File

@ -84,14 +84,6 @@ void Line::write(HalfCycles cycles, int count, int levels) {
}
}
HalfCycles Line::write_data_time_remaining() {
return HalfCycles(remaining_delays_);
}
HalfCycles Line::transmission_data_time_remaining() {
return HalfCycles(remaining_delays_ + transmission_extra_);
}
void Line::reset_writing() {
remaining_delays_ = 0;
events_.clear();

View File

@ -12,6 +12,7 @@
#include <vector>
#include "../../Storage/Storage.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../ClockReceiver/ForceInline.hpp"
namespace Serial {
@ -44,11 +45,15 @@ class Line {
void write(HalfCycles cycles, int count, int levels);
/// @returns the number of cycles until currently enqueued write data is exhausted.
HalfCycles write_data_time_remaining();
forceinline HalfCycles write_data_time_remaining() const {
return HalfCycles(remaining_delays_);
}
/// @returns the number of cycles left until it is guaranteed that a passive reader
/// has received all currently-enqueued bits.
HalfCycles transmission_data_time_remaining();
forceinline HalfCycles transmission_data_time_remaining() const {
return HalfCycles(remaining_delays_ + transmission_extra_);
}
/// Eliminates all future write states, leaving the output at whatever it is now.
void reset_writing();