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

Support for heterogeneous-arrays #51

Open
kevbroch opened this issue Apr 23, 2020 · 18 comments
Open

Support for heterogeneous-arrays #51

kevbroch opened this issue Apr 23, 2020 · 18 comments
Labels
feature New feature or request
Milestone

Comments

@kevbroch
Copy link

kevbroch commented Apr 23, 2020

I wanted to put in a request for support of heterogeneous-arrays.

The use case that I am running into is arrayed registers that have different reset values.

I would also be curious about any other workarounds, as all I can think to do right now is use preprocessing to unroll the arrayed registers but that has plenty of negative consequences.

@tolaszi
Copy link

tolaszi commented Apr 24, 2020

Hi @kevbroch

Are your reset values the function of the array index in some way (e.g. BASE_RESET + i)? In your RTL would you expect to see a parameterized reset value expression for you array? Or are these reset values completely arbitrary between the individual array elements?

@kevbroch
Copy link
Author

kevbroch commented Apr 24, 2020 via email

@tolaszi
Copy link

tolaszi commented Apr 24, 2020

Hm, ok. This means that they would need to be unrolled anyway at a certain point (at the RTL as the latest). So (to me) they sound more like different registers that happen to share the same properties apart from their reset values and a programmatic way to capture them in bulk would be handy. Of course I may misinterpret this - I would be curious about the underlying use case but I assume that it is not something you could discuss on Github...

@kevbroch
Copy link
Author

@tolaszi : I appreciate your comments and thinking through this but you are correct I'm not at liberty to say more about the exact use case.

@tapanther
Copy link

Hi, I also have a use case for dynamic assignments to allow non-homogeneous arrays.

I have a set of processing elements that internally have a memory-mapped matrix of "coefficients". Different instances of the same base block have different "coefficients" which results in distinct behavior. It would be nice to have these values programmed-in at built-time so that the reset state is valid and does not require a programming sequence to boot.

I can't say much more than that, but I've working to post-process the AST and inject the reset state, and I agree that at some point it really does become loop unrolling.

@tolaszi
Copy link

tolaszi commented Apr 30, 2020

I have come across a construct/property that was called 'reset strap' that may be of help in this case. It basically meant that internally the RTL generator created a one clock cycle delayed version of the reset signal and used that to load a value from the functional block right after reset.

For this, you may not need to anything specific to add to the SystemRDL description - you could just simply set the register array to be RW from the hw_access perspective. This should give you a HW write enable and HW write data line for each register in the array Then in the functional block you can create the one clock cycle delayed reset signal and use that as the HW write enable for all these registers. The 'delayed reset values' can be any arbitrary value then coming from localparams and assigned to the individual data lines of the HW access. I think this could work even without loop unrolling.

Would something like this solve the problem for the use cases of both of you?

@amykyta3
Copy link
Member

Definitely appreciate the feedback. I hadn't considered that use-case of augmenting reset values like that.

I originally avoided the feature since it exposes some really nasty situations I didn't quite want to deal with. When interpreting the RDL spec, I'm forced to consider the most pathological edge cases. With nonuniform arrays in RDL, dynamic property assignment rules hypothetically allow you to define something totally absurd like:

my_reg_t reg_array[8];

reg_array[0]->accesswidth = 8;
reg_array[1]->accesswidth = 32;
reg_array[2].my_field->counter = true;
reg_array[3].my_field->counter = false;
reg_array[4].my_field->intr = true;
reg_array[5].my_field->sw = r;
reg_array[6].my_field->sw = w;

I don't even know where to begin when it comes to validating that 😝.
In most compiled languages, when you declare an array of something, you expect the type of the array elements to be uniform to some extent.

Obviously you guys aren't insane, and just want to be able to distribute some initial reset values which is totally sensible.

I'll add this feature to the docket, but please understand that it isn't exactly trivial to implement so it may take me some time. Currently the internal object model encodes an array of elements as a single object and a descriptor of its array dimensions. I'll have to figure out a reasonable way to represent heterogeneous arrays, preferably without totally unrolling them internally as that would be incredibly inefficient.
Also, there may need to be some bounds to which properties can be heterogeneously applied to an array. To me it seems that assignments of certain structural properties should not be allowed in this situation in the interest of keeping type-uniformity of the array somewhat intact.. It does not look like the the RDL spec authors gave this much consideration since it is not mentioned at all.

@amykyta3 amykyta3 added the feature New feature or request label Apr 30, 2020
@kevbroch
Copy link
Author

I have come across a construct/property that was called 'reset strap' that may be of help in this case. It basically meant that internally the RTL generator created a one clock cycle delayed version of the reset signal and used that to load a value from the functional block right after reset.

For this, you may not need to anything specific to add to the SystemRDL description - you could just simply set the register array to be RW from the hw_access perspective. This should give you a HW write enable and HW write data line for each register in the array Then in the functional block you can create the one clock cycle delayed reset signal and use that as the HW write enable for all these registers. The 'delayed reset values' can be any arbitrary value then coming from localparams and assigned to the individual data lines of the HW access. I think this could work even without loop unrolling.

Would something like this solve the problem for the use cases of both of you?

@tolaszi : Sorry I missed your reply till now. Unfortunately one of my biggest reasons for using systemRDL is for documentation, C headers, uvm, ip-xact and for all of those I need to reflect correct reset values.

@tolaszi
Copy link

tolaszi commented Jun 11, 2020

@kevbroch : But as far as I know neither of these formats support non-homogeneous arrays. How would your generators translate the SystemRDL description of these arrays to UVM, IP-XACT, etc.? Do you have control over the generators to customize them to unroll the non-homogeneous arrays?

@kevbroch
Copy link
Author

@tolaszi : Yes

@tolaszi
Copy link

tolaszi commented Jun 12, 2020

@kevbroch: Ok, I see. If you willing to unroll these then wouldn't it be less work to use SystemRDL's Perl preprocessing capabilities and programatically create these registers with a for loop while setting their unique reset values from a list? It probably would be just a few lines as shown in example 16.1.2 in the SystemRDL spec. If this is done at the SystemRDL source then I assume you wouldn't need to modify all the generators one by one.

@kevbroch
Copy link
Author

kevbroch commented Jun 18, 2020

@tolaszi : Yes, I went down the preprocessor route of unrolling the arrays but because I had to support all different permutations of multi-dimensional arrays this became a performance issues with the compiler. I'm also concerned that all these unrolled arrays will also affect downstream tools adversely (ex: uvm)

@tolaszi
Copy link

tolaszi commented Jun 20, 2020

@kevbroch: Well, as the same limitations for non-homogeneous arrays exists in UVM I don't see any easy way to escape this downstream performance penalty. The UVM tests could be constrained to hit only the first/last/middle of the arrays (as the test writer knows they are actually arrays) which could help with the runtime but not the memory consumption. It is real a pity that apparently there was no solution to avoid these negative consequences. Just out of curiosity - as you mentioned the performance issues - what is the order of registers you need to work with after unrolling? Is it hundreds, thousands, tens of thousands or even more?

@kevbroch
Copy link
Author

@tolaszi : tens of thousands

@kjeldbeg
Copy link

I really need this. I have a lot of RDL files with constructions like this:

addrmap t_addrmap {
  reg {
    field {} field1;
  } reg1[2];

  reg {
    field {} field2;
  } reg2[2];

  reg1[0].field1->enable = reg2[0].field2;
  reg1[1].field1->enable = reg2[1].field2;
};

@amykyta3 amykyta3 added this to the v2.0.0 milestone Apr 2, 2021
@amykyta3 amykyta3 changed the title Support for non-homogeneous-arrays Support for heterogeneous-arrays Sep 8, 2022
@erang20
Copy link

erang20 commented Dec 6, 2022

+1 I'm also interested in heterogeneous arrays support for the same purpose: providing different reset values for an array of registers.
I think this is a pretty common use case when you have registers that hold opaque data.

@nachumg
Copy link

nachumg commented Nov 11, 2024

Hi all. First, thanks for producing such a great toolset!

Heterogeneous arrays is a hard requirement for the group I am supporting.

In our case, we have:

  1. Deep hierarchies with component-arrays at multiple levels in the hierarchy.
  2. Scenarios where we need to modify a deeply nested element,
    e.g. some_map[1].some_file[2].some_reg[3][4]->some_field = expr

We often don't know ahead of time which deep elements need to be modified.
Once we do know, it's not feasible to rework the design in order to expose non-indexed references to the elements that must be modified.

Wrt https://systemrdl-compiler.readthedocs.io/en/stable/model_structure.html
I think we could do this one of two ways (but only when we detect dynamic assignment to an array element):

  1. Duplicate each array instance in the dot-expression and modify the indexed elements.
    This would quickly OOM in deep hierarchies that have MN... components.

  2. In the target AddressableComponent instance: remember those elements that have been modified.
    Consider this example:

reg my_reg_t {
field {
desc = "abc";
} f1;
field {} f2;
};

regfile my_file_t {
my_reg_t A[4];
my_reg_t B;
};

addrmap top {
my_file_t F[5];
}

top.F[0].A[1].f1->desc = "xyz";

In the top AddressableComponent instance we would store the info:
F[0]: A[1].f1->desc = "xyz"

Then as we traverse the model with unroll=True, we do:

Pass to the unroll of F[0]: A[1].f1->desc = "xyz"
Pass to the unroll of A[1]: f1->desc = "xyz"
Pass to the unroll of f1: desc = "xyz"
When creating the node for f1:
Create a copy of f1 and set desc = "xyz"
Point the node to that copy of f1

Thus we minimize memory usage by creating instance copies only for the leaf nodes that have been modified.

The node overlay would look like
model

WDYT?

Thanks, regards.

@nachumg
Copy link

nachumg commented Nov 13, 2024

Gentle ping re: my message above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Development

No branches or pull requests

7 participants