SystemRDL / systemrdl-compiler

SystemRDL 2.0 language compiler front-end
http://systemrdl-compiler.readthedocs.io
MIT License
222 stars 58 forks source link

Support for heterogeneous-arrays #51

Open kevbroch opened 4 years ago

kevbroch commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

Unfortunately, they are arbitrary.

tolaszi commented 4 years ago

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 commented 4 years ago

@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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 :stuck_out_tongue_closed_eyes:. 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.

kevbroch commented 4 years ago

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 commented 4 years ago

@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 commented 4 years ago

@tolaszi : Yes

tolaszi commented 4 years ago

@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 commented 4 years ago

@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 commented 4 years ago

@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 commented 4 years ago

@tolaszi : tens of thousands

kjeldbeg commented 3 years ago

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;
};
erang20 commented 1 year ago

+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.