-
-
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
Inout fix #1046
Conversation
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.
First off: thanks for spending the effort on this!
Some good news first: I had a look at my initial issue - that is fixed and Vivado is also happy with the outcome.
I had a bit of a look on the code and noticed a few corner cases
In addition we have a small inconsistency that I did not want to hunt down today (too late ;-)):
We can leave all analog inputs of one signal unconnected
case class Top() extends Component {
val y = inout(Analog(Bits(2 bit)))
}
But once we connect one of them, we have to all?
case class Top() extends Component {
val y = inout(Analog(Bits(2 bit)))
y(0) := True
}
}) | ||
for(bitId <- 0 until widthOf(seed)){ | ||
val flushes = ArrayBuffer[(AggregateKey, AggregateCtx)]() | ||
val island = bitToIsland(Bit(seed, bitId, c.dslBody)) |
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.
Two issues here
First
Island building in 341 has a small issue in the sense that an assignment like y(0 downto 0) := sub.x
works, while sub.x := y(0 downto 0)
doesn't. I tried fixing that carrying along the analog flag when creating the extract, but that breaks if a user calls setAsAnalog
after making the extract.
It's not per-se an issue if we have to call setAsAnalog
on the extracts, but if one forgets we currently crash here (y(0) will never be added to any island since the target is not analog) with
Exception in thread "main" java.util.NoSuchElementException: key not found: Bit((toplevel/y : inout Bits[2 bits]),0,spinal.core.internals.ScopeStatement@ec38bef)
test code for that
case class Sub() extends Component {
val x = inout(Analog(Bits(1 bit)))
x(0) := True
}
case class Top() extends Component {
val sub = Sub()
val y = inout(Analog(Bits(2 bit)))
sub.x := y(0 downto 0)
y(1) := True
}
We could make that a bit more understandable if we check here like:
val island = bitToIsland.get(Bit(seed, bitId, c.dslBody)) match {
case Some(x) => x
case None => SpinalError("DISCONTINUITY IN ANALOG CONNECTION ...")
}
As far as I see it I think we can do either:
- add in the error check from above (and possibly a explanation to RTD ;-))
- extend all the extraction functions to carry along the analog attribute (and document the weird corner cases in RTD :-( )
- I also tried extending the check in 328 to also build the island if the source is analog, but that creates a host of other problems...
So just bite the bullet and require .setAsAnalog()
?
Edit: remove the "second" issue, that was due to some local changes...
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.
The issue you had was that sub.x := y(0 downto 0).setAsAnalog() was required when you tested it.
Now that .setAsAnalog() isn't necessary anymore (today push) it is all good.
Can you confirm ? (as far as i can see)
Fixed with 28636e8 |
Most of the issues are gone, but the changes now seem to have broken the "normal" generation of a driver for the val x = new Component {
val read = out Bool()
val write = in Bool()
val en = in Bool()
val pad = inout(Analog(Bits(width bit)))
for (i <- 0 until width) {
read := pad(i)
when(en) {
pad(i) := write
}
}
} in which case the current code suspects that This time I pushed my test cases (currently w/o real verification) here: https://github.com/andreasWallner/SpinalHDL/tree/inout-fix |
Should be fixed with 56b956c Note : val read = out Bits(width bit) //!!!
val write = in Bool()
val en = in Bool()
val pad = inout(Analog(Bits(width bit)))
for (i <- 0 until width) {
read(i) := pad(i)
when(en) {
pad(i) := write
}
} |
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.
Thanks for all the effort!
LGTM - should we also pull add a few testcases
I added a few here: https://github.com/andreasWallner/SpinalHDL/tree/inout-fix - while there is currently no simulation with them, but at least they are testing generation
It would be great, especialy corner cases. It was my plan to add some, but currently i'm in a 2 week work trip, so realy busy, i realy lagging behind, trying to catch up emails XD |
I'm so sorry, writing tests it looks like I stumbled over another corner case: object Blub extends App {
SpinalVerilog(new Component {
val pad = inout(Analog(Bits(2 bit)))
val sliced_sub = new Component {
val pad = inout(Analog(Bits(1 bit)))
}
pad(0 downto 0) <> sliced_sub.pad
})
} Which fails with
Also: something seems to be weird with |
Good catch ^^ |
@andreasWallner Hi ^^ |
@Dolu1990 I initially tried to also test the direction from driving the |
Add testcases for analog connections
@andreasWallner I pushed a thing to disable VHDL from AnalogConnectionCocotbBoot. |
I had a look at the generated VHDL and that looks good to me... just to be sure I'll try testing it with xcelium in case I overlooked something, I should find some time to do that today. |
Any deposit to a pad signal breaks the analog tests since these act as forces on the signal. Therefore driving 'z' fixes the pad level to 'z'. `Release` also does not improve the situation - so simply never touch those signals.
Fix cocotb test cases
Nice :D |
@Dolu1990 sounds good to me! |
This PR reimplement how Analog are managed in order to allows much more flexibility and also fix existing issues.
Now, analog connections are tracked bit by bit (Island) then aggreged together for the final connection.
All the assignements between analogs are deleted and then regenerated into a solved manner.
This is kind of a big change XD