Support arrayed SystemC I/O pins.

This commit is contained in:
Wilson Snyder 2012-02-01 20:20:43 -05:00
parent 3429f41489
commit 9df8966f4a
8 changed files with 210 additions and 39 deletions

View File

@ -10,6 +10,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Report MULTIDRIVEN on memories set in multiple clock domains.
*** Support arrayed SystemC I/O pins. [Christophe Joly]
**** Fix core dump with over 100 deep UNOPTFLAT, bug432. [Joe Eiler]

View File

@ -872,9 +872,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) {
bool isArray = !nodep->dtypeSkipRefp()->castBasicDType();
if (nodep->isSc()) {
if (isArray) {
nodep->v3error("Unsupported: SystemC inputs and outputs must be simple data types; no arrays");
}
m_ctorVarsVec.push_back(nodep);
ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment
if (nodep->attrScClocked() && nodep->isInput()) {
@ -889,6 +886,11 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(">\t");
}
puts(nodep->name());
if (isArray) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
}
puts(";\n");
} else { // C++ signals
ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(),
@ -961,22 +963,29 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
}
void EmitCStmts::emitVarCtors() {
ofp()->indentInc();
bool first = true;
for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) {
if (first) {
first=false;
puts("\n");
puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer
puts(" : ");
if (!m_ctorVarsVec.empty()) {
ofp()->indentInc();
puts("\n");
puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer
bool first = true;
for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) {
AstVar* varp = *it;
bool isArray = !varp->dtypeSkipRefp()->castBasicDType();
if (isArray) {
puts("// Skipping array: ");
puts(varp->name());
puts("\n");
} else {
if (first) { puts(" : "); first=false; }
else puts(", ");
if (ofp()->exceededWidth()) puts("\n ");
puts(varp->name());
puts("("); putsQuoted(varp->name()); puts(")");
}
}
else puts(", ");
if (ofp()->exceededWidth()) puts("\n ");
puts((*it)->name());
puts("("); putsQuoted((*it)->name()); puts(")");
puts ("\n#endif\n");
ofp()->indentDec();
}
if (!first) puts ("\n#endif\n");
ofp()->indentDec();
}
bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
@ -1500,7 +1509,22 @@ void EmitCImp::emitSensitives() {
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstVar* varp = nodep->castVar()) {
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
puts("sensitive << "+varp->name()+";\n");
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(arrayp->lsb())+";");
puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb()));
puts("; ++"+ivar+") {\n");
}
puts("sensitive << "+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(";\n");
for (int v=0; v<vects; ++v) puts( "}}\n");
}
}
}

View File

@ -41,7 +41,8 @@ class AstNetlist;
class V3Global {
// Globals
AstNetlist* m_rootp; // Root of entire netlist
AstNetlist* m_rootp; // Root of entire netlist
int m_debugFileNumber; // Number to append to debug files created
bool m_assertDTypesResolved; // Tree should have dtypep()'s
bool m_assertWidthsMatch; // Tree should have width()==widthMin()

View File

@ -0,0 +1,89 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Lane Brooks
#if defined(T_MEM_MULTI_IO2_CC)
# include "Vt_mem_multi_io2_cc.h"
#elif defined(T_MEM_MULTI_IO2_SC)
# include "Vt_mem_multi_io2_sc.h"
#else
# error "Unknown test"
#endif
VM_PREFIX* tb = NULL;
bool pass = true;
double sc_time_stamp() {
return 0;
}
void check(const char* bus, int got, int exp) {
if (got != exp) {
VL_PRINTF("%%Error: Data mismatch on '%s', got=%x, exp=%x\n", bus, got, exp);
pass = false;
}
}
int main() {
Verilated::debug(0);
tb = new VM_PREFIX ("tb");
#ifdef SYSTEMC_VERSION
sc_signal<vluint32_t> i3;
sc_signal<vluint32_t> o3;
sc_signal<vluint32_t> i34[4];
sc_signal<vluint32_t> o34[4];
sc_signal<vluint32_t> i345[4][5];
sc_signal<vluint32_t> o345[4][5];
tb->i3(i3);
tb->o3(o3);
for (int i=0; i<4; i++) {
tb->i34[i](i34[i]);
tb->o34[i](o34[i]);
for (int j=0; j<5; j++) {
tb->i345[i][j](i345[i][j]);
tb->o345[i][j](o345[i][j]);
}
}
#endif
// loop through every possibility and check the result
#ifdef SYSTEMC_VERSION
sc_start(1,SC_NS);
# define ASSIGN(s,v) s.write(v)
# define READ(s) s.read()
#else
tb->eval();
# define ASSIGN(s,v) tb->s = (v)
# define READ(s) tb->s
#endif
ASSIGN(i3, 13);
for (int i=0; i<4; i++) {
ASSIGN(i34[i], i);
for (int j=0; j<5; j++) {
ASSIGN(i345[i][j], i*8 + j);
}
}
#ifdef SYSTEMC_VERSION
sc_start(1,SC_NS);
#else
tb->eval();
#endif
check("o3", READ(o3), 13);
for (int i=0; i<4; i++) {
check("o34", READ(o34[i]), i);
for (int j=0; j<5; j++) {
check("o345", READ(o345[i][j]), i*8 + j);
}
}
if (pass) {
VL_PRINTF("*-* All Finished *-*\n");
} else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n");
}
return 0;
}

View File

@ -0,0 +1,37 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Lane Brooks
module t (/*AUTOARG*/
// Outputs
o3, o34, o345,
// Inputs
i3, i34, i345
);
input [15:0] i3;
output wire [15:0] o3;
input [15:0] i34 [3:0];
output wire [15:0] o34 [3:0];
input [15:0] i345 [3:0][4:0];
output wire [15:0] o345 [3:0][4:0];
sub sub (.*);
endmodule
module sub (/*AUTOARG*/
// Outputs
o3, o34, o345,
// Inputs
i3, i34, i345
);
input [15:0] i3;
output wire [15:0] o3;
input [15:0] i34 [3:0];
output wire [15:0] o34 [3:0];
input [15:0] i345 [3:0][4:0];
output wire [15:0] o345 [3:0][4:0];
assign o3 = i3;
assign o34 = i34;
assign o345 = i345;
endmodule

View File

@ -2,19 +2,24 @@
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
# Copyright 2003-2009 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.
top_filename("t/t_mem_multi_io2.v");
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
verilator_flags2 => ["-sp"],
fails=>$Self->{v3},
nc=>0,
expect=>
'%Error: t/t_mem_multi_io_bad.v:\d+: Unsupported: SystemC inputs and outputs must be simple data types; no arrays
%Error: Exiting due to.*',
);
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io2.cpp"],
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,25 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
top_filename("t/t_mem_multi_io2.v");
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io2.cpp --sc"],
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -1,12 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2005 by Wilson Snyder.
module t (/*AUTOARG*/
// Outputs
dim1
);
reg [1:0] dim1 [1:0];
output dim1; // Bad, can't output multi-dim
endmodule