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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [cpp/] [div_tb.cpp] - Diff between revs 147 and 154

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

Rev 147 Rev 154
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    div_tb.cpp
// Filename:    div_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 divide unit found within the Zip CPU.
// Purpose:     Bench testing for the divide unit found within the Zip CPU.
//
//
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015, 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.
//
//
// 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 <ctype.h>
#include <ctype.h>
 
 
#include "verilated.h"
#include "verilated.h"
#include "Vdiv.h"
#include "Vdiv.h"
 
 
#include "testb.h"
#include "testb.h"
// #include "twoc.h"
// #include "twoc.h"
 
 
class   DIV_TB : public TESTB<Vdiv> {
class   DIV_TB : public TESTB<Vdiv> {
public:
public:
        DIV_TB(void) {
        DIV_TB(void) {
        }
        }
 
 
        ~DIV_TB(void) {}
        ~DIV_TB(void) {}
 
 
        void    reset(void) {
        void    reset(void) {
                // m_flash.debug(false);
                // m_flash.debug(false);
                TESTB<Vdiv>::reset();
                TESTB<Vdiv>::reset();
        }
        }
 
 
        bool    on_tick(void) {
        bool    on_tick(void) {
                tick();
                tick();
                return true;
                return true;
        }
        }
 
 
        void    bprint(char *str, int nbits, unsigned long v) {
        void    bprint(char *str, int nbits, unsigned long v) {
                while(*str)
                while(*str)
                        str++;
                        str++;
                for(int i=0; i<nbits; i++) {
                for(int i=0; i<nbits; i++) {
                        if ((1l<<(nbits-1-i))&v)
                        if ((1l<<(nbits-1-i))&v)
                                *str++ = '1';
                                *str++ = '1';
                        else
                        else
                                *str++ = '0';
                                *str++ = '0';
                        if (((nbits-1-i)&3)==0)
                        if (((nbits-1-i)&3)==0)
                                *str++ = ' ';
                                *str++ = ' ';
                } *str = '\0';
                } *str = '\0';
        }
        }
 
 
        void    tick(void) {
        void    dbgdump(void) {
                bool    debug = false;
 
 
 
                if (debug) {
 
                        char    outstr[2048], *s;
                        char    outstr[2048], *s;
                        sprintf(outstr, "Tick %4ld %s%s%s%s%s%s %2d",
                sprintf(outstr, "Tick %4ld %s%s%s%s%s%s%s %2d(%s= 0)",
                                m_tickcount,
                                m_tickcount,
                                (m_core->o_busy)?"B":" ",
                                (m_core->o_busy)?"B":" ",
 
                        (m_core->v__DOT__r_busy)?"R":" ",
                                (m_core->o_valid)?"V":" ",
                                (m_core->o_valid)?"V":" ",
                                (m_core->i_wr)?"W":" ",
                        (m_core->i_wr)?"W":" ",
                                (m_core->v__DOT__pre_sign)?"+":" ",
                        (m_core->v__DOT__pre_sign)?"+":" ",
                                (m_core->v__DOT__r_sign)?"-":" ",
                        (m_core->v__DOT__r_sign)?"-":" ",
                                (m_core->v__DOT__r_z)?"Z":" ",
                                (m_core->v__DOT__r_z)?"Z":" ",
                                m_core->v__DOT__r_bit);
                        m_core->v__DOT__r_bit,
 
                        (m_core->v__DOT__last_bit)?"=":"!");
                        s = &outstr[strlen(outstr)];
                        s = &outstr[strlen(outstr)];
                        sprintf(s, "%s\n%10s %40s",s, "Div","");
                sprintf(s, "%s\n%10s %40s",s, "Div","");
                                s = &s[strlen(s)];
                        s = &s[strlen(s)];
                        bprint( s, 32, m_core->v__DOT__r_dividend);
                bprint( s, 32, m_core->v__DOT__r_dividend);
                                s=&s[strlen(s)];
                        s=&s[strlen(s)];
                        sprintf(s, "%s\n%10s ",s, "Div"); s = &s[strlen(s)];
                sprintf(s, "%s\n%10s ",s, "Div"); s = &s[strlen(s)];
                        bprint( s, 64, m_core->v__DOT__r_divisor);
                bprint( s, 64, m_core->v__DOT__r_divisor);
                                s=&s[strlen(s)];
                        s=&s[strlen(s)];
                        sprintf(s, "%s\n%10s %40s",s, "Q",""); s=&s[strlen(s)];
                sprintf(s, "%s\n%10s %40s",s, "Q",""); s=&s[strlen(s)];
                        bprint( s, 32, m_core->o_quotient); s = &s[strlen(s)];
                bprint( s, 32, m_core->o_quotient); s = &s[strlen(s)];
                        sprintf(s, "%s\n%10s %38s",s, "Diff","");
                sprintf(s, "%s\n%10s %38s",s, "Diff","");
                                s=&s[strlen(s)];
                        s=&s[strlen(s)];
                        bprint( s, 33, m_core->v__DOT__diff); s = &s[strlen(s)];
                bprint( s, 33, m_core->v__DOT__diff); s = &s[strlen(s)];
                        strcat(s, "\n");
                strcat(s, "\n");
                        puts(outstr);
                puts(outstr);
                }
                }
 
 
 
        void    tick(void) {
 
                bool    debug = false;
 
 
 
                if (debug)
 
                        dbgdump();
                TESTB<Vdiv>::tick();
                TESTB<Vdiv>::tick();
        }
        }
 
 
        void    divs(int n, int d) {
        void    divs(int n, int d) {
                bool    dbg = false;
                bool    dbg = false;
                int     ans;
                int     ans;
                ans = (d==0)?0:   (n / d);
                ans = (d==0)?0:   (n / d);
                assert(m_core->o_busy == 0);
                assert(m_core->o_busy == 0);
 
 
                m_core->i_rst = 0;
                m_core->i_rst = 0;
                m_core->i_wr = 1;
                m_core->i_wr = 1;
                m_core->i_signed = 1;
                m_core->i_signed = 1;
                m_core->i_numerator = n;
                m_core->i_numerator = n;
                m_core->i_denominator = d;
                m_core->i_denominator = d;
 
 
                tick();
                tick();
 
 
                m_core->i_wr = 0;
                m_core->i_wr = 0;
                m_core->i_signed = 0;
                m_core->i_signed = 0;
                m_core->i_numerator = 0;
                m_core->i_numerator = 0;
                m_core->i_denominator = 0;
                m_core->i_denominator = 0;
 
 
 
                // Make certain busy is immediately true upon the first clock
 
                // after we issue the divide.
                assert(m_core->o_busy);
                assert(m_core->o_busy);
                assert(m_core->o_valid == 0);
                assert(m_core->o_valid == 0);
 
 
                // while((!m_core->o_valid)&&(!m_core->o_err))
                // while((!m_core->o_valid)&&(!m_core->o_err))
                while(!m_core->o_valid)
                while(!m_core->o_valid) {
 
                        if (!m_core->o_busy) {
 
                                // Make certain busy is asserted whenever
 
                                // valid is false and we're ... well, busy
 
                                dbgdump();
 
                                assert(m_core->o_busy);
 
                        }
                        tick();
                        tick();
 
                } if (dbg) dbgdump();
 
                assert(!m_core->o_busy);
 
 
                if (dbg) {
                if (dbg) {
                        printf("%s%s: %d / %d =? %d\n",
                        printf("%s%s: %d / %d =? %d\n",
                                (m_core->o_valid)?"V":" ",
                                (m_core->o_valid)?"V":" ",
                                (m_core->o_err)?"E":" ",
                                (m_core->o_err)?"E":" ",
                                n, d, m_core->o_quotient);
                                n, d, m_core->o_quotient);
                }
                }
                if ((m_core->o_err)||(d==0)) {
                if ((m_core->o_err)||(d==0)) {
                        if (d==0)
                        if (d==0)
                                assert(m_core->o_err);
                                assert(m_core->o_err);
                        else    assert(!m_core->o_err);
                        else    assert(!m_core->o_err);
                } else
                } else
                        assert(ans == (int)m_core->o_quotient);
                        assert(ans == (int)m_core->o_quotient);
        }
        }
 
 
        void    divu(unsigned n, unsigned d) {
        void    divu(unsigned n, unsigned d) {
                bool    dbg = false;
                bool    dbg = false;
                unsigned        ans;
                unsigned        ans;
                ans = (d==0)?0:   (n / d);
                ans = (d==0)?0:   (n / d);
                assert(m_core->o_busy == 0);
                assert(m_core->o_busy == 0);
 
 
                m_core->i_rst = 0;
                m_core->i_rst = 0;
                m_core->i_wr = 1;
                m_core->i_wr = 1;
                m_core->i_signed = 0;
                m_core->i_signed = 0;
                m_core->i_numerator = n;
                m_core->i_numerator = n;
                m_core->i_denominator = d;
                m_core->i_denominator = d;
 
 
                tick();
                tick();
 
 
                m_core->i_wr = 0;
                m_core->i_wr = 0;
                m_core->i_signed = 0;
                m_core->i_signed = 0;
                m_core->i_numerator = 0;
                m_core->i_numerator = 0;
                m_core->i_denominator = 0;
                m_core->i_denominator = 0;
 
 
                assert(m_core->o_busy);
                assert(m_core->o_busy);
                assert(m_core->o_valid == 0);
                assert(m_core->o_valid == 0);
 
 
                while(!m_core->o_valid)
                while(!m_core->o_valid) {
 
                        assert(m_core->o_busy);
                        tick();
                        tick();
 
                } assert(!m_core->o_busy);
 
 
                if (dbg) {
                if (dbg) {
                        printf("%s%s: %u / %u =? %d (Expecting %u)\n",
                        printf("%s%s: %u / %u =? %d (Expecting %u)\n",
                                (m_core->o_valid)?"V":" ",
                                (m_core->o_valid)?"V":" ",
                                (m_core->o_err)?"E":" ",
                                (m_core->o_err)?"E":" ",
                                n, d, m_core->o_quotient, ans);
                                n, d, m_core->o_quotient, ans);
                }
                }
                if ((m_core->o_err)||(d==0)) {
                if ((m_core->o_err)||(d==0)) {
                        if (d==0)
                        if (d==0)
                                assert(m_core->o_err);
                                assert(m_core->o_err);
                        else    assert(!m_core->o_err);
                        else    assert(!m_core->o_err);
                } else
                } else
                        assert(ans == (unsigned)m_core->o_quotient);
                        assert(ans == (unsigned)m_core->o_quotient);
        }
        }
 
 
        void    divide(int n, int d) {
        void    divide(int n, int d) {
                divs(n,d);
                divs(n,d);
        }
        }
};
};
 
 
void    usage(void) {
void    usage(void) {
        printf("USAGE: div_tb\n");
        printf("USAGE: div_tb\n");
        printf("\n");
        printf("\n");
        printf("\t\n");
        printf("\t\n");
}
}
 
 
int     main(int argc, char **argv) {
int     main(int argc, char **argv) {
        Verilated::commandArgs(argc, argv);
        Verilated::commandArgs(argc, argv);
        DIV_TB  *tb = new DIV_TB();
        DIV_TB  *tb = new DIV_TB();
        int     rcode = EXIT_SUCCESS;
        int     rcode = EXIT_SUCCESS;
 
 
        tb->reset();
        tb->reset();
        tb->divide(125,7);
        tb->divide(125,7);
        tb->tick();
        tb->tick();
        tb->divide(125,-7);
        tb->divide(125,-7);
        tb->tick();
        tb->tick();
        tb->divu((1u<<31),7);
        tb->divu((1u<<31),7);
        tb->divu((7u<<29),(1u<<31));
        tb->divu((7u<<29),(1u<<31));
        tb->tick();
        tb->tick();
        tb->divs(32768,0);
        tb->divs(32768,0);
        tb->tick();
        tb->tick();
        tb->divu((1u<<31),0);
        tb->divu((1u<<31),0);
        tb->tick();
        tb->tick();
        tb->divs((1u<<30),0);
        tb->divs((1u<<30),0);
        tb->tick();
        tb->tick();
        for(int i=32767; i>=0; i--) {
        for(int i=32767; i>=0; i--) {
                tb->divs((1u<<30),i);
                tb->divs((1u<<30),i);
                tb->tick();
                tb->tick();
        } for(int i=32767; i>=0; i--) {
        } for(int i=32767; i>=0; i--) {
                // tb->divu(-1, i);
                // tb->divu(-1, i);
                tb->divu((1u<<31), i);
                tb->divu((1u<<31), i);
                tb->tick();
                tb->tick();
        } for(int i=32767; i>=0; i--) {
        } for(int i=32767; i>=0; i--) {
                tb->divide(32768, i);
                tb->divide(32768, i);
                tb->tick();
                tb->tick();
        }
        }
        /*
        /*
         * While random data is a nice test idea, the following just never
         * While random data is a nice test idea, the following just never
         * really tested the divide unit thoroughly enough.
         * really tested the divide unit thoroughly enough.
         *
         *
        tb->divide(rand(),rand()/2);
        tb->divide(rand(),rand()/2);
        tb->tick();
        tb->tick();
        tb->divide(rand(),rand()/2);
        tb->divide(rand(),rand()/2);
        tb->tick();
        tb->tick();
        tb->divide(rand(),rand()/2);
        tb->divide(rand(),rand()/2);
        tb->tick();
        tb->tick();
        tb->divide(rand(),rand()/2);
        tb->divide(rand(),rand()/2);
        */
        */
 
 
        printf("SUCCESS!\n");
        printf("SUCCESS!\n");
        exit(rcode);
        exit(rcode);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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