[sv-bc] RE: Mantis 210 Use Cases

From: Maidment, Matthew R <matthew.r.maidment@intel.com>
Date: Wed May 11 2011 - 08:57:28 PDT

Hi Dave.

I have been giving your input and Mantis 210 some thought based on feedback from the committee. I believe that macros, default values of input ports, interfaces and configs provide features to achieve the goal of evolving a module's port definition over time. Would appreciate your feedback as well as feedback from the SV-BC.

Consider this design:

  module svbc210();
  logic ck;
  logic d0,q0;
  logic d1,q1;

  dff dff0(d0,ck,q0);
  dff dff1(d1,ck,q1);

  endmodule

  module dff (input logic d,ck, output logic q);

    always_ff @(posedge ck)
       q <= d;

  endmodule

The first issue raised was:

1. Modules that need different views (RTL, DFT) at different points in
the design cycle. Additional ports are added as the view is refined.
A typical case might be a flip-flop with or without scan ports.

Option 1: Declare all ports and ground unused scan inputs early on:

  module dff (input logic d,
              input logic ck,
              output logic q,
              input logic si = 1'b0,
              input logic se = 1'b0,
         );

    always_ff @(posedge ck)
      q <= d;

  endmodule

Option 2: Declare 2 modules and use configs to replace them

Before:

  module dff (input logic d,ck, output logic q);

    always_ff @(posedge ck)
       q <= d;

  endmodule

  config top;
    design rtlLib.svbc210;
    default liblist rtlLib dfflib;
  endconfig

After:

  module dff (input logic d,
              input logic ck,
              output logic q,
           input logic si = 0,
           input logic se = 0,
         );

    always_ff @(posedge ck)
       if (se)
         q <= si;
       else
         q <= d;

  endmodule

  config top;
    design rtlLib.svbc210;
    default liblist rtlLib dfflib;
    instance svbc2010.submodulea use lib1.submodulea:config;
  endconfig

  config submodulea;
    design rtllib.submodulea;
    default liblist rtlLib scandfflib;
  endconfig

This approach allows one to address specific instances as needed. One
can add a parameter to the design to select scan or non-scan flop
behavior:

  module dff #(parameter SE = 0)
             (input logic d,
              input logic ck,
              output logic q,
           input logic si = 0,
           input logic se = 0,
         );

    if (SE)
      always_ff @(posedge ck)
         if (se)
           q <= si;
         else
           q <= d;
    else
      always_ff @(posedge ck)
        q <= d;

  endmodule

Option 3: Use macros with default arguments

At project start define the DFF macro:

  `define DFF(inst,d,ck,q) dff inst(d,ck,q)

As the project adds more features to the flop, add macro aruguments
with default values:

  `define DFF(inst_a,d_a,ck_a,q_a,si_a=(1'b0),se_a=(1'b0)) \
      dff inst(.d(d_a),.ck(c_a),.q(q_a),.si(si_a),.se(se_a));

Now `DFF can continue to be called as:

  `DFF(inst,d,ck,q)

and as users address the new functionality, add port connections:

  `DFF(inst,d,ck,q,si,se)

2. Modules that appear multiple times in the design with different ports.
This can happen when different generations of a common module are used in
different parts of an SoC.

  See response to #1, Option 2. Configurations allow different definitions of
  same module to be used by different IPs in SoC. In fact configurations become
  a necessity when integration IP from many teams.

3. Modules that appear in multiple SoCs in the same family, with differences
controlled by per-design features. Here the desire is to maintain a single
codebase for all variants.

For SoCs I've seen that it's very challenging to get one module shared
by multiple IPs to be of the same version. If I have a sub-IP A and
it is integrated into IP B and IP C. It may be that IP B has rev 1.0
and IP C has rev 1.2, so despite appearances, IP B and IP C require
configs to ensure that they use their respective versions of IP A.

Lastly, this response has not proposed how to use an interface to address
this issue. Consider the dff module now coded using and interface:

  interface dff_intf;
    logic d;
    logic q;
    logic ck;
  endinterface

  module dff (interface intf);

    always_ff @(posedge intf.ck)
       intf.q <= intf.d;

  endmodule

  module dff_inst();
    dff_intf intf;

    dff dff(dff_intf);
  endmodule

Now add scan and enable only where desired. First the interface is extended with scan
signals and scan and non-scan modports are added:

  interface dff_int;
    logic d;
    logic q;
    logic ck;
    logic si;
    logic se;

    modport se_driver(output q, input d, input, ck, input si, input se);
    modport driver(output q, input d, input, ck);
  endinterface

The dff module can include scan if the appropriate parameter value is set:

  module dff #(parameter SE=0) (interface intf);

    if (SE) begin
      always_ff @(posedge intf.ck)
        if (intf.se)
          intf.q <= intf.si;
        else
          intf.q <= intf.d;
    end else begin
      always_ff @(posedge intf.ck)
        intf.q <= intf.d;
    end

  endmodule

And here are two instances of the dff, one with and one without scan:

  module dff_inst();
    dff_intf intf;
    dff_intf se_intf;

    dff dff(dff_intf.driver);
    dff #(.SE(1)) se_dff (dff_intf.se_driver);
  endmodule

An interface scenario was also offered. It covered a bus with a sideband.

  module bus_master(
      bus_if.master B
  `ifdef USE_SIDEBAND
      , sideband_if.master SB
  `endif
  )
  endmodule

  module bus_slave(
      bus_if.slave B
  `ifdef USE_SIDEBAND
      , sideband_if.slave SB
  `endif
  );
  endmodule

  `ifdef USE_SIDEBAND
  module bus_sideband_helper(
      sideband_if.slave SBI,
      sideband_if.master SBO
  );
  endmodule
  `endif

  module top();
      bus_if B1();
  `ifdef USE_SIDEBAND
      sideband_if SB1(), SB2();
  `endif
      bus_master bm(
          .B(B1)
  `ifdef USE_SIDEBAND
          , .SB(SB1)
  `endif
      );
      bus_slave bs(
          .B(B1)
  `ifdef USE_SIDEBAND
          , .SB(SB2)
  `endif
      );
  `ifdef USE_SIDEBAND
      bus_sideband_helper bsh( .SBI(SB1), .SBO(SB2) );
  `endif
  endmodule

This example attempts to add ports by changing the module definition. The suggestion
is to instead add ports by extending the bus interface. Consider the bus_master:

  module bus_master(
      bus_if.master B
  `ifdef USE_SIDEBAND
      , sideband_if.master SB
  `endif
  )
  endmodule

There's a bus interface already. Isn't the sideband part of the larger bus specification?
Instead of introducing a sideband interface port, how about extending the bus interface:

  interface bus_primary;
  ...
  endinterface
  interface bus_sideband;
  ...
  endinterface

  interface bus_if #(parameter USE_SIDEBAND=0)();
    bus_primary bus_primary();
    modport master(...);
    modport slave(...);
    if (USE_SIDEBAND) begin
      bus_sideband bus_sideband();
      modport sideband(...);
      modport sideband_slave(...);
      modport sideband_master(...);
    end
  endinterface

And use the corresponding modports:

  module bus_master #(parameter USE_SIDEBAND=0) (
      interface.master B
  );
  ...
  endmodule

  module bus_slave #(parameter USE_SIDEBAND=0) (
      interface.slave B
  );
  ...
  endmodule

  module bus_sideband_helper(
      interface.sideband SBI,
  );
  ...
  endmodule

  module top #(USE_SIDEBAND=0) ();
      bus_if #(.USE_SIDEBAND(USE_SIDEBAND) B1();

      bus_master #(.USE_SIDEBAND(USE_SIDEBAND)) bm(
          .B(B1)
      );
      bus_slave #(.USE_SIDEBAND(USE_SIDEBAND)) bs(
          .B(B1)
      );
      if (USE_SIDEBAND)
        bus_sideband_helper bsh( .SBI(B1));

  endmodule

You could make this more flexible by choosing the modport at the instantiation
or by using tasks to access the interfaces.

It may be also interesting to note that each module uses only those modports of
which it's aware. Adding modports to address future bus specfications does not
necessarily require one to go back and change all agents on the bus. This
notion of feature control and visibility would be very helpful when trying to
address the following:

  `ifdef BUS_GEN2
  `define USE_SIDEBAND
  `endif

  interface bus_if;
      logic signal1;
  `ifdef BUS_GEN2
      logic signal2;
  `endif
      ...
  endinterface

  `ifdef BUS_GEN2
  interface sideband_if;
      logic signal1;
  endinterface
      ...
  `endif

"Here I have two different generations of the bus specification: Gen1 and Gen2. In the 2nd generation,
another signal is added to the main bus, and the sideband is introduced.

If one assumes that Gen1 and Gen2 are implemented in the same module with parameters, then
let's update the previous example accordingly. First the Gen1 and Gen2 bus:

  interface bus_primary();
  ...
  endinterface
  interface bus_sideband();
  ...
  endinterface

  interface bus_if #(parameter GEN=1)();
    bus_primary bus_primary();
    if (GEN==2) begin: SIDEBAND
        bus_sideband #(.GEN(GEN) bus_sideband();
        modport default(...);
        modport slave(...);
        modport master(...);
    end
    modport master(...);
    modport slave(...);
  endinterface

  module bus_master #(parameter GEN = 1) (
      interface.master B
  );
  ...
  endmodule

  module bus_slave #(parameter GEN = 1) (
      interface.slave B
  );
  ...
  endmodule

  module bus_sideband_helper #(parameter GEN = 1) (
      interface.sideband SBI,
  );
  ...
  endmodule

  module top #(GEN=1) ();
      bus_if #(.GEN(GEN) B1();

      bus_master #(.GEN(GEN)) bm(
          .B(B1)
      );
      bus_slave #(.GEN(GEN)) bs(
          .B(B1)
      );
      if (GEN==2)
        bus_sideband_helper bsh( .SBI(B1));

  endmodule

In summary, there appear to be several features in the language that enable one to
evolve the definition of module ports through the design process.

--
Matt Maidment
mmaidmen@ichips.intel.com
From: owner-sv-bc@eda.org [mailto:owner-sv-bc@eda.org] On Behalf Of Gates, David
Sent: Monday, February 14, 2011 10:05 AM
To: Gates, David; sv-bc@eda.org
Subject: [sv-bc] RE: Mantis 210 Use Cases
To expand on this a little, consider the following definitions of the interfaces:
`ifdef BUS_GEN2
`define USE_SIDEBAND
`endif
interface bus_if;
    logic signal1;
`ifdef BUS_GEN2
    logic signal2;
`endif
    ...
endinterface
`ifdef BUS_GEN2
interface sideband_if;
    logic signal1;
endinterface
    ...
`endif
Here I have two different generations of the bus specification: Gen1 and Gen2.  In the 2nd generation, another signal is added to the main bus, and the sideband is introduced.
Suppose I want to create an SoC that wants to control two external instances of such a bus, one for Gen1 and one for Gen2.  (Assume I've added appropriate I/O to module 'top' to create an interface controller.)  I now need to instantiate both a Gen1 controller and a Gen2 controller.  I want to replace all of my conditional `ifdef behavior with parametric behavior.  With current SystemVerilog, I need to run an external preprocessor to generate modules top_gen1, top_gen2 (and two versions of all of the submodules) with different values for `define BUS_GEN2.  Each user can do this, but it won't lead to very standard source code, especially as the configurability gets more complicated.  (You can standardize the flow using IP-XACT generator chains though.)
~ Dave
From: owner-sv-bc@eda.org [mailto:owner-sv-bc@eda.org] On Behalf Of Gates, David
Sent: Monday, February 14, 2011 8:59 AM
To: sv-bc@eda.org
Subject: [sv-bc] RE: Mantis 210 Use Cases
For my action item for the 1/31 meeting, I tried to figure out how to use interfaces with internal generate statements, but ran into the problem that we are internally using conditional interface ports.
Here is a cooked-up example that uses `ifdef instead of parameters.
module bus_master(
    bus_if.master  B
`ifdef USE_SIDEBAND
    , sideband_if.master SB
`endif
)
endmodule
module bus_slave(
    bus_if.slave B
`ifdef USE_SIDEBAND
    , sideband_if.slave SB
`endif
);
endmodule
`ifdef USE_SIDEBAND
module bus_sideband_helper(
    sideband_if.slave SBI,
    sideband_if.master SBO
);
endmodule
`endif
module top();
    bus_if B1();
`ifdef USE_SIDEBAND
    sideband_if SB1(), SB2();
`endif
    bus_master bm(
        .B(B1)
`ifdef USE_SIDEBAND
        , .SB(SB1)
`endif
    );
    bus_slave bs(
        .B(B1)
`ifdef USE_SIDEBAND
        , .SB(SB2)
`endif
    );
`ifdef USE_SIDEBAND
    bus_sideband_helper bsh( .SBI(SB1), .SBO(SB2) );
`endif
endmodule
I don't see how using generate statements inside an interface can describe this situation parametrically.
~ Dave
From: Gates, David
Sent: Friday, January 28, 2011 11:01 AM
To: 'sv-bc@eda.org'
Subject: Mantis 210 Use Cases
I polled internally at AMD and uncovered the following 5 use cases where language support for configurable module port lists would be useful:
1.  Modules that need different views (RTL, DFT) at different points in the design cycle.  Additional ports are added as the view is refined.  A typical case might be a flip-flop with or without scan ports.
2.  Modules that appear multiple times in the design with different ports.  This can happen when different generations of a common module are used in different parts of an SoC.
3.  Modules that appear in multiple SoCs in the same family, with differences controlled by per-design features.  Here the desire is to maintain a single codebase for all variants.
4.  Modules that might have the same types of ports, but where the port names are changed to indicate the actual client.  This customizes the design to make debugging / tracing of signals easier.
5.  Modules that have lists of ports with indexed names, because a parameterized port array cannot be or is not used for other reasons.
I think generated ports/connections would be usable in the first 3 cases.  The second case really isn't possible to cover using a global `ifdef, but I believe the SV configuration mechanism could be used to alias two different modules to the same name in different parts of a design.  For the 4th & 5th cases, you'd need a more complex interaction between the SV lexer/parser, such that a parsed parameter can modify a lexical name.  I don't think generate would solve that.
Largely through the use of external preprocessors (aka language extensions), all 5 of these use cases appear within AMD designs, some of them extensively.
One other note: although the description doesn't state this, a followup comment makes it clear you'll need generate for module instantiations as well to take advantage of this language change.
~ Dave
// David A. Gates, Ph.D.         408.749.4497
// Fellow, Design Automation
// Advanced Micro Devices         www.amd.com<http://www.amd.com/>
// The Doctor is IN.  Primum non nocere.
--
This message has been scanned for viruses and
dangerous content by MailScanner<http://www.mailscanner.info/>, and is
believed to be clean.
--
This message has been scanned for viruses and
dangerous content by MailScanner<http://www.mailscanner.info/>, and is
believed to be clean.
-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Wed May 11 08:58:13 2011

This archive was generated by hypermail 2.1.8 : Wed May 11 2011 - 08:58:27 PDT