I want to create this generic wrapper for a bunch of modules I am writing. The wrapper should provide the ability to connect these modules to different type of NoCs without having to change the behavior of the inner modules.
I thought that one way to do this would be the following.
Considering a very simple module to wrap:
module add #(
parameter COLUMN_WIDTH = 32
)
(
//data in
input logic [COLUMN_WIDTH-1:0] col_1,
input logic [COLUMN_WIDTH-1:0] col_2,
//data out
output logic [COLUMN_WIDTH-1:0] col_o
);
assign col_o = col_1 + col_2;
endmodule
The wrapper should be the following:
module wrapper #(
parameter COLUMN_WIDTH = 32,
parameter WRAPPED_MODULE = add
)
(
//data in
input logic [COLUMN_WIDTH-1:0] col_1,
input logic [COLUMN_WIDTH-1:0] col_2,
//data out
output logic [COLUMN_WIDTH-1:0] col_o,
/* std signals */
input logic clk,
input logic reset_i // reset everything
);
logic [COLUMN_WIDTH-1:0] max_result;
WRAPPED_MODULE #(.COLUMN_WDITH(COLUMN_WIDTH),
) a(
.*
);
always #(posedge clk) begin
if (reset_i)
max_result <= 0;
else
max_result <= (col_o > max_result) ? col_o : max_result;
end
endmodule
The error I get is the following:
Error-[IND] Identifier not declared
wrapper.sv, 4
Identifier 'add' has not been declared yet. If this error is not expected,
please check if you have set `default_nettype to none.
Which makes sense since a parameter is not the same as a macro.
A complete design should possibly instantiate a bunch of wrapped modules and I don't want to duplicate code by creating a wrapper for each inner module.
How can I do that?
A parameter cannot be a module name. It can be a data_type, implicit data_type, or type
IEEE Std 1800-2012 ยง A.2.1.1 Module parameter declarations:
parameter_declaration ::=
parameter data_type_or_implicit list_of_param_assignments
| parameter type list_of_type_assignments
A workaround is to use a generate block and compare the value of the parameter.
module wrapper #(
parameter COLUMN_WIDTH = 32,
parameter string WRAPPED_MODULE = "add"
)
(
// ...
);
// ...
generate
if (WRAPPED_MODULE=="add") begin
add #(.COLUMN_WDITH(COLUMN_WIDTH) ) a( .* );
end
else begin
// ...
end
endgenerate
// ...
endmodule
If you're using Vivado and SystemVerilog (only tested on 2017.4, likely would work on later versions too), I've been able to use something like parameter type WRAPPED_MODULE = add and it will synthesize as well.
Related
I have created a CDS Table Function with 2 parameters as below below:
define table function ZV_TF_TRGT_GRP_ID
with parameters id_date_fr : dats,
id_date_to : dats
Within an ABAP Class, I have defined two variables as per below:
data: ld_date_low type dats,
ld_date_high type dats.
In the class code, I determine the values for ld_date_low & ld_date_high - for which I ultimately want to pass to the Table Function parameters id_date_fr & id_date_to.
When I call the Table Function in the class using the code below, I get the error message:
"LD_DATE_LOW" is invalid here (due to grammar). contains an invalid character or it is a
select 'I' as sign,
'EQ' as opt,
HCMKTGID as low,
' ' as high
from ZV_TF_TRGT_GRP_ID( id_date_fr = ld_date_low, id_date_to = ld_date_high )
However, if I "hardcode" the values for parameters ld_date_fr and ld_date_to as per below, it is accepted and all works as expected.
select 'I' as sign,
'EQ' as opt,
HCMKTGID as low,
' ' as high
from ZV_TF_TRGT_GRP_ID( id_date_fr = '19000101', id_date_to = '20221231' )
Is it possible to use ABAP variables for Table Function parameters? And if so, where am I going wrong?
Please take a look on this following piece of code in which I put zeros in Test2 as value and two zeros in Test3 as value.
i used set_leading_zero but still leading zeros are removed.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
TYPES: BEGIN OF l_tys_test,
name TYPE string,
value TYPE i,
END OF l_tys_test,
l_tyt_test TYPE STANDARD TABLE OF l_tys_test WITH EMPTY KEY.
DATA(lt_test) = VALUE l_tyt_test(
( name = `Test1` value = 1 )
( name = `Test2` value = 02 )
( name = `Test3` value = 003 )
).
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_salv_table)
CHANGING
t_table = lt_test
).
lo_salv_table->get_columns( )->get_column( 'VALUE' )->set_leading_zero( abap_true ).
lo_salv_table->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).
Agree with Jozsef and Sandra, there is no way you can do it with integer data type.
The only way how to implement this by means of ALV grid is to redeclare you VALUE field as numchar
TYPES: BEGIN OF
...
value TYPE n LENGTH 10,
...
END OF.
and utilize EDIT_MASK function, which is available both for WRITE statement and for ALV grid as well.
Put this instead of set_leading_zero( ) call in your method
lo_salv_table->get_columns( )->get_column( 'VALUE' )->set_edit_mask( '___________' ).
LENGTH specification in type definition is the number of leading zeroes to put.
You can use set_zero method to false.
DATA(lo_column) = lo_alv->get_columns( )->get_column( 'PERNR' ). lo_column->set_long_text( 'Staff No' ). lo_column->set_zero( abap_false ).
I have a procedure with the parameter IT_ATINN:
IMPORTING
REFERENCE(IT_ATINN) TYPE STRING_TABLE
IT_ATINN contains a list of characteristics.
I have the following code:
LOOP AT values_tab INTO DATA(value).
SELECT ( #value-INSTANCE ) AS CUOBJ
FROM IBSYMBOL
WHERE SYMBOL_ID = #value-SYMBOL_ID
AND ATINN ??? "<======== HERE ???
APPENDING TABLE #DATA(ibsymbol_tab).
ENDLOOP.
How can I check if ATINN (in the WHERE clause) is equal to any entry in IT_ATINN?
To achieve what you want (and I assume you want dynamic SELECT fields) you cannot use inline declarations here, both in LOOP and in SELECT:
The structure of the results set must be statically identifiable. The SELECT list and the FROM clause must be specified statically and host variables in the SELECT list must not be generic.
So either you use inline or use dynamics, not both.
Here is the snippet that illustrates Sandra good suggestion:
TYPES: BEGIN OF ty_value_tab,
instance TYPE char18,
symbol_id TYPE id,
END OF ty_value_tab.
DATA: it_atinn TYPE string_table.
DATA: rt_atinn TYPE RANGE OF atinn,
value TYPE ty_value_tab,
values_tab TYPE RANGE OF ty_value_tab,
ibsymbol_tab TYPE TABLE OF ibsymbol.
rt_atinn = VALUE #( FOR value_atinn IN it_atinn ( sign = 'I' option = 'EQ' low = value_atinn ) ).
APPEND VALUE ty_value_tab( instance = 'ATWRT' ) TO values_tab.
LOOP AT values_tab INTO value.
SELECT (value-instance)
FROM ibsymbol
WHERE symbol_id = #value-symbol_id
AND atinn IN #rt_atinn
APPENDING CORRESPONDING FIELDS OF TABLE #ibsymbol_tab.
ENDLOOP.
Overall, it makes no sense select ibsymbol in loop, 'cause it has only 8 fields, so you can easily collect all necessary fields from values_tab and pass them as dynamic fieldstring.
If you wanna use alias CUOBJ for your dynamic field you should add it like this:
LOOP AT values_tab INTO value.
DATA(aliased_value) = value-instance && ` AS cuobj `.
SELECT (aliased_value)
...
Remember, that your alias should exists among ibsymbol fields, otherwise in case of static ibsymbol_tab declaration this statement will throw a short dump.
Is there a way to access the import parameters passed into a function module without addressing them individually? Does ABAP store them in some internal table, so I can work with them by looping through rows in some table, or fields of a structure?
We can use the PATTERN function, knowing only the function module's name, to have ABAP print out the function module's interface for us, so I'm wondering where this information is stored and if I can work with it once the function group has been loaded into memory.
Thanks in advance!
You can use the function module RPY_FUNCTIONMODULE_READ to obtain information about the parameter structure of a function module and then access the parameters dynamically. This has several drawbacks - most noticeably, the user doing so will need (additional) S_DEVELOP authorizations, and logging this way will usually impose a serious performance impact.
I'd rather add the function module parameters to the logging/tracing function manually once - with a sufficiently generic method call, it's not that difficult. I also tend to group individual parameters into structures to facilitate later enhancements.
PARAMETER-TABLE construct exists in ABAP since ancient times, it allows passing params in batch:
One should create two parameter tables of types abap_func_parmbind_tab and abap_func_excpbind_tab and fill them like this:
DATA: ptab TYPE abap_func_parmbind_tab,
etab TYPE abap_func_excpbind_tab,
itab TYPE TABLE OF string.
ptab = VALUE #(
( name = 'FILENAME' kind = abap_func_exporting value = REF #( 'c:\text.txt' ) )
( name = 'FILETYPE' kind = abap_func_exporting value = REF #( 'ASC' ) )
( name = 'DATA_TAB' kind = abap_func_tables value = REF #( itab ) )
( name = 'FILELENGTH' kind = abap_func_importing value = REF #( space ) ) ).
etab = VALUE #( ( name = 'OTHERS' value = 10 ) ) .
CALL FUNCTION 'GUI_DOWNLOAD'
PARAMETER-TABLE ptab
EXCEPTION-TABLE etab.
I'm working on a routine which moves the lines of a string table (in this case fui_elements) into a structure of unknown type (fcwa_struct).
DATA(li_temp) = ... "fill assignment table here
LOOP AT fui_elements ASSIGNING FIELD-SYMBOL(<lfs_element>).
ASSIGN COMPONENT li_temp[ sy-tabix ] OF STRUCTURE fcwa_struct
TO FIELD-SYMBOL(<lfs_field>).
IF sy-subrc <> 0.
"somethings wrong with the fui_elements data
ENDIF.
<lfs_field> = <lfs_element>.
ENDLOOP.
If the table i_field_customizing (STANDARD TABLE OF string) is not initial, I want to use its values.
Otherwise I want to generate an integer table (so that the loop runs equally often regardless of the table's values). Here lw_max is the amount of fields the imported structure has:
DATA(li_temp) = COND #( WHEN i_field_customizing[] IS INITIAL
THEN VALUE t_integer_tt( FOR X = 1
THEN X + 1
WHILE X <= lw_max
( X ) )
ELSE i_field_customizing ).
But when I run the report with i_field_customizing like that:
DATA(i_field_customizing) = VALUE t_string_tt( ( `KUNNR` ) ( `NAME1` ) ).
I get this exception on the line where I try to construct li_temp:
CX_SY_CONVERSION_NO_NUMBER (KUNNR cannot be interpreted as a number)
My current guess is that COND gets its type statically. Does anybody know how I can get around this?
What you are trying to achieve will not be possible because the type of an inline definition of a variable using COND is decided at compilation time and not at runtime.
Please see my question here. The type that will be taken is always the type of the variable that stands directly after THEN. You can decide what type will be chosen at compilation time by fiddling with negating the condition and switching places of variables after THEN at ELSE but it will be always either or and from what I understand you want to be able to do it dynamically so your ASSIGN COMPONENT statement works as expected with integers.
Even by specifically casting the variable after ELSE one gets the same short dump as you do.
DATA(li_temp) = COND #( WHEN i_field_customizing IS INITIAL
THEN VALUE t_integer_tt( ( 1 ) ( 2 ) )
ELSE CAST t_string_tt( REF #( i_field_customizing ) )->* ).
Alternatively you could cast to REF TO DATA but then you have to dereference it to a field symbol of type STANDARD TABLE.
REPORT zzy.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
TYPES:
t_integer_tt TYPE STANDARD TABLE OF i WITH EMPTY KEY,
t_string_tt TYPE STANDARD TABLE OF string WITH EMPTY KEY.
FIELD-SYMBOLS:
<fs_table> TYPE STANDARD TABLE.
DATA: BEGIN OF l_str,
kunnr TYPE kunnr,
name1 TYPE name1,
END OF l_str.
* DATA(i_field_customizing) = VALUE t_string_tt( ( `KUNNR` ) ( `NAME1` ) ).
DATA(i_field_customizing) = VALUE t_string_tt( ).
DATA(li_temp) = COND #( WHEN i_field_customizing IS INITIAL
THEN CAST data( NEW t_integer_tt( ( 1 ) ( 2 ) ) )
ELSE CAST data( REF #( i_field_customizing ) ) ).
ASSIGN li_temp->* TO <fs_table>.
LOOP AT <fs_table> ASSIGNING FIELD-SYMBOL(<fs_temp>).
ASSIGN COMPONENT <fs_temp> OF STRUCTURE l_str TO FIELD-SYMBOL(<fs_field>).
ENDLOOP.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).