Skip to content
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

[regif] feature upgrade refactoring #1409

Merged
merged 34 commits into from
May 31, 2024
Merged

[regif] feature upgrade refactoring #1409

merged 34 commits into from
May 31, 2024

Conversation

jijingg
Copy link
Collaborator

@jijingg jijingg commented May 8, 2024

This update is based on practical feedback from real projects, and the changes are quite significant. In addition to adding some important features, many factory functions have been added, and common register file reuse scenarios have been solved. suggestions from software usage have been adopted to optimize..h file.
Despite such significant refactoring modifications, backward compatibility should be maintained in principle, and it will not affect old code.

  • 1. remove BusIfVistor mode instead directly access for simplify
  • 2. suport fifo[wrfifo/rdfifo]/ram interface
  • 3. readLogic support replace
  • 4. add RegInstGrp layer
  • 5. refactor BusIf Document, but keep old api
  • 6. add usefull Factory method(Interrupt, SCR etc..)
  • 7. localbus add
  • 8. demo example update
  • 9. add reuse Block layer
  • 10. optmize CHeader /HTML format

Checklist

  • Unit tests were added done
  • API changes are or will be documented: TODO

1. remove BusIfVistor mode instead directly access for simplify
2. add RegInstGrp layer
3. refactor BusIf Document, but keep old api
4. add usefull Factory method(Interrupt, SCR etc..)
5. localbus
@jijingg jijingg marked this pull request as draft May 8, 2024 17:54
@andreasWallner
Copy link
Collaborator

I know this is still a draft, but a few thoughts:

  • what is lbus/mbus - I couldn't find any spec; is this some company internal bus that you are using? Should it be in spinal.lib?
  • removing the visitor breaks current users of the library - we should not do that
  • in general many of these changes seem to break existing users (ones with custom output generators, by moving classes, etc.)
  • this seems to only support FIFO writes, not reads, when adding FIFO access it should allow for both; the current design can't be easily extended for read

possibly more to follow, have to look at it some more

@jijingg
Copy link
Collaborator Author

jijingg commented May 10, 2024

  • removing the visitor breaks current users of the library - we should not do that
    @andreasWallner
  1. Although there isn't a standard, it's basically an unwritten but widely used bus approach, which may have some naming differences, but the logic is the same. Since every team will use it, I suggest providing an implementation in Spinal to avoid everyone reinventing the wheel. (Of course, we can discuss naming further. I also don't think "lbus" or "mbus" is a good idea. That includes their signal names as well.)
  2. Secondly, maintaining backward compatibility as the first priority for open-source projects, which is not violated here. The original method can still be used, and API conversion can be used to accomplish this seamlessly, without impacting users.
  3. Same as 2, it is insensitive to existing users and cannot cause crashes of existing code
  4. Regarding the logic behind bus.readata, there is still work to be done, which is why it's currently in draft status. However, the FIFO reading you mentioned is indeed a good idea, even though I haven't encountered such a scenario yet. I believe FIFO reading could have potential use, and I will consider implementing it.

@Readon
Copy link
Collaborator

Readon commented May 23, 2024

FIFO is really a special case, when writing to a FIFO it should be tested if it is writable first. So the data and status of FIFO might need to be added separately, which is a little bit different from the existing regif interface.

On the other hand, before read, the host should check if there is data in the FIFO.

@jijingg
Copy link
Collaborator Author

jijingg commented May 24, 2024

FIFO is really a special case, when writing to a FIFO it should be tested if it is writable first. So the data and status of FIFO might need to be added separately, which is a little bit different from the existing regif interface.

yes the FIFO port cannot strictly guarantee no data loss,
if the user scenario is sensitive to operation loss, there are two ways for users to solve it

  1. Calculate the maximum throughput per unit time and choose the issuance operation to ensure that the FIFO does not overflow per unit time.
  2. The status information of FIFO can be hung on registers for software to read, and the software's issuance operation needs to refer to the FIFO's status as handshake

On the other hand, before read, the host should check if there is data in the FIFO.

right, If it is an effective read operation, the software does need to first determine whether there is data. to be honest,
FIFO reading may have use-case , but I haven't encountered them yet. I'm still on the fence about whether it's necessary to implement the read functionality of a FIFO.
So the functionality of reading from a FIFO seems to have too many limitations and is somewhat redundant. It has to worry about HW-write overflows and also consider the possibility of SW-read miss

@Readon
Copy link
Collaborator

Readon commented May 24, 2024

n the fence about whether it's necessary to implement the read functionality of a FIFO.
So the functionality of reading from a FIFO seems to have too many limitations and is somewhat redundant. It has to worry about HW-write overflows and also consider the possibility of SW-read miss

Ahhh,We use a lot while designing an instrument.
On common case is that a streamlized SPI or UART controller might want to use FIFO to cache the data to be transmitted.

@jijingg
Copy link
Collaborator Author

jijingg commented May 24, 2024

Ahhh,We use a lot while designing an instrument.
On common case is that a streamlized SPI or UART controller might want to use FIFO to cache the data to be transmitted.

i got it, so now If we sensitive to packet loss, we may need some peripheral auxiliary circuits or handshake to ensure data. Since that's the case, it's necessary to add this feature , but the specific data caching correctness needs to be guaranteed by the user themselves, is it OK?

@Readon
Copy link
Collaborator

Readon commented May 24, 2024

Ahhh,We use a lot while designing an instrument.
On common case is that a streamlized SPI or UART controller might want to use FIFO to cache the data to be transmitted.

i got it, so now If we sensitive to packet loss, we may need some peripheral auxiliary circuits or handshake to ensure data. Since that's the case, it's necessary to add this feature , but the specific data caching correctness needs to be guaranteed by the user themselves, is it OK?

Yes, I think they should guarantee the correctness by software. We can only provide the option.

@jijingg jijingg marked this pull request as ready for review May 27, 2024 15:50
@jijingg
Copy link
Collaborator Author

jijingg commented May 29, 2024

At present, I think it ready for merge The update of the document is still in progress it will completed within this week. do you guys have any comments @andreasWallner @Readon @mrberman87 @Dolu1990

@Dolu1990
Copy link
Member

For me, you can merge you feel it.

@andreasWallner
Copy link
Collaborator

@jijingg
comment are coming up, just takes a while to get through 66 files ...

@jijingg
Copy link
Collaborator Author

jijingg commented May 31, 2024

@jijingg comment are coming up, just takes a while to get through 66 files ...

hi, Let me merge first. If there are any issue need improvement, we will continue to initiate the PR

@jijingg jijingg merged commit 9f74204 into SpinalHDL:dev May 31, 2024
11 checks passed
Copy link
Collaborator

@andreasWallner andreasWallner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long time, but since this is nearly a rewrite I had to copy code to an external editor to have useful diffs - a PR of this size is not reviewable.


case class MemBusConfig(aw: Int, dw: Int)

case class MemBus(c: MemBusConfig) extends Interface with IMasterSlave {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MemBus is a near duplicate of the BRAM bus (slight difference in WE, which would actually be a reasonable future feature request to support) and the AsyncMemoryBus (which can stall) - I think we should extend one of those with a parameter instead of adding yet another new Bus that is not reasonably different.

val sw = dw >> 3
}

case class MinBus(c: MinBusConfig) extends Interface with IMasterSlave {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope you'll describe the meaning (and timing) of these signals somewhere - its really hard to know what some of them are supposed to be (e.g. the difference between rvld and rdy, what prot does).
Apart from that this is a slight extension of AsyncMemoryBus and would maybe be better as some parameters there?

import spinal.core._
import spinal.core.sim._
class MemVIP{
private val mem = scala.collection.mutable.HashMap[Long, BigInt]()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would make sense if this would reuse SparseMemory

import spinal.core._
import spinal.core.sim._

case class MemBusDriver(bus : MemBus, clockdomain : ClockDomain) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other bus drivers initialize the bus when constructed - this one should do this as well.

bus.ce #= true
bus.wr #= false
bus.addr #= address
bus.wdat #= 1234 //.randomize()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should use randomize like in the comment?

}
}

def hang(bus: MinBus, delay: Int = 10)(cd: ClockDomain): MemVIP = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does hang mean - the only thing that comes to my mind is that it gets stuck which doesn't appear to be the case - looking at this and the one above shouldn't these just be apply methods?

val hitDoRead: Bool
val hitDoWrite : Bool

val bus = Stream(Bits(bi.busDataWidth bit))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a Stream here creates an issue for WrFifoInst where it's lying to the user: Stream implies that backpressure can be applied, which is not the case there. So for write this should be a Flow instead. This would correctly indicate that it can't stall the bus, and the user can use toStream(overflow: Bool) to convert to a stream with an overflow check (or use toStream if they don't care).

In short: this should be moved to WrFifoInst (as a Flow) and RdFifoInst (kept as a Stream)

res
}

def creatRAM(name: String, addr: BigInt, size: BigInt, doc: String, grp: GrpTag = null) = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why leave out a single character in create? typing this I always have to remind myself to make this mistake.
I see that creatReg existed for the old API - we should deprecate that one and fix the spelling.

val wstrb: Bits = withStrb generate (Bits(strbWidth bit))
val wmask: Bits = withStrb generate (Bits(busDataWidth bit))
val wmaskn: Bits = withStrb generate (Bits(busDataWidth bit))
initStrbMasks()
override def getModuleName = moduleName.name

val readError = Bool()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were one of the changes that I was referring to when I said that the PR can't be backwards compatible: since you are changing the name of a public field every code referring to it is broken after this


val readData: Bits
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was one of the changes I was referring to when I said this PR is not backwards compatible. This change breaks ever custom bus implementation a user of the library has

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants