2019-09-14 19:11:20 +00:00
|
|
|
package razorvine.ksim65
|
|
|
|
|
|
|
|
import razorvine.ksim65.components.Address
|
|
|
|
import razorvine.ksim65.components.BusComponent
|
|
|
|
import razorvine.ksim65.components.MemMappedComponent
|
|
|
|
import razorvine.ksim65.components.UByte
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The system bus that connects all other components together.
|
|
|
|
* Usually, there is just a single Bus present.
|
|
|
|
*
|
|
|
|
* It distributes reset and clock signals to every connected component.
|
|
|
|
* Data bytes can be read from the bus or written to the bus. It's distributed to the corresponding component(s).
|
|
|
|
*/
|
2019-09-11 00:17:59 +00:00
|
|
|
class Bus {
|
|
|
|
|
|
|
|
private val components = mutableListOf<BusComponent>()
|
|
|
|
private val memComponents = mutableListOf<MemMappedComponent>()
|
|
|
|
|
|
|
|
fun reset() {
|
|
|
|
components.forEach { it.reset() }
|
|
|
|
memComponents.forEach { it.reset() }
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clock() {
|
|
|
|
components.forEach { it.clock() }
|
|
|
|
memComponents.forEach { it.clock() }
|
|
|
|
}
|
|
|
|
|
2019-09-15 03:04:57 +00:00
|
|
|
operator fun plusAssign(memcomponent: MemMappedComponent) = add(memcomponent)
|
|
|
|
operator fun plusAssign(component: BusComponent) = add(component)
|
|
|
|
operator fun get(address: Address): UByte = read(address)
|
|
|
|
operator fun set(address: Address, data: UByte) = write(address, data)
|
|
|
|
|
|
|
|
|
2019-09-11 00:17:59 +00:00
|
|
|
fun add(component: BusComponent) {
|
|
|
|
components.add(component)
|
|
|
|
component.bus = this
|
|
|
|
}
|
|
|
|
|
|
|
|
fun add(component: MemMappedComponent) {
|
|
|
|
memComponents.add(component)
|
|
|
|
component.bus = this
|
|
|
|
}
|
|
|
|
|
2019-09-14 19:11:20 +00:00
|
|
|
/**
|
|
|
|
* Read a data byte at the given address.
|
|
|
|
* The first memory mapped component that listens to that address, will respond.
|
|
|
|
*/
|
2019-09-11 00:17:59 +00:00
|
|
|
fun read(address: Address): UByte {
|
|
|
|
memComponents.forEach {
|
2019-09-11 00:19:33 +00:00
|
|
|
if (address >= it.startAddress && address <= it.endAddress)
|
2019-09-11 00:17:59 +00:00
|
|
|
return it[address]
|
|
|
|
}
|
|
|
|
return 0xff
|
|
|
|
}
|
|
|
|
|
2019-09-14 19:11:20 +00:00
|
|
|
/**
|
|
|
|
* Write a data byte to the given address.
|
|
|
|
* Any memory mapped component that listens to the address, will receive the data.
|
|
|
|
*/
|
2019-09-11 00:17:59 +00:00
|
|
|
fun write(address: Address, data: UByte) {
|
2019-09-15 03:04:57 +00:00
|
|
|
require(data in 0..255) { "data must be a byte 0..255" }
|
2019-09-11 00:17:59 +00:00
|
|
|
memComponents.forEach {
|
2019-09-11 00:19:33 +00:00
|
|
|
if (address >= it.startAddress && address <= it.endAddress)
|
2019-09-11 00:17:59 +00:00
|
|
|
it[address] = data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|