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

Subversion Repositories ezidebug

[/] [ezidebug/] [trunk/] [EziDebug_src/] [ezidebuginstancetreeitem.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 EziDebug
#include <QString>
2
#include <QStringList>
3
#include <QDir>
4
#include <QMap>
5
#include <QDebug>
6
#include <QObject>
7
 
8
#include "ezidebuginstancetreeitem.h"
9
 
10
#include "ezidebugmodule.h"
11
#include "ezidebugvlgfile.h"
12
#include "ezidebugvhdlfile.h"
13
#include "ezidebugscanchain.h"
14
 
15
 
16
EziDebugPrj* EziDebugInstanceTreeItem::sm_pprj = 0 ;
17
 
18
EziDebugInstanceTreeItem::EziDebugInstanceTreeItem(const QString instance, const QString module)
19
    :m_iinstanceName(instance),m_imoduleName(module)
20
{
21
    m_pChainInfo = NULL ;
22
}
23
 
24
EziDebugInstanceTreeItem:: ~EziDebugInstanceTreeItem()
25
{
26
    EziDebugInstanceTreeItem *pitem = NULL  ;
27
 
28
    for(int i = 0 ; i < m_ichildModules.count() ; i++)
29
    {
30
        pitem = m_ichildModules.at(i) ;
31
        if(pitem)
32
            delete pitem ;
33
        pitem = NULL ;
34
    }
35
 
36
}
37
 
38
EziDebugInstanceTreeItem* EziDebugInstanceTreeItem::parent(void) const
39
{
40
    return m_pparentInstance ;
41
}
42
 
43
EziDebugInstanceTreeItem* EziDebugInstanceTreeItem::child(int num) const
44
{
45
    if((num >= 0)&&(num < m_ichildModules.count()))
46
    {
47
        //qDebug() <<  m_imoduleName <<  m_iinstanceName ;
48
        return m_ichildModules[num] ;
49
    }
50
    else
51
    {
52
        qDebug() << " the num have exceed the scope ! " ;
53
        return NULL ;
54
    }
55
}
56
 
57
void EziDebugInstanceTreeItem::appendChild(EziDebugInstanceTreeItem *child)
58
{
59
    m_ichildModules.append(child);
60
}
61
 
62
void EziDebugInstanceTreeItem::removeChild(EziDebugInstanceTreeItem *child)
63
{
64
    for(int i = 0 ; i < m_ichildModules.count() ;i++)
65
    {
66
        if(m_ichildModules.at(i) == child)
67
        {
68
            m_ichildModules.removeAt(i);
69
            break ;
70
        }
71
    }
72
    return ;
73
}
74
 
75
void EziDebugInstanceTreeItem::setScanChainInfo(EziDebugScanChain * chaininfo)
76
{
77
    m_pChainInfo = chaininfo ;
78
    return ;
79
}
80
 
81
EziDebugScanChain* EziDebugInstanceTreeItem::getScanChainInfo()
82
{
83
    return m_pChainInfo ;
84
}
85
 
86
 
87
 
88
QString EziDebugInstanceTreeItem::getNameData() const
89
{
90
    return  (m_imoduleName + QObject::tr(":") + m_iinstanceName) ;
91
}
92
 
93
const QString &EziDebugInstanceTreeItem::getModuleName() const
94
{
95
    return m_imoduleName ;
96
}
97
 
98
const QString &EziDebugInstanceTreeItem::getInstanceName() const
99
{
100
    return m_iinstanceName ;
101
}
102
 
103
QMap<QString,QString> EziDebugInstanceTreeItem::getInstancePortMapTbl(const QString &instancename) const
104
{
105
    return m_iinstancePortMap.value(instancename) ;
106
}
107
 
108
//void EziDebugInstanceTreeItem::traverseChainTreeItem(void)
109
//{
110
//    for(int i = 0 ;i < m_ichildModules.count(); i++)
111
//    {
112
//        m_ichildModules.at(i)->traverseChainTreeItem();
113
//        int ntimes = sm_pprj->getPrjModuleMap().value(getModuleName())->getInstanceTimes();
114
//        ntimes += 1 ;
115
//        sm_pprj->getPrjModuleMap().value(getModuleName())->setInstanceTimes(ntimes);
116
//    }
117
//    return ;
118
//}
119
 
120
int EziDebugInstanceTreeItem::getAllRegNum(const QString &clock,QString chainname ,int &regbitcount , int &bitwidth ,const QStringList &instancelist)    // 从本节点开始遍历所有子节点
121
{
122
    EziDebugModule *pmodule = NULL ;
123
    QVector<EziDebugModule::RegStructure*> sregVec ;
124
    QVector<EziDebugModule::RegStructure*> vregVec ;
125
    int nregCount = 0 ;
126
    int nlistNum = 0 ;
127
    int nmaxRegBitNum = sm_pprj->getMaxRegNumPerChain() ;
128
    int nsRegNumSum = 0 ;
129
    int nvRegNumSum = 0 ;
130
    int nresult = 0 ;
131
 
132
    // 传进来的 是 module 中 的 clock
133
    // 遍历节点时应 根据 本节点的clockmap 找到 子module 与之对应的 clock
134
 
135
    for( nlistNum = 0 ; nlistNum < m_ichildModules.count() ;nlistNum++)
136
    {
137
        pmodule = sm_pprj->getPrjModuleMap().value(m_ichildModules.at(nlistNum)->getModuleName());
138
        if(pmodule->isLibaryCore())
139
        {
140
            continue ;
141
        }
142
        QMap<QString,QString> iclockMap = getModuleClockMap(m_ichildModules.at(nlistNum)->getInstanceName()) ;
143
        QString iclock = iclockMap.value(clock);  // 当前module中的clock
144
        if(!iclock.isEmpty())
145
        {
146
            nresult = m_ichildModules.at(nlistNum)->getAllRegNum(clock , chainname ,regbitcount , bitwidth , instancelist);
147
            if(nresult)
148
            {
149
                qDebug() << "EziDebug Error: travereall reg error!" ;
150
                return 1 ;
151
            }
152
        }
153
    }
154
 
155
    pmodule  = sm_pprj->getPrjModuleMap().value(this->getModuleName());
156
 
157
    pmodule->getAllRegMap(clock,sregVec,vregVec);
158
 
159
    /*
160
         判断当前module是否单独例化(只有静态寄存器)
161
         YES
162
         {
163
            判断剩余的扫描链个数 是否够用,够用则在旧的扫描链上继续添加,
164
            不够则新创建一条扫描链继续添加
165
           (不够再添加新的扫描链 ,至到结束为止)(计算最后剩余的寄存器个数)
166
         }
167
         NO (可能同时存在 静态与动态的寄存器 添加方法是 先添加静态的寄存器 再添加动态的寄存器)
168
         {
169
            原则:由于多次例化,寄存器不能因为链的变化 在不同的例化中 放在了不同的链里面
170
                if(静态+动态 < 剩余寄存器链个数)
171
                {
172
                    if(这次添加扫描链时和上一次的链相同 )
173
                    {
174
                       则只记录寄存器位置信息 不添加任何
175
                    }
176
                    // 所有的里面放  计算剩余的 扫描链寄存器个数
177
                }
178
                else
179
                {
180
                    // 从新的扫描链 开始添加
181
                }
182
         }
183
         // 最终目的是保证代码的唯一性
184
    */
185
    for(;nregCount < sregVec.count() ;nregCount++)
186
    {
187
        EziDebugModule::RegStructure* preg = sregVec.at(nregCount) ;
188
        nsRegNumSum += preg->m_unMaxBitWidth ;
189
    }
190
 
191
    nregCount = 0 ;
192
 
193
    for(;nregCount < vregVec.count();nregCount++)
194
    {
195
        EziDebugModule::RegStructure* preg = sregVec.at(nregCount) ;
196
        nvRegNumSum += preg->m_unMaxBitWidth ;
197
    }
198
 
199
 
200
    if(pmodule->getConstInstacedTimesPerChain(chainname) == 1)
201
    {
202
        for( nregCount = 0 ; nregCount < sregVec.count();nregCount++)
203
        {
204
            EziDebugModule::RegStructure* preg = sregVec.at(nregCount);
205
            int nRegNumCount = 0 ;
206
            for( ; nRegNumCount < preg->m_unRegNum ; nRegNumCount++)
207
            {
208
 
209
                if((regbitcount + preg->m_unRegBitWidth) >= nmaxRegBitNum)
210
                {
211
                    bitwidth += ((preg->m_unRegBitWidth -(nmaxRegBitNum - regbitcount))/nmaxRegBitNum + 1 );
212
 
213
                    regbitcount = (preg->m_unRegBitWidth -(nmaxRegBitNum - regbitcount))%nmaxRegBitNum ;
214
                }
215
                else
216
                {
217
                    regbitcount += preg->m_unRegBitWidth ;
218
                }
219
            }
220
        }
221
    }
222
    else if(pmodule->getConstInstacedTimesPerChain(chainname) > 1)
223
    {
224
        if((nsRegNumSum + nvRegNumSum) <= (nmaxRegBitNum - regbitcount))
225
        {
226
            regbitcount += (nvRegNumSum + nsRegNumSum) ;
227
        }
228
        else
229
        {
230
            bitwidth++ ;
231
            // 新的扫描链开始添加
232
            for(nregCount = 0 ; nregCount < sregVec.count();nregCount++)
233
            {
234
                EziDebugModule::RegStructure* preg = sregVec.at(nregCount);
235
                int nRegNumCount = 0 ;
236
                for( ; nRegNumCount < preg->m_unRegNum ; nRegNumCount++)
237
                {
238
                    regbitcount += preg->m_unRegBitWidth ;
239
 
240
                    if(regbitcount >= nmaxRegBitNum)
241
                    {
242
                        bitwidth += ((preg->m_unRegBitWidth -(nmaxRegBitNum - regbitcount))/nmaxRegBitNum + 1 );
243
 
244
                        regbitcount = (preg->m_unRegBitWidth -(nmaxRegBitNum - regbitcount))%nmaxRegBitNum ;
245
                    }
246
                }
247
            }
248
 
249
            for(nregCount = 0 ; nregCount < vregVec.count() ;nregCount++)
250
            {
251
                EziDebugModule::RegStructure* preg = vregVec.at(nregCount) ;
252
 
253
                if((nmaxRegBitNum - regbitcount) >= preg->m_unMaxBitWidth)
254
                {
255
                   regbitcount += preg->m_unMaxBitWidth ;
256
                }
257
                else
258
                {
259
                    bitwidth++ ;
260
                    regbitcount = nmaxRegBitNum - preg->m_unMaxBitWidth ;
261
                }
262
            }
263
        }
264
    }
265
    else
266
    {
267
        // do nothting
268
        qDebug() << "EziDebug Error: instance times error!";
269
        return 1 ;
270
    }
271
    return 0 ;
272
}
273
 
274
int  EziDebugInstanceTreeItem::insertScanChain(QMap<QString,SCAN_CHAIN_STRUCTURE*> &chainStructuremap ,EziDebugScanChain* pchain ,QString topinstance)
275
{
276
    /*获取父节点 找到对应的module的文件 插入定时器模块的例化 在需要插入扫描链的例化上增加相应的端口 并连接定时器以及 例化对应的端口 */
277
    QString iinstanceName =  getInstanceName() ;
278
    EziDebugInstanceTreeItem* pparent = this->parent();
279
    EziDebugModule *pparentModule = sm_pprj->getPrjModuleMap().value(pparent->getModuleName()) ;
280
    EziDebugModule *pmodule = sm_pprj->getPrjModuleMap().value(this->getModuleName()) ;
281
    QMap<QString,SCAN_CHAIN_STRUCTURE*> ichildChainStructureMap ;
282
 
283
 
284
    if(iinstanceName == topinstance)
285
    {
286
       /*加入定时器模块 的 例化 连接定时器 对应的端口*/
287
 
288
       //EziDebugModule *pchildModule = sm_pprj->getPrjModuleMap().value(this->getModuleName());
289
       if(pparentModule->getLocatedFileName().endsWith(".v"))
290
       {
291
           //pchain->addToInstanceItemList(pparent->getModuleName(),pparent->getInstanceName());
292
 
293
           /*根据文件名找到 对应的文件对象指针*/
294
           EziDebugVlgFile *pfile = sm_pprj->getPrjVlgFileMap().value(pparentModule->getLocatedFileName()) ;
295
 
296
           if(pfile->addScanChain(EziDebugVlgFile::InsertTimer,chainStructuremap,pchain,this))
297
           {
298
               qDebug() << "EziDebug Error: Insert Chain \" InsertTimer \" Error  ";
299
               return 1 ;
300
           }
301
       }
302
       else if(pparentModule->getLocatedFileName().endsWith(".vhd"))
303
       {
304
 
305
       }
306
       else
307
       {
308
 
309
       }
310
 
311
       pchain->addToClockSetMap(this);
312
       /*打开相应的文件*/
313
       /*循环插入 所有扫描链 代码*/
314
       for(int i = 0 ; i < this->childCount() ; i++)
315
       {
316
           // 如果系统core 文件 跳过
317
           EziDebugModule *pchild = sm_pprj->getPrjModuleMap().value(m_ichildModules.at(i)->getModuleName());
318
           if(pchild->isLibaryCore())
319
           {
320
               // pchain->addToInstanceItemList(m_ichildModules.at(i)->getModuleName(),m_ichildModules.at(i)->getInstanceName());
321
               continue ;
322
           }
323
 
324
           if(!pchild->getClockSignal().count())
325
           {
326
               continue ;
327
           }
328
 
329
           /*修改 key - value 把时钟换成 instance 的 时钟 - value*/
330
           QMap<QString,QString> inewMap = m_imoduleClockMap.value(m_ichildModules.at(i)->getInstanceName());
331
           QMap<QString,QString>::const_iterator m = inewMap.constBegin() ;
332
           while(m != inewMap.constEnd())
333
           {
334
               struct SCAN_CHAIN_STRUCTURE* pchainSt = chainStructuremap.value(m.key(),NULL) ;
335
               if(!pchainSt)
336
               {
337
                   return 1 ;
338
               }
339
               ichildChainStructureMap.insert(m.value(),pchainSt);
340
               ++m ;
341
           }
342
 
343
           if(!ichildChainStructureMap.count())
344
           {
345
               qDebug() << "EziDebug Info: There is no corresponding clock  in the module:" << pchild->getModuleName() << "!" ;
346
               continue ;
347
           }
348
 
349
 
350
//         QString iname =  hiberarchyname ;
351
//         iname.append(QObject::tr("%1:%2|").arg(m_ichildModules.at(i)->getModuleName()).arg(m_ichildModules.at(i)->getInstanceName()));
352
           if(m_ichildModules.at(i)->insertScanChain(ichildChainStructureMap,pchain,topinstance))
353
           {
354
               return 1 ;
355
           }
356
       }
357
 
358
       //pchain->addToInstanceItemList(this->getModuleName(),this->getInstanceName());
359
       EziDebugVlgFile *pfile = sm_pprj->getPrjVlgFileMap().value(pmodule->getLocatedFileName()) ;
360
       if(pfile->addScanChain(EziDebugVlgFile::InsertUserCore,chainStructuremap,pchain,this))
361
       {
362
           qDebug() << "EziDebug Error: InsertChain \" InsertUserCore \" Error " << "In the node " << m_imoduleName << ":" << m_iinstanceName ;
363
           return 1 ;
364
       }
365
    }
366
    else
367
    {
368
        pchain->addToClockSetMap(this);
369
        /*循环插入 所有扫描链 代码*/
370
        for(int i = 0 ; i < this->childCount() ; i++)
371
        {
372
            // 如果系统core 文件 跳过
373
            EziDebugModule *pchild = sm_pprj->getPrjModuleMap().value(m_ichildModules.at(i)->getModuleName());
374
            if(pchild->isLibaryCore())
375
            {
376
                // pchain->addToInstanceItemList(m_ichildModules.at(i)->getModuleName(),m_ichildModules.at(i)->getInstanceName());
377
                continue ;
378
            }
379
 
380
            if(!pchild->getClockSignal().count())
381
            {
382
                continue ;
383
            }
384
 
385
            /*修改 key - value 把时钟换成 instance 的 时钟 - value*/
386
            QMap<QString,QString> inewMap = m_imoduleClockMap.value(m_ichildModules.at(i)->getInstanceName());
387
            QMap<QString,QString>::const_iterator m = inewMap.constBegin() ;
388
            while(m != inewMap.constEnd())
389
            {
390
                // chainmap 是 parent 的 clockmap 加入到扫描链
391
                struct SCAN_CHAIN_STRUCTURE* pchainSt = chainStructuremap.value(m.key(),NULL) ;
392
                if(!pchainSt)
393
                {
394
                    return 1 ;
395
                }
396
                ichildChainStructureMap.insert(m.value(),pchainSt);
397
                ++m ;
398
            }
399
 
400
            //pchain->addToInstanceItemList(m_ichildModules.at(i)->getModuleName(),m_ichildModules.at(i)->getInstanceName());
401
 
402
            if(!ichildChainStructureMap.count())
403
            {
404
                qDebug() << "EziDebug Info: There is no corresponding clock  in the module:" << pchild->getModuleName() << "!" ;
405
                continue ;
406
            }
407
 
408
            if(m_ichildModules.at(i)->insertScanChain(ichildChainStructureMap,pchain,topinstance))
409
            {
410
                return 1 ;
411
            }
412
        }
413
 
414
        // pchain->addToInstanceItemList(this->getModuleName(),this->getInstanceName());
415
        EziDebugVlgFile *pfile = sm_pprj->getPrjVlgFileMap().value(pmodule->getLocatedFileName()) ;
416
        if(pfile->addScanChain(EziDebugVlgFile::InsertUserCore,chainStructuremap,pchain,this))
417
        {
418
            qDebug() << "EziDebug Error: InsertChain \" InsertUserCore \" Error " << "In the node " << m_imoduleName << ":" << m_iinstanceName ;
419
            return 1 ;
420
        }
421
    }
422
    return 0 ;
423
}
424
 
425
 
426
 
427
int EziDebugInstanceTreeItem::deleteScanChain(EziDebugPrj::OPERATE_TYPE type)
428
{
429
    EziDebugScanChain* pchainInfo = getScanChainInfo() ;
430
    EziDebugVlgFile*   pvlgFile = NULL ;
431
    EziDebugVhdlFile*   pvhdlFile = NULL ;
432
 
433
    if(!pchainInfo)
434
    {
435
        /*向窗口传递信息  删除链失败*/
436
        return 1 ;
437
    }
438
 
439
 
440
    QMap<QString,QStringList> ichainCodeBlock = pchainInfo->getLineCode() ;
441
    QMap<QString,QStringList>::const_iterator i = ichainCodeBlock.constBegin() ;
442
 
443
    while( i!= ichainCodeBlock.constEnd())
444
    {
445
        EziDebugModule *pmodule = sm_pprj->getPrjModuleMap().value(i.key(),NULL);
446
        if(!pmodule)
447
        {
448
            /*向窗口传递信息  删除链失败 失败原因*/
449
            return 1 ;
450
        }
451
        // 清空加链过程中 module保存的信息,防止影响下次加链,不用备份,加完之后无用处
452
        pmodule->clearChainInfo(pchainInfo->getChainName());
453
        // 相对路径
454
        QString irelativeFileName = pmodule->getLocatedFileName();
455
 
456
        if(irelativeFileName.endsWith(QObject::tr(".v")))
457
        {
458
            pvlgFile = sm_pprj->getPrjVlgFileMap().value(irelativeFileName) ;
459
            QStringList ilineCodeList = pchainInfo->getLineCode().value(i.key()) ;
460
            if(pvlgFile->deleteScanChain(ilineCodeList,pchainInfo->getBlockCode().value(i.key()),pchainInfo,type))
461
            {
462
               qDebug() << "Error:Delete The Scan Chain Failed!";
463
               return 1 ;
464
            }
465
            else
466
            {
467
               // do nothing
468
            }
469
        }
470
        else if(irelativeFileName.endsWith(QObject::tr(".vhd")))
471
        {
472
        }
473
        else
474
        {
475
            /*向窗口传递信息  删除链失败 失败原因*/
476
            return 1 ;
477
        }
478
 
479
        ++i ;
480
    }
481
 
482
    return 0 ;
483
 
484
 
485
 
486
//    EziDebugInstanceTreeItem* pparent = this->parent();
487
//    EziDebugModule *pparentModule = sm_pprj->getPrjModuleMap().value(pparent->getModuleName()) ;
488
//    EziDebugVlgFile *pfile = sm_pprj->getPrjVlgFileMap().value(pparentModule->getLocatedFileName()) ;
489
 
490
 
491
}
492
 
493
QString EziDebugInstanceTreeItem::findCorrespondClock(QString hiberarchyname, QString clock ,EziDebugInstanceTreeItem * headitem)
494
{
495
    int i = 0 ;
496
    int j = 0 ;
497
    QString iclock = clock;
498
    QStringList ihiberarchyNameList =  hiberarchyname.split(QObject::tr("|"));
499
    if((headitem->getNameData()) != ihiberarchyNameList.at(0))
500
    {
501
        return QString();
502
    }
503
 
504
    /*0 为观察模块的 module:instance*/
505
    for(j = 1 ; j < ihiberarchyNameList.count() ; j++)
506
    {
507
        for(i = 0 ; i < headitem->childCount();i++)
508
        {
509
            if(headitem->child(i)->getNameData() == ihiberarchyNameList.at(j))
510
            {
511
                headitem = headitem->child(i) ;
512
                iclock = headitem->getModuleClockMap(headitem->child(i)->getInstanceName()).value(iclock,QString());
513
                if(iclock.isEmpty())
514
                {
515
                    return iclock ;
516
                }
517
                j++ ;
518
                break ;
519
            }
520
        }
521
        if(i == headitem->childCount())
522
        {
523
            return QString();
524
        }
525
    }
526
    return iclock ;
527
}
528
 
529
 
530
 
531
 
532
void EziDebugInstanceTreeItem::setModuleClockMap(const QString &instancename,const QMap<QString,QString> &clockmap)
533
{
534
    m_imoduleClockMap.insert(instancename,clockmap);
535
    return ;
536
}
537
 
538
QMap<QString,QString> EziDebugInstanceTreeItem::getModuleClockMap(const QString& instancename) const
539
{
540
    return m_imoduleClockMap.value(instancename) ;
541
}
542
 
543
//void EziDebugInstanceTreeItem::traverseAllNode(TRANVERSE_TYPE type)
544
//{
545
//    if(type == TranvereModule)
546
//    {
547
//        if(!m_ichildModules.count())
548
//        {
549
//            return ;
550
//        }
551
//        else
552
//        {
553
//            for(int i = 0 ; i < m_ichildModules.count() ;i++)
554
//            {
555
//                int count = 0 ;
556
//                EziDebugModule *pmodule = sm_pprj->getPrjModuleMap().value(m_ichildModules.at(i)->getModuleName());
557
//                count += pmodule->getRegNumber();
558
//                //traverseAllNode(type);
559
 
560
//            }
561
//        }
562
//    }
563
//    else if(type == TranvereFile)
564
//    {
565
//        return ;
566
//    }
567
//    else
568
//    {
569
//        return ;
570
//    }
571
 
572
//}
573
 
574
const QString & EziDebugInstanceTreeItem::getItemHierarchyName(void) const
575
{
576
    return m_ihierarchyName ;
577
}
578
 
579
void EziDebugInstanceTreeItem::setItemParent(EziDebugInstanceTreeItem* parentitem)
580
{
581
    m_pparentInstance = parentitem ;
582
    return ;
583
}
584
 
585
void EziDebugInstanceTreeItem::settItemHierarchyName(const QString& name)
586
{
587
    m_ihierarchyName = name ;
588
}
589
 
590
void EziDebugInstanceTreeItem::setProject(EziDebugPrj * prj)
591
{
592
   sm_pprj = prj ;
593
   return ;
594
}
595
 
596
const EziDebugPrj* EziDebugInstanceTreeItem::getProject(void)
597
{
598
    return sm_pprj ;
599
}
600
 
601
int EziDebugInstanceTreeItem::childCount() const
602
{
603
    return  m_ichildModules.size();
604
}
605
 
606
int EziDebugInstanceTreeItem::row() const
607
{
608
 
609
    EziDebugInstanceTreeItem* pparentItem = parent();
610
 
611
 
612
    for(int i = 0 ; i < pparentItem->m_ichildModules.count();i++)
613
    {
614
        if(pparentItem->m_ichildModules.at(i) == this)
615
        {
616
            return i ;
617
        }
618
    }
619
    return 0 ;
620
}
621
 
622
 
623
 
624
 
625
 

powered by: WebSVN 2.1.0

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