Records have not Atributes – Is there an other way?

Why OSVVM™? Forums VHDL Records have not Atributes – Is there an other way?

This topic contains 4 replies, has 2 voices, and was last updated by Avatar of Eilert Backhus Eilert Backhus 1 week, 3 days ago.

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #1752

    Hi,
    while working on some OSVVM Testbenches I came across the problem of initializing records used to define some interfaces.
    e.g.:

      type uut_inputs is record
        A  : std_logic_vector(7 downto 0);
        B  : std_logic_vector(7 downto 0);
        S  : std_logic_vector(1 downto 0);
        M  : std_logic;
        Ci : std_logic;
      end record uut_inputs;
    
      signal UUT_Driver  : uut_inputs;
    
      constant UUT_DriverDefaults : uut_inputs := (A  => (others => 'U'),
                                                   B  => (others => 'U'),
                                                   S  => (others => 'U'),
                                                   M  => 'U',
                                                   Ci => 'U');

    The idea is to reduce the aggregate size to avoid writing overhead in each new testbench.
    The Method of using := (others => (others => ‘U’)); only works for identical types, but my record uses SLV and SL types.

    I thought of writing a generic function like

    function InitRecord(MySignal:UUT_Driver, InitValue: std_logic) return uut_inputs;

    The problem is that the record elements are unknown, so there’s no way of iterating over them like

    for RecordElement in MySignal'first to MySignal'last loop
       MySignal.RecordElement <= (others => InitValue);
    end loop;

    (Yes, it’s clear that RecordElement is not an integer. This is just to illustrate the idea)

    So, is there some other way to achieve the intended result?
    If not, has anybody thought of a proposal for sth. like record attributes in the next VHDL version yet?

    Kind regards
    Eilert

    PS.: [OT] Why is osvvm.org not https secured by default?
    And even when called as https://osvvm.org it’s marked as unsafe in the browser.

    #1756
    Avatar of Jim Lewis
    Jim Lewis
    Member

    Hi Eilert,
    Currently there is nothing that iterates records. We looked at it for 2019, but
    did not come up with anything we liked – maybe next revision – but only if we get
    the right people participating – and if you are reading this, perhaps you
    should consider participating.

    That said, for testbench to testbench connections, there is a simple solution –
    I use the types std_logic_max, std_logic_vector_max (for Mentor) or
    std_logic_vector_max_c (for Aldec, but requires type conversion – aka casting –
    but also works in all simulators). With these types, there is no need for
    initialization since ‘U’ is the default value and it is low strength when
    using maximum as a resolution.

    I have not tried these with testbench to DUT connections – the plain “_max”
    types are subtypes and should convert automatically to std_logic_vector at
    the DUT if individually connected.

    The “_max” types are from OSVVM.ResolutionPkg and use the VHDL-2008 maximum
    function for resolution – I note the maximum function is in proper form to
    be a resolution function, however, support is currently on the bleeding edge.

    For examples on how these work, see the OSVVM/VerificationIP page on the
    OSVVM github site:
    https://github.com/OSVVM/VerificationIP

    Note I did something wrong in creating some of the SubModules on GitHub
    and they do not link directly through via the website. You can navigate
    via the github OSVVM project.

    Under there you will find AXI4LiteMaster, Axi4LiteSlave, AxiStreamMaster,
    AxiStreamSlave, UartTx, and UartRx models. THe UART is the newest one
    to be released and I put some time in making it a reference as to how I
    intend to go forward.
    The Axi4LiteMaster demonstrates how I currently implemented the testbench to
    DUT connections. Looking back at it, I do not like the record there.
    Maybe it is just the AXI4Lite interface as most seem comfortable working
    with it bitwise. In a number of places, I find myself breaking it apart
    with aliases – because the shorter Axi4 names are easier to work with.

    I will be making another pass through the AXI models before I consider
    them in a final form. I plan to factor a “BusMasterTransactionPkg”
    package like I factored out a StreamTransactionPkg from the UART.
    I also plan to use StreamTransactionPkg with AxiStream models.

    Best Regards,
    Jim

    • This reply was modified 2 weeks, 4 days ago by Avatar of Jim Lewis Jim Lewis.
    • This reply was modified 2 weeks, 4 days ago by Avatar of Jim Lewis Jim Lewis.
    #1759

    Hi Jim,
    thanks for the hints, I’m going to take a look at the ResolutionPkg.
    I will also check the VIP examples. Unfortunately by now only the AXI4 is accessible.
    What about the .pro files? Is that some meta scripting language to work tool independent or is there some tool that can read them?

    I found a solution to my problem. Not as elegant as attributes could be, but on the long run saving me from multiple retyping long port lists in every new testbench.

    -- UUT Declarations
      type uut_input_names is (A, B, S, M, Ci);
      type uut_inputs is record
        A  : std_logic_vector(7 downto 0);
        B  : std_logic_vector(7 downto 0);
        S  : std_logic_vector(1 downto 0);
        M  : std_logic;
        Ci : std_logic;
      end record uut_inputs;
    
      type uut_output_names is (Co, Equal, Zeros, Y);
      type uut_outputs is record
        Co    : std_logic;
        Equal : std_logic;
        Zero  : std_logic;
        Y     : std_logic_vector(7 downto 0);
      end record uut_outputs;
    
      type uut_ports is record
        inputs  : uut_inputs;
        outputs : uut_outputs;
      end record uut_ports;
    
      signal UUT_Driver  : uut_inputs;
      signal UUT_Monitor : uut_ports;
    
      function To_StdLogicVector (
        constant Arg : std_ulogic)
        return std_ulogic_vector is
        variable ReturnSLV : std_ulogic_vector(0 downto 0);
      begin
        ReturnSLV(0) := Arg;
        return ReturnSLV;
      end function To_StdLogicVector;
    
      alias To_Std_Logic_Vector is
        To_StdLogicVector[std_ulogic return std_logic_vector];
      alias To_SLV is
        To_StdLogicVector[std_ulogic return std_logic_vector];
    
      procedure SetVariable_UUT_Inputs (constant SelectElement : in    uut_input_names;
                                        variable Data          : inout uut_inputs;
                                        constant Value         : in    std_logic_vector) is
      begin
        case SelectElement is
          when A  => Data.A  := Value;
          when B  => Data.B  := Value;
          when S  => Data.S  := Value;
          when M  => Data.M  := Value(0);
          when Ci => Data.Ci := Value(0);
        end case;
      end procedure SetVariable_UUT_Inputs;
    
      procedure SetSignal_UUT_Inputs (constant SelectElement : in    uut_input_names;
                                      signal Data            : inout uut_inputs;
                                      constant Value         : in    std_logic_vector) is
      begin
        case SelectElement is
          when A  => Data.A  <= Value;
          when B  => Data.B  <= Value;
          when S  => Data.S  <= Value;
          when M  => Data.M  <= Value(0);
          when Ci => Data.Ci <= Value(0);
        end case;
      end procedure SetSignal_UUT_Inputs;
    
      function Init_UUT_Inputs (InitValue : std_logic) return uut_inputs is
        variable Data : uut_inputs;
      begin
        SetVariable_UUT_Inputs(A, Data, (Data.A'range => InitValue));
        SetVariable_UUT_Inputs(B, Data, (Data.B'range => InitValue));
        SetVariable_UUT_Inputs(S, Data, (Data.S'range => InitValue));
        SetVariable_UUT_Inputs(M, Data, to_std_logic_vector(InitValue));
        SetVariable_UUT_Inputs(Ci, Data, to_std_logic_vector(InitValue));
        return Data;
      end function Init_UUT_Inputs;
    
      constant UUT_DriverDefaults         : uut_inputs := Init_UUT_Inputs('U');
      constant UUT_SequencerOutDefaults   : uut_inputs := Init_UUT_Inputs('0');
      constant UUT_SequencerValidInactive : uut_inputs := Init_UUT_Inputs('0');
      constant UUT_SequencerValidActive   : uut_inputs := Init_UUT_Inputs('1');

    I can put this in a package, so the utility functions do not inflate the testbench code too much.
    (Still wondering why the overloading of the set procedures for variable and signal did not work. Simulator says it’s abiguous, so I had to choose different names. Very unpleasant.)

    Kind regards
    Eilert

    #1762

    Update to my former post:
    These direct links work and the explanation to the .pro-files can be found in the OSVVM-Scripts.

    https://github.com/OSVVM/UART
    https://github.com/OSVVM/AXI4

    Note each of them use the scripts from:
    https://github.com/OSVVM/OSVVM-Scripts

    #1763

    Update to my former post:
    Not to forget this part, which is needed for the UART testbench:

    https://github.com/OSVVM/OSVVM_VIP

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.