OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sim/] [verilator/] [mpy_tb.cpp] - Diff between revs 204 and 209

Only display areas with differences | Details | Blame | View Log

Rev 204 Rev 209
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    mpy_tb.cpp
// Filename:    mpy_tb.cpp
//
//
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
//
//
// Purpose:     Bench testing for the multiply ALU instructions used within the
// Purpose:     Bench testing for the multiply ALU instructions used within the
//              Zip CPU.  This depends upon the cpuops.v module, but should be
//              Zip CPU.  This depends upon the cpuops.v module, but should be
//      independent of the internal settings within the module.
//      independent of the internal settings within the module.
//
//
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
 
// You should have received a copy of the GNU General Public License along
 
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
 
// target there if the PDF file isn't present.)  If not, see
 
// <http://www.gnu.org/licenses/> for a copy.
 
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
#include <signal.h>
#include <signal.h>
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <unistd.h>
#include <assert.h>
#include <assert.h>
 
#include <stdint.h>
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <ctype.h>
#include <ctype.h>
 
 
#include "verilated.h"
#include "verilated.h"
#include "Vcpuops.h"
#include "Vcpuops.h"
 
 
 
#ifdef  NEW_VERILATOR
 
#define VVAR(A) cpuops__DOT_ ## A
 
#else
 
#define VVAR(A) v__DOT_ ## A
 
#endif
 
 
 
 
#include "testb.h"
#include "testb.h"
#include "cpudefs.h"
#include "cpudefs.h"
// #include "twoc.h"
// #include "twoc.h"
 
 
class   CPUOPS_TB : public TESTB<Vcpuops> {
class   CPUOPS_TB : public TESTB<Vcpuops> {
public:
public:
        // Nothing special to do in a startup.
        // Nothing special to do in a startup.
        CPUOPS_TB(void) {}
        CPUOPS_TB(void) {}
 
 
        // ~CPUOPS_TB(void) {}
        // ~CPUOPS_TB(void) {}
 
 
        //
        //
        // Calls TESTB<>::reset to reset the core.  Makes sure the i_ce line
        // Calls TESTB<>::reset to reset the core.  Makes sure the i_stb line
        // is low during this reset.
        // is low during this reset.
        //
        //
        void    reset(void) {
        void    reset(void) {
                // m_flash.debug(false);
                // m_flash.debug(false);
                m_core->i_ce = 0;
                m_core->i_stb = 0;
 
 
                TESTB<Vcpuops>::reset();
                TESTB<Vcpuops>::reset();
        }
        }
 
 
        //
        //
        // dbgdump();
        // dbgdump();
        //
        //
        // Just before the positive edge of every clock, we call this function
        // Just before the positive edge of every clock, we call this function
        // (if the debug flag is set).  This prints out a line of information
        // (if the debug flag is set).  This prints out a line of information
        // telling us what is going on within the logic, allowing us access
        // telling us what is going on within the logic, allowing us access
        // for debugging purposes to inspect things.
        // for debugging purposes to inspect things.
        //
        //
        // Other than debugging, this isn't necessary for the functioning of the
        // Other than debugging, this isn't necessary for the functioning of the
        // test bench.  At the same time, what are you using a test bench for if
        // test bench.  At the same time, what are you using a test bench for if
        // not for debugging?
        // not for debugging?
        //
        //
        void    dbgdump(void) {
        void    dbgdump(void) {
                char    outstr[2048], *s;
                char    outstr[2048], *s;
                sprintf(outstr, "Tick %4ld %s%s ",
                sprintf(outstr, "Tick %4lld %s%s ",
                        m_tickcount,
                        (unsigned long long)m_tickcount,
                        (m_core->i_rst)?"R":" ",
                        (m_core->i_reset)?"R":" ",
                        (m_core->i_ce)?"CE":"  ");
                        (m_core->i_stb)?"CE":"  ");
                switch(m_core->i_op) {
                switch(m_core->i_op) {
                case  0: strcat(outstr, "   SUB"); break;
                case  0: strcat(outstr, "   SUB"); break;
                case  1: strcat(outstr, "   AND"); break;
                case  1: strcat(outstr, "   AND"); break;
                case  2: strcat(outstr, "   ADD"); break;
                case  2: strcat(outstr, "   ADD"); break;
                case  3: strcat(outstr, "    OR"); break;
                case  3: strcat(outstr, "    OR"); break;
                case  4: strcat(outstr, "   XOR"); break;
                case  4: strcat(outstr, "   XOR"); break;
                case  5: strcat(outstr, "   LSR"); break;
                case  5: strcat(outstr, "   LSR"); break;
                case  6: strcat(outstr, "   LSL"); break;
                case  6: strcat(outstr, "   LSL"); break;
                case  7: strcat(outstr, "   ASR"); break;
                case  7: strcat(outstr, "   ASR"); break;
                case  8: strcat(outstr, "   MPY"); break;
                case  8: strcat(outstr, "   MPY"); break;
                case  9: strcat(outstr, "LODILO"); break;
                case  9: strcat(outstr, "LODILO"); break;
                case 10: strcat(outstr, "MPYUHI"); break;
                case 10: strcat(outstr, "MPYUHI"); break;
                case 11: strcat(outstr, "MPYSHI"); break;
                case 11: strcat(outstr, "MPYSHI"); break;
                case 12: strcat(outstr, "  BREV"); break;
                case 12: strcat(outstr, "  BREV"); break;
                case 13: strcat(outstr, "  POPC"); break;
                case 13: strcat(outstr, "  POPC"); break;
                case 14: strcat(outstr, "   ROL"); break;
                case 14: strcat(outstr, "   ROL"); break;
                case 15: strcat(outstr, "   MOV"); break;
                case 15: strcat(outstr, "   MOV"); break;
                default: strcat(outstr, "UNKWN!"); break;
                default: strcat(outstr, "UNKWN!"); break;
                } s = &outstr[strlen(outstr)];
                } s = &outstr[strlen(outstr)];
                sprintf(s, "(%x) 0x%08x 0x%08x -> 0x%08x [%x] %s%s",
                sprintf(s, "(%x) 0x%08x 0x%08x -> 0x%08x [%x] %s%s",
                        m_core->i_op,
                        m_core->i_op,
                        m_core->i_a, m_core->i_b,
                        m_core->i_a, m_core->i_b,
                        m_core->o_c, m_core->o_f,
                        m_core->o_c, m_core->o_f,
                        (m_core->o_valid)?"V":" ",
                        (m_core->o_valid)?"V":" ",
                        (m_core->o_busy)?"B":" ");
                        (m_core->o_busy)?"B":" ");
                s = &outstr[strlen(outstr)];
                s = &outstr[strlen(outstr)];
 
 
#if(OPT_MULTIPLY==1)
#if(OPT_MULTIPLY==1)
 
#define mpy_result      VVAR(_mpy_result)
                sprintf(s, "1,MPY[][][%016lx]",
                sprintf(s, "1,MPY[][][%016lx]",
                        m_core->v__DOT__mpy_result);
                        (unsigned long)m_core->mpy_result);
                s = &outstr[strlen(outstr)];
                s = &outstr[strlen(outstr)];
#elif(OPT_MULTIPLY==2)
#elif(OPT_MULTIPLY==2)
                sprintf(s, "2,MPY[%016lx][%016lx][%016lx]",
                sprintf(s, "2,MPY[%016lx][%016lx][%016lx]",
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_a_input,
#define MPY2VAR(A)      VVAR(_thempy__DOT__IMPY__DOT__MPN1__DOT__MPY2CK__DOT_ ## A)
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_b_input,
#define r_mpy_a_input   MPY2VAR(_r_mpy_a_input)
                        m_core->v__DOT__mpy_result);
#define r_mpy_b_input   MPY2VAR(_r_mpy_b_input)
 
#define mpy_result      VVAR(_mpy_result)
 
                        m_core->r_mpy_a_input,
 
                        m_core->r_mpy_b_input,
 
                        m_core->mpy_result);
                s = &outstr[strlen(outstr)];
                s = &outstr[strlen(outstr)];
#elif(OPT_MULTIPLY==3)
#elif(OPT_MULTIPLY==3)
                sprintf(s, "3,MPY[%08x][%08x][%016lx], P[%d]",
#define MPY3VAR(A)      VVAR(_thempy__DOT__IMPY__DOT__MPN1__DOT__MPN2__DOT__MPY3CK__DOT_ ## A)
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_a_input,
#define r_mpy_a_input   MPY3VAR(_r_mpy_a_input)
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_b_input,
#define r_mpy_b_input   MPY3VAR(_r_mpy_b_input)
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_smpy_result,
#define r_smpy_result   MPY3VAR(_r_smpy_result)
                        m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__mpypipe);
#define mpypipe         MPY3VAR(_mpypipe)
 
                sprintf(s, "3,MPY[%08x][%08x][%016llx], P[%d]",
 
                        m_core->r_mpy_a_input,
 
                        m_core->r_mpy_b_input,
 
                        (long long)m_core->r_smpy_result,
 
                        m_core->mpypipe);
 
 
#endif
#endif
 
 
#if(OPT_MULTIPLY != 1)
#if(OPT_MULTIPLY != 1)
                if (m_core->v__DOT__this_is_a_multiply_op)
#define this_is_a_multiply_op   ((m_core->i_stb)&&(((m_core->i_op&0xe) == 5)||((m_core->i_op&0x0f)==0xc))) // VVAR(_this_is_a_multiply_op)
 
                if (this_is_a_multiply_op)
                        strcat(s, " MPY-OP");
                        strcat(s, " MPY-OP");
#endif
#endif
                puts(outstr);
                puts(outstr);
        }
        }
 
 
        //
        //
        // tick()
        // tick()
        //
        //
        // Call this to step the processor.
        // Call this to step the processor.
        //
        //
        // This is a bit unusual compared to other tick() functions I have in
        // This is a bit unusual compared to other tick() functions I have in
        // my simulators in that there are a lot of calls to eval() with clk==0.
        // my simulators in that there are a lot of calls to eval() with clk==0.
        // This is because the multiply logic for OPT_MULTIPLY < 3 depends upon
        // This is because the multiply logic for OPT_MULTIPLY < 3 depends upon
        // it to be valid.  I assume any true Xilinx, or even higher level,
        // it to be valid.  I assume any true Xilinx, or even higher level,
        // implementation wouldn't have this problem.
        // implementation wouldn't have this problem.
        //
        //
        void    tick(void) {
        void    tick(void) {
                bool    debug = false;
                bool    debug = false;
 
 
                // Insist that we are never both busy and producing a valid
                // Insist that we are never both busy and producing a valid
                // result at the same time.  One or the other may be true,
                // result at the same time.  One or the other may be true,
                // but never both.
                // but never both.
                assert((!m_core->o_busy)||(!m_core->o_valid));
                assert((!m_core->o_busy)||(!m_core->o_valid));
                //
                //
                TESTB<Vcpuops>::tick();
                TESTB<Vcpuops>::tick();
 
 
                if (debug)
                if (debug)
                        dbgdump();
                        dbgdump();
        }
        }
 
 
        //
        //
        // clear_ops
        // clear_ops
        //
        //
        // Runs enough clocks through the device until it is neither busy nor
        // Runs enough clocks through the device until it is neither busy nor
        // valid.  At this point, the ALU should be thoroughly clear.  Then
        // valid.  At this point, the ALU should be thoroughly clear.  Then
        // we tick things once more.
        // we tick things once more.
        //
        //
        void    clear_ops(void) {
        void    clear_ops(void) {
                m_core->i_ce    = 0;
                m_core->i_stb    = 0;
                m_core->i_op    = 0;
                m_core->i_op    = 0;
 
 
                do {
                do {
                        tick();
                        tick();
                } while((m_core->o_busy)||(m_core->o_valid));
                } while((m_core->o_busy)||(m_core->o_valid));
                tick();
                tick();
        }
        }
 
 
        //
        //
        // This is a fairly generic CPU operation call.  What makes it less
        // This is a fairly generic CPU operation call.  What makes it less
        // than generic are two things: 1) the ALU is cleared before any
        // than generic are two things: 1) the ALU is cleared before any
        // new instruction, and 2) the tick count at the end is compared
        // new instruction, and 2) the tick count at the end is compared
        // against the tick count OPT_MULTIPLY says we should be getting.
        // against the tick count OPT_MULTIPLY says we should be getting.
        // A third difference between this call in simulation and a real
        // A third difference between this call in simulation and a real
        // call within the CPU is that we never set the reset mid-call, whereas
        // call within the CPU is that we never set the reset mid-call, whereas
        // the CPU may need to do that if a jump is made and the pipeline needs
        // the CPU may need to do that if a jump is made and the pipeline needs
        // to be cleared.
        // to be cleared.
        //
        //
        unsigned        op(int op, int a, int b) {
        uint32_t        op(int op, int a, int b) {
                // Make sure we start witht he core idle
                // Make sure we start witht he core idle
                if (m_core->o_valid)
                if (m_core->o_valid)
                        clear_ops();
                        clear_ops();
 
 
                // Set the arguments to the CPUOPS core to get a multiple
                // Set the arguments to the CPUOPS core to get a multiple
                // started
                // started
                m_core->i_ce    = 1;
                m_core->i_stb    = 1;
                m_core->i_op    = op;
                m_core->i_op    = op;
                m_core->i_a     = a;
                m_core->i_a     = a;
                m_core->i_b     = b;
                m_core->i_b     = b;
 
 
                unsigned long now = m_tickcount;
                uint64_t now = m_tickcount;
 
 
                // Tick once to get it going
                // Tick once to get it going
                tick();
                tick();
 
 
                // Clear the input arguments to the multiply
                // Clear the input arguments to the multiply
                m_core->i_ce    = 0;
                m_core->i_stb    = 0;
                m_core->i_a     = 0;
                m_core->i_a     = 0;
                m_core->i_b     = 0;
                m_core->i_b     = 0;
 
 
                // Wait for the result to be valid
                // Wait for the result to be valid
                while(!m_core->o_valid)
                while(!m_core->o_valid)
                        tick();
                        tick();
 
 
                // Check that we used the number of clock ticks we said we'd
                // Check that we used the number of clock ticks we said we'd
                // be using.  OPT_MULTIPLY is *supposed* to be equal to this
                // be using.  OPT_MULTIPLY is *supposed* to be equal to this
                // number.
                // number.
                if((m_tickcount - now)!=OPT_MULTIPLY) {
                if((m_tickcount - now)!=OPT_MULTIPLY) {
                        printf("%ld ticks seen, %d ticks expected\n",
                        printf("%lld ticks seen, %d ticks expected\n",
                                m_tickcount-now, OPT_MULTIPLY);
                                (unsigned long long)(m_tickcount-now), OPT_MULTIPLY);
                        dbgdump();
                        dbgdump();
                        printf("TEST-FAILURE!\n");
                        printf("TEST-FAILURE!\n");
                        closetrace();
                        closetrace();
                        exit(EXIT_FAILURE);
                        exit(EXIT_FAILURE);
                }
                }
 
 
                return m_core->o_c;
                return m_core->o_c;
        }
        }
 
 
        //
        //
        // Here's our testing function.  Pardon the verbosity of the error
        // Here's our testing function.  Pardon the verbosity of the error
        // messages within it, but ...  well, hopefully you won't ever encounter
        // messages within it, but ...  well, hopefully you won't ever encounter
        // any of those errors. ;)
        // any of those errors. ;)
        //
        //
        // The function works by applying the two inputs to all three of the
        // The function works by applying the two inputs to all three of the
        // multiply functions, MPY, MPSHI, and MPYUHI.  Results are compared
        // multiply functions, MPY, MPSHI, and MPYUHI.  Results are compared
        // against a local multiply on the local (host) machine.  If there's
        // against a local multiply on the local (host) machine.  If there's
        // any mismatch, an error message is printed and the test fails.
        // any mismatch, an error message is printed and the test fails.
        void    mpy_test(int a, int b) {
        void    mpy_test(int a, int b) {
                const   int OP_MPY = 0x08, OP_MPYSHI=0xb, OP_MPYUHI=0x0a;
                const   int OP_MPY = 0x0c, OP_MPYSHI=0xb, OP_MPYUHI=0x0a;
                long    ia, ib, sv;
                const   bool    debug = false;
                unsigned long   ua, ub, uv;
                int64_t         ia, ib, sv;
 
                uint64_t        ua, ub, uv;
                unsigned        r, s, u;
                unsigned        r, s, u;
 
 
                clear_ops();
                clear_ops();
 
 
 
                if (debug)
                printf("MPY-TEST: 0x%08x x 0x%08x\n", a, b);
                printf("MPY-TEST: 0x%08x x 0x%08x\n", a, b);
 
 
                ia = (long)a; ib = (long)b; sv = ia * ib;
                ia = (long)a; ib = (long)b; sv = ia * ib;
                ua = ((unsigned long)a)&0x0ffffffffu;
                ua = ((uint64_t)a)&0x0ffffffffu;
                ub = ((unsigned long)b)&0x0ffffffffu;
                ub = ((uint64_t)b)&0x0ffffffffu;
                uv = ua * ub;
                uv = ua * ub;
 
 
                r = op(OP_MPY, a, b);
                r = op(OP_MPY, a, b);
                s = op(OP_MPYSHI, a, b);
                s = op(OP_MPYSHI, a, b);
                u = op(OP_MPYUHI, a, b);
                u = op(OP_MPYUHI, a, b);
                tick();
                tick();
 
 
                // Let's check our answers, and see if we got the right results
                // Let's check our answers, and see if we got the right results
                if ((r ^ sv)&0x0ffffffffu) {
                if ((r ^ sv)&0x0ffffffffu) {
                        printf("TEST FAILURE(MPY), MPY #1\n");
                        printf("TEST FAILURE(MPY), MPY #1\n");
                        printf("Comparing 0x%08x to 0x%016lx\n", r, sv);
                        printf("Comparing 0x%08x to 0x%016llx\n", r, (long long)sv);
                        printf("TEST-FAILURE!\n");
                        printf("TEST-FAILURE!\n");
                        closetrace();
                        closetrace();
                        exit(EXIT_FAILURE);
                        exit(EXIT_FAILURE);
                } if ((r ^ uv)&0x0ffffffffu) {
                } if ((r ^ uv)&0x0ffffffffu) {
                        printf("TEST FAILURE(MPY), MPY #2\n");
                        printf("TEST FAILURE(MPY), MPY #2\n");
                        printf("Comparing 0x%08x to 0x%016lx\n", r, uv);
                        printf("Comparing 0x%08x to 0x%016llx\n", r, (unsigned long long)uv);
                        printf("TEST-FAILURE!\n");
                        printf("TEST-FAILURE!\n");
                        closetrace();
                        closetrace();
                        exit(EXIT_FAILURE);
                        exit(EXIT_FAILURE);
                }
                }
 
 
                if ((s^(sv>>32))&0x0ffffffffu) {
                if ((s^(sv>>32))&0x0ffffffffu) {
                        printf("TEST FAILURE(MPYSHI), MPY #3\n");
                        printf("TEST FAILURE(MPYSHI), MPY #3\n");
                        printf("Comparing 0x%08x to 0x%016lx\n", s, sv);
                        printf("Comparing 0x%08x to 0x%016llx\n", s, (long long)sv);
                        printf("TEST-FAILURE!\n");
                        printf("TEST-FAILURE!\n");
                        closetrace();
                        closetrace();
                        exit(EXIT_FAILURE);
                        exit(EXIT_FAILURE);
                } if ((u^(uv>>32))&0x0ffffffffu) {
                } if ((u^(uv>>32))&0x0ffffffffu) {
                        printf("TEST FAILURE(MPYUHI), MPY #4\n");
                        printf("TEST FAILURE(MPYUHI), MPY #4\n");
                        printf("Comparing 0x%08x to 0x%016lx\n", u, uv);
                        printf("Comparing 0x%08x to 0x%016llx\n", u, (unsigned long long)uv);
                        printf("TEST-FAILURE!\n");
                        printf("TEST-FAILURE!\n");
                        closetrace();
                        closetrace();
                        exit(EXIT_FAILURE);
                        exit(EXIT_FAILURE);
                }
                }
        }
        }
};
};
 
 
void    usage(void) {
void    usage(void) {
        printf("USAGE: mpy_tb [a b]\n");
        printf("USAGE: mpy_tb [a b]\n");
        printf("\n");
        printf("\n");
        printf(
        printf(
"The test is intended to be run with no arguments.  When run in this fashion,\n"
"The test is intended to be run with no arguments.  When run in this fashion,\n"
"a series of multiplcation tests will be conducted using all three multiply\n"
"a series of multiplcation tests will be conducted using all three multiply\n"
"instructions.  Any test failure will terminate the program with an exit\n"
"instructions.  Any test failure will terminate the program with an exit\n"
"condition.  Test success will terminate with a clear test condition.  \n"
"condition.  Test success will terminate with a clear test condition.  \n"
"During the test, you may expect a large amount of debug output to be\n"
"During the test, you may expect a large amount of debug output to be\n"
"produced.  This is a normal part of testing.  For the meaning of the debug\n"
"produced.  This is a normal part of testing.  For the meaning of the debug\n"
"output, please consider the source code.  The last line of the debug output,\n"
"output, please consider the source code.  The last line of the debug output,\n"
"however, will always include either the word \"FAIL\" or \"SUCCESS\"\n"
"however, will always include either the word \"FAIL\" or \"SUCCESS\"\n"
"depending on whether the test succeeds or fails.\n\n"
"depending on whether the test succeeds or fails.\n\n"
"If the two arguments a and b are given, they will be interpreted according\n"
"If the two arguments a and b are given, they will be interpreted according\n"
"to the form of strtol, and the test will only involve testing those two\n"
"to the form of strtol, and the test will only involve testing those two\n"
"parameters\n\n");
"parameters\n\n");
}
}
 
 
int     main(int argc, char **argv) {
int     main(int argc, char **argv) {
        // Setup verilator
        // Setup verilator
        Verilated::commandArgs(argc, argv);
        Verilated::commandArgs(argc, argv);
        // Now, create a test bench.
        // Now, create a test bench.
        CPUOPS_TB       *tb = new CPUOPS_TB();
        CPUOPS_TB       *tb = new CPUOPS_TB();
        int     rcode = EXIT_SUCCESS;
        int     rcode = EXIT_SUCCESS;
        // tb->opentrace("mpy_tb.vcd");
        // tb->opentrace("mpy_tb.vcd");
 
 
        // Get us started by a couple of clocks past reset.  This isn't that
        // Get us started by a couple of clocks past reset.  This isn't that
        // unreasonable, since the CPU needs to load up the pipeline before
        // unreasonable, since the CPU needs to load up the pipeline before
        // any first instruction will be executed.
        // any first instruction will be executed.
        tb->reset();
        tb->reset();
        tb->tick();
        tb->tick();
        tb->tick();
        tb->tick();
        tb->tick();
        tb->tick();
 
 
        // Look for options, such as '-h'.  Trap those here, and produce a usage
        // Look for options, such as '-h'.  Trap those here, and produce a usage
        // statement.
        // statement.
        if ((argc > 1)&&(argv[1][0]=='-')&&(isalpha(argv[1][1]))) {
        if ((argc > 1)&&(argv[1][0]=='-')&&(isalpha(argv[1][1]))) {
                usage();
                usage();
                exit(EXIT_SUCCESS);
                exit(EXIT_SUCCESS);
        }
        }
 
 
        if (argc == 3) {
        if (argc == 3) {
                // Were we given enough arguments to run a user-specified test?
                // Were we given enough arguments to run a user-specified test?
                tb->mpy_test(
                tb->mpy_test(
                        strtol(argv[1], NULL, 0),
                        strtol(argv[1], NULL, 0),
                        strtol(argv[2], NULL, 0));
                        strtol(argv[2], NULL, 0));
        } else {
        } else {
                // Otherwise we run through a canned set of tests.
                // Otherwise we run through a canned set of tests.
                tb->mpy_test(0,0);
                tb->mpy_test(0,0);
                tb->mpy_test(-1,0);
                tb->mpy_test(-1,0);
                tb->mpy_test(-1,-1);
                tb->mpy_test(-1,-1);
                tb->mpy_test(1,-1);
                tb->mpy_test(1,-1);
                tb->mpy_test(1,0);
                tb->mpy_test(1,0);
                tb->mpy_test(0,1);
                tb->mpy_test(0,1);
                tb->mpy_test(1,1);
                tb->mpy_test(1,1);
 
 
                for(int a=0; ((a&0xfff00000)==0); a+=137)
                for(int a=0; ((a&0xfff00000)==0); a+=137)
                        tb->mpy_test(139, a);
                        tb->mpy_test(139, a);
 
 
                for(int a=0; ((a&0x80000000)==0); a+=0x197e2)
                for(int a=0; ((a&0x80000000)==0); a+=0x197e2)
                        tb->mpy_test(0xf97e27ab, a);
                        tb->mpy_test(0xf97e27ab, a);
        }
        }
 
 
        printf("SUCCESS!\n");
        printf("SUCCESS!\n");
        exit(rcode);
        exit(rcode);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.