DSPOM2
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: Open Source Device Interface (OSDI) Specification - Working Draft subtitle: Version 0.1 author: name: SemiMod UG (haftungsbeschränkt) ... \pagebreak # Introduction All circuit simulators have their own unique interface for incorporating compact semiconductor device models. This slows down model integration, development, distribution and standardization. To remedy this situation, the Verilog-A language has been introduced as a means of having a unified description of compact models. Most simulators have used the transpiler ADMS for incorporating Verilog-A models, yet ADMS's XML file based transpilation approach has significant disadvantages w.r.t. execution time, compilation time and language standard support. OSDI targets to overcome these disadvantages by defining a simulator-independent interface for compiled models. Models will be compiled to shared object files that adhere to the OSDI interface. Then, the simulation engine just needs to implement code that makes this interface suitable for the respective engine. The open-source Verilog-A compiler OpenVAF will serve as a back-end for OSDI. Foremost, this will position OpenVAF and OSDI as the new open-source standard compiler for Verilog-A models, which in turn would be excellent for Verilog-A standardization. Furthermore, having a ready-to-use compiler will help circuit simulators obtain Verilog-A language support quicker, at reduced implementation and time effort. # General Overview Each compiled object file exports the following four symbols: * `uint32_t` **`OSDI_VERSION_MAJOR`** * `uint32_t` **`OSDI_VERSION_MINOR`** * `OsdiDescriptor[]` **`OSDI_DESCRIPTORS`** * `uint32_t` **`OSDI_NUM_DESCRIPTORS`** The symbols `OSDI_VERSION_MAJOR` and `OSDI_VERSION_MINOR` indicate the OSDI version that the object file was compiled with. Simulators that implement OSDI version `X.Y` must be able to load all shared libraries with `OSDI_VERSION_MAYOR = X` and `OSDI_VERSION_MINOR <=Y`. While OSDI is under developoment (Version `X=0`) simulator implementations only have to support `OSDI_VERSION_MINOR =Y`. `OSDI_DESCRIPTORS` is a list of device descriptors of length `OSDI_NUM_DESCRIPTORS`. A device descriptor is an instance of the `OsdiDescriptor` struct that contains all compiled information about a device model (Verilog-A module). It encodes everything required to simulate the model and is the main API surfe of OSDI. Compared to more traditional hardcoded models OSDI model do not call simulator specific functions (with a couple exceptions). Instead `OsdiDescriptor` contains a lot of static metadata. This allows more flexability for the simulator implementation. Compiler implementations are also simplified because static data is less complex than executable code. To facilitate this metadata OSDI contains a larger number of datastructures. The static metata is closely intertwined with the behaviour of the compiled functions. Therefore describing the metadata and functions seperatly would be inadequate. Instead the overall function of the interface will be roughly explained for each simulation stages. Afterwards all datastructures and routines are formally documented. ## Terminology To adequatly describe the various stages a consistent set of terminology is required. There a three basic entities that are at the centre of the interface. An *instance* refers to a **single physical device** used within a netlist. A *model* is a set of parameters that is **shared between multiple physical devices** (instances). A *device descriptor* is a single model implementation (eg `BSIMCMG` or `HICUM/L2`) and does not change during runtime. These three entities form a strict hierachy. ## Parameter Input During the first stage the simulator reads the user configuration, creates the (+^model)/(+^instance) and populates these with parameters. After the correct (+device_descriptor) is identified by the simulator the size of the (+model) and (+instance) data can be obtained. The simulator must allocate the required memory. A list of all parameters is provided in `OsdiDescriptor.param_opvar`. This list contains all static information about the parameter such as the name, type etc. It does **not contain** the default value and bounds as these can depend on the value of other parameters, simulator parameters and even temperature. Populating default values and bounds checking are handled by OSDI during the initalization stage. The value of parameters are stored within the (+model) and (+instance) data. However the simulator can not access these values directly because later stages must know which values were explictly set. Instead the `OsdiDescriptor.access` function is called to obtain access to obtain access to parameter storage. A set of flags is provided to this function which tell OSDI how the pointer will be used by the simulator so it can update addtional internal data correctly. ## Circuit Setup After the (+model)/(+instance) data is created and populated, the simulator must create the required (+^node) and (+^matrix_entry). Furthermore default values for all parameters that were not explicitly set during the parameter input stage must be calculated. Finally any evalutations that only depends on parameter values and temperature are executed. The `setup_model` routine handles model parameters (and dependent calculations). The `setup_instance` and routines does the same for instance parameters. Furthermore this function handles node collapsing and is therfore closely intertwined with the metadata describing (+^node) and (+^matrix_entry). A list of all (+^node) is provided in `OsdiDescriptor.nodes`. It indicates whether a (+node) is a (+terminal) and its name for use within user configuration. The index within this list is used to refer to (+^node) elsewhere. All **non-zero** (+^matrix_entry) are listed in `OsdiDescriptor.jacobian_entries`. A matrix entry is characterised by its row and column within the matrix. The index within this list is used to refer to (+^matrix_entry) elsewhere. Multiple nodes may be collapsed into a single node when some aspect of a (+compact_model) is not used. `OsdiDescriptor.collapsible` contains all pairs of nodes that **might** be collapsed. Which of these collapsible pairs actually takes effect for an (+instace) is determined during the `setup_instance` routine and saved within the instance data. The simulator must used all of this information to create a mapping from OSDI ids to global data. This mapping is the most important result during the setup phase and will be used extensively during the evaluate phase ## Evaluation ```C struct OsdiDescriptor { // metadata char *name; uint32_t num_nodes; /* nodes */ uint32_t num_terminals; OsdiNode *nodes; uint32_t num_jacobian_entries; /* jacobian */ OsdiNodePair *jacobian_entries; bool *const_jacobian_entries; size_t instance_size; /* memory */ size_t model_size; size_t ptrs_offset; uint32_t num_collapsible; /* node collapsing */ OsdiNodePair *collapsible; size_t is_collapsible_offset; OsdiNoiseSource *noise_sources; /* noise */ uint32_t num_sources; uint32_t num_params; /* parameters and op variables */ uint32_t num_instance_params; uint32_t num_opvars; OsdiParamOpVar *inout; // routines void *(*access)(void *inst, void *model, uint32_t id, uint32_t flags); OsdiModelInfo (*setup_model)(void *handle, void *model); OsdiInstanceInfo (*setup_instance)(void *handle, void *inst, void *model, double temperature, uint32_t num_terminals); uint32_t (*eval)(void *handle, void *inst, void *model, OsdiSimInfo *info); void (*eval_noise)(void *inst, void *model, double freq, double *noise_dens, double *ln_noise_dens); void (*to_spice)(void *inst, uint32_t flags); } ``` \pagebreak # Metadata ## `char *name` The name of the device model/Verilog-A module. <!-- MM: Sollte hier nicht Verilog-A module name stehen oder so? Ja --> ## `uint32_t num_nodes` The **total** number of nodes (including terminals and other unkowns) used in the device model. The number of nodes during simulation may be lower due to node collapsing. ## `uint32_t num_terminals` The number of device terminals. Each terminal corresponds to a Verilog-A port (marked `inout`, `input` or `output` in the Verilog-A source). ## `OsdiNode *nodes` ```C struct OsdiNode { char *name; char *units; } ``` A list of size `num_nodes` that contains metadata for each node. The node's index in this list is used to represent a node in all parts of the interface. The first `num_terminals` entries in the `nodes` list are filled with the model's terminals in the same order as defined in Verilog-A. The remaining entries do not follow a specific defined order. Each element of the list is an instances of the `OsdiNode` structure, defined above. It contains the `name` of the node (for node potentials the name of the Verilog-A nets) and the nodes `units`. The `units` field here corresponds to the contents of the `units` attributes of the Verilog-A nature associated with the unknown (`potential_nature` for node potential and `flow_nature` for branch flows). \pagebreak ## `uint32_t num_jacobian_entries` The number of jacobian entries with **non-zero** values in the resistive or reactive jacobian. ## `OsdiNodePair *jacobian_entries` A list with length `num_jacobian_entries` that defines the **non-zero** entries in the resistive jacobian. Each entry contains two indices. The first node corresponds to the row, the second entry corresponds to the column in the jacobian. Other parts of the interface refer to jacobian entries via the indices in this list. ## `bool *const_jacobian_entries` A list of booleans with length `num_jacobian_entries`. The boolean value with index `i` indicates if jacobian entry `i` is constant, i.e. **independent of the operating point**. ## `size_t instance_size` The size of the instance data in bytes. ## `size_t model_size` The size of the model data in bytes. ## `size_t ptrs_offset` The offset of the `instance_ptrs` list within the instance data. This list has a length fo `2*num_nodes + 2*num_jacobian_entries` and entries of type `double*`. The `instance_ptrs` list is accessed as follows: ```C doubles **instance_ptrs = (double **) ((char *)inst) + ptrs_offset; ``` The `instance_ptrs` list contains pointers to the jacobian entries and rhs that are used in the `eval` and `to_spice` functions for writing jacobian and rhs entries into the simulator's global matrix. This `instance_ptrs` list must be populated by the simulator before these functions are called. The first `num_nodes` elements correspond to the resistive rhs. The next `num_nodes` elements correspond to the reactive rhs. The next `num_resist_jacobian_entries` elements correspond to the resistive jacobian elements, The next `num_react_jacobian_entries` elements correspond to the reactive jacobian elements. \pagebreak ## `uint32_t num_collapsible` The number of node pairs that can be collapsed, typically indicated by `V(x,y) <+ 0` in Verilog-A. ## `OsdiNodePair *collapsible` A list with length `num_collapsible` that contains the pairs of nodes that are collapsible, typically indicated by `V(x,y) <+ 0` in Verilog-A. The `setup_instance` routine tells the simulator which of these pairs to collapse for a specific instance. ## `size_t is_collapsible_offset` Provides the offset of the `is_collapsible` lists' beginning from the beginning of the instance data in byes. The `is_collapsible` list has length`num_collapsible` and contains `bool` elements. A pointer to the list is obtained as follows: ```C bool *is_collapsible = (bool *) ((char *)inst) + is_collapsible_offset; ``` `is_collapsible[i]` is set true if the `collapsible` node pair at `collapsible[i]` is collapsed for the given instance. This entries of `is_collapsible` are set in the `setup_instance` routine. ## `uint32_t num_noise_src` The number of uncorrelated noise sources used in the model (`white_noise`, `flicker_noise`, `table_noise` and `table_noise_log` in Verilog-A). ## `OsdiNoiseSource *noise_sources` ```C struct OsdiNoiseSource { char *name; OsdiNodePair nodes; } ``` A list of all noise sources used within the device model with length `num_noise_src`. Each element is an instance of the `OsdiNoiseSource` struct defined above. The field `name` corresponds to the name specified in Verilog-A or an empty string otherwise. The `nodes` field corresponds to the nodes that the noise source is connected to. The first node corresponds to the positive node (first node in Verilog-A contribution). Correlated sources are not directly supported at the moment. For that purpose a correlation network can be used instead. \pagebreak ## `uint32_t num_params` The number of Verilog-A model parameters. ## `uint32_t num_instance_params` The number of Verilog-A parameters marked with the attribute `type="instace"`. ## `uint32_t num_opvar` The number of operating point variables (marked with `description` and `units` attribute). ## `OsdiParamOpvar* inout_data` ```C struct OsdiParamOpvar { char **name; uint32_t num_alias; char *description; char *units; uint32_t base_type; uint32_t len; } ``` A list of metadata for each Verilog-A parameter with length `num_params + num_opvar`. Each element is an instance of the `OsdiParamOpvar` struct defined above. The first `num_opvar` elements correspond to the models operating point variables. The following `num_instance_params` elements correspond to the models instance parameters. The remaining elements correspond to the model parameters. The `name` field contains a list of identifiers with `1 + num_alias` entries. Its first entry corresponds to the canonical identifier while the remaining `num_alias` entries are aliases. The `description` and `units` field correspond the values of the Verilog-A attributes with the same name. Type information is encoded in the `base_type` and `len` fields. The 2 least significant bits within the `base_type` fields indicate which Verilog-A base type (`real`, `integer` or `string`). Additionally the most significant bit (MSB) is set for instance parameter and the second MSB for operating point variables. For arrays the `len` field contains the length of the array while for scalar parameters the `len` field is set to 0. ```C #define INOUT_TY_REAL 0; // double #define INOUT_TY_INT 1; // int32_t #define INOUT_TY_STR 2; // char* #define INOUT_OPVAR (1 << 30); #define INOUT_INSTANCE (1 << 31); ``` \pagebreak <!-- void *(*access_param)(void* inst, void *model, char *name, --> <!-- uint32_t flags); --> <!-- // teardown --> <!-- void (*teardown_model)(void *model); --> <!-- void (*teardown_instance)(void* inst); --> <!-- // evaluation --> <!-- uint32_t (*eval)(void *handle, void* inst, void *model, --> <!-- double **resist_jacobian, double **react_jacobian, --> <!-- double **resist_residual, double **reactive_residual, --> <!-- SimInfo *sim_info, void **state_vec); --> <!-- void (*eval_noise)(void* inst, void *model, double freq, --> <!-- double *noise_dens, double *ln_noise_dens); --> \pagebreak # Routines Routines provide access to information that can not be exposed as static metadata. This includes mainly compiled behavioral Verilog-A code and access to heterogeneous data inside the model and instance data. All routines get a pointer to the model and/or instance data as arguments from the simulator. These pointers must be allocated by the simulator with correct size, alignment and are initialized with zeroed bytes. This can be achieved as follows: ```C void* inst = calloc(1, descriptor.instance_size); void* model = calloc(1, descriptor.model_size); ``` All functions that execute Verilog-A behavioural code have the `void *handle` argument. This argument is then given to `osdi_init_log_message` and `osdi_finish_log_message` whenever Verilog-A emits messages. The contents of this pointer are entirely up to the simulator. See the documentation for `osdi_init_log_message` and `osdi_finish_log_message` for more details. ## `access` ```C void *access(void *inst, void *model, uint32_t id, uint32_t flags); ``` This function allows the simulator to read and write parameters as well as operating point variables. The data corresponding to `inout_data[id]` is accessed. The `flags` argument indicates what kind of operation the returned pointer shall be used for. The following bit-flags are available: ```C #define ACCESS_FLAG_SET 1 #define ACCESS_FLAG_INIT 2 #define ACCESS_FLAG_INSTANCE 4 ``` Reading the pointer is always allowed. When `ACCESS_FLAG_SET` is set the pointer can be written as well. During initial reading of the netlist `ACCESS_FLAG_INIT` must also be set. This allows the simulator to determine which parameters are explicitly set, and which retain their default value. If `ACCESS_FLAG_INIT` is not set only parameters that were explicitly provided during initialization can be updated. If such an access is attempted regardless a null pointer will be returned. By default the `access` function will always access model parameters. To access the corresponding instance parameter instead `ACCESS_FLAG_INSTANCE` must be provided. If an instance parameter is not set for an instance, the parameter is copied from the model during `setup_instance`. Note that operating point variables can only be read and therefore the method returns a null pointer when `flags != 0`. \pagebreak ## `setup_model` ```C OsdiModelInfo setup_model(void *handle, void *model); struct OsdiInitInfo { uint32_t flags; uint32_t num_errors; InitError *errors; } ``` This function initializes all parameters that were not explicitly set and also performs bounds check on all model parameters (and instance parameters that were set for the model). Additionally it executes all Verilog-A code that does not depend on: * operating point * analysis mode * time step * absolute time * values of instance parameter * `$param_given` with instance parameters as argument * `$port_connected` * `$temperature` * `@final_step` event The function returns an instance of the `OsdiModelInfo` struct. It contains a list of errors that occurred while checking the model parameters. Additionally it contains any execution flags emitted by the behavioural Verilog-A code. The documentation for these flags can be found in the documentation of the `eval` function. This function must be called whenever the model parameters change. Whenever this function is called for a model the `setup_instance` routine must be called for all its instances. \pagebreak ## `setup_instance` ```C OsdiInstanceInfo setup_instance(void *handle, void *inst, void *model, double temperature, uint32_t num_terminals); struct OsdiInitInfo { uint32_t flags; uint32_t num_errors; InitError *errors; } ``` This function initializes all instance parameters that were not explicitly set and also performs bounds check on all instance parameters. Instance parameters that were not set for the instance but are set for the model are copied into the instance. The routine executes all Verilog-A code that was not executed in `setup_model` and does not depend on: * operating point * analysis mode * time step * absolute time * `@final_step` event This function returns an instance of the `OsdiInstanceInfo` struct. It contains a list of errors that occurred while checking the instance parameters. Furthermore any execution flags emitted by the behavioural Verilog-A code are also provided. The documentation for these flags can be found in the documentation of the `eval` function. This function also populates the `is_collapsible` list within the instance data. When this function is called repeatedly (during a parameter sweep) the simulator must ensure that node collapsing is updated whenever `is_collapsible` changes. Alternatively the simulator can disallow such sweeps producing an error whenever `is_collapsible` changes. This function must be called whenever the model or instance parameters are changed. \pagebreak ## `eval` ```C uint32_t eval(void *handle, void *inst, void *model, OsdiSimInfo *info); struct OsdiSimInfo { uint32_t flags; double timestep; double abstime; } ``` This function evaluates the remaining behavioral code in the Verilog-A analog block and writes the jacobian and rhs entries. This function contains the bulk of the Verilog-A code. Due to its complexity, the documentation for this function is split in multiple parts as follows. ### Arguments Apart from the standard pointers, `eval` requires a pointer to an instance of the `OsdiSimInfo` struct. This struct contains generic information about the current simulation. The `flags` field is a bitset where each bit indicates a different property of the current simulation. ```C #define SIMINFO_CALC_NOISE 1 #define SIMINFO_CALC_REACT_RHS 2 #define SIMINFO_CALC_RESIST_RHS 4 #define SIMINFO_CALC_REACT_JACOBIAN 8 #define SIMINFO_CALC_RESIST_JACOBIAN 16 #define SIMINFO_CALC_OP 32 #define SIMINFO_ANALYSIS_NOISE 256 #define SIMINFO_ANALYSIS_STATIC 512 #define SIMINFO_ANALYSIS_DC 1024 #define SIMINFO_ANALYSIS_AC 2048 #define SIMINFO_ANALYSIS_IC 4096 #define SIMINFO_ANALYSIS_NODESET 8192 ``` The `SIMINFO_CALC_<X>` flags indicate which results are required. Setting only the required flags allows faster execution time. For example, not calculating the reactive rhs and jacobian can significantly speed up DC simulations. The `SIMINFO_ANALYSIS_<X>` flags indicate which analysis is being run for use with analysis dependent function in Verilog-A. The flags match those outlined in *Table 4-21* of the Verilog-AMS standard. It is up to the simulator when to emit these when there is no 1 to 1 correspondence with behaviour outlined in the language standard. The `timestep` and `abstime` fields contain information about the time in large signal (transient) analysis. The `timestep` field indicates the time difference between the previous and current time step in seconds. The `abstime` field indicates the time of the current operating point in seconds. <!-- The `state_vec` argument is an array where each entry contain an allocation of size `state_vec_size`. --> <!-- The entry `state_vec[0]` corresponds to the current time step while increasing indices correspond to previous time steps (for large signal analysis). --> <!-- The total number of state vec entries are definied in the `num_states` argument. --> Apart from the explicit function arguments the `eval` function also reads the `instance_ptrs` list. This list contains pointers to the rhs and jacobian entries. Is is contained within the instance data and must be populated by the simulator. The simulator must correctly take node collapsing into account when populating this list. ### Returned Flags Verilog-A allows behavioural code to control the simulation flow. This functionality is accommodated by setting bit-flags for the return value. ```C #define EVAL_RET_FLAG_LIM 1 #define EVAL_RET_FLAG_FATAL 2 #define EVAL_RET_FLAG_FINISH 4 #define EVAL_RET_FLAG_STOP 8 ``` The `EVAL_RET_FLAG_LIM` flag indicates that a `$limit` function (like `pnjlim`) has reduced the change of a potential. If the `EVAL_RET_FLAG_FATAL` flag is set at a fatal error occurred. The simulator must **abort** the current simulation with an error. The `EVAL_RET_FLAG_FINISH` flag indicates that `$finish` was called. If the current iteration has converged the simulator must **exit gracefully**. Otherwise this flag should be ignored. The `EVAL_RET_FLAG_STOP` flag indicates that `$stop` was called. If the current iteration has converged the simulator must **pause** the current simulation. Otherwise this flag should be ignored. ## `eval_noise` ```C void eval_noise(void *inst, void *model, double freq, double *noise_dens, double *ln_noise_dens); ``` This function is the primary function called during noise analysis. It generates the (potentially) frequency dependent noise densities based upon the (operating point dependent) results of the `eval` function. The results are written into `noise_dens` and `ln_noise_dens`. These two pointer must each point to a list of doubles with length `num_noise_src`. The element `noise_dens[i]` is set to the noise density that corresponds to the noise source described in `noise_sources[i]`. `ln_noise_dens[i]` is set to `log(noise_dens[i])`. \pagebreak ## `to_spice` ```C void to_spice(void *inst, double timestep); ``` OSDI uses a seperate reactive and resistive RHS and jacobian. This approach allows OSDI to support a large array of analysis modes (like HB, tran, AC and DC simulations) without providing a separate function for each analysis type. This approach is well suited for many circuit simulators which use a similar formulation internally. However, SPICE based simulators only have a single jacobian and rhs. Therefore these matrices must be merged to support transient simulations in SPICE-like simulators. Additionally, SPICE based simulators use a different formulation of the NEWTON method: \begin{gather} J(x_{k+1} - x_k) = - F(x_k) \label{eq:newton}\\ J x_{k+1} = J x_{k} - F(x_k) \label{eq:newton_spice} \end{gather} While the newton method is more commonly formulated as shown in \eqref{eq:newton}, SPICE uses the formulation shown in \eqref{eq:newton_spice}. Therefore, the rhs is also converted for use within SPICE based simulators. This function assumes that the `eval` function was run previously. For transient simulations the time difference between the last operating point and this operating point must be provided as the `timestep` argument. For other analysis types the `timestep` argument must be set to `+0.0`. In case of transient analysis this function adds `react_jacobian[i]/time_step` to each entry in the resistive jacobian. Furthermore the reactive rhs is added to the resistive rhs. Therefore the simulator must perform a numeric time derivative on the reactive RHS before calling this function. This functionality can not be provided within the `to_spice` function as the exact time derivative algorithm is simulator dependent. In any analysis mode the final rhs entry $x_\mathrm{i}^\prime$ is then calculated with the formula below. Here $J_\mathrm{jl}$ is the (resistive) jacobian entry with row $j$ and column $l$ generated by the eval function and $x_\mathrm{i}$ is the (resistive) rhs entry for node `` by the eval function. $$ x_\mathrm{i}^\prime = - x_\mathrm{i} + \sum_{j} \sum_{l} J_\mathrm{lj} x_\mathrm{j} $$ The functionality provided by this function could be implemented by the simulator. However the implementation would become involved as the mapping between pointers and jacobian entries and node collapsing would have to be taken into account. As a result the implementation would involve a lot of branching and require memory allocations. This can have a non trivial performance overhead. In contrast a compiler that can target OSDI already has access to all information required to generate such a function without branches or allocations. Therefore OSDI provides this function to make integration with SPICE based simulator easier and performant. \pagebreak # Callbacks ```C extern FILE *osdi_init_log_message(void *handle, uint32_t lvl); extern void osdi_finish_log_message(void *handle, FILE *stream, uint32_t lvl); ``` OSDI generally tries to avoid callbacks to simulator specific functions. However such callbacks can not be entirely avoided. Any implementation must provide symbols for all callbacks defined herein. Every callback accepts a `handle` pointer. This pointer is passed by the simulator to any function that executes Verilog-A behavioral code. It is intended to allow the callbacks to access to simulator specific data. The `osdi_init_log_message`/`osdi_finish_log_message` callbacks are required to allow behavioral Verilog-A code to emit log messages. Simulators may wish to redirect these log messages or attach additional metadata. They are are called before/after a message is emitted. The returned `FILE` pointer will be used as the destination for the message. Both functions receive the level of the log messages as an integer. Appropriate constants are defined in the OSDI header file and shown below. ``` C #define LOG_LVL_DEBUG 0 #define LOG_LVL_INFO 1 #define LOG_LVL_WARN 2 #define LOG_LVL_ERR 3 #define LOG_LVL_FATAL 4 ``` A basic implementation that writes each message to a separate line in stdout prefixed with the level is shown below. ```C extern FILE *osdi_init_log_message(void *handle, uint32_t lvl){ switch(lvl){ case LOG_LVL_DEBUG: fwrite(stdout, "VA debug: "); break; case LOG_LVL_INFO: fwrite(stdout, "VA info: "); break; case LOG_LVL_WARN: fwrite(stdout, "VA warn: "); break; case LOG_LVL_ERR: fwrite(stdout, "VA error: "); break; case LOG_LVL_FATAL: fwrite(stdout, "VA fatal: "); break; default: fwrite(stdout, "VA unkown message: "); break; } return stdout; } ``` ```C extern void osdi_finish_log_message(void *handle, FILE *stream, uint32_t lvl){ fwrite(stream, "\n"); return; } ``` \pagebreak # Verilog-A Standard Compliance OSDI is predominantly aimed at compact modelling. In the compact modeling community some parts of the Verilog-A language are de-facto not used. For allowing fast and consistent results some limitations of the Verilog-A language subset are necessary as defined below. ## `limexp` The `limexp` function is commonly used in Verilog-A because exponential overflow is a major cause of convergence issues. The language standard defines that `limexp` should limit the change of its argument between iterations. This requires access to values from previous iterations and also a limiting algorithm that is applicable in the general case. As a result all implementations known to the author have opted to use a simple linearised exponential instead, for example: ```C if (x < EXP_LIM){ return exp(x) }else{ return exp(EXP_LIM) *(x + 1 - EXP_LIM) } ``` OSDI uses this linearised function as well with `EXP_LIM = 80`. This may change in future versions if tangible improvements can be demonstrated with a different algorithm. ## Hidden State OSDI compliant compilers must assume that a compiled model does not have hidden states. This often allows more code to be moved into the `model_setup` and `instance_setup` functions, significantly improving performance. If a variables has the `hidden_state` attribute in Verilog-A, the compiler can not make that assumption. The same attribute can be placed on a Verilog-A module to allow hidden state for all variables within the module. \pagebreak ## Small Signal Operators The arguments of the following analog operators are linearised during small signal and noise simulations: * `ddt` * `idt` * `idt_mod` * `white_noise` * `flicker_noise` * `table_noise` * `table_noise_log` As a result they can only appear in linear expressions on the rhs of a contribute statement. This is demonstrated with a couple examples: ``` verilog I(c,a) <+ Id + c*ddt(Qd); // possible y = Id + ddt(Qd); // not possible I(c,a) <+ y; I(c,a) <+ Id + exp(ddt(Qd)); // not possible ``` \pagebreak

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully