-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Bittide.ObliviousFifo #299
base: staging
Are you sure you want to change the base?
Conversation
ba75b30
to
c04ad8a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure about this. This seems to "stack" complexity instead of composing it. What I had in mind was the following reset strategy (i.e., after each step the reset of the next step is deasserted):
- Clock board initialization
- Transceiver initialization
- Counters + clock control
- DcFifo and its control logic
- ....
This seems to squash together (3 + 4), though not exactly everything. I guess my question is: what is the advantage of this over "just" keeping them separate?
15e137d
to
c880d9c
Compare
c880d9c
to
64af089
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've got trouble parsing the implementation, I thought the whole point of the oblivious FIFO was to eliminate the separate domainDiffCounter
. This just seems to move it, which I don't really see the point of.
If we want to fold it up into one FIFO, couldn't we:
- Count the write-on-full transactions on the write side
- Count the read-on-empty transactions on the read side
Then:
- On the write side
- full: up counter
- not full and counter != 0: decrease counter, write garbage
- otherwise: write valid frame
- On the read side:
- empty: up counter
- not empty and counter != 0: decrease counter, report garbage
- otherwise: read word (might be garbage if write side indicated so)
If we then want to know the virtual data counter on the read side then: count reported by FIFO - read_on_empty_counter + synced_write_on_full_counter
. Where synced_write_on_full_counter
is periodically synchronized from the write side by a handshake.
-- | This FIFO combines 'Clash.Cores.Xilinx.DcFifo.dcFifo' with | ||
-- 'Bittide.Counter.domainDiffCounter' to create an oblivious FIFO | ||
-- that supports a much larger _virtual_ data counter than the number | ||
-- of elements that it can actually hold. The FIFO is able to hold | ||
-- @2^n-1@ virtual elements and @2^m-1@ real data elements, where @n@ | ||
-- can be much larger than @m@. When its real size @m@ is exceeded, | ||
-- then the FIFO does not loose the frames, but only forgets about | ||
-- their data. This means, that the frames are still counted, | ||
-- "traverse" the FIFO and are output at the other end in the same | ||
-- order as they are written to the component. The only difference is | ||
-- that frames, which are written to the FIFO, when its real capacity | ||
-- is already utilized, are output with a @lost@ status instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: In retrospect this documentation might just be hard because I don't understand the point of this implementation, see main PR comment.
I found it hard to read this documentation. It's hard to put a finger on what exactly is causing this difficulty but I think it is because:
- It assumes the reader is familiar with both
dcFifo
anddomainDiffCounter
- It assumes it's "obvious" how
dcFifo
anddomainDiffCounter
would marry so-to-speak - It introduces the name "oblivious" without explaining what exactly is oblivious about it
- It is quick to introduce very exact notation (mentioning type variables)
I think it should be restructured such that:
$what
$why
$details
E.g.,
Like a normal dual clock FIFO, but instead of dropping a write transaction on a write-on-full it inserts a "lost" (garbage) word instead. It does this without dropping any existing data. Lost words are kept track of using a counter, so the virtual size of the FIFO can grow arbitrarily large.
This is used within Bittide to....
Mention
n
,m
, ...
IMO it's worth renaming to noDropFifo
or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noDropFifo
also sounds misleading to me, as this FIFO still drops the data, but keeps the frame skeleton in the right order.
No doubt, however, naming the functionality of this thing turns out to be hard 🙃
No, the idea behind the oblivious FIFO is that it elides the need for a detection mechanism figuring out the point in time at which the real buffer, i.e. the
But with the proposed implementation the value would not be cycle accurate. With the current implementation it is. Please also note that the PR still is WIP and by no means complete. Nevertheless, thanks a lot for the early review comments. |
Ah ok, then I think I might have been conflating multiple ideas. What would a "detection mechanism" look like otherwise? Isn't it just observing the out-of-bound signal from the FIFO on either end?
Does this matter at all? A handshake takes between ~10-20 cycles (depending on settings), while the clock offsets are measured in parts per million. I.e., for a clock offset of 25 ppm we expect to do ~2000-4000 handshakes before measuring a single tick too much or tock too little. I also don't really understand the idea on why the current implementation would be "cycle accurate" btw, but I'll have to study the current algo more.
Yes, noted. I saw some activity on it, and we mentioned pulling it from the shelve again a few weeks ago so I figure I'd take another look. |
ae85e86
to
a98cca5
Compare
Dismissing my review as the changes requested was more for dropping the |
a98cca5
to
c8e1bb2
Compare
c8e1bb2
to
13a7113
Compare
This FIFO combines
Clash.Cores.Xilinx.DcFifo.dcFifo
withBittide.Counter.domainDiffCounter
to create an oblivious FIFO that supports a much larger virtual data counter than the number of elements that it can actually hold. The FIFO is able to hold2^n-1
virtual elements and2^m-1
real data elements, wheren
can be much larger thanm
. When its real sizem
is exceeded, then the FIFO does not loose the frames, but only forgets about their data. This means, that the frames are still counted, "traverse" the FIFO and are output at the other end in the same order as they are written to the component. The only difference is that frames, which are written to the FIFO, when its real capacity is reached, are output with alost
status instead.Note: This implementation is completely untested and currently only serves as a "proof-of-concept".