[long] look up table for procedure call

Discussion in 'VHDL' started by alb, Jun 28, 2013.

  1. alb

    alb Guest

    Hi all,

    this thread is intended for testbench only, no RTL needed.

    I've just finished to read JB's 'Writing Testbenches' 2nd edition and I
    must say that I found it quite enlightening.

    The model he proposes to write testbenches is essentially to wrap away
    the physical interface of the DUT and provide a level of abstraction to
    the testcases so that interface implementation changes do not affect the
    rewrite of the testcases.

    The book covers well the fact that a package is not a 'structural
    element' in VHDL, therefore you cannot abstract away the interface by
    means of a package (you always need to pass all the signals in your
    procedure call) and a bus functional model entity is proposed in place
    (for details see pag. 325 - VHDL TEST HARNESS).

    His proposal, as I think I have understood, is to use an entity with a
    'server' process which is implementing the bus functional model while
    serving 'abstract' requests from the client process which does not know
    the details of the physical interface. Abstract signals to handle
    handshake between client and server are also needed, but the great
    advantage of the proposed method is that test cases are now at a much
    higher level and have no details referred to the DUT (a test case for a
    read/modify/write operation can be completely independent on the DUT and
    the test case may be reused for very many projects where read/write
    operations are meaningful).

    I started out writing like hell the various elements of my bus
    functional model, the test harness and some of the test cases, but now
    my problem is the following: my 'server' has to perform abstract actions
    (read_data, write_data, setup_interface, generate_input_pattern, ...)
    which are essentially mapped to an 'address'. To be more specific, my
    test case would call a procedure like this:

    procedure exec( type: in bool; -- read/write
    addr: in natural; -- what to do
    data: inout natural; -- data provided or returned
    signal: to_server: out to_srv_control; --handshake
    signal: from_server: in frm_srv_control;); --handshake

    while the test case will look like:

    -- RD/WR are type defined as true/false
    exec(RD, reg0, data, to_srv, frm_srv);
    exec(WR, reg1, data, to_srv, frm_srv);
    exec(WR, reg2, data, to_srv, frm_srv);

    by changing the address (reg[0,1,2]) we may want to either send a pulse
    to the interface or have a write cycle, the server needs to have some
    sort of switch statement based on the 'address' content and call the
    appropriate procedure where the appropriate operation is performed.

    Given the fact that I'm extremely lazy, in C I would solve this problem
    with a simple table (possibly stored in a struct) with two elements, an
    address and a function pointer initialized to a specific function. A
    'for loop' will then check the function to call every time there's a new
    request from the client (only problem is that with this approach the
    function parameters should be standardized for all functions, but this
    is a different problem).

    Now, after all this chatter, comes the real question: is there a way to
    write a 'table' (maybe an array of registers), in which one element is
    the address and the other is a procedure call, in such a way that every
    time I need to add a new address and a new procedure call I simply
    extend the table without touching the 'for loop' part of the code?

    I'm not sure the problem is clear and if the additional context is
    helping understanding my question, but that was my intent.

    Thank you all for any hint.

    alb, Jun 28, 2013
    1. Advertisements

  2. alb

    Jim Lewis Guest

    I use a case statement. If you use procedures like you suggest and keep
    the choice and procedure call on one line, it looks similar to a table.

    wait <sync_event> ;
    case to_srv.addr is
    when ADDR1 => DO_ADDR1_ACTION(...) ;
    when ADDR2 => DO_ADDR2_ACTION(...);

    For most BFMs (TLM/server) that I do I don't bother with calling procedures, I just write the code following the case target. I suppose it depends onthe complexity of the code.

    A couple of things I do different:
    Rather than using a generalized "exec", I put the operation name into the procedure. So I do CpuWrite rather than CpuExec(WR, ... With writing, this means that data can be a constant rather than a variable and you can passa value directly to the call. CpuWrite(reg0, X"A5", ...) ;

    I use a single record and resolution functions. The resolution functions make it more complicated, but I prefer only one record in the call.


    SynthWorks' VHDL Testbench and Verification class covers this, OSVVM, and more. See http://www.synthworks.com/vhdl_testbench_verification.htm
    Jim Lewis, Jun 28, 2013
    1. Advertisements

  3. alb

    alb Guest

    Indeed it is actually quite easy to maintain as long as you use
    procedures to simplify the 'when' clause. Adding testcases to the server
    should be straight forward.
    I'm somehow quite reluctant with writing code for the case target since
    it exposes too many details at the server level. Encapsulating the bus
    functional details in packaged procedures allows to hide and separate
    the physical interface a great deal.
    I agree with that, my example was a bit oversimplified. The 'CpuWrite'
    name you suggest simplifies also the interface since you would not need
    an extra bit of information to pass along in order to distinguish
    between Write/Read.
    Could you elaborate on that?
    The 'client' call still passes only one register with the appropriate
    elements (data, address, to_srv, frm_srv) so there's only one register
    passed between the test cases and the test harness. Am I missing
    something? Why would you need resolution functions?
    alb, Jul 3, 2013
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.