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

(System-)Verilog: Parameters/Localparams/Specparams should be seperated #2537

Closed
markusdd opened this issue May 9, 2020 · 22 comments
Closed
Assignees

Comments

@markusdd
Copy link

markusdd commented May 9, 2020

ctags -f - ../../os_clk_lib/os_clk_div.sv                                                                                                                                       
DIV_BY	../../os_clk_lib/os_clk_div.sv	/^  parameter DIV_BY = 4$/;"	c	module:os_clk_div
ONE_P	../../os_clk_lib/os_clk_div.sv	/^  localparam [$clog2(DIV_BY)-1:0] ONE_P = {{$clog2(DIV_BY)-1{1'b0}},1'b1};$/;"	c	module:os_clk_div
clk_i	../../os_clk_lib/os_clk_div.sv	/^  input logic clk_i,$/;"	p	module:os_clk_div
clk_o	../../os_clk_lib/os_clk_div.sv	/^  output logic clk_o$/;"	p	module:os_clk_div
cnt_r	../../os_clk_lib/os_clk_div.sv	/^  logic [$clog2(DIV_BY)-1:0] cnt_r;$/;"	r	module:os_clk_div
div_clk_r	../../os_clk_lib/os_clk_div.sv	/^  logic div_clk_r;$/;"	r	module:os_clk_div
div_proc	../../os_clk_lib/os_clk_div.sv	/^  always_ff @(posedge clk_i or negedge rst_an_i) begin : div_proc$/;"	b	module:os_clk_div
en_i	../../os_clk_lib/os_clk_div.sv	/^  input logic en_i,$/;"	p	module:os_clk_div
os_clk_div	../../os_clk_lib/os_clk_div.sv	/^module os_clk_div #($/;"	m
rst_an_i	../../os_clk_lib/os_clk_div.sv	/^  input logic rst_an_i,$/;"	p	module:os_clk_div

The name of the parser: Systemverilog/Verilog

The command line you used to run ctags:

see above

The content of input file:

module os_clk_div #(
  parameter DIV_BY = 4
) (
  input logic clk_i,
  input logic rst_an_i,
  input logic en_i,
  output logic clk_o
);

  //param check
  if ((DIV_BY < 2) || (DIV_BY % 2 != 0)) begin
    $error("OS IP ERROR: os_clk_div parameter DIV_BY must be dividable by and >= 2 for simple ff divider.");
  end

  //declarations
  logic div_clk_r;
  logic [$clog2(DIV_BY)-1:0] cnt_r;
  localparam [$clog2(DIV_BY)-1:0] ONE_P = {{$clog2(DIV_BY)-1{1'b0}},1'b1};

  //business logic
  always_ff @(posedge clk_i or negedge rst_an_i) begin : div_proc
    if (rst_an_i == 1'b0) begin
      div_clk_r <= 1'b0;
      if (DIV_BY > 2) begin
        cnt_r <= {$clog2(DIV_BY){1'b0}};
      end
    end else begin
      if (DIV_BY == 2) begin //simple toggle divider
        if (en_i == 1'b1) begin
          div_clk_r <= ~div_clk_r;
        end
      end else begin 
        if (DIV_BY > 2) begin //use counter
          if (en_i == 1'b1) begin
            cnt_r <= cnt_r + ONE_P;
            if (cnt_r == {$clog2(DIV_BY){1'b0}}) begin
              div_clk_r <= ~div_clk_r;
            end
          end
        end
      end
    end
  end

  assign clk_o = div_clk_r;

endmodule

The tags output you are not satisfied with:

DIV_BY	../../os_clk_lib/os_clk_div.sv	/^  parameter DIV_BY = 4$/;"	c	module:os_clk_div
ONE_P	../../os_clk_lib/os_clk_div.sv	/^  localparam [$clog2(DIV_BY)-1:0] ONE_P = {{$clog2(DIV_BY)-1{1'b0}},1'b1};$/;"	c	module:os_clk_div

The tags output you expect:

parameters, localparams and specparams have their own groups, because they differ significantly in terms of semantics. (e.g. a localparam is not totally 'constant' as it may depend on a parameter passed on instantiation). Currently they are just 'constants'.
The biggest practical problem though is that ctags is used by many editor plugins to enable
auto instantiation of verilog modules. But in an instance declaration, only parameters can be used, localparams and specparams are local to the scope of the module internals and cannot be set externally.

The current 'workaround' is to actually parse the line contents, but this is error prone because parameter must not be the first thing in the line when it is multi-dimensional and it may also be contained inside a variable name that follows. So a simple 'contains' check is by far not enough. And writing a line parser on top sort of defeats the prupose of ctags imho.

The version of ctags:

ctags --version                                                                                                                                                                 
Universal Ctags 0.0.0(ca0412a), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: May  9 2020, 00:44:35
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath, +case-insensitive-filenames, +packcc

How do you get ctags binary:

macOSx homebrew

@masatake
Copy link
Member

parameters, localparams and specparams have their own groups, because they differ significantly in terms of semantics. (e.g. a localparam is not totally 'constant' as it may depend on a parameter passed on instantiation). Currently they are just 'constants'.

Do you mean we should introduce new kinds for localparams and specparams?
If yes, tell me what I should add?
The current kinds of Verilog and SystemVerilog are:

[yamato@slave]~/var/ctags-github% ./ctags --list-kinds-full=Verilog
#LETTER NAME     ENABLED REFONLY NROLES MASTER DESCRIPTION
b       block    yes     no      0      NONE   blocks
c       constant yes     no      0      NONE   constants (define, parameter, specparam)
e       event    yes     no      0      NONE   events
f       function yes     no      0      NONE   functions
m       module   yes     no      0      NONE   modules
n       net      yes     no      0      NONE   net data types
p       port     yes     no      0      NONE   ports
r       register yes     no      0      NONE   register data types
t       task     yes     no      0      NONE   tasks
[yamato@slave]~/var/ctags-github% ./ctags --list-kinds-full=SystemVerilog
#LETTER NAME       ENABLED REFONLY NROLES MASTER DESCRIPTION
A       assert     yes     no      0      NONE   assertions
C       class      yes     no      0      NONE   classes
E       enum       yes     no      0      NONE   enumerators
I       interface  yes     no      0      NONE   interfaces
K       package    yes     no      0      NONE   packages
M       modport    yes     no      0      NONE   modports
P       program    yes     no      0      NONE   programs
Q       prototype  no      no      0      NONE   prototypes
R       property   yes     no      0      NONE   properties
S       struct     yes     no      0      NONE   structs and unions
T       typedef    yes     no      0      NONE   type declarations
V       covergroup yes     no      0      NONE   covergroups
b       block      yes     no      0      NONE   blocks
c       constant   yes     no      0      NONE   constants (define, parameter, specparam, enum values)
e       event      yes     no      0      NONE   events
f       function   yes     no      0      NONE   functions
m       module     yes     no      0      NONE   modules
n       net        yes     no      0      NONE   net data types
p       port       yes     no      0      NONE   ports
r       register   yes     no      0      NONE   register data types
t       task       yes     no      0      NONE   tasks

I would like to know the name and descriptions for the new kinds we should add.
@antoinemadec, @vhda, could you give us comments if you have.

@masatake
Copy link
Member

Another approach is adding parser specific fields like C parser does:

[yamato@slave]~% cat /tmp/baz.c 
cat /tmp/baz.c 
inline int f (int i)
{
  return i + 3
}
[yamato@slave]~% u-ctags -o - /tmp/baz.c
u-ctags -o - /tmp/baz.c
f	/tmp/baz.c	/^inline int f (int i)$/;"	f	language:C	typeref:typename:int
[yamato@slave]~% u-ctags -o - --fields-C='*' /tmp/baz.c
u-ctags -o - --fields-C='*' /tmp/baz.c
f	/tmp/baz.c	/^inline int f (int i)$/;"	f	language:C	typeref:typename:int	properties:inline

The c parser doesn't introduce inline kind. Instead it attaches properties:inline parser specific field to f/function kind tag.

I'm not sure which is better (adding new kinds or storing the extra information to fields).

@markusdd
Copy link
Author

I very much like the property proposal from @masatake, as it would alo preserve backward compatibility.

This should also be done for defines as well, as they are preprocessor commands and treated very much differently when it comes to compileing/elbaortaing the desing.

@masatake
Copy link
Member

I very much like the property proposal from @masatake, as it would alo preserve backward compatibility.

Could you show me how the tags file should be?
What kind of field should we add?

@markusdd
Copy link
Author

I would propose exactly what you suggested from C.
Keep the constant type and add a properties field

properties:parameter properties:specparam properties:define properties:localparam

I think that would be excellent and should be backwards compatible.

@masatake
Copy link
Member

I wonder why it is not "property". Is "properties" better than "property"?
As far as my VERY short study about SystemVerilog, "definedWith:" or "definedBy:" describes what it is more specifically.

With patch:

[yamato@slave]~/var/ctags-github% git diff |cat
git diff |cat
diff --git a/parsers/verilog.c b/parsers/verilog.c
index 737fc815..885b063d 100644
--- a/parsers/verilog.c
+++ b/parsers/verilog.c
@@ -91,6 +91,14 @@ typedef struct sTokenInfo {
 	bool                classScope;    /* Context is local to the current sub-context */
 } tokenInfo;
 
+typedef enum {
+	F_VERILOG_DEFINE_WITH,
+} verilogField;
+
+typedef enum {
+	F_SYSTEM_VERILOG_DEFINE_WITH,
+} systemVerilogField;
+
 /*
  *   DATA DEFINITIONS
  */
@@ -204,6 +212,18 @@ static const keywordAssoc KeywordTable [] = {
 	{ "void",      K_IGNORE,    { 1, 0 } }
 };
 
+static fieldDefinition VerilogFields[] = {
+	{ .name = "definedWith",
+	  .description = "keyword used for defining the constant",
+	  .enabled = false },
+};
+
+static fieldDefinition SystemVerilogFields[] = {
+	{ .name = "definedWith",
+	  .description = "keyword used for defining the constant",
+	  .enabled = false },
+};
+
 static tokenInfo *currentContext = NULL;
 static tokenInfo *tagContents = NULL;
 
@@ -608,7 +628,7 @@ static void dropEndContext (tokenInfo *const token)
 }
 
 
-static void createTag (tokenInfo *const token)
+static void createTag (tokenInfo *const token, const char *definedWith)
 {
 	tagEntryInfo tag;
 	verilogKind kind;
@@ -652,6 +672,13 @@ static void createTag (tokenInfo *const token)
 		verbose ("Class %s extends %s\n", vStringValue (token->name), tag.extensionFields.inheritance);
 	}
 
+	if (kind == K_CONSTANT && definedWith)
+		attachParserField (&tag, false,
+						   isInputLanguage (Lang_verilog)
+						   ? VerilogFields [F_VERILOG_DEFINE_WITH].ftype
+						   : SystemVerilogFields [F_SYSTEM_VERILOG_DEFINE_WITH].ftype,
+						   definedWith);
+
 	int corkIndex = makeTagEntry (&tag);
 	if (isInputLanguage (Lang_systemverilog)
 		&& corkIndex != CORK_NIL
@@ -690,7 +717,7 @@ static void createTag (tokenInfo *const token)
 			verbose ("Including tagContents\n");
 			do
 			{
-				createTag (content);
+				createTag (content, NULL);
 				content = content->scope;
 			} while (content);
 		}
@@ -744,7 +771,7 @@ static void processBlock (tokenInfo *const token)
 		verbose ("Found block: %s\n", vStringValue (token->name));
 		if (blockStart)
 		{
-			createTag (token);
+			createTag (token, NULL);
 			verbose ("Current context %s\n", vStringValue (currentContext->name));
 		}
 		if (blockEnd && currentContext->kind == K_BLOCK && currentContext->nestLevel <= 1)
@@ -803,7 +830,7 @@ static void processPortList (int c)
 					{
 						verbose ("Found port: %s\n", vStringValue (token->name));
 						token->kind = K_PORT;
-						createTag (token);
+						createTag (token, NULL);
 					}
 				}
 				else
@@ -864,14 +891,14 @@ static void processFunction (tokenInfo *const token)
 		verbose ("Found function: %s\n", vStringValue (token->name));
 
 		/* Create tag */
-		createTag (token);
+		createTag (token, NULL);
 
 		/* Get port list from function */
 		processPortList (c);
 	}
 }
 
-static void tagNameList (tokenInfo* token, int c);
+static void tagNameList (tokenInfo* token, int c, const char *defineWith);
 
 static void processEnum (tokenInfo *const token)
 {
@@ -902,7 +929,7 @@ static void processEnum (tokenInfo *const token)
 		{
 			verbose ("Prototype enum found \"%s\"\n", vStringValue (type->name));
 			type->kind = K_PROTOTYPE;
-			createTag (type);
+			createTag (type, NULL);
 			pruneTokens (typeQueue);
 			return;
 		}
@@ -967,7 +994,7 @@ static void processEnum (tokenInfo *const token)
 
 	/* Following identifiers are tag names */
 	verbose ("Find enum tags. Token %s kind %d\n", vStringValue (token->name), token->kind);
-	tagNameList (token, c);
+	tagNameList (token, c, NULL);
 }
 
 static void processTypedef (tokenInfo *const token)
@@ -1061,7 +1088,7 @@ static void processTypedef (tokenInfo *const token)
 
 	/* Use last identifier to create tag, but always with kind typedef */
 	token->kind = K_TYPEDEF;
-	createTag (token);
+	createTag (token, NULL);
 }
 
 static void processClass (tokenInfo *const token)
@@ -1125,12 +1152,12 @@ static void processClass (tokenInfo *const token)
 	}
 
 	/* Use last identifier to create tag */
-	createTag (token);
+	createTag (token, NULL);
 
 	/* Add parameter list */
 	while (parameters)
 	{
-		createTag (parameters);
+		createTag (parameters, NULL);
 		parameters = popToken (parameters);
 	}
 }
@@ -1158,7 +1185,7 @@ static bool isAlreadyTaggedAs (tokenInfo *token, verilogKind kind)
 								   doesNameForKindExist, &kind) == false);
 }
 
-static void tagNameList (tokenInfo* token, int c)
+static void tagNameList (tokenInfo* token, int c, const char *defineWith)
 {
 	verilogKind localKind;
 	bool repeat;
@@ -1206,7 +1233,7 @@ static void tagNameList (tokenInfo* token, int c)
 			else
 			/* Create tag in case name is not a known kind ... */
 			{
-				createTag (token);
+				createTag (token, defineWith);
 			}
 		}
 		else
@@ -1259,7 +1286,7 @@ static void findTag (tokenInfo *const token)
 		/* Bug #961001: Verilog compiler directives are line-based. */
 		int c = skipWhite (vGetc ());
 		readIdentifier (token, c);
-		createTag (token);
+		createTag (token, NULL);
 		/* Skip the rest of the line. */
 		do {
 			c = vGetc();
@@ -1284,7 +1311,7 @@ static void findTag (tokenInfo *const token)
 		if (vStringLength (currentContext->blockName) > 0)
 		{
 			vStringCopy (token->name, currentContext->blockName);
-			createTag (token);
+			createTag (token, NULL);
 			skipToSemiColon ();
 		}
 	}
@@ -1308,7 +1335,9 @@ static void findTag (tokenInfo *const token)
 	{
 		int c = skipWhite (vGetc ());
 
-		tagNameList (token, c);
+		char* definedWith = vStringStrdup (token->name);
+		tagNameList (token, c, definedWith);
+		eFree (definedWith);
 	}
 	else if (token->kind != K_UNDEFINED && token->kind != K_IGNORE)
 	{
@@ -1322,7 +1351,7 @@ static void findTag (tokenInfo *const token)
 				c = skipWhite (vGetc ());
 				readIdentifier (token, c);
 			}
-			createTag (token);
+			createTag (token, NULL);
 
 			/* Get port list if required */
 			c = skipWhite (vGetc ());
@@ -1403,6 +1432,8 @@ extern parserDefinition* VerilogParser (void)
 	parserDefinition* def = parserNew ("Verilog");
 	def->kindTable      = VerilogKinds;
 	def->kindCount  = ARRAY_SIZE (VerilogKinds);
+	def->fieldTable = VerilogFields;
+	def->fieldCount = ARRAY_SIZE (VerilogFields);
 	def->extensions = extensions;
 	def->parser     = findVerilogTags;
 	def->initialize = initializeVerilog;
@@ -1415,6 +1446,8 @@ extern parserDefinition* SystemVerilogParser (void)
 	parserDefinition* def = parserNew ("SystemVerilog");
 	def->kindTable      = SystemVerilogKinds;
 	def->kindCount  = ARRAY_SIZE (SystemVerilogKinds);
+	def->fieldTable = SystemVerilogFields;
+	def->fieldCount = ARRAY_SIZE (SystemVerilogFields);
 	def->extensions = extensions;
 	def->parser     = findVerilogTags;
 	def->initialize = initializeSystemVerilog;

With patch ctags emits:

[yamato@slave]~/var/ctags-github% ./ctags -o - --fields=-l --fields-SystemVerilog='+{definedWith}' foo.sv
./ctags -o - --fields=-l --fields-SystemVerilog='+{definedWith}' foo.sv
DIV_BY	foo.sv	/^  parameter DIV_BY = 4$/;"	c	module:os_clk_div	definedWith:parameter
ONE_P	foo.sv	/^  localparam [$clog2(DIV_BY)-1:0] ONE_P = {{$clog2(DIV_BY)-1{1'b0}},1'b1};$/;"	c	module:os_clk_div	definedWith:localparam
clk_i	foo.sv	/^  input logic clk_i,$/;"	p	module:os_clk_div
clk_o	foo.sv	/^  output logic clk_o$/;"	p	module:os_clk_div
cnt_r	foo.sv	/^  logic [$clog2(DIV_BY)-1:0] cnt_r;$/;"	r	module:os_clk_div
div_clk_r	foo.sv	/^  logic div_clk_r;$/;"	r	module:os_clk_div
div_proc	foo.sv	/^  always_ff @(posedge clk_i or negedge rst_an_i) begin : div_proc$/;"	b	module:os_clk_div
en_i	foo.sv	/^  input logic en_i,$/;"	p	module:os_clk_div
os_clk_div	foo.sv	/^module os_clk_div #($/;"	m
rst_an_i	foo.sv	/^  input logic rst_an_i,$/;"	p	module:os_clk_div

@markusdd
Copy link
Author

You would be correct. definedWith is probably more appropriate.
At the end of the day it is important that an easily mchaine readable output is produced.

The output of the patch looks good to me.

@hirooih
Copy link
Contributor

hirooih commented Oct 6, 2020

@masatake san,

Shall I take over this issue?

You already made the fix above. But it is not merged yet.
I'd like to add defineWith member on the tokenInfo structure instead of adding defineWith argument on createTag().
How do you think?

@masatake
Copy link
Member

masatake commented Oct 6, 2020

Yes, please.

You already made the fix above. But it is not merged yet.
I'd like to add defineWith member on the tokenInfo structure instead of adding defineWith argument on createTag().
How do you think?

Your idea may be better.

@masatake
Copy link
Member

masatake commented Oct 6, 2020

@hirooih, do you think adding the field is better than introducing more kinds?
I proposed the field because I don't know well about Verilog; adding a field has a smaller impact than adding a kind.
However, it is not a positive approach.

You know well about Verilog. So you can take a more aggressive approach.
At a quick glance, the "constant" kinds represent too many things.
Splitting it to "parameter" and "macro" is one of the ways.
Furthermore, you can introduce parameters, localparam, and specparam kinds. (Just ideas).

If you have a favorite editor plugin for editing or reading (System)Verilog code with tags file, talking with its developers is also good idea.

@hirooih
Copy link
Contributor

hirooih commented Oct 6, 2020

If we could break backward compatibility, I would add new kind for define-macro ("d", "macro definitions" as c-parser), and add a field for parameter, localparam, and specparam as you proposed. define-macro is a part of pre-processor like C. *param* are similar beasts.

But I also understand you have a strict rule, " do not to break compatibility". I think it is very important.


I don't know any good ctags plugin designed for (System)Verilog. I am using ctags extension (plugin) designed for C on Visual Studio Code. It works well with Verilog extension.
In this sense, as far as Verilog plugin is concerned, it might be more important to behave like C-parser than to stick to backward-compatibility. But I might be wrong.

@markusdd
Copy link
Author

markusdd commented Oct 6, 2020

In my view, for verilog, breaking compatibility would be acceptable, for one simple reason:
The current implementation does not do what it is supposed to, as it throws sematically incompatible things into one bucket.

The problem originated from the fact, that e.g. an instantiation for modules would pick up localparams or specparams next to the regular module parameters, without a good way to tell to which scope they belong.
Obviously a localparam is local to the module scope and cannot be touched from outside, so there is currently no way to use ctags to implement proper instantiation mechanisms. Also there is no way to lint for proper usage.

@masatake
Copy link
Member

masatake commented Oct 6, 2020

Changing the kinds of (System)Verilog similar to the kinds of C is not a good idea if the motivation of change is to make the tags output for (System)Verilog input acceptable to the VSCode extension for C language.

I would like you to imagine an ideal VSCode extension for (System)Verilog.
Changing the kinds of (System)Verilog is for the ideal extension.

@hirooih, if you don't know pseudo tags (ptag), I would like you to know it.
Please read man/ctags-client-tools.7.rst (or https://docs.ctags.io/en/latest/man/ctags-client-tools.7.html ).

We can introduce !_TAG_PARSER_MAJOR_VERSION and !_TAG_PARSER_MINOR_VERSION ptags.

Consider the current version of the kinds of SystemVerilog is 1.0.
If we cannot avoid incompatiblies, you can update the version to 2.0.

Well-written client tools may read the version number of the parser and can handle the incompatiblities well.

If you would like to try the ptags, let me know. I will implement them.

BTW, I found the kind names are used in
https://github.com/mshr-h/vscode-verilog-hdl-support/blob/6cbacb09f06cba40e1d134741cbcb0bac1522925/src/ctags.ts#L66

@hirooih
Copy link
Contributor

hirooih commented Oct 6, 2020

BTW, I found the kind names are used in
https://github.com/mshr-h/vscode-verilog-hdl-support/blob/6cbacb09f06cba40e1d134741cbcb0bac1522925/src/ctags.ts#L66

I'm using this extension. It is a great Verilog extension but its ctags support is useless. It execs ctags on each editing file (at L123). It cannot find symbols defined in other files. So I am using ctags extension (plugin) designed for C.

@masatake
Copy link
Member

masatake commented Oct 6, 2020

I see.

@markusdd
Copy link
Author

markusdd commented Oct 6, 2020

The VS code extension mentioned is exactly the one I am using, and where this ticket originates from.

Using the ctag kinds, it is currently not possible to implement certain functions correctly, like the mentioned seperation of localparams and parameters for instantiating a module.

This is the downstream ticket:
mshr-h/vscode-verilog-hdl-support#102

@masatake
Copy link
Member

masatake commented Oct 6, 2020

I implemented !_TAG_PARSER_VERSION.

parserDefinition * CParser (void)
{
...
	def->version.major = 1;
	def->version.minor = 0;
	return def;
}
$ ./ctags --extras=+p -o - main/main.c
!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_FILESEP	slash	/slash or backslash/
!_TAG_OUTPUT_MODE	u-ctags	/u-ctags or e-ctags/
!_TAG_PARSER_VERSION!C	1.0.0	/major.minor.patchlvl/

If a parser doesn't specify its version, the value for the ptag of the parser is "0.0.0".
When the kinds and fields for (System)Verilog are changed, you can specify the version field explicitly: 1.0.0.

Client tools deal with the ptag. It will take costs of development. However, it will be better than introducing incompatible change silently.

@hirooih
Copy link
Contributor

hirooih commented Oct 8, 2020

@masatake san

I don't think the current definition of Verilog parser is so bad that we have to introduce new specification. We will have to maintain two versions (or more...)

Adding a property as you proposed solves this paramter-issue.

@markusdd

Let me confirm your request.
(LRM means SystemVerilog 2017 Language Reference Manual)

parameters, localparams and specparams have their own groups, because they differ significantly in terms of semantics. (e.g. a localparam is not totally 'constant' as it may depend on a parameter passed on instantiation).

All of them are constants defined in LRM 6.20 Constants as

SystemVerilog provides three elaboration-time constants: parameter, localparam, and specparam.

The value of parameter can be overridden directly in each instance. The value of localparam can not be overridden directly in each instance, but can be overridden indirectly via parameter values as in your example above.

This is the downstream ticket: mshr-h/vscode-verilog-hdl-support#102

I understand what you require is a list of parameters for a module instantiation.
You need a list of parameters can be overridden directly, and you don't care how they are defined.

Let me explain what I mean. (It is more complicated than I thought first...)

From LRM 6.20.1 Parameter declaration syntax

The list_of_param_assignments can appear in a module, interface, program, class, or package or in the parameter_port_list of a module (see 23.2), interface, program, or class. If the declaration of a design element uses a parameter_port_list (even an empty one), then in any parameter_declaration directly contained within the declaration, the parameter keyword shall be a synonym for the localparam keyword (see 6.20.4). ...

In the example below, you need P1, P2, P3, and P.4. You don't need L1, L3, L5, although they are defined by parameter.

parameter L1 = 0;  //  synonym for the localparam
module with_parameter_port_list #(P1, P2, localparam L2, parameter P3)
( port list... );
  parameter  L3 = ...;  // synonym for the localparam
  localparam L4 = ...;
   ...
endmodule

module with_empty_parameter_port_list #()
( port list... );
  parameter  L5 = ...;  // synonym for the localparam
  localparam L6 = ...;
   ...
endmodule

module no_parameter_port_list
( port list... );
  parameter  P4 = ...;
  localparam L5 = ...;
   ...
endmodule

The biggest practical problem ...

If you have any other problem, let me know.

@markusdd
Copy link
Author

markusdd commented Oct 8, 2020

It is not about 'needing' them, it is, as you pointed out, simply not possible to set a localparam in a module instantiation, as it is not visible to the outside (hence LOCALparam).

Currently there is no way to split these from ctags output, which makes it very inconvenient if not impossible to autogenerate instances with parameter lists.

specparams are once again a different topic, but they are used more rarely in day-to-day development, they usually
only appear in tech-sensitive lib components.

@masatake
Copy link
Member

masatake commented Oct 8, 2020

I don't think the current definition of Verilog parser is so bad that we have to introduce new specification

I see.

@hirooih
Copy link
Contributor

hirooih commented Oct 13, 2020

I've sent a pull-request of the fix for this issue on #2666.

hirooih added a commit to hirooih/ctags that referenced this issue Oct 16, 2020
hirooih added a commit to hirooih/ctags that referenced this issue Oct 21, 2020
hirooih added a commit that referenced this issue Oct 22, 2020
SystemVerilog: support property:parameter (update for #2537)
@hirooih
Copy link
Contributor

hirooih commented Oct 22, 2020

@markusdd

Finally the pull request is merged. Choosing the name of the new field was the most difficult problem.

By default this feature is disabled. Add --fields-Verilog=+{parameter} and/or --fields-SystemVerilog=+{parameter} option.
See https://docs.ctags.io/en/latest/man/ctags-lang-verilog.7.html for more details.

The biggest practical problem ...

If you have any other problem, let me know.

Again if you have any other issue or request, please open new issue.
Thanks.

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

No branches or pull requests

3 participants