Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

How do we clock a contended bus controller? [OC2]

Recommended Posts

This is something that I'm scratching my head over. It would be great if this were written in C (and if I had a dollar for every time I thought that... I think I'm up to about $5 now?), but alas, it isn't, and thus multiple return values are very much out of the question.

Having a think about it, it would make sense if the bus ran at 1MHz. The Z80 currently runs at 2MHz, and all memory accesses on the Z80 tend to take a minimum of 3 cycles (in reality it's more like 2 cycles followed by a DRAM refresh but we'll just skip on that and assume the whole window is available for it). The MIPS3 core I'm working on also runs at 2MHz. I would like to be able to clock that at a higher speed than the main bus, but in order for that to work, the bus needs an API for it.

Easy case: Only one CPU on the bus


public int getTime(int cpuid);
public int ensureTime(int cpuid, int currentTick);
public int eatCycles(int cpuid, int startTick, int lengthInTicks);
Reason for providing cpuid anyway is so that the same API can be used for a multi-CPU setup.

Reason for returning an int in ensureTime is to get the correct point in time.

How to access the bus (a proposal):

int targetBusTime = this.currentTimeSliceBusTicks - (this.cycleBudget/this.clockMultiplier);
int actualBusTime = memory.ensureTime(this.cpuid, targetBusTime);

// do reads and writes here - eatCycles is called by the bus components

int endBusTime = memory.getTime(this.cpuid);
this.cycleBudget = this.currentTimeSliceCpuTicks - endBusTime;
Of course, a more advanced CPU implementation would track this as a separate variable, and dispatch reads and writes in a manner that avoids stalling the CPU where possible.

In a system which ignores the cpuid, these can be implemented like so:


private int busTime = 0;

private int onTickStart_ResetBusTime() {
    this.busTime = 0;

public int getTime(int cpuid) {
    return this.busTime;

public int ensureTime(int cpuid, int currentTick) {
    if(this.busTime < currentTick) {
        this.busTime = currentTick;
    return this.busTime;

public int eatCycles(int cpuid, int startTick, int lengthInTicks) {
    this.busTime += lengthInTicks;
    return this.busTime;
Hard case: More than one CPU on the bus

Oh yeah, the thing that makes this more fun? By "CPU", anything which does DMA could be classified as a "CPU".

If all CPUs execute in parallel, then the one-CPU approach can work just fine. Otherwise, that bus is going to suffer horribly.

Ultimately you need to track each CPU's busTime in an array (i.e. private int[] busArray;), and implement what is basically a memory allocator minus the memory.

You'll basically need to track various windows into the bus in a sorted manner. I'd say a bitfield implemented in terms of ints would be the most suitable approach.

As for ensuring that no one CPU can hog the bus the whole time, well, you could possibly inject a few windows into the bus on the bus controller. Or you could just punch anyone who decides to use a 6502 on a multiprocessor system.

One more thing, I've just noticed an issue with this "time travel" approach: There is no guarantee that I/O will be executed in the correct order or RAM updated in the correct order between CPUs.

Easy solution for hard case: Timeslicing

Each CPU gets given a reasonably short timeslice of the bus. Possibly two timeslices per tick.

Really easy solution for hard case: Don't even bother with accuracy

Just run each CPU in its own thread and completely ignore this proposal. Simple.

Edited by GreaseMonkey
Link to post
Share on other sites

OC-ARM's timing simulation isn't very detailed. Every instruction and every memory access incurs a cycle cost with no simulation of contention or other wait states. As much as I enjoy optimizing around low-level details like bus timings, a less precise scheme like that is probably enough for OpenComputers purposes.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.