On 2007-09-08, Timothy Normand Miller wrote:
> On 9/8/07, Petter Urkedal <[EMAIL PROTECTED]> wrote:
> > Here is my attempt to refine the I/O ports. For PCI I'm making wild
> > guesses, so nailing down the ports is just an easy way to expose my
> > misunderstandings. The point is to gain some understanding of how the
> > nanocontroller will interact with the PCI controller (and memory).
> >
> > Memory read
> > in MEM_READREQ_FREE Free slots in command pipe.
> > out MEM_READREQ_ADDR First address to read.
> > out MEM_READREQ_COUNT Number of words to read.
> > in MEM_READREPLY_DATA Data stream from memory.
> > in MEM_READREPLY_AVAIL Number of words in FIFO.
>
> Perfect.
>
> BTW, in the symbol name, we may want to add a reminder to the human
> programmer as to which ones are "trigger" writes. For instance,
> MEM_READREQ_COUNT triggers the read at the address that was programmed
> in.
We could use MEM_READREQ_ADDR so that we can allow skipping the count if
it's the same as the last one, then
Memory read
in MEM_READREQ_FREE Free slots in command pipe.
out MEM_READREQ_COUNT Number of words to read.
out MEM_READREQ_ADDR_TRIG First address to read.
in MEM_READREPLY_DATA Data stream from memory.
in MEM_READREPLY_AVAIL Number of words in FIFO.
>
> I'm not sure that the count has much meaning. Writes are nice in that
> in some cases like this one, we can just "fire and forget." :)
All this great new terminology ;-)
So now we have,
Memory write
out MEM_WRITE_ADDR Start address.
in MEM_WRITE_FREE Free slots in output FIFO.
out MEM_WRITE_DATA Data stream to memory.
And, this is unchanged:
Master read
in PCI_MASTER_READREQ_FREE Free slots in command pipe.
out PCI_MASTER_READREQ_ADDR Host-mapped address to read.
out PCI_MASTER_READREQ_COUNT Number of words to receive.
in PCI_MASTER_READREPLY_DATA Data stream from host.
in PCI_MASTER_READREPLY_AVAIL Number of words in FIFO.
> Now that I think about it, I rather prefer the idea of indicating
> count up front, rather than having to tag the last word. This way,
> nothing (besides the master, which really needs to know the most and
> soonest) has to keep track of when the last word is going to come
> through.
I though the master needed to know in advance, but now that you mention
it I remember the PCI allows us to just terminate at will. Is there an
advantage with not using the count, that we can continue streaming past
the 2^6 or so limit if we wish? And for the number of instructions, it
does not matter. We write to a count before, or we write to another
register after. If we want to optimise, we replace the count port with
PCI_MASTER_WRITE_DATA_FINAL.
> And moreover, I'm also thinking that perhaps the DMA master should
> have separate command and write data fifos. This way, some other
> agent can be filling the data fifo asynchronously. For instance, some
> data words come in from the memory system, but the master doesn't know
> what to do with them, so it doesn't do anything, and then the
> nanocontroller gets around to sending a command to the master, and
> then it can do something with the data. More opportunity to make
> things asynchronous.
Great idea! Let's put in a reminder (PCI_MASTER_WRITE_ROUTE). Now, if
we also replace the count, we have
Master write
out PCI_MASTER_WRITE_ADDR Host-mapped address to write.
out PCI_MASTER_WRITE_ROUTE FIFO routing commands.
in PCI_MASTER_WRITE_FREE Free words in output FIFO.
out PCI_MASTER_WRITE_DATA Data stream to host.
out PCI_MASTER_WRITE_DATA_FINAL Final data word to host.
Maybe using PCI_MASTER_WRITE_ROUTE should be mandatory, also when
filling the pipeline with PCI_MASTER_WRITE_DATA. That way, we can make
sure enough data to avoid PCI timeout before triggering the DMA.
> > Target of write (we're reading)
> > in PCI_TARGET_WRITEREQ_ADDR Target address of write.
> > in PCI_TARGET_WRITEREQ_COUNT Number of words to receive.
> > in PCI_TARGET_WRITEREPLY_AVAIL Number of words in FIFO.
> > out PCI_TARGET_WRITEREPLY_DATA Data stream from host.
>
> This one's tricky. With the target, we have absolutely no control
> here. For one thing, we "config" ports that set whether or not we're
> take PIO accesses. Either they go directly over to the Spartan, or
> they all come to us. Or perhaps we want to select by BAR. Not sure
> exactly yet.
>
> Now, the only time we do intercept PIO transactions is when we're
> really going to process them somehow, so the flow control can be as
> complex as we can afford in the time available.
>
> So, basically, I think we could make do with one physical fifo. The
> target keeps track of addresses for PIO bursts, so we could just push
> 64-bit entries into a fifo. 4 bits are byte flags. 28 bits are a
> word address (1 GiB max space). 32 bits are data. One way to handle
> this is to have one I/O port samples (but doesn't dequeue) the
> flags/address word. The other I/O port grabs the data and dequeues.
> This way, in the unlikely event that you KNEW what the next address
> would be, you could just ignore it and grab the data in one cycle.
>
> These would be the I/O ports:
>
> in PCI_TARGET_WRITE_COUNT The number of words in the write queue
> in PCI_TARGET_WRITE_ADDRFLAGS Address and flags for a write data word
> in PCI_TARGET_WRITE_DATA Data of write word
Looks good to me.
But this raises a question. I assume we can ignore byte-enables for
master mode, since we're deciding. For target read it also does not
matter for non-config space since we are just be filling in redundant
information. So is target write the only non-config mode where we care
about byte-enables?
That also brings up a general question about all addresses. In the
nanocontroller we have a 32 bit granularity on scratch space. Would it
not save us code if address ports are all right-shifted 2 bits, and in
the case we need byte-enable, they are on a separate port?
> You know what? We'll never be able to keep up with that. It's too
> complicated. There's absolutely no reason why PIO reads have to be
> fast, ESPECIALLY in the cases where we would actually intercept
> requests. PIO reads suck, and we should not put gobs of logic into
> trying to make it not suck. So, no, I think we should handle one at a
> time, and each individual transaction should be only one word. In
> this state, the target would be in a mode where it always asserts STOP
> at the same time as TRDY, on top of the usual timeout mechanism.
>
> So here are the ports:
>
> in PCI_TARGET_READ_PENDING Is a read pending?
> in PCI_TARGET_READ_ADDR The one address that is pending
> out PCI_TARGET_READ_DATA Where we write the one data word
I like this simple solution if PIOs efficiency is secondary. We'd would
probably need interrupts to handle them without timing out.
> So, if the read times out, the controller is smart enough to recognize
> that the address of a later retry is the same as the posted one and
> automatically returns the data (if we've supplied any) or times out
> (if we haven't supplied any).
That sounded easy at first, but isn't there a race condition here? The
PCI target sets the address. The nanocode sees the address and start
computing the reply. The PCI target has timed out and gotten a new
request, then updates the address. The nanocode writes the reply to the
previous address. Hmm, we'll need to let the PCI target also detect
when the nanocontroller reads the address, and discard any data which
the nanocode writes prior to reading the last address.
> Note that we could probably combine PENDING and ADDR. It's not a
> queue. Most of the bits will be the address, and one is a flag
> indicating if it's valid. The PENDING flag will be cleared whenever
> we write to the DATA port (which is also not a queue).
I suggest we let ADDR be negative if there is nothing pending, since we
don't need addresses above 2 GiB. That way, we can use the bneg
instruction.
in PCI_TARGET_READ_ADDR The one address that is pending or -1.
out PCI_TARGET_READ_DATA Where we write the one data word
> In the microcode we would do well to do some sort of caching, so that
> we can return data before timeout (by my design, we have only 8 PCI
> cycles, though). But that's all an implementation detail.
Okay, let's postpone that, since it doesn't affect the ports. It'll
probably be more clear at we start to write the code.
> Oh, and don't forget PCI_TARGET_INTERCEPT_CONFIG or whatever.
Will this be unified with target-write ports? Can you type it out?
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)