From 8f79a2b97a7fda07023778473b4c4a287f4618f3 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 19 Sep 2022 19:04:43 -0400 Subject: [PATCH 1/5] [major] Move Extmodule Params to Instantiation This changes the format for FIRRTL external modules to move parameter values to the site of instantiation as opposed to being declared along with the extmodule definition. This has the added benefit of removing the "defname" as this is now unified with the name of the external module. Signed-off-by: Schuyler Eldridge --- spec.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/spec.md b/spec.md index 8e59c9f3..8879c87b 100644 --- a/spec.md +++ b/spec.md @@ -217,12 +217,9 @@ instance statement for details on how to instantiate a module ## Externally Defined Modules Externally defined modules are modules whose implementation is not provided in -the current circuit. Only the ports and name of the externally defined module -are specified in the circuit. An externally defined module may include, in -order, an optional _defname_ which sets the name of the external module in the -resulting Verilog and zero or more name--value _parameter_ statements. Each -name--value parameter statement will result in a value being passed to the named -parameter in the resulting Verilog. +the current circuit. Only the ports of the externally defined module are +specified in the circuit. No other statements may exist in the external module +body. An example of an externally defined module is: @@ -231,15 +228,31 @@ extmodule MyExternalModule : input foo: UInt<2> output bar: UInt<4> output baz: SInt<8> - defname = VerilogName - parameter x = "hello" - parameter y = 42 ``` The widths of all externally defined module ports must be specified. Width inference, described in [@sec:width-inference], is not supported for module ports. +Externally defined modules may have zero or more parameters. Parameters may be +of known-width `UInt`{.firrtl} or `String`{.firrtl}. The value of a parameter +is set at each instantiation of an external module using a literal value. + +An example of a parametric externally defined module and its instantiation is: + +``` firrtl +extmodule MyExternalModule2> : + ; ... +module Top: + inst foo of MyExternalModule2<"hello", UInt<8>(42)> + inst bar of MyExternalModule2<"world", UInt(0)> +``` + +As shown above, it is allowable to use a smaller, unknown width `UInt`{.firrtl} +literal to set a parameter value so long as the width of the underlying +parameter value is large enough to store the literal type. A literal that is +too large for a given parameter type is illegal. + A common use of an externally defined module is to represent a Verilog module that will be written separately and provided together with FIRRTL-generated Verilog to downstream tools. From 442b8b2ce4c71a4541babdb198ea7fa84787e02a Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 19 Sep 2022 21:16:36 -0400 Subject: [PATCH 2/5] squash! [major] Move Extmodule Params to Instantiation Also allow for SInt parameters. --- spec.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/spec.md b/spec.md index 8879c87b..ca5b15a3 100644 --- a/spec.md +++ b/spec.md @@ -235,20 +235,25 @@ inference, described in [@sec:width-inference], is not supported for module ports. Externally defined modules may have zero or more parameters. Parameters may be -of known-width `UInt`{.firrtl} or `String`{.firrtl}. The value of a parameter -is set at each instantiation of an external module using a literal value. +of known-width `UInt`{.firrtl} or `SInt`{.firrtl} types or `String`{.firrtl} +type. The value of a parameter is set at each instantiation of an external +module using a literal value. An example of a parametric externally defined module and its instantiation is: ``` firrtl -extmodule MyExternalModule2> : +extmodule MyExternalModule2< + parameter x: String, + parameter y: UInt<8>, + parameter z: SInt<4> +> : ; ... module Top: - inst foo of MyExternalModule2<"hello", UInt<8>(42)> - inst bar of MyExternalModule2<"world", UInt(0)> + inst foo of MyExternalModule2<"hello", UInt<8>(42), SInt<4>(-1)> + inst bar of MyExternalModule2<"world", UInt(0), SInt(-2)> ``` -As shown above, it is allowable to use a smaller, unknown width `UInt`{.firrtl} +As shown above, it is allowable to use a smaller, unknown width integer type literal to set a parameter value so long as the width of the underlying parameter value is large enough to store the literal type. A literal that is too large for a given parameter type is illegal. From 75126fccb82688ca1f70e4d7fc41ec84137c8cd9 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 19 Sep 2022 21:17:04 -0400 Subject: [PATCH 3/5] squash! [major] Move Extmodule Params to Instantiation Update EBNF grammar for external module parameters. --- spec.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spec.md b/spec.md index ca5b15a3..eba4a464 100644 --- a/spec.md +++ b/spec.md @@ -2917,8 +2917,8 @@ primop_1expr2int = primop = primop_2expr | primop_1expr | primop_1expr1int | primop_1expr2int ; (* Expression definitions *) -expr = - ( "UInt" | "SInt" ) , [ width ] , "(" , ( int ) , ")" +int_lit = ( "UInt" | "SInt" ) , [ width ] , "(" , int , ")" +expr = int_lit | reference | "mux" , "(" , expr , "," , expr , "," , expr , ")" | "validif" , "(" , expr , "," , expr , ")" @@ -2942,11 +2942,13 @@ memory = "mem" , id , ":" , [ info ] , newline , indent , dedent ; (* Statements *) +parameter = uint_lit | string ; +parameter_seq = parameter | parameter , "," , parameter_seq ; statement = "wire" , id , ":" , type , [ info ] | "reg" , id , ":" , type , expr , [ "(with: {reset => (" , expr , "," , expr ")})" ] , [ info ] | memory - | "inst" , id , "of" , id , [ info ] + | "inst" , id , "of" , id , [ "<" , parameter_seq , ">" ] , [ info ] | "node" , id , "=" , expr , [ info ] | reference , "<=" , expr , [ info ] | reference , "<-" , expr , [ info ] @@ -2966,10 +2968,11 @@ module = "module" , id , ":" , [ info ] , newline , indent , { port , newline } , { statement , newline } , dedent ; -extmodule = "extmodule" , id , ":" , [ info ] , newline , indent , +parameter_decl = "parameter" , id , ":" , type ; +parameter_decl_seq = parameter_decl | parameter_decl , "," , parameter_decl_seq ; +extmodule = "extmodule" , id , [ "<" , parameter_decl_seq , ">" ] , ":" , + [ info ] , newline , indent , { port , newline } , - [ "defname" , "=" , id , newline ] , - { "parameter" , "=" , ( string | int ) , newline } , dedent ; (* Version definition *) From 48093c7f898e0e91d5e0bd8f99a474a289fc1691 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 19 Sep 2022 22:13:40 -0400 Subject: [PATCH 4/5] fixup! squash! [major] Move Extmodule Params to Instantiation --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index eba4a464..6f30fe3d 100644 --- a/spec.md +++ b/spec.md @@ -2942,7 +2942,7 @@ memory = "mem" , id , ":" , [ info ] , newline , indent , dedent ; (* Statements *) -parameter = uint_lit | string ; +parameter = int_lit | string ; parameter_seq = parameter | parameter , "," , parameter_seq ; statement = "wire" , id , ":" , type , [ info ] | "reg" , id , ":" , type , expr , From dbb406b73d3ca9fd91afa0b9af345cd7458c479b Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Tue, 20 Sep 2022 15:11:19 -0400 Subject: [PATCH 5/5] squash! squash! [major] Move Extmodule Params to Instantiation Make parameter types explicitly boxed. Restrict the locations where parameter types can show up to nodes and external module parameters. Allow aggregate, passive parameter types. Add a new parameter primitive operation section. This is presently incomplete, but includes a single `primAdd` operation to show how this would work. Update the EBNF grammar and the FIRRTL syntax highlighting XML file. --- include/firrtl.xml | 2 ++ spec.md | 71 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/include/firrtl.xml b/include/firrtl.xml index 0c09934a..f5df1c6a 100644 --- a/include/firrtl.xml +++ b/include/firrtl.xml @@ -27,6 +27,7 @@ Clock Reset AsyncReset + Param when @@ -78,6 +79,7 @@ assert assume cover + paramAdd diff --git a/spec.md b/spec.md index 6f30fe3d..9ed4b7a0 100644 --- a/spec.md +++ b/spec.md @@ -243,14 +243,18 @@ An example of a parametric externally defined module and its instantiation is: ``` firrtl extmodule MyExternalModule2< - parameter x: String, - parameter y: UInt<8>, - parameter z: SInt<4> + parameter x: Param, + parameter y: Param>, + parameter z: Param> > : ; ... module Top: - inst foo of MyExternalModule2<"hello", UInt<8>(42), SInt<4>(-1)> - inst bar of MyExternalModule2<"world", UInt(0), SInt(-2)> + inst foo of MyExternalModule2, Param(42)>, Param(-1)>> + inst bar of MyExternalModule2, Param, Param> + node _x = Param<"baz"> + node _y = Param + node _z = Param + inst baz of MyExternalModule2<_x, _y, _z> ``` As shown above, it is allowable to use a smaller, unknown width integer type @@ -581,6 +585,37 @@ flipped orientations. Thus all ground types are passive types. Vector types are passive if their element type is passive. And bundle types are passive if no fields are flipped and if all field types are passive. +## Parameter Types + +A `UInt`{.firrtl}, `SInt`{.firrtl}, or `String`{.firrtl} type may be boxed with +a `Param`{.firrtl}` type. This indicates that this is a type that is used to +express parameterization. Parameter types may be used to express +parameterization on externally defined modules. Parameter types may be used as +nodes. Parameter types may be used in passive aggregates. All other uses of +parameter types are explicitly illegal. E.g., parameter types may not appear in +wires, registers, ports, or connections. + +The following shows the creation of two parameter types, an expression involving +these parameter types, and the use of the result of the expression in an +external module instantiation. + +``` firrtl +extmodule Foo> : + input a : UInt +module Bar: + input a: UInt<8> + + node x = Param(UInt<7>(1)) + node y = Param(UInt<7>(2)) + node z = paramAdd(x, y) + + inst foo of Foo +``` + +Certain operations are supported on parameter types. See Section +[@sec:parameter-primitive-operations] for a listing of all parameter primitive +operations. + ## Type Equivalence The type equivalence relation is used to determine whether a connection between @@ -2397,6 +2432,18 @@ fixed-point number. This will cause the binary point and consequently the total width of the fixed-point result type to differ from those of the fixed-point argument type. See [@sec:fixed-point-math] for more detail. +# Parameter Primitive Operations + +Operations are defined for manipulating parameter types. For operations which +have overlapping functionality with normal primitive operations (see Section +[@sec:primitive-operations]), the result width expressions are intentionally +kept the same. + +| Name | Arguments | Arg Types | Result Type | Result Width | +|----------|-----------|-------------------------------|---------------|--------------------| +| paramAdd | (e1,e2) | (Param\,Param\) | Param\ | max(w~e1~,w~e2~)+1 | +| | | (Param\,Param\) | Param\ | max(w~e1~,w~e2~)+1 | + # Flows An expression's flow partially determines the legality of connecting to and from @@ -2890,6 +2937,7 @@ type_aggregate = "{" , field , { field } , "}" | type , "[" , int , "]" ; field = [ "flip" ] , id , ":" , type ; type = type_ground | type_aggregate ; +type_param = "Param<" , ( ( "UInt" | "SInt" ) , width | "String" ) , ">" (* Primitive operations *) primop_2expr_keyword = @@ -2928,6 +2976,17 @@ reference = id | reference , "[" , int , "]" | reference , "[" , expr , "]" ; +(* Parameter primitive operations *) +primop_param_2expr_keyword = "add" ; +primop_param_2expr = + primop_param_2expr_keyword , "(" , parm_expr , "," , parm_expr ")" ; +param_primop = primop_param_2expr ; + +(* Parameter expression definitions *) +param_expr = int_lit ; + | reference + | param_primop ; + (* Memory *) ruw = ( "old" | "new" | "undefined" ) ; memory = "mem" , id , ":" , [ info ] , newline , indent , @@ -2968,7 +3027,7 @@ module = "module" , id , ":" , [ info ] , newline , indent , { port , newline } , { statement , newline } , dedent ; -parameter_decl = "parameter" , id , ":" , type ; +parameter_decl = "parameter" , id , ":" , type_param ; parameter_decl_seq = parameter_decl | parameter_decl , "," , parameter_decl_seq ; extmodule = "extmodule" , id , [ "<" , parameter_decl_seq , ">" ] , ":" , [ info ] , newline , indent ,