-
-
Notifications
You must be signed in to change notification settings - Fork 303
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
Ability to remap address for BusSlaveFactory #1354
base: dev
Are you sure you want to change the base?
Conversation
50b9c34
to
c5140f2
Compare
A use-case can be seen here: https://github.com/KireinaHoro/enzian-pio-nic/blob/69c8548e905e72ae899f2b0b10dd52b6d75f737f/hw/spinal/pionic/eci/EciDecoupledRxTxProtocol.scala#L57-L63 I remap 0x40 of the bus to 0xc0, in order to allow aliasing the two memory regions filled by memory read. |
Hi, That's interresting ^^ But at the same time, having it there in the bus slave factory base would allow to have a portable aproache. So, why not ? |
Yeah I agree. So what happened is that I tried doing it outside of the bus slave factory first by first unbursting the AXI bus and then remapping it, but for some reason it didn't work (I didn't investigate why). The approach of doing it in the slave factory has the benefit of not having to worry about bus details. For example, AXI4-MM has bursts, so simply remapping part of the address space will not work: a master can issue a burst read that does not start directly at the remapped address (AR is only transmitted once and the beat addresses are calculated by burst mode). I'll put together a more general version next week and hopefully see how we can test it with some other bus protocols. |
…nalHDL into busslavefactory-remap-pr
After some backend P&R work, it became apparent that if I do something complicated in remap, I need a pipeline stage between remap and the downstream operators. I pushed a new commit for this. New questions @Dolu1990:
|
8c9acfd
to
7bad6f7
Compare
def mapElement[E <: Data](locator: T => E)(f: E => E): T = { | ||
val ret = b.clone.asInstanceOf[T].allowOverride() | ||
ret := b | ||
locator(ret) := f(locator(b)) |
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.
locator(ret).removeAssignments() := f(locator(b))
Would remove the need of allowOverride and avoid the double assignement.
def mapElement[E <: Data](locator: T => E)(f: E => E): T = { | ||
val ret = b.clone.asInstanceOf[T].allowOverride() | ||
ret := b | ||
locator(ret) := f(locator(b)) |
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.
locator(ret).removeAssignments() := f(locator(b))
Would remove the need of allowOverride and avoid the double assignement.
implicit class RichMultiData[T <: MultiData](b: T) { | ||
def mapElement[E <: Data](locator: T => E)(f: E => E): T = { | ||
val ret = b.clone.asInstanceOf[T].allowOverride() | ||
ret := b |
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.
val ret = CombInit(b).allowOverride()
:)
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.
What's the difference between CombInit
and clone
?
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.
clone => create a new signal of the same kind => type copy
CombInit => create a new signal of the same kind and assign it with the provided argument aswell => type + value copy
Hi,
The one issue i have with it, is may push people to chain mapElement to modify multiple elements. In general, i'm doing things more like : val miaou = CombInit(original)
miaou.x.removeAssignements() := 0x42
miaou.y.removeAssignements() := 0x42 So maybe a more sane aproache overall would be to have a dedicated assignement operator ? val miaou = CombInit(original)
val miaou.x :=!! 0x42 //Override value of x completly
For timing reasons ? |
Thanks for the review!
This I agree, mapElement on MultiData is in principle equivalent to this and I think this syntax is clearer.
Yes. In the AXI slave factory originally the unburst and downstream actions are in the same clock cycle and it was still passable; chaining in remapping the address made the comb path very long (>15 stages). |
at the same time short hands are good <3 What's about : val wuff = miaou.combInit(_.x := miaou.y + 0x42)
Hmmm, else an alternative is to RegNext the result of the remap, and systematicaly block the access first cycle (half throughput) |
This would then become: val remapped = awChan.map { aw =>
aw.combInit(_.addr := aw.addr + 0x42)
} Feels quite concise already, I feel like I can take this. It has the advantage of not having to specialise on
Yeah but that would require changing everywhere |
Hmm wouldn't it just be a specific implementation in the frontend of Axi4SlaveFactory ? |
This draft PR is intended more as a discussion point; I don't think it can be merged as is.
Context, Motivation & Description
I'm working on a slave design that involves aliasing a resource into multiple places; this is necessary for
Mem
for example, since callingreadMemSync
multiple times would create multiple memory ports.I've implemented a simple remap functionality on
Axi4SlaveFactory
for this purpose; it works for my test case so far. However, I feel like such a feature would belong in the generalBusSlaveFactory
through duplicating the relevant the job elements. I'm not so familiar with the internals with the general version, so I'm not sure if it's actually doable there.@jiegec since you're the original author of
Axi4SlaveFactory
.Checklist
/** */
?