diff --git a/Changes b/Changes index ada6b668e..373fb6b8e 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 0c3bd55c6..66c2a7cf9 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -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::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::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 i3; + sc_signal o3; + sc_signal i34[4]; + sc_signal o34[4]; + sc_signal i345[4][5]; + sc_signal 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; +} diff --git a/test_regress/t/t_mem_multi_io2.v b/test_regress/t/t_mem_multi_io2.v new file mode 100644 index 000000000..33d8cfa94 --- /dev/null +++ b/test_regress/t/t_mem_multi_io2.v @@ -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 diff --git a/test_regress/t/t_mem_multi_io_bad.pl b/test_regress/t/t_mem_multi_io2_cc.pl similarity index 51% rename from test_regress/t/t_mem_multi_io_bad.pl rename to test_regress/t/t_mem_multi_io2_cc.pl index 7c03ae629..7433eb85b 100755 --- a/test_regress/t/t_mem_multi_io_bad.pl +++ b/test_regress/t/t_mem_multi_io2_cc.pl @@ -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; diff --git a/test_regress/t/t_mem_multi_io2_sc.pl b/test_regress/t/t_mem_multi_io2_sc.pl new file mode 100755 index 000000000..a2693e658 --- /dev/null +++ b/test_regress/t/t_mem_multi_io2_sc.pl @@ -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; diff --git a/test_regress/t/t_mem_multi_io_bad.v b/test_regress/t/t_mem_multi_io_bad.v deleted file mode 100644 index a66ef1186..000000000 --- a/test_regress/t/t_mem_multi_io_bad.v +++ /dev/null @@ -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