mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Fix DPI svGetBitselLogic and svPutPartselLogic.
This commit is contained in:
parent
173f71dca6
commit
b888158907
@ -72,7 +72,8 @@ svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
|
||||
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
|
||||
// Not VL_BITRSHIFT_W as sp is a different structure type
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
return (sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1;
|
||||
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
|
||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
|
||||
}
|
||||
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
|
||||
@ -83,6 +84,9 @@ void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
|
||||
dp[VL_BITWORD_I(bit)].aval
|
||||
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&1)<<VL_BITBIT_I(bit)));
|
||||
dp[VL_BITWORD_I(bit)].bval
|
||||
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&2)>>1<<VL_BITBIT_I(bit)));
|
||||
}
|
||||
|
||||
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
|
||||
@ -133,113 +137,54 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
|
||||
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
|
||||
}
|
||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lbit, int width) {
|
||||
// See also _VL_INSERT_WW
|
||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
|
||||
// See also _VL_INSERT_WI
|
||||
int hbit = lbit+width-1;
|
||||
int hoffset = hbit & VL_SIZEBITS_I;
|
||||
int loffset = lbit & VL_SIZEBITS_I;
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
int words = VL_WORDS_I(hbit-lbit+1);
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
// Fast and common case, word based insertion
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[lword+i] = sp[i];
|
||||
}
|
||||
}
|
||||
else if (loffset==0) {
|
||||
// Non-32bit, but nicely aligned, so stuff all but the last word
|
||||
for (int i=0; i<(words-1); ++i) {
|
||||
dp[lword+i] = sp[i];
|
||||
}
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1)); // Know it's not a full word as above fast case handled it
|
||||
dp[lword+words-1] = (dp[words+lword-1] & ~hinsmask) | (sp[words-1] & hinsmask);
|
||||
dp[VL_BITWORD_I(lbit)] = s;
|
||||
}
|
||||
else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int hword = VL_BITWORD_I(hbit);
|
||||
for (int i=0; i<words; ++i) {
|
||||
{ // Lower word
|
||||
int oword = lword+i;
|
||||
IData d = sp[i]<<loffset;
|
||||
IData od = (dp[oword] & ~linsmask) | (d & linsmask);
|
||||
if (oword==hword) dp[oword] = (dp[oword] & ~hinsmask) | (od & hinsmask);
|
||||
else dp[oword] = od;
|
||||
}
|
||||
{ // Upper word
|
||||
int oword = lword+i+1;
|
||||
if (oword <= hword) {
|
||||
IData d = sp[i]>>nbitsonright;
|
||||
IData od = (d & ~linsmask) | (dp[oword] & linsmask);
|
||||
if (oword==hword) dp[oword] = (dp[oword] & ~hinsmask) | (od & hinsmask);
|
||||
else dp[oword] = od;
|
||||
}
|
||||
}
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
if (hword==lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
||||
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
|
||||
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lbit, int width) {
|
||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
|
||||
int hbit = lbit+width-1;
|
||||
int hoffset = hbit & VL_SIZEBITS_I;
|
||||
int loffset = lbit & VL_SIZEBITS_I;
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
int words = VL_WORDS_I(hbit-lbit+1);
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
// Fast and common case, word based insertion
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[lword+i].aval = sp[i].aval;
|
||||
dp[lword+i].bval = sp[i].bval;
|
||||
}
|
||||
}
|
||||
else if (loffset==0) {
|
||||
// Non-32bit, but nicely aligned, so stuff all but the last word
|
||||
for (int i=0; i<(words-1); ++i) {
|
||||
dp[lword+i].aval = sp[i].aval;
|
||||
dp[lword+i].bval = sp[i].bval;
|
||||
}
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1)); // Know it's not a full word as above fast case handled it
|
||||
dp[lword+words-1].aval = (dp[words+lword-1].aval & ~hinsmask) | (sp[words-1].aval & hinsmask);
|
||||
dp[lword+words-1].bval = (dp[words+lword-1].bval & ~hinsmask) | (sp[words-1].bval & hinsmask);
|
||||
dp[VL_BITWORD_I(lbit)].aval = s.aval;
|
||||
dp[VL_BITWORD_I(lbit)].bval = s.bval;
|
||||
}
|
||||
else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int hword = VL_BITWORD_I(hbit);
|
||||
for (int i=0; i<words; ++i) {
|
||||
{ // Lower word
|
||||
int oword = lword+i;
|
||||
IData d_a = sp[i].aval << loffset;
|
||||
IData d_b = sp[i].bval << loffset;
|
||||
IData od_a = (dp[oword].aval & ~linsmask) | (d_a & linsmask);
|
||||
IData od_b = (dp[oword].bval & ~linsmask) | (d_b & linsmask);
|
||||
if (oword==hword) {
|
||||
dp[oword].aval = (dp[oword].aval & ~hinsmask) | (od_a & hinsmask);
|
||||
dp[oword].bval = (dp[oword].bval & ~hinsmask) | (od_b & hinsmask);
|
||||
} else {
|
||||
dp[oword].aval = od_a;
|
||||
dp[oword].bval = od_b;
|
||||
}
|
||||
}
|
||||
{ // Upper word
|
||||
int oword = lword+i+1;
|
||||
if (oword <= hword) {
|
||||
IData d_a = sp[i].aval >> nbitsonright;
|
||||
IData d_b = sp[i].bval >> nbitsonright;
|
||||
IData od_a = (d_a & ~linsmask) | (dp[oword].aval & linsmask);
|
||||
IData od_b = (d_b & ~linsmask) | (dp[oword].bval & linsmask);
|
||||
if (oword==hword) {
|
||||
dp[oword].aval = (dp[oword].aval & ~hinsmask) | (od_a & hinsmask);
|
||||
dp[oword].bval = (dp[oword].bval & ~hinsmask) | (od_b & hinsmask);
|
||||
} else {
|
||||
dp[oword].aval = od_a;
|
||||
dp[oword].bval = od_b;
|
||||
}
|
||||
}
|
||||
}
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
if (hword==lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
||||
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
|
||||
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
|
||||
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ XXTERN void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w);
|
||||
XXTERN void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
|
||||
|
||||
XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w);
|
||||
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
|
||||
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w);
|
||||
|
||||
/*
|
||||
* Open array querying functions
|
||||
|
20
test_regress/t/t_dpi_lib.pl
Executable file
20
test_regress/t/t_dpi_lib.pl
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["t/t_dpi_lib_c.cpp"],
|
||||
verilator_flags2 => ["-Wall -Wno-DECLFILENAME"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
25
test_regress/t/t_dpi_lib.v
Normal file
25
test_regress/t/t_dpi_lib.v
Normal file
@ -0,0 +1,25 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2017 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
import "DPI-C" function int dpii_failure();
|
||||
import "DPI-C" function void dpii_check();
|
||||
|
||||
initial begin
|
||||
dpii_check();
|
||||
|
||||
if (dpii_failure()!=0) begin
|
||||
$write("%%Error: Failure in DPI tests\n");
|
||||
$stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
137
test_regress/t/t_dpi_lib_c.cpp
Normal file
137
test_regress/t/t_dpi_lib_c.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include "svdpi.h"
|
||||
|
||||
//======================================================================
|
||||
|
||||
#if defined(VERILATOR)
|
||||
# include "Vt_dpi_lib__Dpi.h"
|
||||
#elif defined(VCS)
|
||||
# include "../vc_hdrs.h"
|
||||
#elif defined(NC)
|
||||
# define NEED_EXTERNS
|
||||
#else
|
||||
# error "Unknown simulator for DPI test"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_EXTERNS
|
||||
extern "C" {
|
||||
// If get ncsim: *F,NOFDPI: Function {foo} not found in default libdpi.
|
||||
// Then probably forgot to list a function here.
|
||||
|
||||
extern int dpii_failure();
|
||||
extern void dpii_check();
|
||||
}
|
||||
#endif
|
||||
|
||||
//======================================================================
|
||||
|
||||
int failure = 0;
|
||||
|
||||
#define CHECK_RESULT_HEX(got, exp) \
|
||||
do { if ((got) != (exp)) { \
|
||||
std::cout<<std::dec<<"%Error: "<<__FILE__<<":"<<__LINE__<<std::hex \
|
||||
<<": GOT="<<(got)<<" EXP="<<(exp)<<std::endl; \
|
||||
failure = __LINE__; \
|
||||
}} while(0)
|
||||
|
||||
int dpii_failure() { return failure; }
|
||||
|
||||
//======================================================================
|
||||
|
||||
void dpii_lib_bit_check() {
|
||||
svBitVecVal bv [3];
|
||||
bv[0] = 0xa3a2a1a0; // 31..0
|
||||
bv[1] = 0xa7a6a5a4; // 63..32
|
||||
bv[2] = 0xabaaa9a8; // 95..64
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 32), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 33), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 34), 1);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 35), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 36), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 37), 1);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 38), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 39), 1);
|
||||
|
||||
svPutBitselBit(bv, 32, 1);
|
||||
svPutBitselBit(bv, 33, 0);
|
||||
svPutBitselBit(bv, 34, 1);
|
||||
svPutBitselBit(bv, 35, 1);
|
||||
CHECK_RESULT_HEX(bv[0], 0xa3a2a1a0);
|
||||
CHECK_RESULT_HEX(bv[1], 0xa7a6a5ad);
|
||||
CHECK_RESULT_HEX(bv[2], 0xabaaa9a8);
|
||||
|
||||
svBitVecVal btmp [1];
|
||||
svGetPartselBit(btmp, bv, 40, 8);
|
||||
CHECK_RESULT_HEX(btmp[0], 0xa5);
|
||||
|
||||
svPutPartselBit(bv, btmp[0], 48, 8);
|
||||
CHECK_RESULT_HEX(bv[0], 0xa3a2a1a0);
|
||||
CHECK_RESULT_HEX(bv[1], 0xa7a5a5ad);
|
||||
CHECK_RESULT_HEX(bv[2], 0xabaaa9a8);
|
||||
}
|
||||
|
||||
void dpii_lib_logic_check() {
|
||||
svLogicVecVal lv [3];
|
||||
lv[0].aval = 0xb3b2b1b0; // 31..0
|
||||
lv[1].aval = 0xb7b6b5b4; // 63..32
|
||||
lv[2].aval = 0xbbbab9b8; // 95..64
|
||||
lv[0].bval = 0xc3c2c1c0; // 31..0
|
||||
lv[1].bval = 0xc7c6c5c4; // 63..32
|
||||
lv[2].bval = 0xcbcac9c8; // 95..64
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 32), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 33), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 34), 3);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 35), 0);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 36), 1);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 37), 1);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 38), 2);
|
||||
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 39), 3);
|
||||
|
||||
svPutBitselLogic(lv, 32, 1);
|
||||
svPutBitselLogic(lv, 33, 0);
|
||||
svPutBitselLogic(lv, 34, 1);
|
||||
svPutBitselLogic(lv, 35, 3);
|
||||
CHECK_RESULT_HEX(lv[0].aval, 0xb3b2b1b0);
|
||||
CHECK_RESULT_HEX(lv[1].aval, 0xb7b6b5bd);
|
||||
CHECK_RESULT_HEX(lv[2].aval, 0xbbbab9b8);
|
||||
CHECK_RESULT_HEX(lv[0].bval, 0xc3c2c1c0);
|
||||
CHECK_RESULT_HEX(lv[1].bval, 0xc7c6c5c8);
|
||||
CHECK_RESULT_HEX(lv[2].bval, 0xcbcac9c8);
|
||||
|
||||
svLogicVecVal ltmp [1];
|
||||
svGetPartselLogic(ltmp, lv, 40, 8);
|
||||
CHECK_RESULT_HEX(ltmp[0].aval, 0xb5);
|
||||
CHECK_RESULT_HEX(ltmp[0].bval, 0xc5);
|
||||
|
||||
svPutPartselLogic(lv, ltmp[0], 48, 8);
|
||||
CHECK_RESULT_HEX(lv[0].aval, 0xb3b2b1b0);
|
||||
CHECK_RESULT_HEX(lv[1].aval, 0xb7b5b5bd);
|
||||
CHECK_RESULT_HEX(lv[2].aval, 0xbbbab9b8);
|
||||
CHECK_RESULT_HEX(lv[0].bval, 0xc3c2c1c0);
|
||||
CHECK_RESULT_HEX(lv[1].bval, 0xc7c5c5c8);
|
||||
CHECK_RESULT_HEX(lv[2].bval, 0xcbcac9c8);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
void dpii_check() {
|
||||
dpii_lib_bit_check();
|
||||
dpii_lib_logic_check();
|
||||
}
|
Loading…
Reference in New Issue
Block a user