SystemVerilog and channels


Subject: SystemVerilog and channels
From: Christian Burisch (burisch@co-design.com)
Date: Thu Aug 01 2002 - 09:52:58 PDT



Hi Guys,

Dave Kelf forwarded the thread proposing channels in SystemVerilog. Some
comments:

First of all Stuart hit the nail on the head that there is some nomenclature
confusion, because sometimes the same term is used in SystemVerilog/SUPERLOG
and SystemC with different meanings.

>From: "Stuart Swan" <stuart@cadence.com>
>SystemC 2.0    SystemVerilog
>-----------    -------------
>channel        interface
>interface      modport

I propose to use the SystemVerilog terminology by default and state explicitely
if you mean something else, like "SystemC channels" or "SystemC interfaces".

In SystemVerilog and SUPERLOG a module encapsulates implementation, while
an interface encapsulates communication.

Different levels of abstractions are possible in both modules and interfaces.
You can have a module at an architectural level, at RTL or at gate level,
similarly you can model the communication in an interface with a cycle
accurate protocol or at higher, more abstract levels.

The easiest thing you can do with an interface is just to use it as a wire
bundle.
So an interface is to a wire in SystemVerilog like a struct is to
an int in C/C++/SystemVerilog/SUPERLOG, a means of grouping the data.

You can also include the way the data is sent and received in the interface,
i.e. its protocol.
In this case an interface is to a wire like a class is to an int in C++ or SUPERLOG,
a means of grouping the data and the protocol.

(I am using the term protocol to include the sequence of data being exchanged, not
just the data types.)

The tasks and functions inside the interface and class are referred to as "methods"
in OO parlance.

For the former use you can look at a wire as the simplest built in interface.
There is no built in interface for the latter usage.

What you are suggesting amounts to defining a "channel" in SystemVerilog as
the simplest possible built in interface.

Sounds like a good idea and we did consider this a few years ago, but we
didn't do it for reasons that I'll outline below.

Here is an interface in SystemVerilog with a read and write task which block.
It is unidirectional, if you need bidirectional, then just use 2 of them.
The data_type is parameterizable, (this is what you call "interface" in SystemC.)

interface channel;

  parameter type data_type = bit;
  data_type data;
  bit valid;

  task write(input data_type d);
    wait(valid == 0);
    data = d;
    valid = 1;
  endtask

  task read(output data_type d);
    wait(valid == 1);
    d = data;
    valid = 0;
  endtask

endinterface

You can add queuing functionality by including a fixed length FIFO,
if you want:

interface channel;

  parameter type data_type = bit;
  parameter int max = 10;
  data_type fifo[max:0];
  int num=0, high=0, low=0;

  task write(input data_type d);
    wait(num <= max);
    fifo[high++]=d;
    if (high > max) high = 0;
    num++;
  endtask

  task read(output data_type d);
    wait(num > 0);
    d = fifo[low++];
    if (low > max) low = 0;
    num--;
  endtask

endinterface

With SUPERLOG you can also have unbounded queues very easily:

interface channel;

  parameter type data_type = bit;
  data_type q[0:$];

  task write(input data_type d);
    q = {q, d};
  endtask

  task read(output data_type d);
    wait(q.$num > 0);
    d = q[0];
    q = q[1:$];
  endtask

endinterface

Note that this example uses SUPERLOG queues which are not
included as part of SystemVerilog, as when the initial
SUPERLOG ESS donation was executed, this higher level behavior
was not specified as part of the implementation requirements.
The use of queues within interfaces does allow additional
functionality as requested by Kevin.


The reason we did not include a built in interface (which you may want to
call "channel") which has this functionality is because we would have to
define names for the write and read tasks inside, which is quite clunky.

We did consider allowing interfaces to be used in assigments, similarly
to Kevin's suggestion. Then we can do away with the read and write task names
in their calls.

i.e. instead of
channel.write(out);
channel.read(in);

you could write:
channel = out;
in = channel;

But of course this syntax would be terrible, because each line could be
blocking, so looking at the code fragment you would not be able to see that.
Verilog assigments are in zero time, so we should not mess with that.
(and the parser would go schizo too)

We could make both of the methods functions (instead of tasks i.e. no timing
inside), and use Kevin's method of triggering off the interface to supply the
timing for one of them:

channel = out;
@(channel) in = channel;

This works, but only if you remain at the abstract level. When you refine
the interface to something real (PCI, SCSI etc) then suddenly both read
and write take time and you are stuck.

In your posts you talked about three different uses of interfaces.
They are, in order of importance,

1) System Modelling
  Here you define a system at a high level and you must be able
  to refine it down to lower levels of abstraction. For this reason we
  don't want a built-in interface where the read and/or the write must
  be a (zero delay) function.

2) Interaction with SystemC
   A SystemVerilog interface is a natural place to make a connection to
   other languages, such as C/C++ or SystemC.

3) Multiprocessing Software
  Actually I agree with you that SUPERLOG/SystemVerilog may turn out
  to be interesting for multiprocessing software, but this is a long
  way away in the future, (even though there is a research project about
  this at a university).
  In any case I believe that Occam is not a good role model for that.

I hope this made sense and that I explained our reasoning behind making
interfaces as they are.

Regards,

Christian



This archive was generated by hypermail 2b28 : Thu Aug 01 2002 - 08:49:46 PDT