-
Notifications
You must be signed in to change notification settings - Fork 549
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
Support NBAs to arrays inside loops #5092
Support NBAs to arrays inside loops #5092
Conversation
940380d
to
579e4fe
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 worry about the include templates. Templates can do nasty things to compile time. Can Verilator instead do some of this?
Have you thought how this would be extended to more complicated types, e.g. array of queues of arrays of structs?
include/verilated_types.h
Outdated
VL_ATTR_ALWINLINE static typename std::enable_if<!IsVlWide<T_Elem>::value, T_Elem>::type | ||
bAnd(const T_Elem& a, const T_Elem& 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.
Should this be in VlWide?
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 commit
template needs to be well formed for both wide a non-wide, so if you put it in VlWide, you need to add it as operator&
/operartor|
/operator~
, but I don't think we want those operators available on VlWide as they are prone to abuse.
If you don't instantiate them, it should cost very little, especially with PCH.
I removed the type traits from VlUnpacked and passed the extra derived info to the As for eliminating the templates completely, yes, Verilator in theory could code
Yes, the general scheme is that you generate a closure, and enqueue that to the commit queue, struct NBAClosureX {
// Pointer to closure code
void (*fptr)(NBAClosureX*, TargetVarType*);
// RHS value to apply
DataType rhs;
// Capture all members requried to perform the update,
// e.g. array indices, selLSB/selWidth, etc.
size_t indices[Rank];
size_t selLsb;
size_t selWidth;
// Whatever else 'fptr' needs
}
void NBAClosureX_code(NBAClosureX* ctxp, TargetVarType* targetp) {
// Generate code here that applies the update captured in 'ctxp' to 'targetp'
reconstructLhs(ctxp) = ctxp->rhs;
} An NBA is then lowered into this: void Vfoo__eval_blah(Vfoo*vlSelf) {
// At site of NBA
NBAClosureX* ctxp = new NBAClosureX;
ctxp->fptr = NBAClosureX_code;
//
ctxp->rhs = RHSOfTheNBA;
// Populate the captured variables to 'ctxp'
ctxp->indices[0] = ... // this is VdlyDim0 today
ctxp->indices[1] = ... // this is VdlyDim1 today
ctxp->selLhb = ... // this is
// etc.
VdlyCommitQueue__targetVar.enqueue(ctxp);
// In the 'post' block
VdlyCommitQueue__targetVar.commit(targetVar);
} And of course 'commit' is just: void VdlyCommitQueue__targetVar::commit(TargetVarType* targetp) {
for (NBAClosureX* ctxp : m_pending) ctxp->fptrp(ctxp, targetp);
m_pending.clear();
} Needless to say, that is a lot of work that is not necessary to support the common synthesisable/RTL case of memories (which is the case this patch enables). |
8b56988
to
cf55b6d
Compare
Done as requested. Please take another look. |
For NBAs that might execute a dynamic number of times in a single evaluation (specifically: those that assign to array elements inside loops), we introduce a new run-time VlNBACommitQueue data-structure (currently a vector), which stores all pending updates and the necessary info to reconstruct the LHS reference of the AstAssignDly at run-time. All variables needing a commit queue has their corresponding unique commit queue. All NBAs to a variable that requires a commit queue go through the commit queue. This is necessary to preserve update order in sequential code, e.g.: a[7] <= 10 for (int i = 1 ; i < 10; ++i) a[i] <= i; a[2] <= 10 needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9. This enables supporting common forms of NBAs to arrays on the left hand side of <= in non-suspendable/non-fork code. (Suspendable/fork implementation is unclear to me so I left it unchanged, see verilator#5084). Any NBA that does not need a commit queue (i.e.: those that were supported before), use the same scheme as before, and this patch should have no effect on the generated code for those NBAs.
3dfc78a
to
f15eda2
Compare
Good to go if you are happy with it. |
--- Patch 3 of 3 towards supporting NBAs to arrays inside loops. ---
Depends on #5091
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.
All variables needing a commit queue has their corresponding unique
commit queue.
All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
a[7] <= 10
for (int i = 1 ; i < 10; ++i) a[i] <= i;
a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.
This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see #5084).
Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.