From f23203dc9697739a9b8b0995a6be4c2deb3ea489 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 30 Nov 2007 22:38:21 +0000 Subject: [PATCH] Make __Inlines.h file so we can build VL_CONST_W_#X funcs automatically git-svn-id: file://localhost/svn/verilator/trunk/verilator@974 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- Changes | 5 + bin/verilator | 1 + include/verilated.h | 85 ++---------- src/Makefile_obj.in | 1 + src/V3EmitC.cpp | 3 + src/V3EmitC.h | 1 + src/V3EmitCInlines.cpp | 126 ++++++++++++++++++ src/V3Global.h | 7 +- src/Verilator.cpp | 2 + test_regress/t/t_emit_constw.pl | 19 +++ test_regress/t/t_emit_constw.v | 70 ++++++++++ .../t/{t_equal.pl => t_math_equal.pl} | 0 test_regress/t/{t_equal.v => t_math_equal.v} | 0 13 files changed, 245 insertions(+), 75 deletions(-) create mode 100644 src/V3EmitCInlines.cpp create mode 100755 test_regress/t/t_emit_constw.pl create mode 100644 test_regress/t/t_emit_constw.v rename test_regress/t/{t_equal.pl => t_math_equal.pl} (100%) rename test_regress/t/{t_equal.v => t_math_equal.v} (100%) diff --git a/Changes b/Changes index 87f63d210..e8bcfe521 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,11 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. [by ...] indicates the contributor was also the author of the fix; Thanks! +* Verilator 3.655 *** + +**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman] + In such cases, a new {prefix}__Inlines.h file will be built and included. + * Verilator 3.655 11/27/2007 *** Support "#delay ;" with associated STMTDLY warning. diff --git a/bin/verilator b/bin/verilator index dec9fa901..a7b17bbb3 100755 --- a/bin/verilator +++ b/bin/verilator @@ -838,6 +838,7 @@ For -sp mode, instead of .cpp and .h it creates: In certain optimization modes, it also creates: + {prefix}__Inlines.h // Inline support functions {prefix}__Slow.cpp // Constructors and infrequent routines {prefix}__Syms.cpp // Global symbol table C++ {prefix}__Syms.h // Global symbol table header diff --git a/include/verilated.h b/include/verilated.h index 58766f460..b7232af89 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1288,123 +1288,60 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int, // VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1)) // Sets wide vector words to specified constant words, zeros upper data. +// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW + #define I IData #define _END(obits,wordsSet) \ for(int i=(wordsSet);i +#include +#include +#include +#include +#include + +#include "V3Global.h" +#include "V3EmitC.h" +#include "V3EmitCBase.h" +#include "V3Stats.h" + +#define EMITCINLINES_NUM_CONSTW 10 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_9X is last) + +//###################################################################### + +class EmitCInlines : EmitCBaseVisitor { + // STATE + vector m_wordWidths; // What sizes are used? + + // METHODS + void emitInt(); + + // VISITORS + virtual void visit(AstVar* nodep, AstNUser*) { + // All wide constants load into variables, so we can just hunt for them + if (nodep->widthWords() >= EMITCINLINES_NUM_CONSTW ) { + if (int(m_wordWidths.size()) <= nodep->widthWords()) { + m_wordWidths.resize(nodep->widthWords()+5); + } + ++ m_wordWidths.at(nodep->widthWords()); + v3Global.needHInlines(true); + } + } + + // NOPs + virtual void visit(AstNodeStmt*, AstNUser*) {} + // Default + virtual void visit(AstNode* nodep, AstNUser*) { + nodep->iterateChildren(*this); + } + //--------------------------------------- + // ACCESSORS +public: + EmitCInlines(AstNetlist* nodep) { + nodep->accept(*this); + if (v3Global.needHInlines()) { + emitInt(); + } + } +}; + +void EmitCInlines::emitInt() { + string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h"; + newCFile(filename, false/*slow*/, false/*source*/); + V3OutCFile hf (filename); + m_ofp = &hf; + + ofp()->putsHeader(); + puts("#ifndef _"+topClassName()+"__Inlines_H_\n"); + puts("#define _"+topClassName()+"__Inlines_H_\n"); + puts("\n"); + + puts("#include \"verilated.h\"\n"); + + puts("\n//======================\n\n"); + + for (unsigned words=0; words=0; --i) { + puts(",IData d"+cvtToStr(i)); + if (i && (i % 8 == 0)) puts("\n\t"); + } + puts(") {\n"); + puts(" "); + for (int i=words-1; i>=0; --i) { + puts(" o["+cvtToStr(i)+"]=d"+cvtToStr(i)+";"); + if (i && (i % 8 == 0)) puts("\n "); + } + puts("\n"); + puts(" for(int i="+cvtToStr(words)+";ideleteTree(); m_rootp=NULL; @@ -70,6 +73,8 @@ public: char digits[100]; sprintf(digits, "%02d", m_debugFileNumber); return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment; } + bool needHInlines() const { return m_needHInlines; } + void needHInlines(bool flag) { m_needHInlines=flag; } }; extern V3Global v3Global; diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 6f21d62dd..2fd447694 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -459,6 +459,8 @@ void process () { // Output the text if (!v3Global.opt.lintOnly()) { + // emitcInlines is first, as it may set needHInlines which other emitters read + V3EmitC::emitcInlines(); V3EmitC::emitcSyms(); V3EmitC::emitcTrace(); } diff --git a/test_regress/t/t_emit_constw.pl b/test_regress/t/t_emit_constw.pl new file mode 100755 index 000000000..a7e6a1f20 --- /dev/null +++ b/test_regress/t/t_emit_constw.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + v_flags2 => [$Last_Self->{v3}?'--Ox':''], + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_emit_constw.v b/test_regress/t/t_emit_constw.v new file mode 100644 index 000000000..47398828c --- /dev/null +++ b/test_regress/t/t_emit_constw.v @@ -0,0 +1,70 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer cyc=0; + reg [63:0] crc; + reg [63:0] sum; + + reg [2*32-1:0] w2; initial w2 = {2 {32'h12345678}}; + reg [9*32-1:0] w9; initial w9 = {9 {32'h12345678}}; + reg [10*32-1:0] w10; initial w10 = {10{32'h12345678}}; + reg [11*32-1:0] w11; initial w11 = {11{32'h12345678}}; + reg [15*32-1:0] w15; initial w15 = {15{32'h12345678}}; + reg [31*32-1:0] w31; initial w31 = {31{32'h12345678}}; + reg [47*32-1:0] w47; initial w47 = {47{32'h12345678}}; + reg [63*32-1:0] w63; initial w63 = {63{32'h12345678}}; + + // Aggregate outputs into a single result vector + wire [63:0] result = (w2[63:0] + ^ w9[64:1] + ^ w10[65:2] + ^ w11[66:3] + ^ w15[67:4] + ^ w31[68:5] + ^ w47[69:6] + ^ w63[70:7]); + + // What checksum will we end up with +`define EXPECTED_SUM 64'h184cb39122d8c6e3 + + // Test loop + always @ (posedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result); +`endif + cyc <= cyc + 1; + crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; + sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]}; + if (cyc==0) begin + // Setup + crc <= 64'h5aef0c8d_d70a4497; + end + else if (cyc<10) begin + sum <= 64'h0; + end + else if (cyc<90) begin + w2 <= w2 >> 1; + w9 <= w9 >> 1; + w10 <= w10 >> 1; + w11 <= w11 >> 1; + w15 <= w15 >> 1; + w31 <= w31 >> 1; + w47 <= w47 >> 1; + w63 <= w63 >> 1; + end + else if (cyc==99) begin + $write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum); + if (crc !== 64'hc77bb9b3784ea091) $stop; + if (sum !== `EXPECTED_SUM) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_equal.pl b/test_regress/t/t_math_equal.pl similarity index 100% rename from test_regress/t/t_equal.pl rename to test_regress/t/t_math_equal.pl diff --git a/test_regress/t/t_equal.v b/test_regress/t/t_math_equal.v similarity index 100% rename from test_regress/t/t_equal.v rename to test_regress/t/t_math_equal.v