[sv-dc] A few SV-DC items from a user's experience...

From: Kyl Scott <kyl.scott@ti.com>
Date: Tue Feb 03 2015 - 19:30:08 PST
Hi Folks:

I am new to the SV-DC list, but have been working on using the excellent 
work that all of you have done over the past several years to work on 
creating a better event driven analog modeling infrastructure than the 
more limited simple real valued models that we have been using in 
SystemVerilog.

I am certainly not as well versed in the nuances and details of the 
language as the committee, so I will rely on all of you to help 
translate these ideas into the specific formats and amount of 
information that the committee needs...  I am also hoping to learn a lot 
from you and the others during the next few years, as well.

Here are several items that we have encountered already or brushed up 
against enough to start thinking about:

1) always @(UDT)

Every user I have seen so far immediately hits this one and is very 
confused.  While always @(*) is a workaround, this is a non-intuitive 
limitation:

   logic sig_logic;
   real sig_real;
   UDN sig_UDN;

always @(sig_logic) is OK, always @(sig_real) is OK, always @(sig_UDN) 
is an error, and this really confuses people.

They think of logic, UDN, etc. as signals, and not as non-struct vs. 
struct, etc.  And I suppose always @(sig_UDN) would work if the UDN was 
a real and not a struct?  So it is not even consistent within the UDN 
space? This is certainly not the highest priority item to think about, 
but it would be nice to clean this up and save a lot of people from some 
very confusing compile errors and wasted time.  My understanding is that 
the LRM does not specify any required behavior for this case, so it 
might be nice to plug that hole, in the context of UDNs.

2) Resolution function error messages

One thing we quickly noticed once we started writing resolution 
functions is that there is no way to get the net name of the net that is 
being resolved.  If you have a design with 10,000 nets, and you get a 
resolution error, it is rather difficult to figure out where the error 
is located in the actual design.  %m is useless in this context, since 
it simply returns the resolution function, which is the same for all 
nets of that type.   So we need either a new % format or system call 
that would return the hierarchical name of the node being resolved.  Our 
preference is that the name would be the top most name (least number of 
hierarchical levels) rather than some deep in the design leaf name 
(since a single node can have many different net names associated with 
it, as it traverses the hierarchy).  I am not sure if there needs to be 
any options to control the format or not (I don't see the need for other 
formats, but it might make sense to have them or it might align the 
system call with other system calls, etc.).

In a similar vein, it would be nice to have an easy way to get the 
hierarchical port name of the node driver/loads from within the 
resolution function.  This would be the full hierarchical path to the 
port on the instantiated module.  Today we can do this by generating 
these names in the models by combining %m with a hard coded port name, 
and then passing this into the resolution function via the UDN struct, 
but this is inefficient, as it requires allocating a fair bit of fixed 
length string space in the UDN struct (for large designs with 
descriptive names and lots of hierarchy, 1024 chars can be reached, and 
that is a lot of extra space on every UDN throughout the design).  So 
this would be a nice place to add a system call that could be called 
from the resolution function with the driver/load index, and which would 
return the hierarchical port name. With these two items, then we can 
produce messages like:

   **ERROR** More than one power supply detected on a power supply node:
   **ERROR**   Net: tb_top.DUT.analog_core.AVDD3P3V.
   **ERROR**   Supply: tb_top.DUT.analog_core.ldo_3P3V.reg_out.
   **ERROR**   Supply: tb_top.DUT.analog_core.ldo_5P0V.reg_out.

This allows a designer or verification person to immediately find the 
problem in the schematic or netlist.

In essence, this would be a capability along the lines of %m, but in the 
context of net/driver/load hierarchies, instead of in the context of 
module/package/function/task/etc. hierarchies.

3) Global variables

I understand some of the reasons why accessing global variables from a 
resolution function is prohibited (for example, it introduces the issue 
of bad code causing execution order dependencies, etc.). However, we 
have seen where global variables can be used safely and add important 
features for us, and power/efficiency to the UDN struct.

a) global error/warning counters - our verification methodology uses a 
number of global (package) error and warning counters.  There is a set 
for test bench/test case errors, another set for design (i.e.: RTL) 
errors, another set for model errors, etc.  At the end of the test, the 
test bench will check these global counters and use them to determine 
the test case pass/fail status, along with generating a summary report.  
Without global variables, it is impossible to reliably produce a count 
of the errors/warnings detected in a resolution function.  Instead the 
test case may indicate PASS but then the log would have to be 
post-processed to see the resolution function messages, which then turns 
the situation into a FAIL. Also, simulations might self terminate early 
if a large error count is reached, rather than running for a long time 
with problems.  If the simulation is not able to track the errors as it 
runs, then this can not happen.

b) UDN struct efficiency - rather than pass in the 1024 char 
hierarchical port name as a member of the UDN struct, we can pass in an 
integer index to a global dynamic array of string, for example. This 
saves overall memory as well as the overhead associated with the UDN 
struct processing.  Another case would be for power supply nodes or 
other special types of node where a model accessible list of all 
driver/load states is desired.  We can pass an index to a global dynamic 
structure that is the proper size for the data related to that specific 
node (which the resolution function would then update), rather than 
having to size the UDN for the worst possible case for any node.

4) Advanced run time timing control

This is a complex one, and we have only thought about it a little bit so 
far.  I'm tossing it out to see where the discussion goes. It is not 
necessarily an SV-DC topic, but I thought since it does relate to using 
SV-DC, I would start here.

The advanced timing infrastructure in SystemVerilog for logic (0/1/Z/X) 
signals is mainly compile and elaboration time based (specify, SDF, 
6/12-tuple timing, etc.), and is aimed at back annotation for gate 
simulation.  There is a reduced level of run time control available 
(such as assign with 1, 2 or 3 values, for example).

Our verification is now SystemVerilog UVM, so it is all run time built 
and configured.  Test cases need to control the various model parameters 
(times, voltages, currents, etc.) at run time and change them during the 
test run phase.  Where we are seeing limitations is with both assign 
(for UDNs it can only accept a single value, since it does not know the 
various transition types for a non 0/1/Z/X signal) and with always and 
<= (where trying to behaviorally assign different delays can lead to 
incorrect results, because events do not cause cancellation of other 
events).

We want to be able to model more complex analog timing, such as turn 
off/turn on times, rise/fall times, output delays that are input state 
dependent, etc.  We want to be able to select inertial/transport delay 
modeling, glitch handling, etc.  However, there is no simple way to do 
this today (and to some extent it is limited for logic signals at run 
time, as well, but less limited for logic than for UDNs).

At the moment, it seems like we would have to write our own scheduler 
code, perhaps using queues, for example, and then handle event queuing, 
cancellation, inertial vs. transport, glitch detection, etc.  I am not 
sure this is even possible, but if it is, it is probably a lot of code 
for each output of each model, and it may not scale well.  Building 
these features into the language and thus into the simulator kernel 
probably speeds things up by several orders of magnitude, and avoids a 
lot of repeated work as different users all try to solve the same basic 
problems in completely different ways. Essentially, it seems like we 
want some kind of arc based timing but based on UDN specific 
conditions.  Honestly, until we can get a lot deeper into real world UDN 
modeling with actual designs, I won't have a lot of details or insight 
into the specifics of this, but perhaps some of you experts have already 
been thinking about it.

A simple contrived example:

analog output ana1 turns on in 50 ns, turns off in 100 ns, and when on 
changes values in 10 ns.

assign can not handle this case (accepts a single time only).

ana1_int is the model internal value, prior to being delayed.  The 
following is psuedocode, rather than actual model code...

always @(ana1_int) begin
   if (turn_on) ana1 <= #50 ana_int;
   else if (turn_off) ana1 <= #100 ana_int;
   else if (driven_change) ana1 <= #10 ana_int;
   else ana1 <= udn_unknown;
end

For the sequence:

0: ana1_int = off (initial value)
100: ana1_int = on (1.0 V)
120: ana1_int = 2.0 V
140: ana1_int = off
160: ana1_int = on (3.0 V)

I think we get events like this (I did not have time to code up a test 
case and simulate it, so my apologies if I make a mistake here).

Listed in event creation order:

0: ana1 = off (initial value)
150: ana1 -> 1.0 V
130: ana1 -> 2.0 V
240: ana1 -> off
210: ana1 -> 3.0 V

Reordering the above events in time order:

0: ana1 = off (initial value)
130: ana1 -> 2.0 V
150: ana1 -> 1.0 V
210: ana1 -> 3.0 V
240: ana1 -> off

which is clearly not the intended model behavior... (for example, the 
final value should be on at 3.0 V, not off).

There are probably other things that we have not hit yet, but these are 
a few that have come up so far.

Thanks,

-Kyl

-- 
+-----------------------------------------------------------------------------+
| Kyl Scott,     Mixed-Signal ASIC Design,      Texas Instruments, Dallas, TX |
| email: horseplay@ieee.org, kyl.scott@ti.com                   (214)480-3810 |
+-----------------------------------------------------------------------------+



-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Tue Feb 3 19:30:27 2015

This archive was generated by hypermail 2.1.8 : Tue Feb 03 2015 - 19:30:32 PST