This shows you the differences between two versions of the page.
|
gnucap:manual:tech:modelgen-verilog [2025/10/27 06:42] felixs adjust headlines |
gnucap:manual:tech:modelgen-verilog [2025/10/27 06:55] (current) felixs add storage types |
||
|---|---|---|---|
| Line 73: | Line 73: | ||
| There is no ELEMENT instanciated for a potential probe branch. A flow probe branch requires one, as it works similar to a | There is no ELEMENT instanciated for a potential probe branch. A flow probe branch requires one, as it works similar to a | ||
| zero-potential source. | zero-potential source. | ||
| + | |||
| + | ===== Code generation ===== | ||
| ==== Computing Partial Derivatives ==== | ==== Computing Partial Derivatives ==== | ||
| Line 162: | Line 164: | ||
| ''fpoly_cap'' limited to 4 external nodes and without self-capacitance. | ''fpoly_cap'' limited to 4 external nodes and without self-capacitance. | ||
| The ''va_ddt'' filter in Modelgen-Verilog retains the arbitrary number of nodes and adds the shunt resistance. | The ''va_ddt'' filter in Modelgen-Verilog retains the arbitrary number of nodes and adds the shunt resistance. | ||
| + | |||
| + | ===== Sequential blocks ===== | ||
| + | ==== Storage types for variables in generated code ==== | ||
| + | |||
| + | Circuit device models may contain procedural code that uses variables. | ||
| + | According to the standard, all variables are initialised to zero and stored with | ||
| + | the device instance, modelling its internal state. Depending on the actual use, | ||
| + | a variable may not need to be stored in the instance, for optimisation | ||
| + | purposes. The storage type of a variable indicates where a variable is stored, | ||
| + | and is deduced from the use pattern. The relevant storage types are 'instance', | ||
| + | 'common', and 'temporary' as follows. | ||
| + | |||
| + | === State variable === | ||
| + | |||
| + | A state variable represents a device internal state that encodes the devices | ||
| + | history and usually determines its future behaviour. Such a variable is stored | ||
| + | once per device instanciating the module where it is declared. | ||
| + | |||
| + | module instance0() | ||
| + | real counter; // <= state variable | ||
| + | parameter real tstart; | ||
| + | analog begin | ||
| + | @(timer(tstart, 1)) counter = counter + 1; | ||
| + | $strobe("value is %d", counter); | ||
| + | end | ||
| + | endmodule; | ||
| + | |||
| + | Also, variables that are accessible from outside the module generally need to | ||
| + | be stored inside the instance. | ||
| + | |||
| + | module instance1(p) | ||
| + | electrical p; | ||
| + | (* desc="sample value"*) real sample; // <= state variable | ||
| + | analog begin | ||
| + | @(timer(0, 1)) sample = V(p); | ||
| + | end | ||
| + | endmodule; | ||
| + | |||
| + | === Temporary variable === | ||
| + | |||
| + | A variable that is assigned to before each use, is of temporary storage type. | ||
| + | If it is not a constant, it may rematerialise during device evaluation. Its | ||
| + | value is never used anywhere outside the scope it was declared in. | ||
| + | |||
| + | module temporary0(p, n); | ||
| + | parameter int q=0; | ||
| + | analog begin : main | ||
| + | int i; // temporary variable | ||
| + | i = q; | ||
| + | while(i>0) begin | ||
| + | I(p,n) <+ 1; | ||
| + | i = i-1; | ||
| + | end | ||
| + | end | ||
| + | endmodule | ||
| + | |||
| + | module temporary1(p, n) | ||
| + | electrical p, n; | ||
| + | parameter real r from (0:inf); | ||
| + | analog begin : main | ||
| + | real i; // temporary variable; | ||
| + | i = V(p,n) / r; | ||
| + | I(p,n) <+ i; | ||
| + | end | ||
| + | endmodule | ||
| + | |||
| + | Since a temporary variable is local it may be further optimised out or even | ||
| + | eliminated at a later stage unrelated to modelling semantics. For example, when | ||
| + | modelgen-verilog generates C++ code, the C++ compiler will be responsible of | ||
| + | such further steps. | ||
| + | |||
| + | === Common variable === | ||
| + | |||
| + | A variable that holds a constant value during simulation only needs to be | ||
| + | stored once per group of identical devices. Identical devices share the | ||
| + | parameter values assigned to them. It only needs computing during | ||
| + | initialisation, at startup or when parameters change. | ||
| + | |||
| + | module common0(p, n) | ||
| + | electrical p, n; | ||
| + | parameter real r=1. from (0:inf); | ||
| + | analog begin : main | ||
| + | real g; // common variable; | ||
| + | g = 1 / r; // initialisation | ||
| + | I(p,n) <+ g * V(p,n); | ||
| + | end | ||
| + | endmodule | ||
| + | |||
| + | Parameters and local parameters may be seen as an explicit form of common | ||
| + | variables. It is not always straightforward to use (local) parameters where | ||
| + | common storage is desired. For example | ||
| + | |||
| + | module common1(p, n) | ||
| + | electrical p, n; | ||
| + | parameter real t=0 from [0:inf); | ||
| + | real mytemp; // common storage | ||
| + | analog initial begin | ||
| + | if($param_given(t)) | ||
| + | mytemp = t; | ||
| + | else | ||
| + | mytemp = $temperature(); | ||
| + | end | ||
| + | |||
| + | analog begin : main | ||
| + | [..] // possibly use mytemp | ||
| + | end | ||
| + | endmodule | ||
| + | |||
| + | === Classification of the storage type === | ||
| + | |||
| + | Common variables may be stored as temporaries or states and likewise, | ||
| + | temporaries may be stored as state variables. | ||
| + | On the other hand, states are more expensive than temporaries, and temporaries | ||
| + | are usually more expensive than commons. | ||
| + | |||
| + | Assigning the optimal storage type to each variable declared in a module is | ||
| + | hard in general. An approximation will select variables that do not need to be | ||
| + | stored as states and from those, the variables that are not used as | ||
| + | temporaries. | ||
| + | |||
| + | A good approximation may be obtained based on assign and use pattern during a | ||
| + | simulated execution. A variable that is (always) assigned before (potential) | ||
| + | use is temporary or common. A variable that is never reassigned after | ||
| + | use is common. | ||
| + | |||
| + | The key issue is the control flow, but in some situations the assign/use status | ||
| + | is easy to determine within each sequential block, to be propagated upwards. | ||
| + | For example in common1, mytemp is assigned in both conditional branches. | ||
| + | Hence after executing the associated conditional statement mytemp is assigned, | ||
| + | before any later use in main. | ||