Compare commits

...
473 Commits
Author SHA1 Message Date
steve 8ae6240947 Snapshot 20070123 2007-01-24 01:24:47 +00:00
steve f77d803aeb Clean up elaboration of for-loop increment expression. 2007-01-21 04:26:36 +00:00
steve 4b829bf04f Get argument widths right for shift results. 2007-01-20 02:10:45 +00:00
steve 17a508047b Better size error details. 2007-01-20 02:09:54 +00:00
steve b350b14f93 DLL API changes for windows. 2007-01-19 23:49:33 +00:00
steve ca9da51a79 Precalculate constant power expressions, and constant function arguments. 2007-01-19 05:42:40 +00:00
steve 98417cb03a Fix calculation of verinum pow operation. 2007-01-19 05:42:04 +00:00
steve f07257067a Handle real constants in vector expressions. 2007-01-19 05:24:53 +00:00
steve e4d7eda02a Fix missing data_type mark for array words. 2007-01-19 04:26:24 +00:00
steve 4d8164945e Fix missing passive setting for array word pins. 2007-01-19 04:25:37 +00:00
steve c0954349e4 Fix bad lookaside references in vvp thread code generator. 2007-01-19 02:30:19 +00:00
steve e89b9fc25e Do not match array words in expression lookaside. 2007-01-18 00:59:48 +00:00
steve 11a83c352d Add missing array source files to CVS. 2007-01-18 00:24:10 +00:00
steve d8d7673d27 Fix typo is hello_vpi.c example. 2007-01-17 05:35:48 +00:00
steve 6f3ddce7c4 Dead code for memories in scopes. 2007-01-17 05:00:12 +00:00
steve f5a7ee0736 Remove dead code related to memories. 2007-01-17 04:39:18 +00:00
steve 91d84e7dc7 Major rework of array handling. Memories are replaced with the
more general concept of arrays. The NetMemory and NetEMemory
 classes are removed from the ivl core program, and the IVL_LPM_RAM
 lpm type is removed from the ivl_target API.
2007-01-16 05:44:14 +00:00
steve 5c3b2f4193 Snapshot 20061210 2006-12-10 17:18:56 +00:00
steve 0ae45e5644 Fix build error overloading pow function. 2006-12-10 17:15:48 +00:00
steve 296c2a575a Snapshot 20061209 2006-12-09 20:07:58 +00:00
steve 316422d93b Handle vpiRealVal reads of signals, and real anyedge events. 2006-12-09 19:06:53 +00:00
steve 2c7d2effd1 Fix an uninitialized variable warning. 2006-12-09 01:59:35 +00:00
steve 4fb5556d1c Handle very wide signed divide. 2006-12-08 19:56:09 +00:00
steve 2eeea7003e @* without inputs is an error. 2006-12-08 04:09:41 +00:00
steve d7de70bdeb Prevent name clash when processing parameter in net. 2006-12-08 03:43:26 +00:00
steve 078019ddec Parse the case of module arrays with port binding by name. 2006-12-06 05:32:36 +00:00
steve b4c3e8208f Parse bit selects in $setuphold notifiers. 2006-12-03 04:46:51 +00:00
steve 2f9a3e90ae Handle comments in file names. 2006-11-30 06:00:28 +00:00
steve 4f8a7ea84a Use new vvp_fun_XXX in place of old functor table for NAND/NOR/XNOR/EEQ. 2006-11-28 05:57:20 +00:00
steve a3da90aa4a Dump nand logic. 2006-11-28 05:56:41 +00:00
steve 48029ed8e5 Fix crash handling constant true conditional. 2006-11-27 02:01:07 +00:00
steve 94f07d16e3 Fix compile time eval of condition expresion to do reduction OR of vectors. 2006-11-26 07:10:30 +00:00
steve 041091cfac Fix nexus widths for direct link assign and ternary nets. 2006-11-26 06:29:16 +00:00
steve 0af4ea7cbe Better document the .scope record. 2006-11-23 23:02:36 +00:00
steve d6f98599f8 Do not intertangle modpaths due to references to input nets. 2006-11-23 22:42:48 +00:00
steve 2ac30824ac Fix spurious event from net8 that is forced. 2006-11-22 06:10:05 +00:00
steve 64b4e2fa01 Get the .event input from the signal instead of the signal input. 2006-11-22 06:09:08 +00:00
steve f5a204720d Support part writes into part select nodes. 2006-11-16 01:11:26 +00:00
steve 21522c90bc Process delay paths in second path over signals. 2006-11-10 05:44:44 +00:00
steve 34b5a31ff4 Add test_width methods for PETernary and PEString. 2006-11-10 04:54:26 +00:00
steve c339dc4bbc Remove last bits of relax_width methods, and use test_width
to calculate the width of an r-value expression that may
 contain unsized numbers.
2006-11-04 06:19:24 +00:00
steve ed5d3188b3 Fix padding of constant eval of NetESelect. 2006-11-04 06:16:27 +00:00
steve 8e379bd634 Handle dup of pad as well as normal select. 2006-11-04 06:10:13 +00:00
steve 841378426f Updates for Cygwin portability (pr1585922) 2006-10-30 22:45:36 +00:00
steve 2302693201 Expression widths with unsized literals are pseudo-infinite width. 2006-10-30 05:44:49 +00:00
steve 2a8b960b06 More detailed internal error message. 2006-10-15 03:25:57 +00:00
steve 0e102a94b2 Fix rendering of signed numbers in real expressions. 2006-10-10 23:54:28 +00:00
steve 168b3f2743 Fix packaging of man directories. 2006-10-09 18:56:17 +00:00
steve 0d71b1cc18 Prepare for 20061009 snapshot. 2006-10-09 18:31:56 +00:00
steve ec23bb0367 Remove dead code. 2006-10-05 01:37:34 +00:00
steve 26e2e85ffa Handle non-constant delays on indexed non-blocking assignments. 2006-10-05 01:23:53 +00:00
steve 4af28e2b77 no-specify turns of specparam elaboration. 2006-10-03 15:33:49 +00:00
steve 69cd007a71 Support real valued specify delays, properly scaled. 2006-10-03 05:06:00 +00:00
steve cbe1a6a3ca Save dep_path because arg space is overrun. 2006-10-02 18:16:18 +00:00
steve 1a0d48c346 Fix handling of dep path in new argument passing method. 2006-10-02 18:15:47 +00:00
steve 549f226c6e Modpath is input to net, draw .modpath to account. 2006-10-01 23:51:15 +00:00
steve e1f712356f Allow rosync events to create new rosync events. 2006-09-29 16:55:04 +00:00
steve 6593b603ad Modpath delay chooses correct delay for edge. 2006-09-29 03:57:01 +00:00
steve 852d10500d Man files go into /usr/share/man. 2006-09-29 01:32:17 +00:00
steve 44ca0fe798 rwsync callback fixes from Ben Staveley (with modifications.) 2006-09-29 01:24:34 +00:00
steve 35ce5f3e2a Improved mingw.txt instructions. 2006-09-28 23:45:20 +00:00
steve d6be82f748 Support selective control of specify and xtypes features. 2006-09-28 04:35:18 +00:00
steve 7e3ea2ffe8 Allow specparams as constants in expressions. 2006-09-28 00:29:49 +00:00
steve b658a3b41f Missing PSpec.cc file. 2006-09-26 19:48:40 +00:00
steve d3ceae7ee0 Accept .cpp source. 2006-09-26 18:54:42 +00:00
steve 0edb5a7547 Basic support for specify timing. 2006-09-23 04:57:19 +00:00
steve ceb6bf4afd Correct return code for vpi_put_userdata. 2006-09-22 22:33:00 +00:00
steve 0e2c6544b9 Proper error message when logic array pi count is bad. 2006-09-22 22:14:27 +00:00
steve b4893dc16f Configure scripts in general need canonical host. 2006-09-22 22:13:07 +00:00
steve f49039a3d6 Missing declaration for Windows. 2006-09-22 15:15:27 +00:00
steve 3617f0346e Bring ivl.def up to date. 2006-09-20 22:31:57 +00:00
steve f20191e6f5 tgt-verilog is not buildable for now. 2006-09-20 22:31:45 +00:00
steve 182734fd4d Remove dead code. 2006-09-20 22:31:23 +00:00
steve 431eee16e4 Do not pass -D__ICARUS__ to ivlpp. 2006-09-20 22:30:52 +00:00
steve 92cb1d4e2d Use elab_and_eval for bit select expressions. 2006-09-19 23:00:15 +00:00
steve 6f34dfc8e5 Scanf formats for character and string. 2006-08-12 04:16:07 +00:00
steve 2c7e96caec scanf support for real values. 2006-08-12 03:38:12 +00:00
steve 54c7ef72cb Snapshot 20060809 2006-08-10 01:23:29 +00:00
steve 50800fd3a1 Add support for real valued modulus. 2006-08-09 05:19:08 +00:00
steve fc0695beb6 Handle 64bit delay constants. 2006-08-08 05:11:37 +00:00
steve 00891db0d2 Fix typo in initialize of new event_time cell. 2006-08-06 18:17:00 +00:00
steve 898b0e0365 Support release of a for/linked reg. 2006-08-04 04:37:37 +00:00
steve 382c4d74fd Add the scanf functions. 2006-08-03 05:06:04 +00:00
steve 5bcf083662 Better comments for vpi_fopen function. 2006-08-03 05:05:31 +00:00
steve 1bd530c144 Fix infinite loop padding binary string to result. 2006-08-03 05:05:06 +00:00
steve 82a85131a8 Use compiletf to check arguments. 2006-08-03 05:02:46 +00:00
steve 49b65e86fe Add support for power in constant expressions. 2006-07-31 03:50:17 +00:00
steve 06d6ac4b33 Fix/implement signed right shift. 2006-07-30 02:51:35 +00:00
steve 2037650080 Pass depfiles through temp defines file. 2006-07-26 00:11:40 +00:00
steve 61f3a84557 Pass defines and includes through temp file. 2006-07-26 00:02:48 +00:00
steve ed70db84ce Handle real valued literals in net contexts. 2006-07-08 21:48:46 +00:00
steve 5348ac14a5 Delay object supports real valued delays. 2006-07-08 21:48:00 +00:00
steve aab6fefd8a Fix context determined with of constants. 2006-07-07 04:06:37 +00:00
steve 1b8e2a17c7 Change the Copyright tag to License. 2006-06-24 05:21:07 +00:00
steve 33a391cb71 Sign extend operands of signed addition. 2006-06-20 05:06:47 +00:00
steve bcc08112aa Snapshot 20060618 2006-06-18 23:56:23 +00:00
steve 80f30be9d0 Add support for system functions in continuous assignments. 2006-06-18 04:15:50 +00:00
steve 71faebd6df Make elaborate_expr methods aware of the width that the context
requires of it. In the process, fix sizing of the width of unary
 minus is context determined sizes.
2006-06-02 04:48:49 +00:00
steve 53ae1f29c9 Fix broken subtraction of small constants. 2006-06-01 03:54:51 +00:00
steve 857b3e15b6 Fix handling of ternary-to-bufif0 constant propagation. 2006-05-24 04:32:57 +00:00
steve 019d61f633 Get self-determined unary - width right. 2006-05-19 04:44:55 +00:00
steve d37b6599f4 eval_const is not strict. 2006-05-19 04:07:24 +00:00
steve 68e52ce6b7 Synchronous primitives only follow edges. 2006-05-18 05:13:45 +00:00
steve 4c885f65e1 Error message if concat expression cannot evaluate. 2006-05-17 16:49:30 +00:00
steve f0e114d59f Lexor os never interactive. 2006-05-17 04:15:12 +00:00
steve aaaa042f73 Add port list format for task arguments. 2006-05-11 03:26:57 +00:00
steve 044da54b41 Be more stubborn about widths. 2006-05-02 04:29:42 +00:00
steve a8b86ea3bb More explicit datatype setup. 2006-05-01 20:47:58 +00:00
steve e98aad1e9b Cleaner rule for parse.h and parse.cc 2006-05-01 20:47:29 +00:00
steve 1ef91f800f Forgot to invert nand output. 2006-05-01 20:47:03 +00:00
steve a19efe181b Install stub target. 2006-05-01 18:48:24 +00:00
steve 81bfbd1549 Reduce steps to make logic output. 2006-05-01 18:44:08 +00:00
steve dc2898cc73 fix net type of multiply output. 2006-05-01 05:40:21 +00:00
steve 0c9fb766b6 Get the data type of part select results right. 2006-04-30 05:17:48 +00:00
steve 10f8c66f4a Dump *all* the reduction operator gates. 2006-04-30 05:16:53 +00:00
steve 56f70ec702 Include math.h with lround implementation. 2006-04-28 15:44:37 +00:00
steve 949054e000 lround takes double, not float. 2006-04-28 15:40:30 +00:00
steve 47b72c3b74 Handle padding of MUX net results. 2006-04-28 05:09:51 +00:00
steve a2c036d5ab Allow concatenations as arguments to inout ports. 2006-04-28 04:28:35 +00:00
steve 0d17e57656 Dump indexes of ident expressions 2006-04-28 04:19:31 +00:00
steve fd94268315 Detect missing lround function. 2006-04-27 05:04:59 +00:00
steve 36039e13ec schedule takes relative, not absolute, time. 2006-04-27 04:38:00 +00:00
steve a702f99c04 Dump function type as string. 2006-04-27 04:26:38 +00:00
steve 4493e3f928 Chop down assign r-values that elaborate too wide. 2006-04-26 04:43:50 +00:00
steve 3727052000 Include bit value in assertion message. 2006-04-26 04:39:23 +00:00
steve 39ff233cf1 Detect the presence of stdint.h 2006-04-25 22:41:10 +00:00
steve 58118bddc5 Warning when file is inadequate for requested range. 2006-04-25 05:00:12 +00:00
steve c2ff3d501c Fix support for indexed part select in continuous assign l-values. 2006-04-24 05:15:07 +00:00
steve 46d86ad276 Get tail counts right in nested concatenations. 2006-04-22 04:27:36 +00:00
steve 4dd1308eb0 Parse specify ifnone statements. 2006-04-17 04:35:49 +00:00
steve a978bb1e14 Cleanup lval part select handling. 2006-04-16 00:54:04 +00:00
steve 707af782b3 Fix part selects in l-values. 2006-04-16 00:15:43 +00:00
steve fc5cf55400 Use elab_and_eval to evaluate genvar expressions. 2006-04-12 05:05:03 +00:00
steve 6a74a090f0 Configure for stub. 2006-04-10 03:07:07 +00:00
steve c448b75f2c fpga target is not installed. 2006-04-10 03:05:54 +00:00
steve aed885ecc5 Add support for generate loops w/ wires and gates. 2006-04-10 02:40:18 +00:00
steve d365c144a8 Snapshot 20060409 2006-04-10 00:54:42 +00:00
steve f001d0001a Add support for generate loops w/ wires and gates. 2006-04-10 00:37:42 +00:00
steve decfbff2b1 Clean up index expression error message. 2006-04-10 00:32:14 +00:00
steve 3e45f4302b Be more accepting of the protect directive. 2006-03-30 05:44:36 +00:00
steve 77a0d7f4db task/function ports can have types. 2006-03-30 05:22:34 +00:00
steve e8efa6df53 Fix instance arrays indexed by overridden parameters. 2006-03-30 01:49:07 +00:00
steve 276f2d0032 Accept attributes in front of module instantiations. 2006-03-25 02:42:58 +00:00
steve 13a660b591 Get rid of excess PESTring:: prefix within class declaration. 2006-03-25 02:36:26 +00:00
steve f4a44df2cc Support more parameter syntax. 2006-03-18 22:53:38 +00:00
steve 5b3ba8c306 Properly handle signedness in compare. 2006-03-18 22:52:27 +00:00
steve 8defa4bcd0 Syntax for carrying sign with parameter. 2006-03-18 22:51:10 +00:00
steve dabdcf0fc9 const/non-const clash. 2006-03-15 19:15:34 +00:00
steve 8ff70410ab Handle multiple part/bi devices connected together. 2006-03-15 05:52:20 +00:00
steve 6f46d12e07 Add support for logic parameters. 2006-03-08 05:29:42 +00:00
steve 5f5a6b5396 Cleanup vpi_const to use vec4 values. 2006-03-06 05:43:15 +00:00
steve 1b911ad87a Add support for memory value change callbacks. 2006-03-05 05:45:58 +00:00
steve b0b614ae0e Some trivial log message improvements. 2006-02-22 03:08:53 +00:00
steve 9c16c34422 Put strings for reg objects. 2006-02-21 05:31:54 +00:00
steve 170e57d662 Callbacks for named event triggers. 2006-02-21 04:57:26 +00:00
steve 065f342278 Remove dead code. 2006-02-21 03:19:03 +00:00
steve a721586acb Get vpiVectorVal from memory words. 2006-02-21 02:56:49 +00:00
steve 50ad415c0d Support string values for memory words. 2006-02-21 02:39:27 +00:00
steve 4ba2afbbe1 Use g++ linker if there are C++ source files. 2006-02-21 02:38:44 +00:00
steve d3f89e0d4f Clean up makefiles to remove unsupported targets. 2006-02-15 18:42:42 +00:00
steve 457cf15b3b Snapshot 20060215 2006-02-15 18:00:33 +00:00
steve d0de678d57 real-to-integer conversions round, not truncate. 2006-02-02 05:48:45 +00:00
steve fa6e4a69a6 Parse more cases of (*). 2006-02-02 05:21:45 +00:00
steve d434dd7296 Allow part selects of memory words in l-values. 2006-02-02 02:43:57 +00:00
steve 3158e2caa1 Snapshot 20060124 2006-01-25 02:16:11 +00:00
steve e1ce72e245 Support wide divide nodes. 2006-01-03 06:19:31 +00:00
steve 368c27c9e4 Handle complex net node delays. 2006-01-03 05:22:14 +00:00
steve a4116efd57 Fix the return type of a synthesized divide. 2006-01-03 05:15:33 +00:00
steve 58f182a159 Node delays can be more general expressions in structural contexts. 2006-01-02 05:33:19 +00:00
steve b7861fa6e8 Require explicit delay node from source. 2006-01-02 05:32:06 +00:00
steve 1721799050 Document binary expression use. 2005-12-22 15:44:29 +00:00
steve df226c5d13 pad_to_width handles signed expressions. 2005-12-22 15:43:47 +00:00
steve e9bf00dff6 Pad part selects 2005-12-22 15:42:22 +00:00
steve c071cc1bbe More detailed check of binary expressions. 2005-12-22 15:38:33 +00:00
steve 101b373293 Allow constant concat expressions. 2005-12-07 04:04:23 +00:00
steve 5cf64dfa70 Include stdint.h if it is present. 2005-12-07 03:43:30 +00:00
steve 1021e5acc8 Fixes for stubborn compilers. 2005-12-05 21:21:18 +00:00
steve 4f7e7a2296 Some systems donot have stding.h? 2005-12-05 21:20:55 +00:00
steve 0c73f209de Be more careful with double types. 2005-12-05 21:19:55 +00:00
steve 0873c52474 vpi_signal supports vvp_fun_signal_vec types. 2005-11-30 00:42:14 +00:00
steve 64d46630e0 Snapshot 20051127 2005-11-27 17:53:28 +00:00
steve 8ed504b064 Fix for stubborn compiler. 2005-11-27 17:01:56 +00:00
steve 6161904bf8 Fix type safety warning from gcc. 2005-11-27 16:47:14 +00:00
steve 908955c72c Handle bit select of parameter with ranges. 2005-11-27 05:56:20 +00:00
steve bab70ccbed Handle indexed l-value to force. 2005-11-26 17:23:17 +00:00
steve 2b8fd28a95 Force instruction that can be indexed. 2005-11-26 17:16:05 +00:00
steve 0e044d6684 More precise about r-value width of constants. 2005-11-26 00:35:42 +00:00
steve 7efa6be236 stop/continue messages go through MCD for logging. 2005-11-25 18:35:38 +00:00
steve 35951510c5 Put vec8 and vec4 nets into seperate net classes. 2005-11-25 17:55:26 +00:00
steve 3f108f08ed Dump IVL_ST_DELAYX statements. 2005-11-20 15:58:53 +00:00
steve 244844c067 Document the IVL_ST_DELAY statements. 2005-11-20 15:58:25 +00:00
steve b416ae047b Fix compile warning. 2005-11-14 22:11:52 +00:00
steve c02b3b8ac6 Reorganize signal part select handling, and add support for
indexed part selects.

 Expand expression constant propagation to eliminate extra
 sums in certain cases.
2005-11-10 13:28:11 +00:00
steve bebcc05aab Handle very wide % and / operations using expanded vector2 support. 2005-11-10 13:27:16 +00:00
steve 8d49abf967 Document the MUXZ functor. 2005-11-10 13:25:31 +00:00
steve c87223170b Prepare for snapshot 20051012 2005-10-13 03:04:06 +00:00
steve 8e2898e51a Fix compile of net/real aliases. 2005-10-12 17:28:07 +00:00
steve 9c8c541f5d MUX nodes get inputs from nets, not from net inputs,
Detect and draw alias nodes to reduce net size and
 handle force confusion.
2005-10-12 17:26:17 +00:00
steve 3cdf655c79 force l-values do not support bit/part select. 2005-10-12 17:26:01 +00:00
steve 560c5a2584 Add alias nodes. 2005-10-12 17:23:15 +00:00
steve c75f0a930e Remove the $ from signal labels. They do not help. 2005-10-11 18:54:10 +00:00
steve bb3f3c1f46 Remove obsolete vvp_memory_label function. 2005-10-11 18:30:50 +00:00
steve 07f345da4d Logical or/and return VT_LOGIC type. 2005-10-11 16:15:52 +00:00
steve fb22bcc96b Remove dead dram_input_from_net and lpm_inputs_a_b 2005-10-10 04:16:13 +00:00
steve 2842a65fd1 Make sure the new size sticks in resize method. 2005-10-04 04:41:07 +00:00
steve a652719876 Add support for indexed select attached to parameters. 2005-10-04 04:09:25 +00:00
steve 16dc3ab4d4 Error message for invalid for-loop index variable. 2005-09-27 04:51:37 +00:00
steve cf85c19f7b Simplify NexusSet set handling. 2005-09-25 23:40:11 +00:00
steve 01a6dd61ca Support put_value of string values. 2005-09-21 01:04:59 +00:00
steve bf8b085159 Clean up compiler warnings. 2005-09-20 18:34:01 +00:00
steve ee22550047 Lazy processing of vvp_fun_part functor. 2005-09-20 00:51:53 +00:00
steve 2b07c7a685 Prevent some excess scheduling of logic propagation events. 2005-09-19 22:47:28 +00:00
steve be73be8c98 Spelling patches from Larry. 2005-09-19 21:45:35 +00:00
steve e2a1b90b12 Use lazy eval of BUF/NOT/OR/XOR gates. 2005-09-19 21:45:09 +00:00
steve d22d88923d Fix warnings about uninitialized variables. 2005-09-19 20:18:20 +00:00
steve 2729d6cd2e Include vvp_config.h instead of config.h 2005-09-19 20:17:59 +00:00
steve 21af0dbe3f Fix data type of parameters to logic. 2005-09-19 15:21:09 +00:00
steve c4d8ab8509 Improve loading of part selects when easy. 2005-09-17 04:01:32 +00:00
steve 988a0a7048 Add the load/v.p instruction. 2005-09-17 04:01:01 +00:00
steve 672aa61ae7 More robust use of precalculated expressions, and
Separate lookaside for written variables that can
 also be reused.
2005-09-17 01:01:00 +00:00
steve 7235706923 Make sure div, mod and mult nodes have line number info. 2005-09-15 23:04:09 +00:00
steve a256613fa6 Fix bug configuring NetModulo pins. 2005-09-15 22:54:47 +00:00
steve 5ec7dde52f Use iostream instead of stdio. 2005-09-15 22:54:04 +00:00
steve 19a1ae8d4f Preserve precalculated expressions when possible. 2005-09-15 02:50:13 +00:00
steve 14d79a655e Better reuse of IVL_EX_SELECT expressions. 2005-09-15 02:49:47 +00:00
steve 293976bacc Spelling fixes. 2005-09-15 02:30:09 +00:00
steve 4dfdc147c5 fit type elaboration of logical not. 2005-09-14 15:15:44 +00:00
steve c946f27d9b Add b0 and b1 edges to parser. 2005-09-14 15:01:07 +00:00
steve 9fd16575d9 Support bool expressions and compares handle them optimally. 2005-09-14 02:53:13 +00:00
steve b9c0b8aa79 Add an extensions.txt file. 2005-09-14 02:51:13 +00:00
steve 65584e6dde Add word integer compares. 2005-09-14 02:50:07 +00:00
steve c39976fbf1 Generate code to handle real valued muxes. 2005-09-01 04:11:37 +00:00
steve 4902c222fb Check operand types for compatibility. 2005-09-01 04:10:47 +00:00
steve ad761069c7 Support MUXR functors. 2005-09-01 04:08:47 +00:00
steve b69f59f2ec Handle memory references is continuous assignments. 2005-08-31 05:07:31 +00:00
steve 3ff2488d4f Clean up a few overflowed shifts. 2005-08-30 00:49:42 +00:00
steve efd7825964 minor correction to address check in of_MOV1XZ 2005-08-30 00:49:21 +00:00
steve 70f146924a Safe handling of C left shift. 2005-08-29 04:46:52 +00:00
steve 7c19eb51e7 Minor cleanup. 2005-08-29 04:46:13 +00:00
steve 6f839aa5df Eliminate int to vvp_bit4_t casts. 2005-08-29 02:38:50 +00:00
steve dac11c2468 Handle synthesis of fully packed case statements. 2005-08-27 04:32:08 +00:00
steve 5cf2ce6499 Fix bit destination address in of_AND 2005-08-27 03:28:57 +00:00
steve 73453996a9 Be more cautios about accessing out-of-range bits. 2005-08-27 03:28:16 +00:00
steve bc489a7761 Bring threads into the vvp_vector4_t structure. 2005-08-27 02:34:42 +00:00
steve 4a8be3db9c Implement bi-directional part selects. 2005-08-06 17:58:16 +00:00
steve 8232b621f1 Fix parse errors related to pr766. 2005-07-27 14:54:51 +00:00
steve 4cbffc6b77 bufif enable is LOGIC. 2005-07-15 19:22:52 +00:00
steve 9a16e030b5 Match data type of PV select input/output. 2005-07-15 04:13:25 +00:00
steve d353ddb660 Get output type correct for binary mux (ternary) expression. 2005-07-15 00:42:02 +00:00
steve bc9f286954 More debug information. 2005-07-15 00:41:09 +00:00
steve fde4ff72f6 Display as version 0.9.devel 2005-07-14 23:38:43 +00:00
steve a8d49921ee gcc4 compile errors. 2005-07-14 23:34:18 +00:00
steve 9cae53988a Dump function call expression node. 2005-07-14 16:15:13 +00:00
steve 559a1fd359 Remove the .word statement. 2005-07-13 04:58:29 +00:00
steve 5bfdd52391 Handle functions with real values. 2005-07-13 04:52:31 +00:00
steve b094ccc3f7 Functions get type from their output signal. 2005-07-13 04:51:36 +00:00
steve b9799cf6ec Remove NetVariable and ivl_variable_t structures. 2005-07-11 16:56:50 +00:00
steve 75ad90534b Generalize signals to carry types. 2005-07-07 16:22:49 +00:00
steve 3ac79c294a Implement real valued signals and arith nodes. 2005-07-06 04:29:25 +00:00
steve e7f3340513 Remove reference to SystemVerilog. 2005-06-28 04:25:55 +00:00
steve 60b9121c6c Make vector2 multiply more portable. 2005-06-27 21:13:14 +00:00
steve e3f300f4c2 AND functor explicitly knows its width. 2005-06-26 21:08:38 +00:00
steve 1c6be44724 More verbose debugging of part select width errors. 2005-06-26 21:08:11 +00:00
steve 6bf7556d65 Check width of part select based on direction. 2005-06-26 18:09:24 +00:00
steve c46f978dbb Fix uninitialzied attr pointers for UDP devices. 2005-06-26 18:08:46 +00:00
steve 9cac88330b AND gates propogate through scheduler, not directly. 2005-06-26 18:06:29 +00:00
steve de1dd2f2b3 Make bit masks of vector4_t 64bit aware. 2005-06-26 01:57:22 +00:00
steve 6c8e1f7834 inline the vvp_send_vec4_pv function. 2005-06-24 02:16:42 +00:00
steve b58705b829 Inline more simple stuff, and more vector4_t by const reference for performance. 2005-06-22 18:30:12 +00:00
steve 7091915b73 Reduce vvp_vector4 copies by using const references. 2005-06-22 00:04:48 +00:00
steve 5513974b78 Optimize vvp_scalar_t handling, and fun_buf Z handling. 2005-06-21 22:48:23 +00:00
steve ad78af2f91 Inline some commonly called vvp_vector4_t methods. 2005-06-20 01:28:14 +00:00
steve 1b30bac9f3 Optimize the LOAD_VEC implementation. 2005-06-19 18:42:00 +00:00
steve 66a579dd67 Handle signed display of unsigned signals. 2005-06-18 15:55:21 +00:00
steve 094dd7e4de threads member for waitable_hook_s needs initailizing. 2005-06-17 23:47:02 +00:00
steve 3b91db96cd Support set of IntVal to memory words. 2005-06-17 05:13:07 +00:00
steve 657ac8168e Debug messages. 2005-06-17 05:06:47 +00:00
steve a79fee39e9 Watch out for signed constants in magnitude compare. 2005-06-17 05:05:53 +00:00
steve 4cc421b3b7 Make functors know their own width. 2005-06-17 03:46:52 +00:00
steve 290c604c62 Fix bit offsets when processing lval concatenation. 2005-06-15 01:33:33 +00:00
steve 466ab5c2c7 Resolv do not propogate inputs that do not change. 2005-06-15 00:47:15 +00:00
steve 4ba195282d gcc3/4 compile errors. 2005-06-14 19:13:43 +00:00
steve cd14ee77ae Add the assign_v0_d instruction. 2005-06-14 01:44:09 +00:00
steve 21c7abf090 Accomodate fussy compilers. 2005-06-14 00:42:06 +00:00
steve 4413dd3c81 Fix compile errors. 2005-06-13 23:22:37 +00:00
steve 73f3589ea6 use NetPartSelect to shrink part from high bits. 2005-06-13 23:22:14 +00:00
steve 9278dad244 Make synthesized padding vector-aware. 2005-06-13 22:26:03 +00:00
steve a0dce80eba Document ivl_logic_delay function. 2005-06-13 22:25:37 +00:00
steve af5f713c0f Dump delays for logic devices. 2005-06-13 22:20:38 +00:00
steve 80cac983c6 More unified vec4 to hex string functions. 2005-06-13 00:54:04 +00:00
steve f5ba93eeb6 Remove unused ft_MOS truth tables. 2005-06-12 21:56:16 +00:00
steve 668781788b Support resistive mos devices. 2005-06-12 15:13:37 +00:00
steve 86729f52ca Remove functor classes, no longer needed. 2005-06-12 01:42:20 +00:00
steve fb8ddbbfde Remove useless references to functor.h 2005-06-12 01:25:27 +00:00
steve 2736859d8f Remove useless references to functor.h 2005-06-12 01:10:26 +00:00
steve a59f3b1fa6 Implement nmos and pmos devices. 2005-06-12 00:44:49 +00:00
steve dd4f765b06 Remove unneeded references to functor.h 2005-06-11 18:11:18 +00:00
steve f465bca305 UD delays use delay node. 2005-06-11 16:21:08 +00:00
steve cb967c10fe Handle all edge types of a synchronous UDP. 2005-06-11 02:04:48 +00:00
steve 3607fb584d Support UDP initial values. 2005-06-09 05:04:45 +00:00
steve 77792dcc2f Support sequential UDP devices. 2005-06-09 04:12:30 +00:00
steve 2f7ec71a78 Support %force/link 2005-06-02 16:03:47 +00:00
steve 42433f4df9 Add support for notif0/1 gates.
Make delay nodes support inertial delay.
 Add the %force/link instruction.
2005-06-02 16:02:11 +00:00
steve aa2e178667 Handle event/or with specific, efficient nodes. 2005-05-25 05:44:51 +00:00
steve 015d280c6a Handle assignments to part-select l-values. 2005-05-24 02:31:18 +00:00
steve 739a1839ed Do sign extension of structuran nets. 2005-05-24 01:44:27 +00:00
steve b6fd4f610b Add a sign-extension node. 2005-05-24 01:43:27 +00:00
steve 06e08dbdf0 Make sure comparison widths match. 2005-05-19 03:51:38 +00:00
steve 28168e0f57 Fixup structural GT comparators. 2005-05-18 03:46:01 +00:00
steve 7796c8bcfb Parameters cannot have their width changed. 2005-05-17 20:56:55 +00:00
steve 82be4ab189 Detect bit selects that need special handling. 2005-05-17 20:55:42 +00:00
steve 3a8e2e688d Clean up definition of vvp_vector4_t insertion into ostream. 2005-05-17 20:54:56 +00:00
steve 037ab9efe9 Document real behavior of set/v instruction. 2005-05-17 20:54:00 +00:00
steve d6a89a40cf Clean up instruction type reverences to bits. 2005-05-17 20:51:06 +00:00
steve 3bd09d1470 synthesis of Logic and shifts using vector gates. 2005-05-15 04:47:00 +00:00
steve d0ade1d082 Debug text. 2005-05-15 04:45:50 +00:00
steve fcb02ee9c2 Disable obsolete logic constant fixup code. 2005-05-15 04:44:30 +00:00
steve 870395e627 Move functor delays to vvp_delay_fun object. 2005-05-14 19:43:23 +00:00
steve c701fb615b Give buffers support for simple delays. 2005-05-13 05:13:12 +00:00
steve adbe734b6c Some debug messages. 2005-05-13 05:12:39 +00:00
steve c34e44dad0 Make sig-eq-constant optimization more effective. 2005-05-10 05:10:40 +00:00
steve 5a2dd3393f Skip assign if index is invalid. 2005-05-09 00:38:12 +00:00
steve ed78c5b677 Force part base out of bounds if index is invalid. 2005-05-09 00:36:58 +00:00
steve 7dd0d255a6 Add support for variable part select. 2005-05-08 23:40:14 +00:00
steve 48aa0f0075 Better handle assignment to bit/part select. 2005-05-07 03:16:31 +00:00
steve 5277124c76 Implement non-blocking part assign. 2005-05-07 03:15:42 +00:00
steve f6da64e2ec ostream insert for vvp_vector4_t objects. 2005-05-07 03:14:50 +00:00
steve 06816e79fe Clarify internal delays for assignments. 2005-05-07 03:14:00 +00:00
steve a1d899112a Include delay expressions for assignments in dump. 2005-05-07 03:13:30 +00:00
steve d548c9a5f8 Handle synthesis of concatenation expressions. 2005-05-06 00:25:13 +00:00
steve 2894cdefc7 Add cassign/link instruction. 2005-05-01 22:05:21 +00:00
steve df271c9fa3 Link signals that are source of procedural continuous assign. 2005-05-01 22:04:12 +00:00
steve 99aff5f10b Remove dead functor code. 2005-04-28 04:59:53 +00:00
steve e9bf021f6c vvp_fun_signal eliminates duplicate propagations. 2005-04-25 04:42:17 +00:00
steve aed8474944 Reimplement basic asynchronous processes. 2005-04-25 01:35:58 +00:00
steve af7e196518 synthesis of add and unary get vector widths right. 2005-04-25 01:30:31 +00:00
steve 365cfedd55 Update DFF support to new data flow. 2005-04-24 23:44:01 +00:00
steve f884652c19 Add DFF nodes. 2005-04-24 20:07:25 +00:00
steve 6244dc1194 Make logic aware of strength. 2005-04-13 06:35:11 +00:00
steve a3f696cd06 Add vvp driver functor for logic outputs,
Add ostream output operators for debugging.
2005-04-13 06:34:20 +00:00
steve 061fdf5a0d scalars with 0-drivers are hiZ by definition. 2005-04-09 06:00:58 +00:00
steve fe91ebe77c Default behavior for recv_vec8 methods. 2005-04-09 05:30:38 +00:00
steve e8a6835d36 Make clear that memory addresses are cannonical. 2005-04-08 04:52:31 +00:00
steve 800e2c6a17 All memory addresses are signed. 2005-04-08 04:51:16 +00:00
steve 29fa9e7321 Don not give to make_add express an unwanted width. 2005-04-08 04:50:31 +00:00
steve 65c7ec00e7 Rework NetRamDq and IVL_LPM_RAM nodes. 2005-04-06 05:29:08 +00:00
steve d62661257a Generate the right coes for unconnected UDP port. 2005-04-04 05:29:53 +00:00
steve c5cf77dc7e Support row level wildcards. 2005-04-04 05:13:59 +00:00
steve 20d3a8508e Remove dead fvectors class. 2005-04-03 06:13:34 +00:00
steve f16b69c1e5 Remove dead fvectors class. 2005-04-03 06:13:34 +00:00
steve 573e07225d Rework the vvp_delay_t class. 2005-04-03 05:45:51 +00:00
steve 236ff2b278 Clean up handle of UDPs. 2005-04-01 06:04:30 +00:00
steve b7ef2fcb0a Reimplement combinational UDPs. 2005-04-01 06:02:45 +00:00
steve becda0e26c popen must be matched by pclose. 2005-03-22 15:53:48 +00:00
steve d8a456bd67 The indexed set can write a vector, not just a bit. 2005-03-22 05:18:34 +00:00
steve 8184dfaed8 Handle wide operands to logical AND. 2005-03-19 06:59:53 +00:00
steve ca488dff4e Handle LPM shifts. 2005-03-19 06:23:49 +00:00
steve 23925b636e vvp.conf files are generated. 2005-03-18 02:57:23 +00:00
steve 53da6e9a33 Add support for LPM_UFUNC user defined functions. 2005-03-18 02:56:03 +00:00
steve 0f914bf35a UPdate elabrate continuous assighn of string to net. 2005-03-13 01:26:48 +00:00
steve f556452403 Handle function/task port vectors. 2005-03-12 23:45:33 +00:00
steve ab1ca54df2 Update support for LPM_MOD. 2005-03-12 06:43:35 +00:00
steve bae8507c90 Implement .arith/mod. 2005-03-12 06:42:28 +00:00
steve 313502f360 Implement VPI access to signal strengths,
Fix resolution of ambiguous drive pairs,
 Fix spelling of scalar.
2005-03-12 04:27:42 +00:00
steve 1c5b4881d7 Handle case inequality in netlists. 2005-03-09 05:52:03 +00:00
steve 53af2949b4 Generate code for new form of memory ports. 2005-03-09 04:53:40 +00:00
steve 789c95b1c1 reimplement memory ports. 2005-03-09 04:52:40 +00:00
steve 72240c460e Remove dead code from scheduler. 2005-03-06 17:25:03 +00:00
steve 8e135a1020 Non blocking assign to memory words. 2005-03-06 17:07:48 +00:00
steve 0fb1fd36ee Handle memory words in l-value concatenations. 2005-03-05 05:47:42 +00:00
steve e7c2e06260 Check that lead.mv vector width matches word. 2005-03-05 05:45:18 +00:00
steve 73997f813c Get read width of unitialized memory words right. 2005-03-05 05:44:32 +00:00
steve 75af32bd3c Get base address from word ranges that VPI user passed. 2005-03-05 05:43:03 +00:00
steve 4ccbb4f0b2 Get rval width right for arguments into task calls. 2005-03-05 05:38:33 +00:00
steve 85286cc086 Rearrange how memories are supported as vvp_vector4 arrays. 2005-03-03 04:33:10 +00:00
steve 04604188df Clock compression fix from Tony. 2005-02-19 16:45:01 +00:00
steve f7dc4307bd Fix duplicate delete from pr1073. 2005-02-19 16:44:38 +00:00
steve 257e1f9516 Support shifts and divide. 2005-02-19 02:43:38 +00:00
steve 5fe5d9184d Handle signed divide. 2005-02-19 02:41:23 +00:00
steve 589eb1d315 Implement .arith/div. 2005-02-19 01:32:52 +00:00
steve 2fcaac4060 Support constant part select writes to l-values, and large part select reads from signals. 2005-02-15 07:12:55 +00:00
steve 4051f7d986 Handle bitmux lvalues for constant r-values. 2005-02-14 05:00:11 +00:00
steve 02d0719529 l-value input may be a vector. 2005-02-14 04:58:50 +00:00
steve aaf35ab1a9 Handle bit selects in l-values to assignments. 2005-02-14 01:51:39 +00:00
steve c5e7e2ec0a Signals may receive part vectors from %set/x0
instructions. Re-implement the %set/x0 to do
 just that. Remove the useless %set/x0/x instruction.
2005-02-14 01:50:23 +00:00
steve ff067bb959 tri0 and tri1 resolvers must replace HiZ with 0/1 after resolution. 2005-02-13 05:26:30 +00:00
steve 1d7235b4f1 Replace supply nets with wires connected to pullup/down supply devices. 2005-02-13 01:15:07 +00:00
steve 97e0723bd1 Cleanup unused truth tables. 2005-02-12 23:05:25 +00:00
steve d4eb4d38bc Implement a-b muxes as vector devices 2005-02-12 22:54:29 +00:00
steve d00e3fc9a9 Check IVL_LPM_MUX configuration. 2005-02-12 22:53:41 +00:00
steve 9ec00e1288 Fix copyright notice. 2005-02-12 22:52:45 +00:00
steve 85d9ebded8 Implement the vvp_fun_muxz functor. 2005-02-12 22:50:52 +00:00
steve d74177634c Restructure NetMux devices to pass vectors.
Generate NetMux devices from ternary expressions,
 Reduce NetMux devices to bufif when appropriate.
2005-02-12 06:25:40 +00:00
steve eca4f4fa97 Draw C4 and C8 constants to account for strength. 2005-02-12 06:25:15 +00:00
steve 6b7b82758a Check nexus widths of IVL_LO_ nodes. 2005-02-12 06:17:43 +00:00
steve 355ead0002 Add debug dumps for vectors, and fix vvp_scaler_t make from BIT4_X values. 2005-02-12 06:13:22 +00:00
steve 4fce321900 Support C8 constants. 2005-02-12 03:27:18 +00:00
steve 2e6d2f8e98 Support scheduling vvp_vector8_t objects. 2005-02-12 03:26:14 +00:00
steve 55b5bf9d39 distinguish between single port namy instances, and single instances many sub-ports. 2005-02-10 04:56:58 +00:00
steve 1979fca239 Get the C4 width right for undriven nexa. 2005-02-10 04:55:45 +00:00
steve a0583ef124 Simplify vvp_scaler strength representation. 2005-02-10 04:54:41 +00:00
steve ee5bb5fcaf Add the NetRepeat node, and code generator support. 2005-02-08 00:12:36 +00:00
steve ca1bbc79a3 Add .repeat functor and BIFIF functors. 2005-02-07 22:42:42 +00:00
steve e74127e1fc Support .concat with arbitrary input counts. 2005-02-04 05:13:57 +00:00
steve b48abb2148 Add wide .arith/mult, and vvp_vector2_t vectors. 2005-02-04 05:13:02 +00:00
steve 97f83ffbe3 laborate reduction gates into LPM_RED_ nodes. 2005-02-03 04:56:20 +00:00
steve 018014368b Add support for reduction logic gates. 2005-02-03 04:55:13 +00:00
steve 20be0351ae Elaborate unary subtract and NOT in netlist
contexts, and concatenation too.
2005-01-30 05:20:38 +00:00
steve 68a788221e Support LPM_SUB 2005-01-30 05:09:04 +00:00
steve 84b3e8e2dc Get .arith/sub working. 2005-01-30 05:06:49 +00:00
steve e6cdd32c19 Clarify width argument to NetNet constructor. 2005-01-30 01:43:48 +00:00
steve c23a35a033 Debug messages for PGAssign elaboration. 2005-01-30 01:42:05 +00:00
steve 609b6a7baa Netlist boolean expressions generate gate vectors. 2005-01-29 18:46:18 +00:00
steve 0609c5f18c Use scheduler to initialize constant functor inputs. 2005-01-29 17:53:25 +00:00
steve d51503ffd8 move AND to buitin instead of table. 2005-01-29 17:52:06 +00:00
steve 7625a6c3e7 Check width of constant attached to nexus. 2005-01-29 16:47:52 +00:00
steve 695718d691 Clarify width of nexus. 2005-01-29 16:47:20 +00:00
steve e04fb5c083 Elaborate parameter reference to desired width without concats. 2005-01-29 16:46:22 +00:00
steve 07f64bc603 Support interactive mode even without readline. 2005-01-29 06:29:17 +00:00
steve bf3679b7d4 Add the -s flag to start up interactive. 2005-01-29 06:28:19 +00:00
steve ade5bdcafe Integrate pr1072 fix from v0_8-branch. 2005-01-29 00:37:06 +00:00
steve 7250337941 Integrate fixes from 0.8 branch. 2005-01-28 19:39:03 +00:00
steve 99ace10774 Simplified NetMult and IVL_LPM_MULT. 2005-01-28 05:39:33 +00:00
steve 6be34bba4d Special handling of constant shift 0. 2005-01-28 05:37:48 +00:00
steve a5b431ad20 Show the lpm_mult device. 2005-01-28 05:36:18 +00:00
steve a121e703f3 Add vector4 implementation of .arith/mult. 2005-01-28 05:34:25 +00:00
steve dfb7c7ba6f Remove the NetEBitSel and combine all bit/part select
behavior into the NetESelect node and IVL_EX_SELECT
 ivl_target expression type.
2005-01-24 05:28:30 +00:00
steve edeb9d8eca Part selects are done in the compiler, not here. 2005-01-24 05:08:02 +00:00
steve 14f557e6f4 Check widths of ternary expressions. 2005-01-24 05:05:25 +00:00
steve 25de448d34 Remove obsolete NetSubnet class. 2005-01-22 18:16:00 +00:00
steve cb4e0d4724 stub dump signed flags of magnitude compare. 2005-01-22 17:36:59 +00:00
steve 6a23f16860 .cmp/x supports signed magnitude compare. 2005-01-22 17:36:15 +00:00
steve a4710f375e LPM_CMP_NE/EQ are vectored devices. 2005-01-22 16:22:13 +00:00
steve 6c5e840617 Implement vectored CMP_EQ and NE 2005-01-22 16:21:11 +00:00
steve e28636776a Change case compare from logic to an LPM node. 2005-01-22 01:06:55 +00:00
steve b86fdd6bbc Implement the .cmp/eeq LPM node. 2005-01-22 01:06:20 +00:00
steve 1d1dda5a5d Implement the %load/x instruction. 2005-01-22 00:58:22 +00:00
steve 3222031970 Add missing concat.cc to cvs 2005-01-22 00:01:09 +00:00
steve bf6a5d0f50 Implement LPM_COMPARE nodes as two-input vector functors. 2005-01-16 04:20:32 +00:00
steve 1c3668ea7f Reimplement comparators as vvp_vector4_t nodes. 2005-01-16 04:19:08 +00:00
steve ead2481793 Fix elaboration of == compared to constants. 2005-01-13 00:23:10 +00:00
steve fcaaec0464 More robust input code generation for LPM_ADD. 2005-01-12 05:31:50 +00:00
steve 4d139b58aa Properly pad vector widths in pgassign. 2005-01-12 03:17:36 +00:00
steve 8c18c9152d More complete drawing of concat inputs. 2005-01-12 03:16:35 +00:00
steve 399dfe5c44 Handle concatenations with up to 16 inputs. 2005-01-10 01:42:59 +00:00
steve 9e94afe399 Use PartSelect/PV and VP to handle part selects through ports. 2005-01-09 20:16:00 +00:00
steve 6c711ee4d8 Merge $fopen robustness fix from 0.8 2005-01-09 20:12:22 +00:00
steve 9735b0e8b3 Add the .part/pv node and related functionality. 2005-01-09 20:11:15 +00:00
steve d5c33420ab vvp_fun_signal propagates vvp_vector8_t vectors when appropriate. 2005-01-01 02:12:34 +00:00
steve 34a14b983b Implement .resolv functors, and stub signals recv_vec8 method. 2004-12-31 06:00:06 +00:00
steve d1e2538aba No need to draw BUF or BUFZ tables. 2004-12-31 05:57:25 +00:00
steve 8bfc75d1ee Add specific BUFZ functor. 2004-12-31 05:56:36 +00:00
steve b1b93f860c Fix uninitialized fun pointer for resolver nodes. 2004-12-31 05:54:46 +00:00
steve 8f2d679c8a Unify elaboration of l-values for all proceedural assignments,
including assing, cassign and force.

 Generate NetConcat devices for gate outputs that feed into a
 vector results. Use this to hande gate arrays. Also let gate
 arrays handle vectors of gates when the outputs allow for it.
2004-12-29 23:55:43 +00:00
steve 83423c978b Generate code for the .concat functors, from NetConcat objects.
Generate C<> constants of correct widths for functor arguments.
2004-12-29 23:52:09 +00:00
steve 1674d692b7 Add the part concatenation node (.concat).
Add a vvp_event_anyedge class to handle the special
 case of .event statements of edge type. This also
 frees the posedge/negedge types to handle all 4 inputs.

 Implement table functor recv_vec4 method to receive
 and process vectors.
2004-12-29 23:45:13 +00:00
steve 7166598ed0 Fix missing output propagation of part node. 2004-12-29 23:44:39 +00:00
steve 5eb25e44e1 Add ivl_event_scope, and better document ivl_event_X methods. 2004-12-18 18:56:18 +00:00
steve 59566158c4 Better detail on event trigger and wait statements. 2004-12-18 18:55:08 +00:00
steve e11ac0b1d8 Use %set/v to trigger events. 2004-12-18 18:53:26 +00:00
steve 8939467ac5 Rework named events and event/or. 2004-12-18 18:52:44 +00:00
steve 26d97558c4 Replace single release with release/net and release/reg. 2004-12-17 04:47:47 +00:00
steve 59bac26f4f Implement release functionality. 2004-12-17 04:46:40 +00:00
steve 78dda42493 Add the force/v instruction. 2004-12-15 17:17:42 +00:00
steve 36f36bd2ac Add basic force/release capabilities. 2004-12-15 17:16:08 +00:00
steve 0193daa436 Display the release statement details. 2004-12-15 17:11:13 +00:00
steve 4444079409 Fixup force statement elaboration. 2004-12-15 17:10:40 +00:00
steve 3947d7dd33 Force r-value padded to width. 2004-12-15 17:09:11 +00:00
steve 7973dad9f5 Arrange statement dumping in new source files. 2004-12-12 18:15:06 +00:00
steve d19e76a193 Fix r-value width of continuous assign. 2004-12-12 18:13:39 +00:00
steve ffedf32476 cassign and deassign handle concatenated l-values. 2004-12-11 05:43:30 +00:00
steve 527ddea811 Add stub conf files to cvs. 2004-12-11 04:22:35 +00:00
steve 65e9b6be12 Rework of internals to carry vectors through nexus instead
of single bits. Make the ivl, tgt-vvp and vvp initial changes
 down this path.
2004-12-11 02:31:25 +00:00
232 changed files with 34538 additions and 17455 deletions
+6 -1
View File
@@ -19,11 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
#ident "$Id: LineInfo.h,v 1.8 2005/06/14 19:13:43 steve Exp $"
#endif
# include <string>
using namespace std;
/*
* This class holds line information for an internal object.
*
@@ -52,6 +54,9 @@ class LineInfo {
/*
* $Log: LineInfo.h,v $
* Revision 1.8 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
+16 -25
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.179 2006/10/30 22:45:36 steve Exp $"
#
#
SHELL = /bin/sh
@@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.8
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -60,15 +60,9 @@ CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
# The TARGETS variable lists the target modules that can be build and
# installed. Some of them depend on external things, so are only
# compiled if the prerequisites are installed.
TARGETS = tgt-null
all: dep ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in ivlpp tgt-verilog tgt-stub; \
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
@@ -90,36 +84,37 @@ check: all
clean:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
do (cd $$dir ; $(MAKE) $@); done
rm -f *.o parse.cc parse.cc.output parse.h lexor.cc
rm -f ivl.exp iverilog-vpi.pdf iverilog-vpi.ps parse.output
rm -f syn-rules.output dosify.exe
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
rm -rf dep ivl@EXEEXT@
distclean: clean
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h
rm -f _pli_types.h
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
elab_sig.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
net_proc.o net_scope.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
PExpr.o PGate.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -169,10 +164,8 @@ lexor.o: lexor.cc parse.h
parse.o: parse.cc
parse.cc: $(srcdir)/parse.y
parse.cc parse.h: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
parse.h: parse.cc
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
syn-rules.cc: $(srcdir)/syn-rules.y
@@ -209,9 +202,8 @@ endif
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
@@ -275,7 +267,6 @@ installdirs: mkinstalldirs
uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in xnf.conf xnf-s.conf ivl; \
+23 -43
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.h,v 1.37 2004/06/13 04:56:53 steve Exp $"
#ident "$Id: Module.h,v 1.41 2006/09/23 04:57:19 steve Exp $"
#endif
# include <list>
@@ -30,11 +30,12 @@
# include "named.h"
# include "LineInfo.h"
# include "netlist.h"
class PData;
class PEvent;
class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PSpecPath;
class PTask;
class PFunction;
class PWire;
@@ -108,15 +109,22 @@ class Module : public LineInfo {
/* Keep a table of named events declared in the module. */
map<perm_string,PEvent*>events;
/* Keep a table of datum variables declared in the module. */
map<hname_t,PData*>datum;
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
/* The module has a list of genvars that may be used in
various generate schemes. */
list<perm_string> genvars;
/* the module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
list<PSpecPath*> specify_paths;
perm_string mod_name() const { return name_; }
void add_gate(PGate*gate);
@@ -146,7 +154,8 @@ class Module : public LineInfo {
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
bool elaborate_scope(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
bool elaborate_sig(Design*, NetScope*scope) const;
@@ -167,45 +176,16 @@ class Module : public LineInfo {
/*
* $Log: Module.h,v $
* Revision 1.37 2004/06/13 04:56:53 steve
* Add support for the default_nettype directive.
* Revision 1.41 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.36 2004/05/25 19:21:06 steve
* More identifier lists use perm_strings.
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.35 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
* Revision 1.39 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
*
* Revision 1.34 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
* Revision 1.33 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.32 2003/06/20 00:53:19 steve
* Module attributes from the parser
* through to elaborated form.
*
* Revision 1.31 2003/06/13 19:10:45 steve
* Properly manage real variables in subscopes.
*
* Revision 1.30 2003/03/06 04:37:12 steve
* lex_strings.add module names earlier.
*
* Revision 1.29 2003/02/27 06:45:11 steve
* specparams as far as pform.
*
* Revision 1.28 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.27 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
* Revision 1.26 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.25 2002/05/19 23:37:28 steve
* Parse port_declaration_lists from the 2001 Standard.
* Revision 1.38 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*/
#endif
-63
View File
@@ -1,63 +0,0 @@
#ifndef __PData_H
#define __PData_H
/*
* Copyright (c) 2003 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
#endif
# include "HName.h"
# include "netlist.h"
# include "LineInfo.h"
/*
* The PData object represents declaration of atomic datum such as
* real and realtime variables. These are variables that cannot be bit
* or part selected, but can be used in expressions.
*/
class PData : public LineInfo {
public:
PData(const hname_t&hname);
~PData();
// Return a hierarchical name.
const hname_t&name() const;
void elaborate_scope(Design*des, NetScope*scope) const;
map<string,PExpr*> attributes;
private:
hname_t hname_;
private:
PData(const PData&);
PData& operator= (const PData&);
};
/*
* $Log: PData.h,v $
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
#endif
+52 -15
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PDelays.cc,v 1.11 2003/06/21 01:21:42 steve Exp $"
#ident "$Id: PDelays.cc,v 1.15 2006/07/08 21:48:46 steve Exp $"
#endif
# include "config.h"
@@ -62,11 +62,10 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
delete_flag_ = df;
}
static unsigned long calculate_val(Design*des, NetScope*scope,
const PExpr*expr)
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
{
NetExpr*dex = expr->elaborate_expr(des, scope);
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
if (NetExpr*tmp = dex->eval_tree()) {
delete dex;
dex = tmp;
@@ -85,7 +84,9 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
delay = 0;
delete tmp;
return delay;
NetEConst*tmp2 = new NetEConst(verinum(delay));
tmp2->set_line(*expr);
return tmp2;
}
@@ -96,35 +97,57 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
des->scale_to_precision(fn.as_ulong(), scope);
delete tmp;
return delay;
NetEConst*tmp2 = new NetEConst(verinum(delay));
tmp2->set_line(*expr);
return tmp2;
}
/* Oops, cannot evaluate down to a constant. Error message. */
delete dex;
/* Oops, cannot evaluate down to a constant. */
return dex;
}
cerr << expr->get_line() << ": sorry: non-constant "
<< "delays not supported here: " << *expr << endl;
des->errors += 1;
return 0;
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
{
if (dynamic_cast<NetESignal*> (expr))
return expr;
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des);
if (sig == 0) {
cerr << expr->get_line() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
return 0;
}
expr = new NetESignal(sig);
return expr;
}
void PDelays::eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag) const
{
assert(scope);
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, rise_time);
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, fall_time);
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, decay_time);
} else {
if (rise_time < fall_time)
@@ -146,6 +169,20 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
/*
* $Log: PDelays.cc,v $
* Revision 1.15 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.14 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.13 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.12 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.11 2003/06/21 01:21:42 steve
* Harmless fixup of warnings.
*
+12 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PDelays.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: PDelays.h,v 1.9 2006/01/03 05:22:14 steve Exp $"
#endif
# include "svector.h"
@@ -34,6 +34,7 @@ using namespace std;
class Design;
class NetScope;
class NetExpr;
class PExpr;
/*
@@ -53,9 +54,10 @@ class PDelays {
void set_delays(const svector<PExpr*>*del, bool delete_flag=true);
void eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag =false) const;
void dump_delays(ostream&out) const;
@@ -72,6 +74,12 @@ ostream& operator << (ostream&o, const PDelays&);
/*
* $Log: PDelays.h,v $
* Revision 1.9 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.8 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+37 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.cc,v 1.35 2004/10/04 01:10:51 steve Exp $"
#ident "$Id: PExpr.cc,v 1.38 2006/10/30 05:44:49 steve Exp $"
#endif
# include "config.h"
@@ -53,6 +53,14 @@ NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
return 0;
}
NetNet* PExpr::elaborate_bi_net(Design*des, NetScope*) const
{
cerr << get_line() << ": error: "
<< "expression not valid as argument to inout port: "
<< *this << endl;
return 0;
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r)
{
@@ -67,6 +75,24 @@ bool PEBinary::is_constant(Module*mod) const
return left_->is_constant(mod) && right_->is_constant(mod);
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBComp::~PEBComp()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms)
{
@@ -140,7 +166,7 @@ bool PEFNumber::is_constant(Module*) const
}
PEIdent::PEIdent(const hname_t&s)
: path_(s), msb_(0), lsb_(0), idx_(0)
: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0)
{
}
@@ -262,6 +288,15 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* Revision 1.38 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.37 2005/10/04 04:09:25 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.36 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.35 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
*
+347 -105
View File
@@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.66 2004/10/04 01:10:51 steve Exp $"
#ident "$Id: PExpr.h,v 1.87 2007/01/16 05:44:14 steve Exp $"
#endif
# include <string>
# include <vector>
# include "netlist.h"
# include "verinum.h"
# include "LineInfo.h"
@@ -50,11 +51,38 @@ class PExpr : public LineInfo {
virtual void dump(ostream&) const;
// Procedural elaboration of the expression. Set the
// bare_memory_ok flag if the result is allowed to be a
// NetEMemory without an index.
// This method tests the width that the expression wants to
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so it the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
// The "lval" is the width of the destination where this
// result is going to go. This can be used to constrain the
// amount that an expression can reasonably expand. For
// example, there is no point expanding an addition to beyond
// the lval. This extra bit of information allows the
// expression to optimize itself a bit. If the lval==0, then
// the subexpression should not make l-value related
// optimizations.
//
// The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment) or -1 if the expression is
// self-determinted. The sys_task_arg flag is true if
// expressions are allowed to be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
// Elaborate expressions that are the r-value of parameter
// assignments. This elaboration follows the restrictions of
@@ -66,30 +94,37 @@ class PExpr : public LineInfo {
// continuous assign or other wholly structural context.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0 =Link::STRONG,
Link::strength_t drive1 =Link::STRONG)
const;
// This method elaborates the expression as NetNet objects. It
// only allows regs suitable for procedural continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// This is similar to elaborate_lnet, except that the
// expression is evaluated to be bi-directional. This is
// useful for arguments to inout ports of module instances and
// ports of tran primitives.
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method.
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
// assignments can be elaborated with this method. If the
// is_force flag is true, then the set of valid l-value types
// is slightly modified to accomodate the Verilog force
// statement
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
// This attempts to evaluate a constant expression, and return
// a verinum as a result. If the expression cannot be
// evaluated, return 0.
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
// This method returns true if that expression is the same as
// this expression. This method is used for comparing
@@ -115,27 +150,31 @@ class PEConcat : public PExpr {
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
~PEConcat();
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
// Concatenated Regs can be on the left of procedural
// continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual bool is_constant(Module*) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
private:
svector<PExpr*>parms_;
PExpr*repeat_;
@@ -182,15 +221,23 @@ class PEFNumber : public PExpr {
/* The eval_const method as applied to a floating point number
gets the *integer* value of the number. This accounts for
any rounding that is needed to get the value. */
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual void dump(ostream&) const;
private:
@@ -204,28 +251,32 @@ class PEIdent : public PExpr {
~PEIdent();
virtual void dump(ostream&) const;
// Regs can be on the left of procedural continuous assignments
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
// Elaborate the PEIdent as a port to a module. This method
@@ -233,39 +284,92 @@ class PEIdent : public PExpr {
NetNet* elaborate_port(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, const NetScope*sc) const;
verinum* eval_const(const Design*des, NetScope*sc) const;
const hname_t& path() const;
private:
// Common functions to calculate parts of part/bit selects.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
private:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_up_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_do_(Design*, NetScope*, NetAssign_*) const;
private:
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_word_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_part_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
hname_t path_;
public:
// Use these to support bit- and part-select operators.
// Use these to support part-select operators.
PExpr*msb_;
PExpr*lsb_;
// If this is a reference to a memory, this is the index
// expression.
PExpr*idx_;
enum { SEL_NONE, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
NetMemory*mem, unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
// If this is a reference to a memory/array, this is the index
// expression. If this is a reference to a vector, this is a
// bit select.
std::vector<PExpr*> idx_;
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const;
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const;
};
@@ -278,19 +382,25 @@ class PENumber : public PExpr {
const verinum& value() const;
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
@@ -314,17 +424,22 @@ class PEString : public PExpr {
string value() const;
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* PEString::eval_const(const Design*, const NetScope*) const;
verinum* eval_const(const Design*, NetScope*) const;
virtual bool is_constant(Module*) const;
@@ -339,17 +454,18 @@ class PEUnary : public PExpr {
~PEUnary();
virtual void dump(ostream&out) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
@@ -367,65 +483,100 @@ class PEBinary : public PExpr {
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
private:
protected:
char op_;
PExpr*left_;
PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
};
/*
* Here are a few specilized classes for handling specific binary
* operators.
*/
class PEBComp : public PEBinary {
public:
explicit PEBComp(char op, PExpr*l, PExpr*r);
~PEBComp();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&flag) const;
NetEBinary* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
};
class PEBShift : public PEBinary {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
};
/*
@@ -441,17 +592,21 @@ class PETernary : public PExpr {
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
private:
PExpr*expr_;
@@ -471,15 +626,16 @@ class PECallFunction : public PExpr {
~PECallFunction();
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
bool sys_task_arg =false) const;
int expr_wid, bool sys_task_arg) const;
private:
hname_t path_;
@@ -488,10 +644,96 @@ class PECallFunction : public PExpr {
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
};
/*
* $Log: PExpr.h,v $
* Revision 1.87 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.86 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.85 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.84 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.83 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.82 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.81 2006/04/28 04:28:35 steve
* Allow concatenations as arguments to inout ports.
*
* Revision 1.80 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.79 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.78 2006/03/25 02:36:26 steve
* Get rid of excess PESTring:: prefix within class declaration.
*
* Revision 1.77 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.76 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.75 2005/12/07 04:04:23 steve
* Allow constant concat expressions.
*
* Revision 1.74 2005/11/27 17:01:56 steve
* Fix for stubborn compiler.
*
* Revision 1.73 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.72 2005/11/10 13:28:11 steve
* Reorganize signal part select handling, and add support for
* indexed part selects.
*
* Expand expression constant propagation to eliminate extra
* sums in certain cases.
*
* Revision 1.71 2005/10/04 04:09:25 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.70 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.69 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.68 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.66 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
*
+65 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.cc,v 1.16 2004/02/18 17:11:54 steve Exp $"
#ident "$Id: PGate.cc,v 1.18 2006/01/03 05:22:14 steve Exp $"
#endif
# include "config.h"
@@ -90,12 +90,69 @@ void PGate::elaborate_scope(Design*, NetScope*) const
* parameters. This method understands how to handle the different
* numbers of expressions.
*/
void PGate::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_expr,
NetExpr*&fall_expr,
NetExpr*&decay_expr,
bool as_net_flag) const
{
delay_.eval_delays(des, scope,
rise_expr, fall_expr, decay_expr,
as_net_flag);
}
void PGate::eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
{
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
NetExpr*rise_expr, *fall_expr, *decay_expr;
delay_.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
if (rise_expr == 0) {
rise_time = 0;
fall_time = 0;
decay_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (rise_expr)) {
rise_time = tmp->value().as_ulong();
} else {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
rise_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (fall_expr)) {
fall_time = tmp->value().as_ulong();
} else {
if (fall_expr != rise_expr) {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
}
des->errors += 1;
fall_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (decay_expr)) {
decay_time = tmp->value().as_ulong();
} else {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
decay_time = 0;
}
}
PGAssign::PGAssign(svector<PExpr*>*pins)
@@ -191,6 +248,12 @@ perm_string PGModule::get_type()
/*
* $Log: PGate.cc,v $
* Revision 1.18 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.17 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.16 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
+26 -5
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.h,v 1.29 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#endif
# include "svector.h"
@@ -66,11 +66,23 @@ class PGate : public LineInfo {
perm_string get_name() const { return name_; }
// This method evaluates the delays all the way to an
// integer. If the delay is non-constant, then set the times
// to 0, print an error message and mark an error to the
// design.
void eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
// This evaluates the delays as far as possible, but returns
// an expression, and do not signal errors.
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_net_flag =false) const;
unsigned pin_count() const { return pins_? pins_->count() : 0; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
@@ -82,7 +94,7 @@ class PGate : public LineInfo {
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -116,7 +128,7 @@ class PGAssign : public PGate {
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
~PGAssign();
void dump(ostream&out) const;
void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
private:
@@ -153,7 +165,7 @@ class PGBuiltin : public PGate {
Type type() const { return type_; }
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
private:
@@ -196,7 +208,7 @@ class PGModule : public PGate {
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -227,6 +239,15 @@ class PGModule : public PGate {
/*
* $Log: PGate.h,v $
* Revision 1.32 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.31 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.30 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2006 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.cc,v 1.1 2006/04/10 02:40:18 steve Exp $"
#endif
# include "PGenerate.h"
# include "PWire.h"
PGenerate::PGenerate(unsigned id)
: id_number(id)
{
}
PGenerate::~PGenerate()
{
}
PWire* PGenerate::add_wire(PWire*wire)
{
PWire*&ep = wires[wire->path()];
if (ep) return ep;
assert(ep == 0);
ep = wire;
return wire;
}
PWire* PGenerate::get_wire(const hname_t&name) const
{
map<hname_t,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
return (*obj).second;
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
+92
View File
@@ -0,0 +1,92 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.h,v 1.1 2006/04/10 02:40:18 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include <list>
# include <map>
class Design;
class NetScope;
class PExpr;
class PGate;
class PWire;
/*
* This represents a generate scheme.
*/
class PGenerate : public LineInfo {
public:
PGenerate(unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
// implicit.
const unsigned id_number;
perm_string scope_name;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT};
scheme_t scheme_type;
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
perm_string loop_index;
PExpr*loop_init;
PExpr*loop_test;
PExpr*loop_step;
map<hname_t,PWire*>wires;
PWire* add_wire(PWire*);
PWire* get_wire(const hname_t&name) const;
list<PGate*> gates;
void add_gate(PGate*);
// This method is called by the elaboration of a module to
// generate scopes. the container is the scope that is to
// contain the generated scope.
bool generate_scope(Design*des, NetScope*container);
bool elaborate_sig(Design*des) const;
bool elaborate(Design*des) const;
void dump(ostream&out) const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
// These are the scopes created by generate_scope.
list<NetScope*>scope_list_;
// internal function called on each scope generated by this scheme.
bool elaborate_sig_(Design*des, NetScope*scope) const;
bool elaborate_(Design*des, NetScope*scope) const;
private: // not implemented
PGenerate(const PGenerate&);
PGenerate& operator= (const PGenerate&);
};
#endif
+6 -24
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006 Stephen Williams <steve@icarus.com>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,34 +17,16 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.cc,v 1.2 2003/11/10 20:11:01 steve Exp $"
#ident "$Id: PSpec.cc,v 1.1 2006/09/26 19:48:40 steve Exp $"
#endif
# include "config.h"
# include "PData.h"
# include "PSpec.h"
PData::PData(const hname_t&h)
: hname_(h)
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
: src(src_cnt), dst(dst_cnt)
{
}
PData::~PData()
PSpecPath::~PSpecPath()
{
}
const hname_t&PData::name() const
{
return hname_;
}
/*
* $Log: PData.cc,v $
* Revision 1.2 2003/11/10 20:11:01 steve
* missing include of config.h
*
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
+48
View File
@@ -0,0 +1,48 @@
#ifndef __PSpec_H
#define __PSpec_H
/*
* Copyright (c) 2006 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.h,v 1.1 2006/09/23 04:57:19 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include <vector>
class PSpecPath : public LineInfo {
public:
PSpecPath(unsigned src_cnt, unsigned dst_cnt);
~PSpecPath();
void elaborate(class Design*des, class NetScope*scope) const;
void dump(std::ostream&out, unsigned ind) const;
public:
// Ordered set of source nodes of a path
std::vector<perm_string> src;
// Ordered set of destination nodes of a path
std::vector<perm_string> dst;
std::vector<class PExpr*>delays;
};
#endif
+36 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams ([email protected])
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,15 +17,19 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.cc,v 1.10 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: PWire.cc,v 1.12 2007/01/16 05:44:14 steve Exp $"
#endif
# include "config.h"
# include "PWire.h"
# include <assert.h>
PWire::PWire(const hname_t&n, NetNet::Type t, NetNet::PortType pt)
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
PWire::PWire(const hname_t&n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
@@ -35,8 +39,12 @@ lidx_(0), ridx_(0)
}
}
PWire::PWire(char*n, NetNet::Type t, NetNet::PortType pt)
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
PWire::PWire(char*n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
@@ -108,6 +116,19 @@ bool PWire::set_port_type(NetNet::PortType pt)
}
}
bool PWire::set_data_type(ivl_variable_type_t dt)
{
if (data_type_ != IVL_VT_NO_TYPE)
if (data_type_ != dt)
return false;
else
return true;
assert(data_type_ == IVL_VT_NO_TYPE);
data_type_ = dt;
return true;
}
void PWire::set_signed(bool flag)
{
signed_ = flag;
@@ -133,13 +154,21 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
{
assert(lidx_ == 0);
assert(ridx_ == 0);
assert(type_ == NetNet::REG);
lidx_ = ldx;
ridx_ = rdx;
}
/*
* $Log: PWire.cc,v $
* Revision 1.12 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.11 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.10 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+20 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.h,v 1.17 2004/02/20 18:53:33 steve Exp $"
#ident "$Id: PWire.h,v 1.19 2006/04/10 00:37:42 steve Exp $"
#endif
# include "netlist.h"
@@ -49,8 +49,14 @@ class Design;
class PWire : public LineInfo {
public:
PWire(const hname_t&hname, NetNet::Type t, NetNet::PortType pt);
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
PWire(const hname_t&hname,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
PWire(char*name,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
// Return a hierarchical name.
const hname_t&path() const;
@@ -65,6 +71,9 @@ class PWire : public LineInfo {
bool get_signed() const;
bool get_isint() const;
bool set_data_type(ivl_variable_type_t dt);
ivl_variable_type_t get_data_type() const;
void set_range(PExpr*msb, PExpr*lsb);
void set_memory_idx(PExpr*ldx, PExpr*rdx);
@@ -72,7 +81,7 @@ class PWire : public LineInfo {
map<perm_string,PExpr*> attributes;
// Write myself to the specified stream.
void dump(ostream&out) const;
void dump(ostream&out, unsigned ind=4) const;
void elaborate_sig(Design*, NetScope*scope) const;
@@ -80,6 +89,7 @@ class PWire : public LineInfo {
hname_t hname_;
NetNet::Type type_;
NetNet::PortType port_type_;
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
@@ -100,6 +110,12 @@ class PWire : public LineInfo {
/*
* $Log: PWire.h,v $
* Revision 1.19 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.18 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.17 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
+17 -51
View File
@@ -114,7 +114,7 @@ configure script that modify its behavior:
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
most out of your install, first make sure you have both 64bit and
32bit development libraries installed. Then configure with this
somewhat more compilcated command:
somewhat more complicated command:
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
@@ -359,7 +359,8 @@ constructs.
Icarus Verilog includes some features that are not part of the
IEEE1364 standard, but have well defined meaning, and also sometimes
gives nonstandard (but extended) meanings to some features of the
language that are defined.
language that are defined. See the "extensions.txt" documentation for
more details.
$is_signed(<expr>)
This system function returns 1 if the expression contained is
@@ -470,6 +471,20 @@ language that are defined.
combinational always blocks to be triggered when the values in
the sensitivity list are initialized by initial threads.
Nets with Types
Icarus Verilog support an extension syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that "logic" and "bool"
are new keywords. Typical syntax is:
wire real foo = 1.0;
reg logic bar, bat;
... and so forth. The syntax can be turned off by using the
-g2 flag to iverilog, and turned on explicitly with the -g2x
flag to iverilog.
6.0 CREDITS
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
@@ -479,52 +494,3 @@ Verilog guidance, and especially testing from many people. Testers in
particular include a larger community of people interested in a GPL
Verilog for Linux.
6.1 PORT MAINTAINERS
This is a list of people who have created ports and precompiled
packages for various operating systems. These folks have graciously
taken on the task of building Icarus Verilog on their systems and
bundled it into neat packages.(+) If you want to be added to the list (or
removed from the list) send e-mail to me.
FreeBSD/{Intel,alpha}
Ying-Chieh Liao <[email protected]>
Linux/{alpha,AMD64,Intel} (RPMS)
Stephen Williams <[email protected]>
Linux/* (.debs)
Hamish Moffatt <[email protected]>
Macintosh -- MacO/S
Yasuhisa Kato <[email protected]>
Mac O/S X
Timothy J. Wood <[email protected]>
NetBSD/*
Dan McMahill <[email protected]>
Solaris/SPARC packages (.pkg)
Dan McMahill <[email protected]>
Cygwin32/*
Venkat Iyer <[email protected]>
Mingw32
Venkat Iyer <[email protected]>
(+) These are not the only systems where Icarus Verilog has been run,
just the systems where precompiled binaries are publicly available.
6.2 TEST SUITE MANAGER
Steve Wilson <[email protected]> has taken on the large task of managing
the test suite. He has maintained the regression test scripts, the
driver list, received submissions from myself and others, and has
written a great many tests on his own. Any compiler writer, for any
language, will tell you that the test suite is at least as important
as the compiler code itself.
+12 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $"
#ident "$Id: Statement.h,v 1.42 2005/12/05 21:21:18 steve Exp $"
#endif
# include <string>
@@ -36,6 +36,7 @@ class Design;
class NetAssign_;
class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
/*
@@ -345,7 +346,7 @@ class PForce : public Statement {
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -393,6 +394,7 @@ class PNoop : public Statement {
public:
PNoop() { }
~PNoop() { }
};
class PRepeat : public Statement {
@@ -456,6 +458,14 @@ class PWhile : public Statement {
/*
* $Log: Statement.h,v $
* Revision 1.42 2005/12/05 21:21:18 steve
* Fixes for stubborn compilers.
*
* Revision 1.41 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
+6 -1
View File
@@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.5 2004/02/18 17:11:54 steve Exp $"
#ident "$Id: StringHeap.h,v 1.6 2005/06/14 19:13:43 steve Exp $"
#endif
# include "config.h"
# include <string>
using namespace std;
class perm_string {
public:
@@ -120,6 +122,9 @@ class StringHeapLex : private StringHeap {
/*
* $Log: StringHeap.h,v $
* Revision 1.6 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.5 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
+3 -3
View File
@@ -7,12 +7,12 @@
# to just run this script to autoconf wherever needed.
#
echo "Autoconf in root..."
autoconf
autoconf -f
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf --include=.. )
( cd ./$dir ; autoconf -f --include=.. )
done
echo "Precompiling lexor_keyword.gperf"
+4 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.11 2004/10/04 01:09:07 steve Exp $"
#ident "$Id: Makefile.in,v 1.12 2006/02/15 18:42:42 steve Exp $"
#
#
SHELL = /bin/sh
@@ -55,7 +55,7 @@ ifeq (@enable_vvp32@,yes)
vpidir32 = $(libdir)/ivl/@vpidir2@
ALL32 = all32
INSTALL32 = install32
UNINSTALL32 = uninistall32
UNINSTALL32 = uninstall32
include $(srcdir)/enable_vvp32.mk
endif
@@ -98,6 +98,8 @@ installdirs: ../mkinstalldirs
uninstall: $(UNINSTALL32)
rm -f $(vpidir)/cadpli.vpl
uninstall32:
ifeq (@enable_vvp32@,yes)
include $(srcdir)/enable_vvp32.mk
endif
+31 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.26 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: compiler.h,v 1.31 2006/09/28 04:35:18 steve Exp $"
#endif
# include <list>
@@ -84,6 +84,7 @@ extern bool verbose_flag;
extern bool debug_scopes;
extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
@@ -93,16 +94,27 @@ extern list<const char*>library_suff;
extern int build_library_index(const char*path, bool key_case_sensitive);
/* This is the generation of Verilog that the compiler is asked to
support. */
support. Then there are also more detailed controls for more
specific language features. */
enum generation_t {
GN_VER1995 = 1,
GN_VER2001 = 2,
GN_SYSVER30 = 3,
GN_VER2001X = 3,
GN_DEFAULT = 3
};
extern generation_t generation_flag;
extern bool gn_cadence_types_flag;
/* These functions test that specific features are enabled. */
inline bool gn_cadence_types_enabled()
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
/* If this flag is true, then elaborate specify blocks. If this flag
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
@@ -126,7 +138,7 @@ extern StringHeapLex lex_strings;
*/
struct sfunc_return_type {
const char* name;
NetExpr::TYPE type;
ivl_variable_type_t type;
unsigned wid;
int signed_flag;
};
@@ -136,6 +148,21 @@ extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* Revision 1.31 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.30 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.29 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.28 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.27 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.26 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+3 -2
View File
@@ -141,6 +141,7 @@ AC_SUBST(vpidir1)
AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2})
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli)
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+127 -189
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2003 Stephen Williams ([email protected])
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
#ident "$Id: cprop.cc,v 1.55 2006/05/24 04:32:57 steve Exp $"
#endif
# include "config.h"
@@ -55,86 +55,6 @@ void cprop_functor::signal(Design*des, NetNet*obj)
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
{
// For now, only additions are handled.
if (obj->attribute(perm_string::literal("LPM_Direction")) != verinum("ADD"))
return;
// If the low bit on the A side is 0, then eliminate it from
// the adder, and pass the B side directly to the
// result. Don't reduce the adder smaller then a 1-bit
// adder. These will be eliminated later.
while ((obj->width() > 1)
&& obj->pin_DataA(0).nexus()->drivers_constant()
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
NetAddSub*tmp = 0;
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// Now do the same thing on the B side.
while ((obj->width() > 1)
&& obj->pin_DataB(0).nexus()->drivers_constant()
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
NetAddSub*tmp = 0;
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataA(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// If the adder is only 1 bit wide, then replace it with the
// simple logic gate.
if (obj->width() == 1) {
NetLogic*tmp;
if (obj->pin_Cout().is_linked()) {
tmp = new NetLogic(obj->scope(),
obj->scope()->local_symbol(),
3, NetLogic::AND);
connect(tmp->pin(0), obj->pin_Cout());
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
des->add_node(tmp);
}
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
connect(tmp->pin(0), obj->pin_Result(0));
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
count += 1;
return;
}
}
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
@@ -153,6 +73,8 @@ void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
{
#if 0
/* XXXX Need to reimplement this code to account for vectors. */
NetScope*scope = obj->scope();
unsigned const_count = 0;
@@ -248,7 +170,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
with a simple XOR gate. */
if (top == 1) {
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
NetLogic::XNOR);
NetLogic::XNOR, 1);
connect(tmp->pin(0), obj->pin_AEB());
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
@@ -271,6 +193,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
delete obj;
des->add_node(tmp);
count += 1;
#endif
}
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
@@ -278,54 +201,15 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
// Look for and count unlinked FF outputs. Note that if the
// Data and Q pins are connected together, they can be removed
// from the circuit, since it doesn't do anything.
unsigned unlinked_count = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))
&& (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) {
obj->pin_Data(idx).unlink();
obj->pin_Q(idx).unlink();
}
if (! obj->pin_Q(idx).is_linked())
unlinked_count += 1;
}
// If the entire FF is unlinked, remove the whole thing.
if (unlinked_count == obj->width()) {
if (connected(obj->pin_Data(), obj->pin_Q())
&& (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) {
obj->pin_Data().unlink();
obj->pin_Q().unlink();
delete obj;
count += 1;
return;
}
// If some of the FFs are unconnected, make a new FF array
// that does not include the useless FF devices.
if (unlinked_count > 0) {
NetFF*tmp = new NetFF(obj->scope(), obj->name(),
obj->width()-unlinked_count);
connect(tmp->pin_Clock(), obj->pin_Clock());
connect(tmp->pin_Enable(), obj->pin_Enable());
connect(tmp->pin_Aload(), obj->pin_Aload());
connect(tmp->pin_Aset(), obj->pin_Aset());
connect(tmp->pin_Aclr(), obj->pin_Aclr());
connect(tmp->pin_Sload(), obj->pin_Sload());
connect(tmp->pin_Sset(), obj->pin_Sset());
connect(tmp->pin_Sclr(), obj->pin_Sclr());
unsigned tidx = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
if (obj->pin_Q(idx).is_linked()) {
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
tidx += 1;
}
assert(tidx == obj->width() - unlinked_count);
delete obj;
des->add_node(tmp);
count += 1;
return;
}
}
@@ -334,7 +218,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
NetScope*scope = obj->scope();
switch (obj->type()) {
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::NAND:
case NetLogic::AND: {
unsigned top = obj->pin_count();
@@ -449,12 +337,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::AND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
break;
case NetLogic::NAND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
break;
default:
assert(0);
@@ -480,7 +368,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@@ -497,7 +385,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
}
break;
}
#endif
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::NOR:
case NetLogic::OR: {
@@ -597,12 +490,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::OR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
break;
case NetLogic::NOR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
break;
default:
assert(0);
@@ -619,7 +512,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
delete obj;
count += 1;
return;
}
v }
/* Finally, this cleans up the gate by creating a
new [N]OR gate that has the right number of
@@ -627,7 +520,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@@ -644,7 +537,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
}
break;
}
#endif
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::XNOR:
case NetLogic::XOR: {
unsigned top = obj->pin_count();
@@ -766,11 +664,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@@ -795,11 +693,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@@ -821,7 +719,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
des->add_node(tmp);
tmp->pin(0).drive0(obj->pin(0).drive0());
tmp->pin(0).drive1(obj->pin(0).drive1());
@@ -834,12 +732,54 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
}
break;
}
#endif
default:
break;
}
}
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, type, obj->width());
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
wide. Connect the select directly to the enable. */
connect(obj->pin_Sel(), tmp->pin(2));
} else {
/* General case that the expression is arbitrarily
wide. Replicate the enable signal (which we
assume is 1 bit wide) to match the expression,
and connect the enable vector to the enable
input of the gate. */
NetReplicate*rtmp = new NetReplicate(scope,
scope->local_symbol(),
obj->width(),
obj->width());
des->add_node(rtmp);
connect(obj->pin_Sel(), rtmp->pin(1));
connect(tmp->pin(2), rtmp->pin(0));
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
rsig->local_flag(true);
rsig->data_type(IVL_VT_LOGIC);
connect(tmp->pin(2), rsig->pin(0));
}
delete obj;
}
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel
@@ -856,66 +796,36 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
NetMux with an array of BUFIF1 devices, with the enable
connected to the select input. */
bool flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
flag = false;
break;
}
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
flag = false;
break;
}
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
NetScope*scope = obj->scope();
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF1);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
}
replace_with_bufif(des, obj, NetLogic::BUFIF1);
count += 1;
delete obj;
return;
}
/* If instead the second input is all constant Vz, replace the
NetMux with an array of BUFIF0 devices. */
flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
flag = false;
break;
}
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
flag = false;
}
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
flag = false;
break;
}
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
NetScope*scope = obj->scope();
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF0);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
}
replace_with_bufif(des, obj, NetLogic::BUFIF0);
count += 1;
delete obj;
return;
}
}
@@ -1038,6 +948,34 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* Revision 1.55 2006/05/24 04:32:57 steve
* Fix handling of ternary-to-bufif0 constant propagation.
*
* Revision 1.54 2005/07/15 19:22:52 steve
* bufif enable is LOGIC.
*
* Revision 1.53 2005/05/15 04:44:30 steve
* Disable obsolete logic constant fixup code.
*
* Revision 1.52 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.51 2005/02/12 22:52:45 steve
* Fix copyright notice.
*
* Revision 1.50 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.49 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors.
*
* Revision 1.48 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings.
*
+302 -111
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: design_dump.cc,v 1.172 2007/01/16 05:44:14 steve Exp $"
#endif
# include "config.h"
@@ -29,7 +29,7 @@
# include <iostream>
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@@ -68,13 +68,55 @@ ostream& operator << (ostream&o, Link::strength_t str)
return o;
}
ostream& operator << (ostream&o, ivl_variable_type_t val)
{
switch (val) {
case IVL_VT_VOID:
o << "void";
break;
case IVL_VT_NO_TYPE:
o << "<no_type>";
break;
case IVL_VT_REAL:
o << "real";
break;
case IVL_VT_BOOL:
o << "bool";
break;
case IVL_VT_LOGIC:
o << "logic";
break;
}
return o;
}
void NetDelaySrc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "specify delay src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
<< "," << transition_delays_[IVL_PE_0z]
<< "/" << transition_delays_[IVL_PE_z1]
<< "," << transition_delays_[IVL_PE_1z]
<< "," << transition_delays_[IVL_PE_z0]
<< "/" << transition_delays_[IVL_PE_0x]
<< "," << transition_delays_[IVL_PE_x1]
<< "," << transition_delays_[IVL_PE_1x]
<< "/" << transition_delays_[IVL_PE_x0]
<< "," << transition_delays_[IVL_PE_xz]
<< "," << transition_delays_[IVL_PE_zx]
<< "): " << endl;
dump_node_pins(o, ind+4);
}
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name() << "[" <<
pin_count() << "]";
o << setw(ind) << "" << type() << ": " << name()
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " " << data_type_;
if (signed_)
o << " signed";
switch (port_type_) {
@@ -96,8 +138,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope()->name();
o << " #(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") init=";
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
<< " init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << pin(idx-1).get_init();
@@ -114,23 +158,15 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << setw(ind+4) << "" << "[" << idx << "]: " << nex
<< " " << nex->name() << endl;
}
for (unsigned idx = 0 ; idx < delay_paths_.size() ; idx += 1) {
const NetDelaySrc*cur = delay_paths_[idx];
cur->dump(o, ind+4);
}
dump_obj_attr(o, ind+4);
}
void NetSubnet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "** " << name() << " is a NetSubnet **"
<< endl;
NetNet::dump_net(o, ind);
}
void NetMemory::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
"[" << idxh_ << ":" << idxl_ << "]" << endl;
}
/* Dump a NetNode and its pins. Dump what I know about the netnode on
the first line, then list all the pins, with the name of the
connected signal. */
@@ -189,16 +225,20 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
void NetAddSub::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCAssign::dump_node(ostream&o, unsigned ind) const
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
<< name() << endl;
o << setw(ind) << "" << "NetArrayDq: " << name()
<< " array=" << mem_->name()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
@@ -216,6 +256,16 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetConcat::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetConcat: "
<< name()
<< " scope=" << (scope()? scope()->name() : "")
<< " width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetDivide::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
@@ -223,12 +273,6 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetForce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << endl;
dump_node_pins(o, ind+4);
}
void NetMult::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
@@ -239,6 +283,7 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
void NetMux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
<< " scope=" << scope()->name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -249,20 +294,24 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ")" << endl;
decay_time() << ") width=" << width() << endl;
dump_node_pins(o, ind+4);
}
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "case compare === : " << name() << endl;
if (eeq_)
o << setw(ind) << "" << "case compare === : " << name() << endl;
else
o << setw(ind) << "" << "case compare !== : " << name() << endl;
dump_node_pins(o, ind+4);
}
void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant ";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << value_[idx-1];
o << ": " << name() << endl;
dump_node_pins(o, ind+4);
@@ -278,6 +327,13 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
<< ": " << name() << endl;
dump_node_pins(o, ind+4);
}
void NetLogic::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "logic: ";
@@ -353,10 +409,81 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetRamDq::dump_node(ostream&o, unsigned ind) const
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
<< name() << endl;
const char*pt = "";
switch (dir_) {
case VP:
pt = "VP";
break;
case PV:
pt = "PV";
break;
case BI:
pt = "BI";
break;
}
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetReplicate::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetReplicate: "
<< name() << " wid=" << width_ << ", repeat_=" << repeat_
<< ", input wid=" << width_/repeat_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: "
<< name() << " output width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUReduce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "reduction logic: ";
switch (type_) {
case NONE:
o << "NONE";
break;
case AND:
o << "and";
break;
case OR:
o << "or";
break;
case XOR:
o << "xor";
break;
case NAND:
o << "nand";
break;
case NOR:
o << "nor";
break;
case XNOR:
o << "xnor";
break;
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name << "(...)" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -433,22 +560,12 @@ void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
o << sig_->name();
if (bmux_) {
o << "[" << *bmux_ << "]";
} else {
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
if (word_) {
o << "[word=" << *word_ << "]";
}
if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
}
} else if (mem_) {
// Is there an obvious way to flag memories in the dump
// as different from the _real_ bit mux case?
// o << "**memory**";
o << mem_->name() << "[";
if (bmux_) o << *bmux_;
else o << "**oops**";
o << "]";
} else if (var_) {
o << "<real " << var_->basename() << ">";
} else {
o << "";
}
@@ -474,10 +591,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const
dump_lval(o);
o << " = ";
#if 0
if (l_val(0)->rise_time())
o << "#" << l_val(0)->rise_time() << " ";
#endif
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
o << *rval() << ";" << endl;
}
@@ -487,10 +604,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
dump_lval(o);
o << " <= ";
#if 0
if (l_val(0)->rise_time())
o << "#" << l_val(0)->rise_time() << " ";
#endif
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
o << *rval() << ";" << endl;
}
@@ -557,8 +674,9 @@ void NetCase::dump(ostream&o, unsigned ind) const
void NetCAssign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
<< name() << ";" << endl;
o << setw(ind) << "" << "cassign ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
}
void NetCondit::dump(ostream&o, unsigned ind) const
@@ -578,8 +696,9 @@ void NetCondit::dump(ostream&o, unsigned ind) const
void NetDeassign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
<< "/* " << get_line() << " */" << endl;
o << setw(ind) << "" << "deassign ";
dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
}
void NetDisable::dump(ostream&o, unsigned ind) const
@@ -632,8 +751,9 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << " = "
<< name() << ";" << endl;
o << setw(ind) << "" << "force ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
}
void NetForever::dump(ostream&o, unsigned ind) const
@@ -648,10 +768,6 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
if (result_sig_)
o << setw(ind+2) << "" << "Return signal: "
<< result_sig_->name() << endl;
if (result_var_)
o << setw(ind+2) << "" << "Return variable: "
<< result_var_->basename() << endl;
if (statement_)
statement_->dump(o, ind+2);
else
@@ -677,12 +793,9 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
void NetRelease::dump(ostream&o, unsigned ind) const
{
if (lval_)
o << setw(ind) << "" << "release " << lval_->name() << "; "
<< "/* " << get_line() << " */" << endl;
else
o << setw(ind) << "" << "release (null); "
<< "/* " << get_line() << " */" << endl;
o << setw(ind) << "" << "release ";
dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
}
void NetRepeat::dump(ostream&o, unsigned ind) const
@@ -712,6 +825,9 @@ void NetScope::dump(ostream&o) const
case TASK:
o << " task";
break;
case GENBLOCK:
o << " generate block";
break;
}
o << endl;
@@ -757,11 +873,6 @@ void NetScope::dump(ostream&o) const
}
}
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
o << " real " << cur->basename() << " // "
<< cur->get_line() << endl;
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
@@ -777,13 +888,25 @@ void NetScope::dump(ostream&o) const
} while (cur != signals_->sig_next_);
}
// Dump the memories,
if (memories_) {
NetMemory*cur = memories_->snext_;
do {
cur->dump(o, 4);
cur = cur->snext_;
} while (cur != memories_->snext_);
// Dump specparams
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; cur ++ ) {
o << " specparam " << (*cur).first
<< " = ";
spec_val_t value = (*cur).second;
switch (value.type) {
case IVL_VT_REAL:
o << "R:" << value.real_val;
break;
case IVL_VT_BOOL:
o << "I:" << value.integer;
break;
default:
o << "<bad type>";
break;
}
o << endl;
}
switch (type_) {
@@ -887,6 +1010,9 @@ void NetEBinary::dump(ostream&o) const
case 'O':
o << "~|";
break;
case 'p':
o << "**";
break;
case 'r':
o << ">>";
break;
@@ -937,7 +1063,7 @@ void NetEConstParam::dump(ostream&o) const
{
o << "<" << name_ << "=";
NetEConst::dump(o);
o << ">";
o << ", wid=" << expr_width() << ">";
}
void NetECReal::dump(ostream&o) const
@@ -995,30 +1121,19 @@ void NetESignal::dump(ostream&o) const
{
if (has_sign())
o << "+";
o << name() << "[" << msi_<<":"<<lsi_ << "]";
}
void NetEBitSel::dump(ostream&o) const
{
sig_->dump(o);
o << "[";
idx_->dump(o);
o << "]";
}
void NetEMemory::dump(ostream&o) const
{
o << mem_->name() << "[";
if (idx_) idx_->dump(o);
o << "]";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << "[" << msi()<<":"<<lsi() << "]";
}
void NetEParam::dump(ostream&o) const
{
if (scope_ != 0)
o << "<" << scope_->name() << "." << name_ << ">";
else
else if (name_)
o << "<" << name_ << ">";
else
o << "<" "???" ">";
}
void NetETernary::dump(ostream&o) const
@@ -1055,11 +1170,6 @@ void NetEUnary::dump(ostream&o) const
o << ")";
}
void NetEVariable::dump(ostream&o) const
{
o << var_->basename();
}
void Design::dump(ostream&o) const
{
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
@@ -1089,6 +1199,87 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.172 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.171 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.170 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
* Revision 1.169 2006/09/26 19:48:40 steve
* Missing PSpec.cc file.
*
* Revision 1.168 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.167 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.166 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.165 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.164 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.163 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
* Revision 1.162 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.161 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.160 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.159 2005/05/17 20:56:55 steve
* Parameters cannot have their width changed.
*
* Revision 1.158 2005/05/07 03:13:30 steve
* Include delay expressions for assignments in dump.
*
* Revision 1.157 2005/03/09 05:52:03 steve
* Handle case inequality in netlists.
*
* Revision 1.156 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.155 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.154 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.153 2005/01/22 18:16:00 steve
* Remove obsolete NetSubnet class.
*
* Revision 1.152 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.151 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.150 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.149 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+8
View File
@@ -277,6 +277,7 @@ static int parse(int argc, char *argv[])
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_cpp_ext[] = ".cpp";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
@@ -301,6 +302,13 @@ static int parse(int argc, char *argv[])
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
}
else if (endsIn(dot_cpp_ext,argv[idx])) { /* check for C++ source files */
++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]);
append(&gstr.pCXSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cpp_ext));
}
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.25 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ all: iverilog@EXEEXT@
clean:
rm -f *.o lexor.c parse.c parse.h parse.output
rm -f cflexor.c cfparse.c cfparse.h cfparse.output
rm -f iverilog@EXEEXT@
rm -f iverilog@EXEEXT@ iverilog.pdf iverilog.ps
distclean: clean
rm -f Makefile
+41 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cflexor.lex,v 1.8 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: cflexor.lex,v 1.9 2006/11/30 06:00:28 steve Exp $"
#endif
# include "cfparse.h"
@@ -37,12 +37,14 @@
YYLTYPE yylloc;
static int comment_enter;
static char* trim_trailing_white(char*txt, int trim);
%}
%x CCOMMENT
%x LCOMMENT
%x PLUS_ARGS
%x FILE_NAME
%%
@@ -112,17 +114,50 @@ static int comment_enter;
/* This rule matches paths and strings that may be file names. This
is a little bit tricky, as we don't want to mistake a comment for
a string word. */
"/"[^\*\/].* { cflval.text = strdup(yytext);
return TOK_STRING; }
[^/\n \t\b\r+-].* { cflval.text = strdup(yytext);
return TOK_STRING; }
"/"[\r\n] { /* Special case of file name "/" */
cflval.text = trim_trailing_white(yytext, 0);
return TOK_STRING; }
"/"[^\*\/] { /* A file name that starts with "/". */
yymore();
BEGIN(FILE_NAME); }
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other then "/" */
yymore();
BEGIN(FILE_NAME); }
<FILE_NAME>"//" {
/* Found a trailing comment. Returning the terminated name. */
cflval.text = trim_trailing_white(yytext, 2);
BEGIN(LCOMMENT);
return TOK_STRING; }
<FILE_NAME>"/"?[^/\n\r]* {
yymore();
/* not a comment... continuing */; }
<FILE_NAME>[\n\r] {
/* No trailing comment. Return the file name. */
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
%%
static char* trim_trailing_white(char*text, int trim)
{
char*cp = text + strlen(text);
while (cp > text && trim > 0) {
trim -= 1;
cp -= 1;
*cp = 0;
}
while (cp > text && strchr("\n\r\t\b", cp[-1]))
cp -= 1;
cp[0] = 0;
return strdup(text);
}
int yywrap()
{
return 1;
+19 -4
View File
@@ -1,10 +1,10 @@
.TH iverilog 1 "$Date: 2004/10/04 01:10:56 $" Version "$Date: 2004/10/04 01:10:56 $"
.TH iverilog 1 "$Date: 2006/09/28 04:35:18 $" Version "$Date: 2006/09/28 04:35:18 $"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g3.0] [-Dmacro[=defn]] [-pflag=value]
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x|-gspecify-gxtypes] [-Dmacro[=defn]] [-pflag=value]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
@@ -48,15 +48,30 @@ is the Verilog input, but with file inclusions and macro references
expanded and removed. This is useful, for example, to preprocess
Verilog source for use by other compilers.
.TP 8
.B -g1\fI|\fP-g2\fI|\fP-g3.0
.B -g1\fI|\fP-g2\fI|\fP-g2x
Select the Verilog language \fIgeneration\fP to support in the
compiler. This selects between \fIIEEE1364-1995\fP(1),
\fIIEEE1364-2001\fP(2), or \fISystemVerilog 3.0\fP(3.0). Normally,
\fIIEEE1364-2001\fP(2), or \fIVerilog with extension\fP(2x). Normally,
Icarus Verilog defaults to the latest known generation of the
language. This flag is most useful to restrict the language to a set
supported by tools of specific generations, for compatibility with
other tools.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable (default) or disable specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
parsed but ignored. Specify blocks are commonly not needed for RTL
simulation, and in fact can hurt performance of the
simulation. However, disabling specify blocks reduces acuracy of
full-timing simulations.
.TP 8
.B -gxtypes\fI|\fP-gno-xtypes
Enable (default) or disable support for extended types. Enabling
extended types allows for new types that are supported by Icarus
Verilog as extensions beyond the baseline verilog. It may be necessary
to disable extended types if compiling code that clashes with the few
new keywords used to implement the type system.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched
for Verilog include files. The \fB-I\fP switch may be used many times
+84 -58
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2001 Stephen Williams ([email protected])
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.65 2004/06/17 14:47:22 steve Exp $"
#ident "$Id: main.c,v 1.72 2006/10/02 18:15:47 steve Exp $"
#endif
# include "config.h"
@@ -39,7 +39,7 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g3.0]\n"
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g2x]\n"
" [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]\n"
" [-N file] [-o filename] [-p flag=value]\n"
" [-s topmodule] [-t target] [-T min|typ|max]\n"
@@ -107,12 +107,12 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "3.0";
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
char warning_flags[16] = "";
char*inc_list = 0;
char*def_list = 0;
char*mod_list = 0;
char*command_filename = 0;
@@ -123,6 +123,9 @@ char*source_path = 0;
FILE*source_file = 0;
unsigned source_count = 0;
char*defines_path = 0;
FILE*defines_file = 0;
char*iconfig_path = 0;
FILE*iconfig_file = 0;
@@ -268,9 +271,12 @@ static int t_default(char*cmd, unsigned ncmd)
rc = system(cmd);
remove(source_path);
if ( ! getenv("IVERILOG_ICONFIG"))
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(source_path);
remove(iconfig_path);
remove(defines_path);
}
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
@@ -340,32 +346,12 @@ void process_library2_switch(const char *name)
void process_include_dir(const char *name)
{
if (inc_list == 0) {
inc_list = malloc(strlen(" -I")+strlen(name)+1);
strcpy(inc_list, " -I");
strcat(inc_list, name);
} else {
inc_list = realloc(inc_list, strlen(inc_list)
+ strlen(" -I")
+ strlen(name) + 1);
strcat(inc_list, " -I");
strcat(inc_list, name);
}
fprintf(defines_file, "I:%s\n", name);
}
void process_define(const char*name)
{
if (def_list == 0) {
def_list = malloc(strlen(" -D")+strlen(name)+1);
strcpy(def_list, " -D");
strcat(def_list, name);
} else {
def_list = realloc(def_list, strlen(def_list)
+ strlen(" -D")
+ strlen(name) + 1);
strcat(def_list, " -D");
strcat(def_list, name);
}
fprintf(defines_file,"D:%s\n", name);
}
/*
@@ -393,8 +379,20 @@ int process_generation(const char*name)
else if (strcmp(name,"2") == 0)
generation = "2";
else if (strcmp(name,"3.0") == 0)
generation = "3.0";
else if (strcmp(name,"2x") == 0)
generation = "2x";
else if (strcmp(name,"xtypes") == 0)
gen_xtypes = "xtypes";
else if (strcmp(name,"no-xtypes") == 0)
gen_xtypes = "no-xtypes";
else if (strcmp(name,"specify") == 0)
gen_specify = "specify";
else if (strcmp(name,"no-specify") == 0)
gen_specify = "no-specify";
else {
fprintf(stderr, "Unknown/Unsupported Language generation "
@@ -402,7 +400,10 @@ int process_generation(const char*name)
fprintf(stderr, "Supported generations are:\n");
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
" 3.0 -- SystemVerilog 3.0\n");
" 2x -- Verilog with extensions\n"
"Other generation flags:\n"
" specify | no-specify\n"
" xtypes | no-xtypes\n");
return 1;
}
@@ -465,6 +466,19 @@ int main(int argc, char **argv)
return 1;
}
defines_path = strdup(my_tempfile("ivrlg2", &defines_file));
if (NULL == defines_file) {
fprintf(stderr, "%s: Error opening temporary file %s\n",
argv[0], defines_path);
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
return 1;
}
fprintf(defines_file, "D:__ICARUS__=1\n");
/* Create another temporary file for passing configuration
information to ivl. */
@@ -485,6 +499,9 @@ int main(int argc, char **argv)
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
fclose(defines_file);
remove(defines_path);
return 1;
}
@@ -616,6 +633,8 @@ int main(int argc, char **argv)
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
fprintf(iconfig_file, "generation:%s\n", generation);
fprintf(iconfig_file, "generation:%s\n", gen_specify);
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
@@ -638,6 +657,10 @@ int main(int argc, char **argv)
}
}
if (depfile) {
fprintf(defines_file, "M:%s\n", depfile);
}
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
@@ -647,6 +670,9 @@ int main(int argc, char **argv)
fclose(source_file);
source_file = 0;
fclose(defines_file);
defines_file = 0;
if (source_count == 0) {
fprintf(stderr, "%s: No input files.\n", argv[0]);
fprintf(stderr, "%s\n", HELP);
@@ -656,33 +682,14 @@ int main(int argc, char **argv)
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", pbase,sep,
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", source_path);
e_flag?"":" -L", defines_path, source_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
if (inc_list) {
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
strcat(cmd, inc_list);
ncmd += strlen(inc_list);
}
if (def_list) {
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
strcat(cmd, def_list);
ncmd += strlen(def_list);
}
if (depfile) {
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
strcat(cmd, " -M ");
strcat(cmd, depfile);
ncmd += strlen(depfile) + 4;
}
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
@@ -720,10 +727,8 @@ int main(int argc, char **argv)
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
pbase, sep,
inc_list? inc_list : "",
def_list? def_list : "");
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F%s\n",
pbase, sep, defines_path);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
@@ -735,6 +740,27 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.72 2006/10/02 18:15:47 steve
* Fix handling of dep path in new argument passing method.
*
* Revision 1.71 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.70 2006/09/20 22:30:52 steve
* Do not pass -D__ICARUS__ to ivlpp.
*
* Revision 1.69 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.68 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
*
* Revision 1.67 2005/07/14 23:38:44 steve
* Display as version 0.9.devel
*
* Revision 1.66 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.65 2004/06/17 14:47:22 steve
* Add a .sft file for the system functions.
*
+16 -14
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.18 2004/06/17 16:06:18 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
#endif
# include "config.h"
@@ -67,7 +67,8 @@ NetEScope* NetEScope::dup_expr() const
NetESelect* NetESelect::dup_expr() const
{
return new NetESelect(expr_->dup_expr(), base_->dup_expr(),
return new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width());
}
@@ -87,7 +88,7 @@ NetESFunc* NetESFunc::dup_expr() const
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
NetESignal*tmp = new NetESignal(net_);
assert(tmp);
tmp->expr_width(expr_width());
return tmp;
@@ -111,11 +112,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = 0;
if (result_sig_)
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
if (result_var_)
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
assert(tmp);
return tmp;
@@ -135,14 +132,19 @@ NetEUReduce* NetEUReduce::dup_expr() const
return tmp;
}
NetEVariable* NetEVariable::dup_expr() const
{
NetEVariable*tmp = new NetEVariable(var_);
return tmp;
}
/*
* $Log: dup_expr.cc,v $
* Revision 1.21 2006/11/04 06:10:13 steve
* Handle dup of pad as well as normal select.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration.
*
+11 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_anet.cc,v 1.10 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elab_anet.cc,v 1.12 2006/05/01 20:47:58 steve Exp $"
#endif
# include "config.h"
@@ -89,10 +89,13 @@ NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT_REG, pins);
/* Assume that all the data types are the same. */
osig->data_type(nets[0]->data_type());
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
assert(cur->data_type() == osig->data_type());
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
@@ -109,11 +112,10 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
NetNet* sig = 0;
NetMemory* mem = 0;
NetVariable* var = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, sig, mem, var, par, eve);
symbol_search(des, scope, path_, sig, mem, par, eve);
if (mem != 0) {
@@ -167,6 +169,12 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
/*
* $Log: elab_anet.cc,v $
* Revision 1.12 2006/05/01 20:47:58 steve
* More explicit datatype setup.
*
* Revision 1.11 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.10 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+1046 -357
View File
File diff suppressed because it is too large Load Diff
+234 -185
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams ([email protected])
* Copyright (c) 2000-2006 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.38 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -25,7 +25,7 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <iostream>
/*
@@ -66,7 +66,9 @@
* is to try to make a net elaboration, and see if the result is
* suitable for assignment.
*/
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PExpr::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
{
NetNet*ll = 0;
if (ll == 0) {
@@ -92,7 +94,9 @@ NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
* NetAssign_ object.
*/
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PEConcat::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
{
if (repeat_) {
cerr << get_line() << ": error: Repeat concatenations make "
@@ -112,7 +116,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
continue;
}
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
/* If the l-value doesn't elaborate, the error was
already detected and printed. We just skip it and let
@@ -140,25 +144,15 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
* Handle the ident as an l-value. This includes bit and part selects
* of that ident.
*/
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PEIdent::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
{
NetNet* reg = 0;
NetMemory* mem = 0;
NetVariable* var = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, reg, mem, var, par, eve);
if (mem) {
return elaborate_mem_lval_(des, scope, mem);
}
if (var) {
NetAssign_*cur = new NetAssign_(var);
return cur;
}
symbol_search(des, scope, path_, reg, par, eve);
if (reg == 0) {
cerr << get_line() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope->name() <<
@@ -170,9 +164,31 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
assert(reg);
if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
if (sel_ == SEL_PART) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_part_(des, scope, lv);
return lv;
}
if (sel_ == SEL_IDX_UP) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_up_(des, scope, lv);
return lv;
}
if (sel_ == SEL_IDX_DO) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_do_(des, scope, lv);
return lv;
}
/* Get the signal referenced by the identifier, and make sure
it is a register. (Wires are not allows in this context. */
if (reg->type() != NetNet::REG) {
it is a register. Wires are not allows in this context,
unless this is the l-value of a force. */
if ((reg->type() != NetNet::REG) && !is_force) {
cerr << get_line() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope->name() <<
"." << endl;
@@ -182,50 +198,22 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
return 0;
}
assert(msb_ == 0);
assert(lsb_ == 0);
long msb, lsb;
NetExpr*mux;
if (msb_ && lsb_) {
/* This handles part selects. In this case, there are
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
verinum*vl = lsb_->eval_const(des, scope);
if (vl == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum*vm = msb_->eval_const(des, scope);
if (vm == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
msb = vm->as_long();
lsb = vl->as_long();
mux = 0;
} else if (msb_) {
if (! idx_.empty()) {
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
assert(lsb_ == 0);
verinum*v = msb_->eval_const(des, scope);
assert(idx_.size() == 1);
verinum*v = idx_[0]->eval_const(des, scope);
if (v == 0) {
NetExpr*m = msb_->elaborate_expr(des, scope);
NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false);
assert(m);
msb = 0;
lsb = 0;
@@ -243,8 +231,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
/* No select expressions, so presume a part select the
width of the register. */
assert(msb_ == 0);
assert(lsb_ == 0);
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
@@ -259,7 +245,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
bmux to select the target bit. */
lv = new NetAssign_(reg);
lv->set_bmux(mux);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
lv = new NetAssign_(reg);
} else {
@@ -283,7 +281,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->pin_count()) {
if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
@@ -292,57 +290,157 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
}
lv = new NetAssign_(reg);
lv->set_part(loff, wid);
assert(moff < reg->pin_count());
lv->set_part(new NetEConst(verinum(loff)), wid);
}
return lv;
}
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope,
NetNet*reg) const
{
if (msb_ == 0) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
des->errors += 1;
return 0;
}
assert(idx_.size() == 1);
if (msb_ && lsb_) {
cerr << get_line() << ": error: Cannot use part select on "
<< "memory \"" << mem->name() << ".\"" << endl;
des->errors += 1;
return 0;
}
NetExpr*word = elab_and_eval(des, scope, idx_[0], -1);
assert(msb_ && !lsb_);
// If there is a non-zero base to the memory, then build an
// expression to calculate the canonical address.
if (long base = reg->array_first()) {
NetExpr*ix = msb_->elaborate_expr(des, scope);
if (ix == 0)
return 0;
/* Evaluate the memory index expression down as must as
possible. Ideally, we can get it down to a constant. */
if (! dynamic_cast<NetEConst*>(ix)) {
NetExpr*tmp = ix->eval_tree();
if (tmp) {
tmp->set_line(*ix);
delete ix;
ix = tmp;
word = make_add_expr(word, 0-base);
if (NetExpr*tmp = word->eval_tree()) {
word = tmp;
}
}
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
lv->set_part(0, mem->width());
NetAssign_*lv = new NetAssign_(reg);
lv->set_word(word);
if (debug_elaborate)
cerr << get_line() << ": debug: Set array word=" << *word << endl;
/* An array word may also have part selects applied to them. */
if (sel_ == SEL_PART)
elaborate_lval_net_part_(des, scope, lv);
if (sel_ == SEL_IDX_UP)
elaborate_lval_net_idx_up_(des, scope, lv);
if (sel_ == SEL_IDX_DO)
elaborate_lval_net_idx_do_(des, scope, lv);
return lv;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
return false;
NetNet*reg = lv->sig();
assert(reg);
if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_line() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return false;
}
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
}
return true;
}
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
NetNet*reg = lv->sig();
assert(reg);
if (reg->type() != NetNet::REG) {
cerr << get_line() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope->name() <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
des->errors += 1;
return false;
}
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
base = make_sub_expr(reg->lsb(), base);
else if (reg->lsb() != 0)
base = make_add_expr(base, - reg->lsb());
if (debug_elaborate)
cerr << get_line() << ": debug: Set part select width="
<< wid << ", base=" << *base << endl;
lv->set_part(base, wid);
return true;
}
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
cerr << get_line() << ": internal error: don't know how to "
"deal with SEL_IDX_DO in lval?" << endl;
des->errors += 1;
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
{
cerr << get_line() << ": error: Constant values not allowed "
<< "in l-value expressions." << endl;
@@ -352,6 +450,47 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.38 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.37 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.36 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.35 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.34 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.33 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.32 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.31 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.30 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
@@ -360,95 +499,5 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
*
* Revision 1.27 2003/09/19 03:30:05 steve
* Fix name search in elab_lval.
*
* Revision 1.26 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.25 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.24 2003/01/19 00:35:39 steve
* Detect null arguments to concatenation operator.
*
* Revision 1.23 2002/11/21 23:27:51 steve
* Precalculate indices to l-value arrays.
*
* Revision 1.22 2002/11/21 18:15:40 steve
* Fix const test of msb in assignment l-values.
*
* Revision 1.21 2002/11/02 01:10:49 steve
* Detect memories without work index in l-value.
*
* Revision 1.20 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.19 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.18 2002/03/09 04:02:26 steve
* Constant expressions are not l-values for task ports.
*
* Revision 1.17 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.16 2001/11/08 05:15:50 steve
* Remove string paths from PExpr elaboration.
*
* Revision 1.15 2001/11/07 04:01:59 steve
* eval_const uses scope instead of a string path.
*
* Revision 1.14 2001/08/25 23:50:02 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.13 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.12 2001/02/09 03:16:48 steve
* Report bit/part select out of range errors. (PR#133)
*
* Revision 1.11 2001/01/10 03:13:23 steve
* Build task outputs as lval instead of nets. (PR#98)
*
* Revision 1.10 2001/01/06 06:31:58 steve
* declaration initialization for time variables.
*
* Revision 1.9 2001/01/06 02:29:36 steve
* Support arrays of integers.
*
* Revision 1.8 2000/12/12 06:14:51 steve
* sorry for concatenated memories in l-values. (PR#76)
*
* Revision 1.7 2000/12/01 02:55:37 steve
* Detect part select errors on l-values.
*
* Revision 1.6 2000/10/31 17:49:02 steve
* Support time variables.
*
* Revision 1.5 2000/10/26 17:09:46 steve
* Fix handling of errors in behavioral lvalues. (PR#28)
*
* Revision 1.4 2000/09/10 15:43:59 steve
* Some error checking.
*
* Revision 1.3 2000/09/10 03:59:59 steve
* Agressively merge NetAssign_ within concatenations.
*
* Revision 1.2 2000/09/10 02:18:16 steve
* elaborate complex l-values
*
* Revision 1.1 2000/09/09 15:21:26 steve
* move lval elaboration to PExpr virtual methods.
*
*/
+1484 -1091
View File
File diff suppressed because it is too large Load Diff
+30 -9
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_pexpr.cc,v 1.21 2004/02/20 06:22:56 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.25 2006/11/04 06:19:25 steve Exp $"
#endif
# include "config.h"
@@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0;
}
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
return tmp;
}
@@ -119,7 +119,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope);
return elaborate_expr(des, scope, -1, false);
}
/*
@@ -140,7 +140,9 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
perm_string perm_name = lex_strings.make(name);
delete name;
const NetExpr*ex = pscope->get_parameter(perm_name);
const NetExpr*ex_msb;
const NetExpr*ex_lsb;
const NetExpr*ex = pscope->get_parameter(perm_name, ex_msb, ex_lsb);
if (ex == 0) {
cerr << get_line() << ": error: identifier ``" << path_ <<
"'' is not a parameter in " << scope->name() << "." << endl;
@@ -152,17 +154,20 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
res->set_line(*this);
assert(res);
assert(idx_ == 0);
if (msb_ && lsb_) {
assert(idx_.empty());
cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl;
des->errors += 1;
} else if (msb_) {
} else if (!idx_.empty()) {
assert(msb_==0);
assert(lsb_==0);
assert(idx_.size() == 1);
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
}
@@ -176,13 +181,13 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
{
return elaborate_expr(des, sc);
return elaborate_expr(des, sc, -1, false);
}
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope);
return elaborate_expr(des, scope, -1, false);
}
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
@@ -231,6 +236,22 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* Revision 1.25 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.24 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.23 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.22 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.21 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
+190 -57
View File
@@ -17,11 +17,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.35 2004/09/10 00:15:17 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
# include "netmisc.h"
# include <iostream>
# include <stdio.h>
@@ -33,10 +34,10 @@
*/
# include "Module.h"
# include "PData.h"
# include "PEvent.h"
# include "PExpr.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
@@ -45,7 +46,8 @@
# include <typeinfo>
# include <assert.h>
bool Module::elaborate_scope(Design*des, NetScope*scope) const
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements) const
{
if (debug_scopes) {
cerr << get_line() << ": debug: Elaborate scope "
@@ -75,8 +77,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
@@ -107,7 +108,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = false;
bool signed_flag = (*cur).second.signed_flag;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
@@ -118,16 +119,47 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
signed_flag = (*cur).second.signed_flag;
}
val->cast_signed(signed_flag);
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if ((*cur).second.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
}
/* run parameter replacements that were collected from the
containing scope and meant for me. */
for (replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
NetExpr*val = (*cur).second;
if (debug_scopes) {
cerr << get_line() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_line() << "." << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope->name() << "." << endl;
}
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
@@ -189,6 +221,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
delete[]attr;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the
@@ -255,13 +298,108 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
(*et).second->elaborate_scope(des, scope);
}
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
; cur != datum.end() ; cur ++ ) {
return des->errors == 0;
}
(*cur).second->elaborate_scope(des, scope);
bool PGenerate::generate_scope(Design*des, NetScope*container)
{
switch (scheme_type) {
case GS_LOOP:
return generate_scope_loop_(des, container);
default:
cerr << get_line() << ": sorry: Generate of this sort"
<< " is not supported yet!" << endl;
return false;
}
}
/*
* This is the elaborate scope method for a generate loop.
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// We're going to need a genvar...
int genvar;
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other paramter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_line() << ": error: Cannot evaluate genvar"
<< " init expression: " << *loop_init << endl;
des->errors += 1;
return false;
}
return des->errors == 0;
genvar = init->value().as_long();
delete init_ex;
if (debug_elaborate)
cerr << get_line() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = 0;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
// that each instance has a unique name in the
// container. The format of using [] is part of the
// Verilog standard.
char name_buf[128];
snprintf(name_buf, sizeof name_buf,
"%s[%d]", scope_name.str(), genvar);
perm_string use_name = lex_strings.make(name_buf);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Create generated scope " << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
// block. Code within this scope thus has access to the
// genvar as a constant.
{
verinum genvar_verinum(genvar);
genvar_verinum.has_sign(true);
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
genvar_verinum);
scope->set_localparam(loop_index, gp);
}
scope_list_.push_back(scope);
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (debug_elaborate)
cerr << get_line() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
genvar = step->value().as_long();
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
// Clear the genvar_tmp field in the scope to reflect that the
// genvar is no longer value for evaluating expressions.
container->genvar_tmp = perm_string();
return true;
}
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
@@ -310,8 +448,10 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
verinum*msb = msb_ ? msb_->eval_const(des, sc) : 0;
verinum*lsb = lsb_ ? lsb_->eval_const(des, sc) : 0;
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
assert( (msb == 0) || (lsb != 0) );
@@ -322,12 +462,15 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
if (msb) {
instance_array = true;
instance_high = msb->as_long();
instance_low = lsb->as_long();
instance_high = msb->value().as_long();
instance_low = lsb->value().as_long();
if (instance_high > instance_low)
instance_count = instance_high - instance_low + 1;
else
instance_count = instance_low - instance_high + 1;
delete mse;
delete lse;
}
NetScope::scope_vec_t instances (instance_count);
@@ -375,13 +518,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
my_scope->time_precision(mod->time_precision);
des->set_precision(mod->time_precision);
// This call actually arranges for the description of the
// module type to process this instance and handle parameters
// and sub-scopes that might occur. Parameters are also
// created in that scope, as they exist. (I'll override them
// later.)
mod->elaborate_scope(des, my_scope);
// Look for module parameter replacements. The "replace" map
// maps parameter name to replacement expression that is
// passed. It is built up by the ordered overrides or named
@@ -424,6 +560,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
}
Module::replace_t replace_net;
// And here we scan the replacements we collected. Elaborate
// the expression in my context, then replace the sub-scope
// parameter value with the new expression.
@@ -433,13 +571,16 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
PExpr*tmp = (*cur).second;
NetExpr*val = tmp->elaborate_pexpr(des, sc);
bool flag = my_scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< sc->name() << "." << endl;
}
replace_net[(*cur).first] = val;
}
// This call actually arranges for the description of the
// module type to process this instance and handle parameters
// and sub-scopes that might occur. Parameters are also
// created in that scope, as they exist. (I'll override them
// later.)
mod->elaborate_scope(des, my_scope, replace_net);
}
/* Stash the instance array of scopes into the parent
@@ -448,34 +589,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
sc->instance_arrays[get_name()] = instances;
}
/*
* Elaborate the datum within the module. This variable may be
* within a subscope (i.e., a function or task) so use the components
* of the name to find the precise scope where this item goes.
*/
void PData::elaborate_scope(Design*des, NetScope*scope) const
{
NetScope*sub_scope = scope;
for (unsigned idx = 0 ; idx < (hname_.component_count()-1); idx += 1) {
sub_scope = sub_scope->child(hname_.peek_name(idx));
if (sub_scope == 0) {
cerr << get_line() << ": internal error: "
<< "Could not find sub-scope "
<< hname_.peek_name(idx) << " of "
<< hname_ << " in module " << scope->name()
<< endl;
des->errors += 1;
return;
}
}
const char*basename = hname_.peek_tail_name();
NetVariable*tmp = new NetVariable(lex_strings.make(basename));
tmp->set_line(*this);
sub_scope->add_variable(tmp);
}
/*
* The isn't really able to create new scopes, but it does create the
* event name in the current scope, so can be done during the
@@ -635,6 +748,26 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.41 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.40 2006/04/12 05:05:03 steve
* Use elab_and_eval to evaluate genvar expressions.
*
* Revision 1.39 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.38 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
*
* Revision 1.37 2006/03/18 22:53:38 steve
* Support more parameter syntax.
*
* Revision 1.36 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.35 2004/09/10 00:15:17 steve
* Missing stdio.h header for warnings.
*
+154 -31
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.43 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -27,6 +27,7 @@
# include "Module.h"
# include "PExpr.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PTask.h"
# include "PWire.h"
# include "compiler.h"
@@ -158,6 +159,16 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1;
}
}
// Run through all the generate schemes to enaborate the
// signals that they hold. Note that the generate schemes hold
// the scopes that they instantiated, so we don't pass any
// scope in.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des);
}
// Get all the gates of the module and elaborate them by
@@ -238,6 +249,44 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
return flag;
}
bool PGenerate::elaborate_sig(Design*des) const
{
bool flag = true;
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate nets in "
<< "scope " << (*cur)->name() << endl;
flag = elaborate_sig_(des, *cur) & flag;
}
return flag;
}
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
typedef map<hname_t,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
PWire*cur = (*wt).second;
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate PWire "
<< cur->path() << " in scope " << scope->name() << endl;
cur->elaborate_sig(des, scope);
}
return true;
}
/*
* A function definition exists within an elaborated module. This
* matters when elaborating signals, as the ports of the function are
@@ -261,7 +310,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
NetNet*ret_sig = 0;
NetVariable*ret_real = 0;
/* Create the signals/variables of the return value and write
them into the function scope. */
@@ -270,10 +318,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG:
if (return_type_.range) {
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0]);
(*return_type_.range)[0], -1);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1]);
(*return_type_.range)[1], -1);
assert(le);
long mnum = 0, lnum = 0;
@@ -302,6 +350,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_INTEGER:
@@ -310,6 +359,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig->set_signed(true);
ret_sig->set_isint(true);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_TIME:
@@ -318,13 +368,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig->set_signed(false);
ret_sig->set_isint(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_REAL:
case PTF_REALTIME:
ret_real = new NetVariable(fname);
ret_real->set_line(*this);
scope->add_variable(ret_real);
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_REAL);
break;
default:
@@ -370,7 +424,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
NetFuncDef*def = 0;
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
if (ret_real) def = new NetFuncDef(scope, ret_real, ports);
assert(def);
scope->set_func_def(def);
@@ -495,7 +548,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
}
NetEConst*tmp;
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
@@ -509,7 +562,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
mnum[idx] = tmp->value().as_long();
delete texpr;
texpr = elab_and_eval(des, scope, lsb_[idx]);
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
cerr << msb_[idx]->get_line() << ": error: "
@@ -563,6 +616,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
des, scope);
long array_s0 = 0;
long array_e0 = 0;
/* If the ident has idx expressions, then this is a
memory. It can only have the idx registers after the msb
and lsb expressions are filled. And, if it has one index,
@@ -570,8 +626,8 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_);
NetExpr*rexp = elab_and_eval(des, scope, ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_line() << ": internal error: There is "
@@ -586,7 +642,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lcon == 0) || (rcon == 0)) {
cerr << get_line() << ": internal error: The indices "
<< "are not constant for memory ``"
<< "are not constant for array ``"
<< hname_.peek_tail_name() << "''." << endl;
des->errors += 1;
return;
@@ -600,29 +656,96 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
perm_string name = lex_strings.make(hname_.peek_tail_name());
long lnum = lval.as_long();
long rnum = rval.as_long();
new NetMemory(scope, name, wid, lnum, rnum);
// The constructor automatically adds the memory object
// to the scope. Do I need to set line number information?
} else {
perm_string name = lex_strings.make(hname_.peek_tail_name());
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
sig->set_isint(get_isint());
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
/* If the net type is supply0 or supply1, replace it
with a simple wire with a pulldown/pullup with supply
strength. In other words, transform:
supply0 foo;
to:
wire foo;
pulldown #(supply0) (foo);
This reduces the backend burden, and behaves exactly
the same. */
NetLogic*pull = 0;
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
? NetLogic::PULLUP
: NetLogic::PULLDOWN;
pull = new NetLogic(scope, scope->local_symbol(),
1, pull_type, wid);
pull->set_line(*this);
pull->pin(0).drive0(Link::SUPPLY);
pull->pin(0).drive1(Link::SUPPLY);
des->add_node(pull);
wtype = NetNet::WIRE;
if (debug_elaborate) {
cerr << get_line() << ": debug: "
<< "Generate a SUPPLY pulldown for the "
<< "supply0 net." << endl;
}
}
perm_string name = lex_strings.make(hname_.peek_tail_name());
if (debug_elaborate) {
cerr << get_line() << ": debug: Create signal "
<< name << "["<<msb<<":"<<lsb<<"]"
<< " in scope " << scope->name() << endl;
}
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb,
array_s0, array_e0);
sig->data_type(data_type_);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (pull)
connect(sig->pin(0), pull->pin(0));
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
}
/*
* $Log: elab_sig.cc,v $
* Revision 1.43 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.42 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.41 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.40 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.39 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.38 2005/02/13 01:15:07 steve
* Replace supply nets with wires connected to pullup/down supply devices.
*
* Revision 1.37 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.36 2004/09/27 22:34:10 steve
* Cleanup and factoring of autoconf.
*
+971 -321
View File
File diff suppressed because it is too large Load Diff
+115 -177
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -57,18 +57,17 @@ bool NetAddSub::emit_node(struct target_t*tgt) const
return true;
}
bool NetArrayDq::emit_node(struct target_t*tgt) const
{
return tgt->lpm_array_dq(this);
}
bool NetCaseCmp::emit_node(struct target_t*tgt) const
{
tgt->net_case_cmp(this);
return true;
}
bool NetCAssign::emit_node(struct target_t*tgt) const
{
tgt->net_cassign(this);
return true;
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@@ -81,6 +80,11 @@ bool NetCompare::emit_node(struct target_t*tgt) const
return true;
}
bool NetConcat::emit_node(struct target_t*tgt) const
{
return tgt->concat(this);
}
bool NetConst::emit_node(struct target_t*tgt) const
{
return tgt->net_const(this);
@@ -98,10 +102,9 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true;
}
bool NetForce::emit_node(struct target_t*tgt) const
bool NetLiteral::emit_node(struct target_t*tgt) const
{
tgt->net_force(this);
return true;
return tgt->net_literal(this);
}
bool NetModulo::emit_node(struct target_t*tgt) const
@@ -122,10 +125,29 @@ bool NetMux::emit_node(struct target_t*tgt) const
return true;
}
bool NetRamDq::emit_node(struct target_t*tgt) const
bool NetPartSelect::emit_node(struct target_t*tgt) const
{
tgt->lpm_ram_dq(this);
return true;
return tgt->part_select(this);
}
bool NetReplicate::emit_node(struct target_t*tgt) const
{
return tgt->replicate(this);
}
bool NetSignExtend::emit_node(struct target_t*tgt) const
{
return tgt->sign_extend(this);
}
bool NetUReduce::emit_node(struct target_t*tgt) const
{
return tgt->ureduce(this);
}
bool NetSysFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_sysfunction(this);
}
bool NetUserFunc::emit_node(struct target_t*tgt) const
@@ -312,9 +334,6 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
tgt->variable(cur);
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
@@ -324,15 +343,19 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->signal(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here becase delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
tgt->signal_paths(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
if (memories_) {
NetMemory*cur = memories_->snext_;
do {
tgt->memory(cur);
cur = cur->snext_;
} while (cur != memories_->snext_);
}
}
bool NetScope::emit_defs(struct target_t*tgt) const
@@ -363,13 +386,12 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const
proc_->emit_proc(tgt);
}
bool Design::emit(struct target_t*tgt) const
int Design::emit(struct target_t*tgt) const
{
bool rc = true;
int rc = 0;
rc = rc && tgt->start_design(this);
if (rc == false)
return false;
if (tgt->start_design(this) == false)
return -2;
// enumerate the scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
@@ -378,27 +400,36 @@ bool Design::emit(struct target_t*tgt) const
// emit nodes
bool nodes_rc = true;
if (nodes_) {
NetNode*cur = nodes_->node_next_;
do {
rc = rc && cur->emit_node(tgt);
nodes_rc = nodes_rc && cur->emit_node(tgt);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
}
// emit task and function definitions
bool tasks_rc = true;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++)
rc &= (*scope)->emit_defs(tgt);
tasks_rc &= (*scope)->emit_defs(tgt);
// emit the processes
bool proc_rc = true;
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
rc = rc && idx->emit(tgt);
proc_rc &= idx->emit(tgt);
if (tgt->end_design(this) != 0)
rc = false;
rc = tgt->end_design(this);
if (nodes_rc == false)
return -1;
if (tasks_rc == false)
return -2;
if (proc_rc == false)
return -3;
return rc;
}
@@ -433,11 +464,6 @@ void NetECRealParam::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_rparam(this);
}
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_memory(this);
}
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
{
cerr << get_line() << ":internal error: unexpected NetEParam."
@@ -474,11 +500,6 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_signal(this);
}
void NetEBitSel::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_subsignal(this);
}
void NetETernary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_ternary(this);
@@ -489,12 +510,7 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_unary(this);
}
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_variable(this);
}
bool emit(const Design*des, const char*type)
int emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
@@ -505,12 +521,60 @@ bool emit(const Design*des, const char*type)
cerr << "error: Code generator type " << type
<< " not found." << endl;
return false;
return -1;
}
/*
* $Log: emit.cc,v $
* Revision 1.89 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.88 2006/11/10 05:44:44 steve
* Process delay paths in second path over signals.
*
* Revision 1.87 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.86 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.85 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.84 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.83 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.82 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.81 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.80 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.79 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.78 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.77 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
@@ -536,131 +600,5 @@ bool emit(const Design*des, const char*type)
* Revision 1.71 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.70 2002/11/03 20:36:10 steve
* Error message for mising code generator type.
*
* Revision 1.69 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.68 2002/06/05 03:44:25 steve
* Add support for memory words in l-value of
* non-blocking assignments, and remove the special
* NetAssignMem_ and NetAssignMemNB classes.
*
* Revision 1.67 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.66 2002/03/09 02:10:22 steve
* Add the NetUserFunc netlist node.
*
* Revision 1.65 2002/01/28 00:52:41 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.64 2002/01/19 19:02:08 steve
* Pass back target errors processing conditionals.
*
* Revision 1.63 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.62 2001/08/25 23:50:02 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.61 2001/07/27 04:51:44 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.60 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.59 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.58 2001/04/06 02:28:02 steve
* Generate vvp code for functions with ports.
*
* Revision 1.57 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.56 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*
* Revision 1.55 2000/11/04 01:54:01 steve
* Modifications in support of gcc 2.96
*
* Revision 1.54 2000/09/26 01:35:42 steve
* Remove the obsolete NetEIdent class.
*
* Revision 1.53 2000/09/17 21:26:15 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.52 2000/09/02 20:54:20 steve
* Rearrange NetAssign to make NetAssign_ separate.
*
* Revision 1.51 2000/08/14 04:39:56 steve
* add th t-dll functions for net_const, net_bufz and processes.
*
* Revision 1.50 2000/08/09 03:43:45 steve
* Move all file manipulation out of target class.
*
* Revision 1.49 2000/08/08 01:50:42 steve
* target methods need not take a file stream.
*
* Revision 1.48 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.47 2000/07/29 16:21:08 steve
* Report code generation errors through proc_delay.
*
* Revision 1.46 2000/07/27 05:13:44 steve
* Support elaboration of disable statements.
*
* Revision 1.45 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.44 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.43 2000/05/02 03:13:31 steve
* Move memories to the NetScope object.
*
* Revision 1.42 2000/05/02 00:58:12 steve
* Move signal tables to the NetScope class.
*
* Revision 1.41 2000/04/23 03:45:24 steve
* Add support for the procedural release statement.
*
* Revision 1.40 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.39 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,
*
* Handle named events within the mix of net events
* and edges. As a unified lot they get caught together.
* wait statements are broken into more complex statements
* that include a conditional.
*
* Do not generate NetPEvent or NetNEvent objects in
* elaboration. NetEvent, NetEvWait and NetEvProbe
* take over those functions in the netlist.
*/
+73 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.36 2003/06/21 01:21:43 steve Exp $"
#ident "$Id: eval.cc,v 1.44 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -26,14 +26,15 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
verinum* PExpr::eval_const(const Design*, const NetScope*) const
verinum* PExpr::eval_const(const Design*, NetScope*) const
{
return 0;
}
verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
{
verinum*l = left_->eval_const(des, scope);
if (l == 0) return 0;
@@ -142,16 +143,50 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
delete r;
return res;
}
verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
{
verinum*accum = parms_[0]->eval_const(des, scope);
if (accum == 0)
return 0;
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
verinum*tmp = parms_[idx]->eval_const(des, scope);
if (tmp == 0) {
delete accum;
return 0;
}
assert(tmp);
*accum = concat(*accum, *tmp);
delete tmp;
}
return accum;
}
/*
* Evaluate an identifier as a constant expression. This is only
* possible if the identifier is that of a parameter.
*/
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
{
assert(scope);
const NetExpr*expr = des->find_parameter(scope, path_);
NetNet*net;
NetEvent*eve;
const NetExpr*expr;
// Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately.
if (scope->genvar_tmp
&& strcmp(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
NetScope*found_in = symbol_search(des, scope, path_,
net, expr, eve);
if (expr == 0)
return 0;
@@ -173,23 +208,23 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
return new verinum(eval->value());
}
verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
verinum* PEFNumber::eval_const(const Design*, NetScope*) const
{
long val = value_->as_long();
return new verinum(val);
}
verinum* PENumber::eval_const(const Design*, const NetScope*) const
verinum* PENumber::eval_const(const Design*, NetScope*) const
{
return new verinum(value());
}
verinum* PEString::eval_const(const Design*, const NetScope*) const
verinum* PEString::eval_const(const Design*, NetScope*) const
{
return new verinum(string(text_));
}
verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
{
verinum*test = expr_->eval_const(des, scope);
if (test == 0)
@@ -209,7 +244,7 @@ verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
}
}
verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
{
verinum*val = expr_->eval_const(des, scope);
if (val == 0)
@@ -223,7 +258,7 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/* We need to expand the value a bit if we are
taking the 2's complement so that we are
guaranteed to not overflow. */
verinum tmp (0UL, val->len()+1);
verinum tmp ((uint64_t)0, val->len()+1);
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
tmp.set(idx, val->get(idx));
@@ -240,6 +275,33 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.44 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.43 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.42 2006/05/19 04:07:24 steve
* eval_const is not strict.
*
* Revision 1.41 2006/05/17 16:49:30 steve
* Error message if concat expression cannot evaluate.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.39 2005/12/07 04:04:23 steve
* Allow constant concat expressions.
*
* Revision 1.38 2005/11/27 17:01:57 steve
* Fix for stubborn compiler.
*
* Revision 1.37 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.36 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
*
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_attrib.cc,v 1.7 2004/02/20 18:53:35 steve Exp $"
#ident "$Id: eval_attrib.cc,v 1.8 2005/11/27 17:01:57 steve Exp $"
#endif
# include "config.h"
@@ -36,7 +36,7 @@
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
unsigned&natt,
const Design*des,
const NetScope*scope)
NetScope*scope)
{
natt = att.size();
if (natt == 0)
@@ -74,6 +74,9 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
/*
* $Log: eval_attrib.cc,v $
* Revision 1.8 2005/11/27 17:01:57 steve
* Fix for stubborn compiler.
*
* Revision 1.7 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
+297 -156
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.62 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.73 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -55,26 +55,64 @@ NetEConst* NetEBAdd::eval_tree()
{
eval_sub_tree_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
/* If both operands are constant, then replace the entire
expression with a constant value. */
if (lc != 0 && rc != 0) {
verinum lval = lc->value();
verinum rval = rc->value();
verinum val;
switch (op_) {
case '+':
val = lval + rval;
break;
case '-':
val = lval - rval;
break;
default:
verinum val;
switch (op_) {
case '+':
val = lval + rval;
break;
case '-':
val = lval - rval;
break;
default:
return 0;
}
return new NetEConst(val);
}
/* Try to combine a right constant value with the right
constant value of a sub-expression add. For example, the
expression (a + 2) - 1 can be rewritten as a + 1. */
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
if (lc != 0 && rc != 0) {
assert(se != 0);
verinum lval = lc->value();
verinum rval = rc->value();
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
/* (a - lval) - rval --> a - (rval+lval) */
val = rval + lval;
} else {
/* (a - lval) + rval --> a + (rval-lval) */
/* (a + lval) - rval --> a - (rval-lval) */
val = rval - lval;
}
NetEConst*tmp = new NetEConst(val);
left_ = se->left_->dup_expr();
delete se;
delete right_;
right_ = tmp;
/* We've changed the subexpression, but the result is
still not constant, so return nil here anyhow. */
return 0;
}
return new NetEConst(val);
/* Nothing more to be done, the value is not constant. */
return 0;
}
NetEConst* NetEBBits::eval_tree()
@@ -175,43 +213,6 @@ NetEConst* NetEBBits::eval_tree()
return new NetEConst(res);
}
NetEConst* NetEBComp::eval_eqeq_()
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
const verinum&lv = l->value();
const verinum&rv = r->value();
unsigned s_len = lv.len();
if (rv.len() < s_len) s_len = rv.len();
verinum result(verinum::V1, 1);
for (unsigned idx = 0 ; idx < s_len; idx += 1) {
if (lv[idx] != rv[idx])
result = verinum::V0;
}
// If one operand was wider than the other, check that the
// remaining bits are all zero
if (lv.len() > s_len) {
for (unsigned idx = s_len; idx < lv.len(); idx += 1) {
if (lv[idx] != 0)
result = verinum::V0;
}
}
if (rv.len() > s_len) {
for (unsigned idx = s_len; idx < rv.len(); idx += 1) {
if (rv[idx] != 0)
result = verinum::V0;
}
}
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_less_()
{
@@ -224,20 +225,27 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result);
}
/* Detect the case where the right side is greater that or
/* Detect the case where the right side is greater than or
equal to the largest value the left side can possibly
have. */
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
if (lv < rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
have. Use the width of the left expression as all 1's to
calculate the maximum possible width for the left_
expression. This test only works of the compare is
unsigned. */
if (! (rv.has_sign() || left_->has_sign())) {
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
if (lv < rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
}
/* Now go on to the normal test of the values. */
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
lv = l->value();
verinum lv = l->value();
if (! lv.is_defined()) {
verinum result(verinum::Vx, 1);
return new NetEConst(result);
@@ -266,7 +274,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
double lv, rv;
switch (left_->expr_type()) {
case ET_REAL:
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (left_);
if (rtmp == 0)
return 0;
@@ -274,7 +282,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
lv = rtmp->value().as_double();
break;
case ET_VECTOR:
case IVL_VT_LOGIC:
vtmp = dynamic_cast<NetEConst*> (left_);
if (vtmp == 0)
return 0;
@@ -288,7 +296,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
switch (right_->expr_type()) {
case ET_REAL:
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (right_);
if (rtmp == 0)
return 0;
@@ -296,7 +304,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
rv = rtmp->value().as_double();
break;
case ET_VECTOR:
case IVL_VT_LOGIC:
vtmp = dynamic_cast<NetEConst*> (right_);
if (vtmp == 0)
return 0;
@@ -317,9 +325,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
NetEConst* NetEBComp::eval_leeq_()
{
if (right_->expr_type() == ET_REAL)
if (right_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_();
if (left_->expr_type() == ET_REAL)
if (left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_();
NetEConst*r = dynamic_cast<NetEConst*>(right_);
@@ -374,8 +382,8 @@ NetEConst* NetEBComp::eval_leeq_()
NetEConst* NetEBComp::eval_gt_()
{
if ((left_->expr_type() == NetExpr::ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) {
if ((left_->expr_type() == IVL_VT_REAL)
&& (right_->expr_type() == IVL_VT_REAL)) {
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
if (tmpl == 0)
@@ -413,7 +421,7 @@ NetEConst* NetEBComp::eval_gt_()
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == NetExpr::ET_REAL) {
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
@@ -450,8 +458,8 @@ NetEConst* NetEBComp::eval_gt_()
NetEConst* NetEBComp::eval_gteq_()
{
if ((left_->expr_type() == NetExpr::ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) {
if ((left_->expr_type() == IVL_VT_REAL)
&& (right_->expr_type() == IVL_VT_REAL)) {
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
if (tmpl == 0)
@@ -479,7 +487,7 @@ NetEConst* NetEBComp::eval_gteq_()
/* Detect the case where the left side is greater than the
largest value the right side can possibly have. */
if (right_->expr_type() == NetExpr::ET_VECTOR) {
if (right_->expr_type() == IVL_VT_LOGIC) {
assert(right_->expr_width() > 0);
verinum rv (verinum::V1, right_->expr_width());
if (lv >= rv) {
@@ -489,7 +497,7 @@ NetEConst* NetEBComp::eval_gteq_()
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == NetExpr::ET_REAL) {
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
@@ -510,21 +518,25 @@ NetEConst* NetEBComp::eval_gteq_()
return new NetEConst(result);
}
if (lv.has_sign() && rv.has_sign() && (lv.as_long() >= rv.as_long())) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
if (lv.has_sign() && rv.has_sign()) {
if (lv.as_ulong() >= rv.as_ulong()) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
if (lv.as_long() >= rv.as_long()) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
} else {
if (lv.as_ulong() >= rv.as_ulong()) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
}
verinum result(verinum::V0, 1);
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_neeq_()
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
@@ -534,7 +546,10 @@ NetEConst* NetEBComp::eval_neeq_()
const verinum&lv = l->value();
const verinum&rv = r->value();
verinum::V res = verinum::V0;
const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
@@ -567,10 +582,18 @@ NetEConst* NetEBComp::eval_neeq_()
break;
if (rv.get(idx) != lv.get(idx))
res = verinum::V1;
res = ne_res;
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
@@ -579,9 +602,14 @@ NetEConst* NetEBComp::eval_neeq_()
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx)
res = verinum::V1;
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
break;
default:
@@ -596,9 +624,14 @@ NetEConst* NetEBComp::eval_neeq_()
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx)
res = verinum::V1;
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
break;
default:
@@ -666,7 +699,7 @@ NetEConst* NetEBComp::eval_tree()
return eval_eqeqeq_();
case 'e': // Equality (==)
return eval_eqeq_();
return eval_eqeq_(false);
case 'G': // >=
return eval_gteq_();
@@ -678,7 +711,7 @@ NetEConst* NetEBComp::eval_tree()
return eval_neeqeq_();
case 'n': // not-equal (!=)
return eval_neeq_();
return eval_eqeq_(true);
case '<': // Less than
return eval_less_();
@@ -699,7 +732,7 @@ NetExpr* NetEBDiv::eval_tree()
{
eval_sub_tree_();
if (expr_type() == NetExpr::ET_REAL) {
if (expr_type() == IVL_VT_REAL) {
NetECReal*lc = dynamic_cast<NetECReal*>(left_);
if (lc == 0) return 0;
@@ -744,7 +777,7 @@ NetExpr* NetEBDiv::eval_tree()
} else {
assert(expr_type() == NetExpr::ET_VECTOR);
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
@@ -837,14 +870,15 @@ NetExpr* NetEBMult::eval_tree_real_()
verireal rval;
switch (left_->expr_type()) {
case ET_REAL: {
case IVL_VT_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return 0;
lval = lc->value();
break;
}
case ET_VECTOR: {
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
verinum tmp = lc->value();
@@ -857,14 +891,15 @@ NetExpr* NetEBMult::eval_tree_real_()
}
switch (right_->expr_type()) {
case ET_REAL: {
case IVL_VT_REAL: {
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
if (rc == 0) return 0;
rval = rc->value();
break;
}
case ET_VECTOR: {
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum tmp = rc->value();
@@ -886,10 +921,10 @@ NetExpr* NetEBMult::eval_tree()
{
eval_sub_tree_();
if (expr_type() == ET_REAL)
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
assert(expr_type() == ET_VECTOR);
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
@@ -902,6 +937,80 @@ NetExpr* NetEBMult::eval_tree()
return new NetEConst(lval * rval);
}
NetExpr* NetEBPow::eval_tree_real_()
{
verireal lval;
verireal rval;
switch (left_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return 0;
lval = lc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
verinum tmp = lc->value();
lval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
switch (right_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
if (rc == 0) return 0;
rval = rc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum tmp = rc->value();
rval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
NetECReal*res = new NetECReal( pow(lval,rval) );
res->set_line(*this);
return res;
}
NetExpr* NetEBPow::eval_tree()
{
eval_sub_tree_();
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
return new NetEConst( pow(lval,rval) );
}
/*
* Evaluate the shift operator if possible. For this to work, both
* operands must be constant.
@@ -929,6 +1038,13 @@ NetEConst* NetEBShift::eval_tree()
unsigned shift = rv.as_ulong();
if (debug_eval_tree) {
cerr << get_line() << ": debug: "
<< "Evaluate " << lv << "<<" << op() << ">> "
<< rv << ", wid=" << wid << ", shift=" << shift
<< ", lv.las_len()=" << lv.has_len() << endl;
}
if ((wid == 0) || ! lv.has_len()) {
/* If the caller doesn't care what the width is,
then calcuate a width from the trimmed left
@@ -1074,57 +1190,22 @@ NetEConst* NetEConcat::eval_tree()
return res;
}
/*
* There are limits to our ability to evaluate a memory reference
* expression, because the content of a memory is never
* constant. However, the index expression may be precalculated, and
* there are certain index values that do give us constant results.
*/
NetExpr* NetEMemory::eval_tree()
{
/* Attempt to evaluate the index expression to a constant, if
it is not already. */
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
NetExpr* tmp = idx_->eval_tree();
if (tmp) {
delete idx_;
idx_ = tmp;
}
}
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
if (itmp == 0)
return 0;
verinum ival = itmp->value();
/* If the index expression has any x or z bits, then we know
already that the expression result is a constant x. */
if (! ival.is_defined()) {
verinum xres (verinum::Vx, mem_->width(), false);
NetEConst*res = new NetEConst(xres);
return res;
}
/* If the index expression is outside the range of the memory,
then the result is a constant x. */
unsigned norm_idx = mem_->index_to_address(ival.as_long());
if (norm_idx >= mem_->count()) {
verinum xres (verinum::Vx, mem_->width(), false);
NetEConst*res = new NetEConst(xres);
return res;
}
return 0;
}
NetExpr* NetEParam::eval_tree()
{
if (des_ == 0)
if (des_ == 0) {
assert(scope_ == 0);
return 0;
}
if (debug_elaborate) {
cerr << get_line() << ": debug: evaluating expression: "
<< *this << endl;
}
assert(scope_);
const NetExpr*expr = scope_->get_parameter(name_);
const NetExpr*expr_msb;
const NetExpr*expr_lsb;
const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
if (expr == 0) {
cerr << get_line() << ": internal error: Unable to match "
<< "parameter " << name_ << " in scope "
@@ -1175,7 +1256,8 @@ NetExpr* NetEParam::eval_tree()
switch (res->expr_type()) {
case NetExpr::ET_VECTOR:
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
if (tmp == 0) {
cerr << get_line() << ": internal error: parameter "
@@ -1192,7 +1274,7 @@ NetExpr* NetEParam::eval_tree()
return ptmp;
}
case NetExpr::ET_REAL:
case IVL_VT_REAL:
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
if (tmp == 0) {
cerr << get_line() << ": internal error: parameter "
@@ -1228,31 +1310,50 @@ NetEConst* NetESelect::eval_tree()
expr = dynamic_cast<NetEConst*>(expr_);
}
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
long bval = 0;
if (base_) {
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
}
base = dynamic_cast<NetEConst*>(base_);
}
base = dynamic_cast<NetEConst*>(base_);
if (base == 0)
return 0;
bval = base->value().as_long();
}
if (expr == 0)
return 0;
if (base == 0)
return 0;
verinum eval = expr->value();
verinum oval (verinum::V0, expr_width(), true);
long bval = base->value().as_long();
verinum::V pad_bit = verinum::Vx;
if (base_ == 0) {
/* If the base is NULL (different from 0) the this
select is here for sign extension. So calculate a
proper pad bit. Extend x or z or 0, and sign extend 1
if this is signed. */
unsigned top = expr->expr_width()-1;
pad_bit = eval.get(top);
if (pad_bit==verinum::V1 && !has_sign())
pad_bit = verinum::V0;
}
for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
if ((bval >= 0) && ((unsigned long) bval < eval.len()))
oval.set(idx, eval.get(bval));
else
oval.set(idx, verinum::Vx);
oval.set(idx, pad_bit);
bval += 1;
}
@@ -1551,6 +1652,46 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.73 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.72 2006/11/04 06:16:27 steve
* Fix padding of constant eval of NetESelect.
*
* Revision 1.71 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.70 2006/09/19 23:00:15 steve
* Use elab_and_eval for bit select expressions.
*
* Revision 1.69 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.68 2006/03/18 22:52:27 steve
* Properly handle signedness in compare.
*
* Revision 1.67 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.66 2005/11/10 13:28:12 steve
* Reorganize signal part select handling, and add support for
* indexed part selects.
*
* Expand expression constant propagation to eliminate extra
* sums in certain cases.
*
* Revision 1.65 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.64 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.63 2005/06/17 05:05:53 steve
* Watch out for signed constants in magnitude compare.
*
* Revision 1.62 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
+8 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: hello_vpi.c,v 1.3 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
#endif
/*
@@ -33,7 +33,7 @@
# include <vpi_user.h>
static int my_hello_calltf(char *xx)
static PLI_INT32 my_hello_calltf(char *xx)
{
vpi_printf("Hello World, from VPI.\n");
return 0;
@@ -62,6 +62,12 @@ void (*vlog_startup_routines[])() = {
};
/*
* $Log: hello_vpi.c,v $
* Revision 1.5 2007/01/17 05:35:48 steve
* Fix typo is hello_vpi.c example.
*
* Revision 1.4 2006/10/30 22:46:25 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+401 -290
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.82 2007/01/20 02:10:45 steve Exp $"
#endif
# include "config.h"
@@ -45,26 +45,25 @@ NetNet* NetEBAdd::synthesize(Design*des)
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
assert(expr_width() >= lsig->pin_count());
assert(expr_width() >= rsig->pin_count());
assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width());
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
assert(lsig->pin_count() == rsig->pin_count());
unsigned width=lsig->pin_count();
assert(lsig->vector_width() == rsig->vector_width());
unsigned width=lsig->vector_width();
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(lsig->pin(idx), adder->pin_DataA(idx));
connect(rsig->pin(idx), adder->pin_DataB(idx));
connect(osig->pin(idx), adder->pin_Result(idx));
}
connect(lsig->pin(0), adder->pin_DataA());
connect(rsig->pin(0), adder->pin_DataB());
connect(osig->pin(0), adder->pin_Result());
des->add_node(adder);
switch (op()) {
@@ -94,148 +93,59 @@ NetNet* NetEBBits::synthesize(Design*des)
assert(scope);
string path = des->local_symbol(scope->name());
if (lsig->pin_count() != rsig->pin_count()) {
if (lsig->vector_width() != rsig->vector_width()) {
cerr << get_line() << ": internal error: bitwise (" << op_
<< ") widths do not match: " << lsig->pin_count()
<< " != " << rsig->pin_count() << endl;
<< ") widths do not match: " << lsig->vector_width()
<< " != " << rsig->vector_width() << endl;
cerr << get_line() << ": : width="
<< lsig->pin_count() << ": " << *left_ << endl;
<< lsig->vector_width() << ": " << *left_ << endl;
cerr << get_line() << ": : width="
<< rsig->pin_count() << ": " << *right_ << endl;
<< rsig->vector_width() << ": " << *right_ << endl;
return 0;
}
assert(lsig->pin_count() == rsig->pin_count());
assert(lsig->vector_width() == rsig->vector_width());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lsig->pin_count());
NetNet::IMPLICIT, lsig->vector_width());
osig->local_flag(true);
osig->data_type(expr_type());
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
perm_string oname = scope->local_symbol();
NetLogic*gate;
perm_string oname = scope->local_symbol();
unsigned wid = lsig->vector_width();
NetLogic*gate;
/* If the rsig bit is constant, then look for special
cases that I can use to reduce the generated
logic. If I find one, then handle it immediately and
skip the rest of the processing of this bit. */
if (rsig->pin(idx).nexus()->drivers_constant()) {
verinum::V bval = rsig->pin(idx).nexus()->driven_value();
/* (A & 0) is (0) */
if ((op() == '&') && bval == verinum::V0) {
connect(osig->pin(idx), rsig->pin(idx));
continue;
}
/* (A & 1) is A */
if ((op() == '&') && bval == verinum::V1) {
connect(osig->pin(idx), lsig->pin(idx));
continue;
}
}
switch (op()) {
case '&':
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
break;
case '|':
gate = new NetLogic(scope, oname, 3, NetLogic::OR);
break;
case '^':
gate = new NetLogic(scope, oname, 3, NetLogic::XOR);
break;
case 'O':
gate = new NetLogic(scope, oname, 3, NetLogic::NOR);
break;
case 'X':
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR);
break;
default:
assert(0);
}
connect(osig->pin(idx), gate->pin(0));
connect(lsig->pin(idx), gate->pin(1));
connect(rsig->pin(idx), gate->pin(2));
des->add_node(gate);
switch (op()) {
case '&':
gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid);
break;
case '|':
gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid);
break;
case '^':
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, wid);
break;
case 'O':
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, wid);
break;
case 'X':
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, wid);
break;
default:
assert(0);
}
connect(osig->pin(0), gate->pin(0));
connect(lsig->pin(0), gate->pin(1));
connect(rsig->pin(0), gate->pin(2));
gate->set_line(*this);
des->add_node(gate);
return osig;
}
NetNet* NetEBComp::synthesize(Design*des)
{
NetEConst*lcon = reinterpret_cast<NetEConst*>(left_);
NetEConst*rcon = reinterpret_cast<NetEConst*>(right_);
/* Handle the special case where one of the inputs is constant
0. We can use an OR gate to do the comparison. Synthesize
the non-const side as normal, then or(nor) the signals
together to get result. */
if ((rcon && (rcon->value() == verinum(0UL,rcon->expr_width())))
|| (lcon && (lcon->value() == verinum(0UL,lcon->expr_width())))) {
NetNet*lsig = rcon
? left_->synthesize(des)
: right_->synthesize(des);
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->local_flag(true);
NetLogic*gate;
switch (op_) {
case 'e':
case 'E':
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
break;
case 'n':
case 'N':
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
break;
case '>':
/* sig > 0 is true if any bit in sig is set. This
is very much like sig != 0. (0 > sig) shouldn't
happen. */
if (rcon) {
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
case '<':
/* 0 < sig is handled like sig > 0. */
if (! rcon) {
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
default:
assert(0);
}
connect(gate->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(gate->pin(idx+1), lsig->pin(idx));
des->add_node(gate);
return osig;
}
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
@@ -243,22 +153,25 @@ NetNet* NetEBComp::synthesize(Design*des)
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->pin_count();
if (rsig->pin_count() > lsig->pin_count())
width = rsig->pin_count();
unsigned width = lsig->vector_width();
if (rsig->vector_width() > width)
width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
/* Handle the special case of a single bit equality
operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR);
3, NetLogic::XNOR, 1);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@@ -271,7 +184,8 @@ NetNet* NetEBComp::synthesize(Design*des)
an XOR instead of an XNOR gate. */
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR);
3, NetLogic::XOR, 1);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@@ -281,13 +195,11 @@ NetNet* NetEBComp::synthesize(Design*des)
NetCompare*dev = new NetCompare(scope, scope->local_symbol(), width);
dev->set_line(*this);
des->add_node(dev);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(dev->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(dev->pin_DataB(idx), rsig->pin(idx));
connect(dev->pin_DataA(), lsig->pin(0));
connect(dev->pin_DataB(), rsig->pin(0));
switch (op_) {
@@ -322,6 +234,14 @@ NetNet* NetEBComp::synthesize(Design*des)
return osig;
}
NetNet* NetEBPow::synthesize(Design*des)
{
cerr << get_line() << ": internal error: Do not yet know how to handle"
<< " power operator in this context." << endl;
des->errors += 1;
return 0;
}
NetNet* NetEBMult::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des);
@@ -338,25 +258,24 @@ NetNet* NetEBMult::synthesize(Design*des)
NetMult*mult = new NetMult(scope, scope->local_symbol(),
expr_width(),
lsig->pin_count(),
rsig->pin_count());
lsig->vector_width(),
rsig->vector_width());
des->add_node(mult);
mult->set_signed( has_sign() );
mult->set_line(*this);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(mult->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(mult->pin_DataB(idx), rsig->pin(idx));
connect(mult->pin_DataA(), lsig->pin(0));
connect(mult->pin_DataB(), rsig->pin(0));
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(lsig->data_type());
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
connect(mult->pin_Result(idx), osig->pin(idx));
connect(mult->pin_Result(), osig->pin(0));
return osig;
}
@@ -370,6 +289,8 @@ NetNet* NetEBDiv::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->local_flag(true);
switch (op()) {
@@ -377,32 +298,28 @@ NetNet* NetEBDiv::synthesize(Design*des)
case '/': {
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
expr_width(),
lsig->pin_count(),
rsig->pin_count());
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
des->add_node(div);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(div->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(div->pin_DataB(idx), rsig->pin(idx));
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
connect(div->pin_Result(idx), osig->pin(idx));
connect(div->pin_DataA(), lsig->pin(0));
connect(div->pin_DataB(), rsig->pin(0));
connect(div->pin_Result(),osig->pin(0));
break;
}
case '%': {
NetModulo*div = new NetModulo(scope, scope->local_symbol(),
expr_width(),
lsig->pin_count(),
rsig->pin_count());
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
des->add_node(div);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(div->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(div->pin_DataB(idx), rsig->pin(idx));
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
connect(div->pin_Result(idx), osig->pin(idx));
connect(div->pin_DataA(), lsig->pin(0));
connect(div->pin_DataB(), rsig->pin(0));
connect(div->pin_Result(),osig->pin(0));
break;
}
@@ -436,6 +353,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
osig->local_flag(true);
@@ -449,7 +367,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog = new NetLogic(scope, oname,
lsig->pin_count()+rsig->pin_count()+1,
NetLogic::OR);
NetLogic::OR, 1);
connect(osig->pin(0), olog->pin(0));
@@ -471,7 +389,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog;
perm_string oname = scope->local_symbol();
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
connect(osig->pin(0), olog->pin(0));
des->add_node(olog);
@@ -528,32 +446,64 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(expr_type());
osig->local_flag(true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
verinum::V0);
des->add_node(zcon);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
connect(zcon->pin(0), zsig->pin(0));
// ushift is the amount of pad created by the shift.
unsigned long ushift = shift>=0? shift : -shift;
if (ushift > osig->vector_width())
ushift = osig->vector_width();
if (shift > 0) {
unsigned long ushift = shift;
for (unsigned idx = 0; idx < osig->pin_count(); idx += 1)
if (idx < ushift) {
connect(osig->pin(idx), zsig->pin(0));
} else {
connect(osig->pin(idx), lsig->pin(idx-ushift));
}
} else {
unsigned long dshift = 0-shift;
for (unsigned idx = 0; idx < osig->pin_count() ; idx += 1)
if (idx+dshift < lsig->pin_count())
connect(osig->pin(idx), lsig->pin(idx+dshift));
else
connect(osig->pin(idx), zsig->pin(0));
// part_width is the bits of the vector that survive the shift.
unsigned long part_width = osig->vector_width() - ushift;
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
/* Detect the special case that the shift is the size of
the whole expression. Simply connect the pad to the
osig and escape. */
if (ushift >= osig->vector_width()) {
connect(zcon->pin(0), osig->pin(0));
return osig;
}
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
connect(zcon->pin(0), zsig->pin(0));
/* Create a part select to reduce the width of the lsig
to the amount left by the shift. */
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
part_width,
NetPartSelect::VP);
des->add_node(psel);
NetNet*psig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, part_width);
psig->data_type(expr_type());
psig->local_flag(true);
psig->set_line(*this);
connect(psig->pin(0), psel->pin(0));
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), 2);
ccat->set_line(*this);
des->add_node(ccat);
connect(ccat->pin(0), osig->pin(0));
if (shift > 0) {
// Left shift.
connect(ccat->pin(1), zsig->pin(0));
connect(ccat->pin(2), psig->pin(0));
} else {
// Right shift
connect(ccat->pin(1), psig->pin(0));
connect(ccat->pin(2), zsig->pin(0));
}
return osig;
}
@@ -564,24 +514,23 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(expr_type());
osig->local_flag(true);
assert(op() == 'l');
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
osig->pin_count(),
rsig->pin_count(),
osig->vector_width(),
rsig->vector_width(),
right_flag, signed_flag);
dev->set_line(*this);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
connect(dev->pin_Result(idx), osig->pin(idx));
connect(dev->pin_Result(), osig->pin(0));
assert(lsig->pin_count() >= dev->width());
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
connect(dev->pin_Data(idx), lsig->pin(idx));
assert(lsig->vector_width() == dev->width());
connect(dev->pin_Data(), lsig->pin(0));
for (unsigned idx = 0 ; idx < dev->width_dist() ; idx += 1)
connect(dev->pin_Distance(idx), rsig->pin(idx));
connect(dev->pin_Distance(), rsig->pin(0));
return osig;
}
@@ -590,8 +539,15 @@ NetNet* NetEConcat::synthesize(Design*des)
{
/* First, synthesize the operands. */
NetNet**tmp = new NetNet*[parms_.count()];
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
bool flag = true;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
tmp[idx] = parms_[idx]->synthesize(des);
if (tmp[idx] == 0)
flag = false;
}
if (flag == false)
return 0;
assert(tmp[0]);
NetScope*scope = tmp[0]->scope();
@@ -601,20 +557,16 @@ NetNet* NetEConcat::synthesize(Design*des)
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
osig->local_flag(true);
osig->data_type(tmp[0]->data_type());
/* Connect the output vector to the operands. */
unsigned obit = 0;
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), parms_.count());
concat->set_line(*this);
des->add_node(concat);
connect(concat->pin(0), osig->pin(0));
assert(tmp[idx-1]);
for (unsigned bit = 0; bit < tmp[idx-1]->pin_count(); bit += 1) {
connect(osig->pin(obit), tmp[idx-1]->pin(bit));
obit += 1;
}
if (tmp[idx-1]->local_flag() && tmp[idx-1]->get_refs() == 0)
delete tmp[idx-1];
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
connect(concat->pin(idx+1), tmp[parms_.count()-idx-1]->pin(0));
}
delete[]tmp;
@@ -629,23 +581,39 @@ NetNet* NetEConst::synthesize(Design*des)
perm_string path = scope->local_symbol();
unsigned width=expr_width();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
for (unsigned idx = 0 ; idx < width; idx += 1)
connect(osig->pin(idx), con->pin(idx));
connect(osig->pin(0), con->pin(0));
des->add_node(con);
return osig;
}
/*
* Create a NetLiteral object to represent real valued constants.
*/
NetNet* NetECReal::synthesize(Design*des)
{
cerr << get_line() << ": error: Real constants are "
<< "not synthesizable." << endl;
des->errors += 1;
return 0;
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
osig->local_flag(true);
osig->data_type(IVL_VT_REAL);
osig->set_signed(has_sign());
osig->set_line(*this);
NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_);
des->add_node(con);
con->set_line(*this);
connect(osig->pin(0), con->pin(0));
return osig;
}
/*
@@ -659,28 +627,28 @@ NetNet* NetEUBits::synthesize(Design*des)
NetScope*scope = isig->scope();
assert(scope);
unsigned width = isig->vector_width();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, isig->pin_count());
NetNet::IMPLICIT, width);
osig->data_type(expr_type());
osig->local_flag(true);
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
perm_string oname = scope->local_symbol();
NetLogic*gate;
perm_string oname = scope->local_symbol();
NetLogic*gate;
switch (op()) {
case '~':
gate = new NetLogic(scope, oname, 2, NetLogic::NOT);
break;
default:
assert(0);
}
connect(osig->pin(idx), gate->pin(0));
connect(isig->pin(idx), gate->pin(1));
des->add_node(gate);
switch (op()) {
case '~':
gate = new NetLogic(scope, oname, 2, NetLogic::NOT, width);
break;
default:
assert(0);
}
connect(osig->pin(0), gate->pin(0));
connect(isig->pin(0), gate->pin(1));
des->add_node(gate);
return osig;
}
@@ -693,6 +661,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
@@ -702,32 +671,32 @@ NetNet* NetEUReduce::synthesize(Design*des)
case 'N':
case '!':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NOR);
NetLogic::NOR, 1);
break;
case '&':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::AND);
NetLogic::AND, 1);
break;
case '|':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::OR);
NetLogic::OR, 1);
break;
case '^':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XOR);
NetLogic::XOR, 1);
break;
case 'A':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NAND);
NetLogic::NAND, 1);
break;
case 'X':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XNOR);
NetLogic::XNOR, 1);
break;
default:
@@ -743,40 +712,122 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
#if 0
NetNet* NetEMemory::synthesize(Design *des)
{
NetNet*adr = idx_->synthesize(des);
NetScope*scope = adr->scope();
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
mem_, adr->vector_width());
des->add_node(ram);
ram->set_line(*this);
connect(ram->pin_Address(), adr->pin(0));
/* Create an output signal to receive the data. Assume that
memories return LOGIC. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, ram->width());
osig->data_type(IVL_VT_LOGIC);
osig->local_flag(true);
osig->set_line(*this);
connect(ram->pin_Q(), osig->pin(0));
return osig;
}
#endif
NetNet* NetESelect::synthesize(Design *des)
{
// XXXX For now, only support pad form
assert(base_ == 0);
NetNet*sub = expr_->synthesize(des);
if (sub == 0)
return 0;
NetScope*scope = sub->scope();
unsigned off = 0;
if (base_ != 0) {
// For now, only handle constant part selects in this
// context. NOTE: the elaboration that created the
// NetESelect already translated the part base to
// canonical form, so the base_ is canonical already.
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
assert(bcon);
long bval = bcon->value().as_long();
assert(bval >= 0);
off = bval;
}
/* If there is a part select, then generate a PartSelect node
to actually do the part select. This does not expansion,
that is handled later. */
if ((off != 0) || (off+expr_width() < sub->vector_width())) {
unsigned wid = expr_width();
if ((wid + off) > sub->vector_width())
wid = sub->vector_width() - off;
NetPartSelect*sel = new NetPartSelect(sub, off, wid,
NetPartSelect::VP);
sel->set_line(*this);
des->add_node(sel);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
sub = tmp;
connect(sub->pin(0), sel->pin(0));
}
/* Done? Vector is already the right width? then stop now. */
if (sub->vector_width() == expr_width())
return sub;
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
net->data_type(expr_type());
if (has_sign()) {
unsigned idx;
NetSignExtend*pad = new NetSignExtend(scope,
scope->local_symbol(),
expr_width());
pad->set_line(*this);
des->add_node(pad);
for (idx = 0 ; idx < sub->pin_count() ; idx += 1)
connect(sub->pin(idx), net->pin(idx));
for ( ; idx < net->pin_count(); idx += 1)
connect(sub->pin(sub->pin_count()-1), net->pin(idx));
connect(pad->pin(1), sub->pin(0));
connect(pad->pin(0), net->pin(0));
} else {
unsigned idx;
for (idx = 0 ; idx < sub->pin_count() ; idx += 1)
connect(sub->pin(idx), net->pin(idx));
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
verinum::V0);
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
expr_width(), 2);
cat->set_line(*this);
des->add_node(cat);
for ( ; idx < net->pin_count() ; idx += 1)
connect(net->pin(idx), tmp->pin(0));
assert(expr_width() > sub->vector_width());
unsigned pad_width = expr_width() - sub->vector_width();
verinum pad((uint64_t)0, pad_width);
NetConst*con = new NetConst(scope, scope->local_symbol(),
pad);
con->set_line(*this);
des->add_node(con);
des->add_node(tmp);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pad_width);
tmp->data_type(expr_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(tmp->pin(0), con->pin(0));
connect(cat->pin(0), net->pin(0));
connect(cat->pin(1), sub->pin(0));
connect(cat->pin(2), con->pin(0));
}
return net;
@@ -796,28 +847,28 @@ NetNet* NetETernary::synthesize(Design *des)
perm_string path = csig->scope()->local_symbol();
assert(csig->pin_count() == 1);
assert(csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
osig->data_type(expr_type());
osig->local_flag(true);
/* Make sure both value operands are the right width. */
tsig = pad_to_width(des, tsig, width);
fsig = pad_to_width(des, fsig, width);
tsig = crop_to_width(des, pad_to_width(des, tsig, width), width);
fsig = crop_to_width(des, pad_to_width(des, fsig, width), width);
assert(width <= tsig->pin_count());
assert(width <= fsig->pin_count());
assert(width == tsig->vector_width());
assert(width == fsig->vector_width());
perm_string oname = csig->scope()->local_symbol();
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(tsig->pin(idx), mux->pin_Data(idx, 1));
connect(fsig->pin(idx), mux->pin_Data(idx, 0));
connect(osig->pin(idx), mux->pin_Result(idx));
}
NetMux *mux = new NetMux(csig->scope(), oname, width,
2, csig->vector_width());
connect(tsig->pin(0), mux->pin_Data(1));
connect(fsig->pin(0), mux->pin_Data(0));
connect(osig->pin(0), mux->pin_Result());
connect(csig->pin(0), mux->pin_Sel());
des->add_node(mux);
connect(csig->pin(0), mux->pin_Sel(0));
return osig;
}
@@ -854,27 +905,87 @@ NetNet* NetETernary::synthesize(Design *des)
*/
NetNet* NetESignal::synthesize(Design*des)
{
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
return net_;
assert(msi_ >= lsi_);
unsigned wid = msi_ - lsi_ + 1;
NetScope*scope = net_->scope();
assert(scope);
perm_string name = scope->local_symbol();
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
tmp->local_flag(true);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(tmp->pin(idx), net_->pin(idx+lsi_));
return tmp;
return net_;
}
/*
* $Log: expr_synth.cc,v $
* Revision 1.82 2007/01/20 02:10:45 steve
* Get argument widths right for shift results.
*
* Revision 1.81 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.80 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.79 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.78 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.77 2006/05/01 20:47:59 steve
* More explicit datatype setup.
*
* Revision 1.76 2006/05/01 05:40:21 steve
* fix net type of multiply output.
*
* Revision 1.75 2006/04/30 05:17:48 steve
* Get the data type of part select results right.
*
* Revision 1.74 2006/01/03 05:15:33 steve
* Fix the return type of a synthesized divide.
*
* Revision 1.73 2005/09/15 23:04:09 steve
* Make sure div, mod and mult nodes have line number info.
*
* Revision 1.72 2005/08/31 05:07:31 steve
* Handle memory references is continuous assignments.
*
* Revision 1.71 2005/06/13 23:22:14 steve
* use NetPartSelect to shrink part from high bits.
*
* Revision 1.70 2005/06/13 22:26:03 steve
* Make synthesized padding vector-aware.
*
* Revision 1.69 2005/05/15 04:47:00 steve
* synthesis of Logic and shifts using vector gates.
*
* Revision 1.68 2005/05/06 00:25:13 steve
* Handle synthesis of concatenation expressions.
*
* Revision 1.67 2005/04/25 01:30:31 steve
* synthesis of add and unary get vector widths right.
*
* Revision 1.66 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.65 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.64 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.63 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.62 2005/01/28 05:39:33 steve
* Simplified NetMult and IVL_LPM_MULT.
*
* Revision 1.61 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors.
*
* Revision 1.60 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
+84
View File
@@ -0,0 +1,84 @@
Icarus Verilog Extensions
Icarus Verilog supports certain extensions to the baseline IEEE1364
standard. Some of these are picked from extended variants of the
language, such as SystemVerilog, and some are expressions of internal
behavior of Icarus Verilog, made available as a tool debugging aid.
* Builtin System Functions
** Extended Verilog Data Types
This feature is turned off if the generation flag "-g" is set to other
then the default "2x". For example, "iverilog -g2x" enables extended
data types, and "iverilog -g2" disables them.
Icarus Verilog adds support for extended data types. This extended
type syntax is based on a proposal by Cadence Design Systems,
originally as an update to the IEEE1364. That original proposal has
apparently been absorbed by the IEEE1800 SystemVerilog
standard. Icarus Verilog currently only takes the new primitive types
from the proposal.
Extended data types separates the concept of net/variable from the
data type. Both nets and variables can declared with any data
type. The primitive types available are:
logic - The familiar 0, 1, x and z, optionally with strength.
bool - Limited to only 0 and 1
real - 64bit real values
Nets with logic type may have multiple drivers with strength, and the
value is resolved the usual way. Only logic values may be driven to
logic nets, so bool values driven onto logic nets are implicitly
converted to logic.
Nets with any other type may not have multiple drivers. The compiler
should detect the multiple drivers and report an error.
- Declarations
The declaration of a net is extended to include the type of the wire,
with the syntax:
wire <type> <wire-assignment-list>... ;
The <type>, if omitted, is taken to be logic. The "wire" can be any of
the net keywords. Wires can be logic, bool, real, or vectors of logic
or bool. Some valid examples:
wire real foo = 1.0;
tri logic bus[31:0];
wire bool addr[23:0];
... and so on.
The declarations of variables is similar. The "reg" keyword is used to
specify that this is a variable. Variables can have the same data
types as nets.
- Ports
Module and task ports in standard verilog are restricted to logic
types. This extension removes that restriction, allowing any type to
pass through the port consistent with the continuous assignment
connectivity that is implied by the type.
- Expressions
Expressions in the face of real values is covered by the baseline
Verilog standard.
The bool type supports the same operators as the logic type, with the
obvious differences imposed by the limited domain.
Comparison operators (not case compare) return logic if either of
their operands is logic. If both are bool or real (including mix of
bool and real) then the result is bool. This is because comparison of
bools and reals always return exactly true or false.
Case comparison returns bool. This differs from baseline Verilog,
which strictly speaking returns a logic, but only 0 or 1 values.
All the arithmetic operators return bool if both of their operands are
bool or real. Otherwise, they return logic.
+38 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.cc,v 1.32 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
#endif
# include "config.h"
@@ -59,6 +59,10 @@ void functor_t::lpm_divide(class Design*, class NetDivide*)
{
}
void functor_t::lpm_literal(class Design*, class NetLiteral*)
{
}
void functor_t::lpm_modulo(class Design*, class NetModulo*)
{
}
@@ -79,6 +83,14 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
{
}
void functor_t::sign_extend(class Design*, class NetSignExtend*)
{
}
void functor_t::lpm_ureduce(class Design*, class NetUReduce*)
{
}
void NetScope::run_functor(Design*des, functor_t*fun)
{
@@ -186,6 +198,11 @@ void NetFF::functor_node(Design*des, functor_t*fun)
fun->lpm_ff(des, this);
}
void NetLiteral::functor_node(Design*des, functor_t*fun)
{
fun->lpm_literal(des, this);
}
void NetLogic::functor_node(Design*des, functor_t*fun)
{
fun->lpm_logic(des, this);
@@ -206,6 +223,16 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this);
}
void NetSignExtend::functor_node(Design*des, functor_t*fun)
{
fun->sign_extend(des, this);
}
void NetUReduce::functor_node(Design*des, functor_t*fun)
{
fun->lpm_ureduce(des, this);
}
proc_match_t::~proc_match_t()
{
}
@@ -267,6 +294,15 @@ int proc_match_t::event_wait(NetEvWait*)
/*
* $Log: functor.cc,v $
* Revision 1.35 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.34 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.33 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.32 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
+19 -2
View File
@@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
#endif
/*
@@ -63,6 +63,9 @@ struct functor_t {
/* This method is called for each structural constant. */
virtual void lpm_divide(class Design*des, class NetDivide*);
/* Constant literals. */
virtual void lpm_literal(class Design*des, class NetLiteral*);
/* This method is called for each structural constant. */
virtual void lpm_modulo(class Design*des, class NetModulo*);
@@ -77,6 +80,11 @@ struct functor_t {
/* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*);
/* This method is called for each unary reduction gate. */
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
virtual void sign_extend(class Design*des, class NetSignExtend*);
};
struct proc_match_t {
@@ -92,6 +100,15 @@ struct proc_match_t {
/*
* $Log: functor.h,v $
* Revision 1.23 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.22 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.21 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.20 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+10 -2
View File
@@ -17,11 +17,11 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.16 2006/09/26 18:54:42 steve Exp $"
# These are the variables used for compiling files
CC=gcc
CXX=gcc
CXX=g++
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
# These are used for linking...
@@ -63,11 +63,19 @@ do
;;
*.cc) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cc`
fi
;;
*.cpp) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cpp`
fi
;;
*.o) OBJ="$OBJ $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .o`
+27 -35
View File
@@ -9,9 +9,10 @@ ivl_design_roots
ivl_design_time_precision
ivl_const_bits
ivl_const_pin
ivl_const_pins
ivl_const_real
ivl_const_signed
ivl_const_type
ivl_const_width
ivl_event_any
ivl_event_basename
@@ -21,14 +22,13 @@ ivl_event_neg
ivl_event_nneg
ivl_event_npos
ivl_event_pos
ivl_event_scope
ivl_expr_type
ivl_expr_bits
ivl_expr_def
ivl_expr_dvalue
ivl_expr_event
ivl_expr_lsi
ivl_expr_memory
ivl_expr_name
ivl_expr_opcode
ivl_expr_oper1
@@ -44,33 +44,34 @@ ivl_expr_signed
ivl_expr_string
ivl_expr_uvalue
ivl_expr_value
ivl_expr_variable
ivl_expr_width
ivl_logic_attr
ivl_logic_attr_cnt
ivl_logic_attr_val
ivl_logic_delay
ivl_logic_name
ivl_logic_basename
ivl_logic_scope
ivl_logic_type
ivl_logic_delay
ivl_logic_drive0
ivl_logic_drive1
ivl_logic_name
ivl_logic_pin
ivl_logic_pins
ivl_logic_scope
ivl_logic_type
ivl_logic_udp
ivl_logic_width
ivl_lpm_array
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_base
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
ivl_lpm_datab
ivl_lpm_data2
ivl_lpm_data2_width
ivl_lpm_define
ivl_lpm_enable
ivl_lpm_memory
ivl_lpm_name
ivl_lpm_q
ivl_lpm_scope
@@ -79,25 +80,17 @@ ivl_lpm_selects
ivl_lpm_signed
ivl_lpm_size
ivl_lpm_sset_value
ivl_lpm_string
ivl_lpm_sync_clr
ivl_lpm_sync_set
ivl_lpm_type
ivl_lpm_width
ivl_lval_idx
ivl_lval_mem
ivl_lval_mux
ivl_lval_part_off
ivl_lval_pin
ivl_lval_pins
ivl_lval_sig
ivl_lval_var
ivl_memory_basename
ivl_memory_root
ivl_memory_scope
ivl_memory_size
ivl_memory_width
ivl_lval_width
ivl_nexus_get_private
ivl_nexus_name
@@ -127,8 +120,6 @@ ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
ivl_scope_lpm
ivl_scope_mem
ivl_scope_mems
ivl_scope_name
ivl_scope_param
ivl_scope_params
@@ -140,23 +131,29 @@ ivl_scope_sig
ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
ivl_scope_var
ivl_scope_vars
ivl_signal_array_base
ivl_signal_array_count
ivl_signal_attr
ivl_signal_attr_cnt
ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_integer
ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
ivl_signal_pin
ivl_signal_pins
ivl_signal_name
ivl_signal_nex
ivl_signal_npath
ivl_signal_path
ivl_signal_port
ivl_signal_signed
ivl_signal_type
ivl_signal_name
ivl_signal_basename
ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
@@ -184,8 +181,6 @@ ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_nevent
ivl_stmt_nexus
ivl_stmt_nexus_count
ivl_stmt_parm
ivl_stmt_parm_count
ivl_stmt_rval
@@ -197,6 +192,3 @@ ivl_udp_nin
ivl_udp_row
ivl_udp_rows
ivl_udp_sequ
ivl_variable_name
ivl_variable_type
+693 -193
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.17 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -44,18 +44,18 @@ CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
all: ivlpp
all: ivlpp@EXEEXT@
clean:
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
distclean: clean
rm -f Makefile
O = main.o lexor.o parse.o
ivlpp: $O
$(CC) $(LDFLAGS) $O -o ivlpp @EXTRALIBS@
ivlpp@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
lexor.c: lexor.lex
flex -s -olexor.c $(srcdir)/lexor.lex
@@ -63,16 +63,16 @@ lexor.c: lexor.lex
parse.h parse.c: parse.y
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
install: all installdirs $(libdir)/ivl/ivlpp
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp: ivlpp
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/ivlpp
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c parse.h globals.h
main.o: main.c globals.h
+1 -1
View File
@@ -37,7 +37,7 @@ valid options include:
Predefine the symbol ``name'' to have the specified
value. If the value is not specified, then ``1'' is
used. This is mostly of use for controlling conditional
compilaiton.
compilation.
This option does *not* override existing `define
directives in the source file.
+88 -34
View File
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $"
#ident "$Id: main.c,v 1.23 2006/10/02 18:16:18 steve Exp $"
#endif
# include "config.h"
@@ -58,6 +58,8 @@ extern int getopt(int argc, char*argv[], const char*fmt);
extern int optind;
extern const char*optarg;
#endif
/* Path to the dependency file, if there is one. */
char *dep_path = NULL;
/*
* Keep in source_list an array of pointers to file names. The array
@@ -89,6 +91,76 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
fprintf(stderr, "%s: unable to open for reading.\n", path);
return -1;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
/* Skip leading white space. */
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace(tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
/* Skip empty lines */
if (*cp == 0)
continue;
/* Skip comment lines */
if (cp[0] == '#')
continue;
/* The arg points to the argument to the keyword. */
char*arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
char*val = strchr(arg, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(arg, val, 0);
} else if (strcmp(cp,"I") == 0) {
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(arg);
include_cnt += 1;
} else if (strcmp(cp,"keyword") == 0) {
char*buf = malloc(strlen(arg) + 2);
buf[0] = '`';
strcpy(buf+1, optarg);
define_macro(optarg, buf, 1);
free(buf);
} else if (strcmp(cp,"M") == 0) {
if (dep_path) {
fprintf(stderr, "duplicate -M flag.\n");
} else {
dep_path = strdup(arg);
}
} else {
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
}
}
fclose(fd);
return 0;
}
/*
* This function reads from a file a list of file names. Each name
* starts with the first non-space character, and ends with the last
@@ -127,7 +199,6 @@ int main(int argc, char*argv[])
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
char *dep_path = NULL;
FILE*out;
/* Define preprocessor keywords that I plan to just pass. */
@@ -153,20 +224,11 @@ int main(int argc, char*argv[])
include_dir[0] = strdup(".");
include_cnt = 1;
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) {
case 'D': {
char*tmp = strdup(optarg);
char*val = strchr(tmp, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(tmp, val, 0);
free(tmp);
break;
}
case 'F':
flist_read_flags(optarg);
break;
case 'f':
if (flist_path) {
@@ -176,13 +238,6 @@ int main(int argc, char*argv[])
flist_path = optarg;
break;
case 'I':
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(optarg);
include_cnt += 1;
break;
case 'K': {
char*buf = malloc(strlen(optarg) + 2);
buf[0] = '`';
@@ -196,14 +251,6 @@ int main(int argc, char*argv[])
line_direct_flag = 1;
break;
case 'M':
if (dep_path) {
fprintf(stderr, "duplicate -M flag.\n");
} else {
dep_path = optarg;
}
break;
case 'o':
if (out_path) {
fprintf(stderr, "duplicate -o flag.\n");
@@ -225,13 +272,11 @@ int main(int argc, char*argv[])
}
if (flag_errors) {
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
" -D<def> - Predefine a value.\n"
fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
" -F<fil> - Get defines and includes from file\n"
" -f<fil> - Read the sources listed in the file\n"
" -I<dir> - Add an include file search directory\n"
" -K<def> - Define a keyword macro that I just pass\n"
" -L - Emit line number directives\n"
" -M<fil> - Write dependencies to <fil>\n"
" -o<fil> - Send the output to <fil>\n"
" -v - Print version information\n",
argv[0]);
@@ -290,6 +335,15 @@ int main(int argc, char*argv[])
/*
* $Log: main.c,v $
* Revision 1.23 2006/10/02 18:16:18 steve
* Save dep_path because arg space is overrun.
*
* Revision 1.22 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.21 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
*
* Revision 1.20 2004/09/10 00:15:45 steve
* Remove bad casts.
*
+26 -6
View File
@@ -1,4 +1,6 @@
%option never-interactive
%{
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
@@ -19,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $"
#ident "$Id: lexor.lex,v 1.92 2006/07/31 03:50:17 steve Exp $"
#endif
# include "config.h"
@@ -132,6 +134,7 @@ W [ \t\b\f\r]+
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
">>" { return K_RS; }
">>>" { return K_RSS; }
"**" { return K_POW; }
"<=" { return K_LE; }
">=" { return K_GE; }
"=>" { return K_EG; }
@@ -154,7 +157,7 @@ W [ \t\b\f\r]+
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it
with "*" and return that. */
"(*"{W}*")" { return '*'; }
"("{W}*"*"{W}*")" { return '*'; }
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
@@ -179,6 +182,8 @@ W [ \t\b\f\r]+
<UDPTABLE>\(01\) { return 'r'; }
<UDPTABLE>\(0[xX]\) { return 'Q'; }
<UDPTABLE>\(b[xX]\) { return 'q'; }
<UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
<UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
<UDPTABLE>\(0\?\) { return 'P'; }
<UDPTABLE>\(10\) { return 'f'; }
<UDPTABLE>\(1[xX]\) { return 'M'; }
@@ -198,12 +203,27 @@ W [ \t\b\f\r]+
[a-zA-Z_][a-zA-Z0-9$_]* {
int rc = lexor_keyword_code(yytext, yyleng);
if (rc == IDENTIFIER) {
switch (rc) {
case IDENTIFIER:
yylval.text = strdup(yytext);
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
rc = PATHPULSE_IDENTIFIER;
} else {
break;
case K_bool:
case K_logic:
case K_wone:
if (! gn_cadence_types_enabled()) {
yylval.text = strdup(yytext);
rc = IDENTIFIER;
} else {
yylval.text = 0;
}
break;
default:
yylval.text = 0;
break;
}
return rc;
@@ -276,10 +296,10 @@ W [ \t\b\f\r]+
^{W}?`disable_portfaults{W}?.* { }
^{W}?`enable_portfaults{W}?.* { }
^{W}?`endcelldefine{W}?.* { }
^{W}?`endprotect{W}?.* { }
`endprotect { }
^{W}?`nosuppress_faults{W}?.* { }
^{W}?`nounconnected_drive{W}?.* { }
^{W}?`protect{W}?.* { }
`protect { }
^{W}?`resetall{W}?.* { }
^{W}?`suppress_faults{W}?.* { }
^{W}?`unconnected_drive{W}?.* { }
+7
View File
@@ -14,6 +14,7 @@ always, K_always
and, K_and
assign, K_assign
begin, K_begin
bool, K_bool
buf, K_buf
bufif0, K_bufif0
bufif1, K_bufif1
@@ -30,6 +31,7 @@ else, K_else
end, K_end
endcase, K_endcase
endfunction, K_endfunction
endgenerate, K_endgenerate
endmodule, K_endmodule
endprimitive, K_endprimitive
endspecify, K_endspecify
@@ -41,9 +43,12 @@ force, K_force
forever, K_forever
fork, K_fork
function, K_function
generate, K_generate
genvar, K_genvar
highz0, K_highz0
highz1, K_highz1
if, K_if
ifnone, K_ifnone
initial, K_initial
inout, K_inout
input, K_input
@@ -51,6 +56,7 @@ integer, K_integer
join, K_join
large, K_large
localparam, K_localparam
logic, K_logic
macromodule, K_macromodule
medium, K_medium
module, K_module
@@ -110,6 +116,7 @@ weak0, K_weak0
weak1, K_weak1
while, K_while
wire, K_wire
wone, K_wone
wor, K_wor
xnor, K_xnor
xor, K_xor
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $"
#ident "$Id: Makefile.in,v 1.35 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -92,7 +92,7 @@ clean:
rm -rf *.o dep libveriuser.a libveriuser.o bin32
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -f Makefile config.status config.log config.cache config.h
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: a_next.c,v 1.3 2003/06/17 16:55:07 steve Exp $"
#ident "$Id: a_next.c,v 1.4 2006/10/30 22:45:37 steve Exp $"
#endif
#include <stdio.h>
@@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
/* trace */
if (pli_trace) {
int *ip;
PLI_INT32 *ip;
fprintf(pli_trace, "acc_next(%p <", type);
for (ip = type; *ip; ip++) {
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
@@ -94,6 +94,9 @@ handle acc_next_scope(handle scope, handle prev)
/*
* $Log: a_next.c,v $
* Revision 1.4 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2003/06/17 16:55:07 steve
* 1) setlinebuf() for vpi_trace
* 2) Addes error checks for trace file opens
+2
View File
@@ -1,6 +1,8 @@
AC_INIT(Makefile.in)
AC_CONFIG_HEADER(config.h)
AC_CANONICAL_HOST
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_RANLIB
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: getinstance.c,v 1.4 2003/05/18 00:16:35 steve Exp $"
#ident "$Id: getinstance.c,v 1.5 2005/09/20 18:34:01 steve Exp $"
#endif
#include <veriuser.h>
@@ -28,11 +28,14 @@
*/
PLI_BYTE8* tf_getinstance(void)
{
return (char *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
return (PLI_BYTE8 *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
}
/*
* $Log: getinstance.c,v $
* Revision 1.5 2005/09/20 18:34:01 steve
* Clean up compiler warnings.
*
* Revision 1.4 2003/05/18 00:16:35 steve
* Add PLI_TRACE tracing of PLI1 modules.
*
+11 -8
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: veriusertfs.c,v 1.15 2004/09/10 23:13:05 steve Exp $"
#ident "$Id: veriusertfs.c,v 1.16 2006/10/30 22:45:37 steve Exp $"
#endif
/*
@@ -44,9 +44,9 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data;
static int compiletf(char *);
static int calltf(char *);
static int callback(p_cb_data);
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 callback(p_cb_data);
/*
* Register veriusertfs routines/wrappers. Iterate over the tfcell
@@ -139,7 +139,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires.
*/
static int compiletf(char *data)
static PLI_INT32 compiletf(char *data)
{
p_pli_data pli;
p_tfcell tf;
@@ -221,7 +221,7 @@ static int compiletf(char *data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static int calltf(char *data)
static PLI_INT32 calltf(char *data)
{
int rc = 0;
p_pli_data pli;
@@ -249,13 +249,13 @@ static int calltf(char *data)
*/
extern int async_misctf_enable;
static int callback(p_cb_data data)
static PLI_INT32 callback(p_cb_data data)
{
p_pli_data pli;
p_tfcell tf;
int reason;
int paramvc = 0;
int rc;
PLI_INT32 rc;
/* not enabled */
if (data->reason == cbValueChange && !async_misctf_enable)
@@ -389,6 +389,9 @@ PLI_INT32 tf_setrealdelay(double dly)
}
/*
* $Log: veriusertfs.c,v $
* Revision 1.16 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.15 2004/09/10 23:13:05 steve
* Compile cleanup of C code.
*
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $"
#ident "$Id: load_module.cc,v 1.13 2005/03/22 15:53:48 steve Exp $"
#endif
# include "config.h"
@@ -88,7 +88,7 @@ bool load_module(const char*type)
cerr << "Executing: " << cmdline << endl;
pform_parse(path, file);
fclose(file);
pclose(file);
free(cmdline);
} else {
@@ -193,6 +193,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
/*
* $Log: load_module.cc,v $
* Revision 1.13 2005/03/22 15:53:48 steve
* popen must be matched by pclose.
*
* Revision 1.12 2003/06/05 04:31:09 steve
* INclude missing assert.h in load_module.
*
+80 -14
View File
@@ -1,6 +1,6 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2004 Stephen Williams ([email protected])";
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
@@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: main.cc,v 1.93 2006/09/28 04:35:18 steve Exp $"
#endif
# include "config.h"
@@ -81,7 +81,14 @@ const char*basedir = ".";
const char*target = "null";
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
* is a major moce, and the gn_* flags control specifc sub-features.
*/
generation_t generation_flag = GN_DEFAULT;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
map<string,const char*> flags;
char*vpi_module_list = 0;
@@ -112,6 +119,7 @@ bool error_implicit = false;
bool debug_scopes = false;
bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
/*
* Verbose messages enabled.
*/
@@ -137,7 +145,9 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@@ -149,7 +159,9 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -175,17 +187,29 @@ const char *net_func_to_name(const net_func func)
static void process_generation_flag(const char*gen)
{
if (strcmp(gen,"1") == 0)
if (strcmp(gen,"1") == 0) {
generation_flag = GN_VER1995;
else if (strcmp(gen,"2") == 0)
} else if (strcmp(gen,"2") == 0) {
generation_flag = GN_VER2001;
else if (strcmp(gen,"3.0") == 0)
generation_flag = GN_SYSVER30;
} else if (strcmp(gen,"2x") == 0) {
generation_flag = GN_VER2001X;
else
generation_flag = GN_DEFAULT;
} else if (strcmp(gen,"xtypes") == 0) {
gn_cadence_types_flag = true;
} else if (strcmp(gen,"no-xtypes") == 0) {
gn_cadence_types_flag = false;
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else {
}
}
static void parm_to_flagmap(const string&flag)
@@ -246,7 +270,7 @@ static void parm_to_flagmap(const string&flag)
* functor:<name>
* Append a named functor to the processing path.
*
* generation:<1|2|3.0>
* generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
* This is the generation flag
*
* ivlpp:<preprocessor command>
@@ -314,6 +338,9 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"elaborate") == 0) {
debug_elaborate = true;
cerr << "debug: Enable elaborate debug" << endl;
} else if (strcmp(cp,"synth2") == 0) {
debug_synth2 = true;
cerr << "debug: Enable synth2 debug" << endl;
} else {
}
@@ -540,11 +567,21 @@ int main(int argc, char*argv[])
case GN_VER2001:
cout << "IEEE1364-2001";
break;
case GN_SYSVER30:
cout << "SystemVerilog 3.0";
case GN_VER2001X:
cout << "IEEE1364-2001+Extensions";
break;
}
if (gn_specify_blocks_flag)
cout << ",specify";
else
cout << ",no-specify";
if (gn_cadence_types_flag)
cout << ",xtypes";
else
cout << ",no-xtypes";
cout << endl << "PARSING INPUT" << endl;
}
@@ -697,12 +734,18 @@ int main(int argc, char*argv[])
cout << "CODE GENERATION -t "<<target<< endl;
}
bool emit_rc;
int emit_rc;
emit_rc = emit(des, target);
if (!emit_rc) {
cerr << "error: Code generation had errors." << endl;
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
if (verbose_flag) {
if (times_flag) {
@@ -744,6 +787,29 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.93 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.92 2005/07/14 23:38:43 steve
* Display as version 0.9.devel
*
* Revision 1.91 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.90 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.89 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.88 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.87 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
+109 -108
View File
@@ -2,7 +2,7 @@
MINGW PORT OF ICARUS VERILOG
Copyright 2003 Stephen Williams <[email protected]>
Copyright 2006 Stephen Williams <[email protected]>
Icarus Verilog source can be compiled with the mingw C/C++ compilers
@@ -12,13 +12,13 @@ or without Cygwin, so this is the preferred Windows distribution form.
The configure scripts automatically detect that the compilers in use
are the mingw compilers and will configure the Makefiles appropriately.
However, the mingw tools do not include all the other tools around the
compiler, including the shell interpreter for the configure script,
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
Icarus Verilog, even if you don't need the Cygwin compilers. There are
also a few precompiled library prerequisites that you need.
The mingw patch doesn't contain tools beyond the compiler, but there
is the "msys" package that the makers of Mingw publish that has enough
extra tools to get most everything else working. There are a few extra
packages needed beyond mingw and msys, and the following instructions
explain how to get them and install them.
* Some Preliminary Comments
* Some Preliminary Comments -- PLEASE READ ME --
The Windows port of Icarus Verilog is the most difficult of all the
ports. The Windows system off the shelf is completely stripped, devoid
@@ -26,7 +26,15 @@ of any support for software development. Everything needed to compile
Icarus Verilog must be collected from various sources and stitched
together by hand. Normal human beings with a basic understanding of
software development can do this, but some patience (and access to the
Internet) is required. You may choose to print these instructions.
Internet) is required. You may choose to print these instructions. FOR
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
NOTE that if you have Cygwin installed, it is best to not use a cygwin
window to do the build, as the Cygwin tools will intermix with the
mingw tools such that it is hard to be sure you are using the right
compiler. Thus, it is recommended that these steps be *not* done in a
Cygwin window. Use an MSYS window instead, and be careful that your
msys/mingw tools are not masked by paths that point to Cygwin binaries.
I have no plans to intentionally support MSVC++ compilation. Don't ask.
@@ -36,13 +44,15 @@ This is a brief list of prerequisite packages, along with the URL
where each can be found. In most cases, the specific version is not
critical, but these are the versions I use.
Cygwin <http://cygwin.com>
Mingw32-2.0.0 <http://www.mingw.org>
msys-1.0 <http://www.mingw/org>
msysDTK-1.0 <http://www.mingw.org>
Mingw32-5.x <http://www.mingw.org>
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net>
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip <http://gnuwin32.sourceforge.net>
zlib-1.1.4-lib.zip <http://gnuwin32.sourceforge.net>
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
bison-2.1 <http://gnuwin32.sourceforge.net>
flex-2.5.4a <http://gnuwin32.sourceforge.net>
The above table lists the packages required. It is convenient to
install them in the above order. Many of these packages are also
@@ -55,59 +65,38 @@ installation of Icarus Verilog is complete. These are only needed to
build the compiler. The Mingw32 package can be used to compile VPI
modules if you choose.
* Install Cygwin
* Install MSYS and msysDTK
So, step 1 is "Download and Install Cygwin." See the web page
http://www.cygwin.com for instructions and the files to do
this. Cygwin *is* a kool package, and is worth having anyhow. There is
a convenient setup program that you download first. You execute the
setup program, and that prompts you to select the package you want.
The msys package is available from the mingw download site. This is
not the compiler but a collection of *nix tools ported to Windows and
wrapped in a convenient installer. The msys package is all the various
basic tools (shells, file utils, etc) and the msysDTK is extra
developer tools other then the compiler.
You need in particular the Cygwin base, bison (see notes) flex, make
and gperf. If you are compiling from CVS, you also need cvs, rcs and
automake packages. You will also need tar and gunzip, but these are
hard to not install. I recommend installing the "which" package as
well. Beyond the basics, be sure to install these Cygwin packages:
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.)
bison (*not* 1.875. See Notes.)
flex
ghostscript (makes the documentation)
gperf
gzip
make
strip
tar (tar and gunzip for unpacking the source)
unzip (For unpacking zip compressed packages.)
which
This install should be easy and reliable.
NOTES:
bison-1.875 is broken, it generates invalid C/C++ code. You
don't want that version for anything you do. If you have that
version (use "bison -V" to check the version) then use the
Cygwin setup program to get a different version. I've downgraded
to 1.75 and couldn't be happier. In fact, a whole host of insane
bison bugs can be avoided that way.
There is a mingw32 runtime package included in the Cygwin
distribution. You do *not* need that, as you will be getting
everything from the mingw32 distribution itself.
Other then the install of mingw32, most of the remaining steps are
best done in a Cygwin window. When you installed Cygwin, a start menu
entry was created to allow you to start up the Cygwin window. I'll use
the string "$ " to represent a command prompt in this window, because
that is the usual bash prompt.
The installation will leave an "msys" icon on your desktop and in the
mingw sub-menu of your Start menu. This icon brings up a shell window
(a command line) that has paths all set up for executing msys and
mingw commands. This is what you will want to use while executing
commands below.
* Install Mingw32
The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version
comes prepackaged in a convenient, Windows style, installer. I
recommend you download this package instead of picking and choosing
bits.
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
is a convenient remote installer. Download this program and run
it. The installer will ask wich components you want to install. You
need only the base C compiler and the C++ compiler. (You may install
other languages if you wish.)
When I install Mingw32 (using the installer) I typically set a
destination directory of d:\mingw-2.0.0 or the like. You will be using
destination directory of d:\mingw or the like. You will be using
that path later.
NOTES:
@@ -115,6 +104,10 @@ that path later.
need Mingw32, even if you are using a precompiled binary. VPI
modules only require Mingw32, and none of the other libraries.
Finally, as part of installing the mingw32 compilers, remember to add
the mingw/bin directory to your path. You will need that to be able to
find the compilers later.
* Install Mingw32 Packages
There is a collection of precompiled libraries and add-on packages
@@ -123,86 +116,94 @@ with simplified Windows installers, but they are pretty easy to
install by hand. Icarus Verilog uses the readline-4.2 package from
that collection.
Since I installed Mingw32 in d:\mingw-2.0.0, I also created a
Mingw-packages directory called d:\mingw-packages. The install, then,
Since I installed Mingw32 in c:\mingw, I also created a
Mingw-packages directory called c:\mingw-packages. The install, then,
is as easy as this:
<cygwin shell>
$ cd d:/mingw-packages
<msys shell>
$ cd c:/mingw-packages
$ unzip readline-4.2-20010727.zip
[lots of inflating...]
There is no need to adjust your execution path for this package as we
are only using a library out of here. However, do remember the
directory name, as you will need it later.
Done. On to the next packages.
* Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and
libraries ported to Windows. These also work well with the Mingw
compiler, and in fact Icarus Verilog uses a few libraries from this
compiler, and in fact Icarus Verilog uses a few pieces from this
collection.
You will need these gnuwin32 packages to compile Icarus Verilog:
<http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip
bzip2-1.0.2-bin.zip
zlib-1.1.4-lib.zip
zlib-1.1.4-bin.zip
bzip2-1.0.3.exe
zlib-1.2.3.exe
gperf-3.0.1.exe
bison-2.1.exe
flex-2.5.4a.exe
I suggest creating a common directory for holding all your gnuwin32
packages. I use D:\gnuwin32.
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
has a "setup" link for each of these packages. Click the setup to
download the installer for each of the desired programes, then execute
the downloaded .exe files to invoke the installer. Install into the
c:\gunwin32 directory.
After downloading these packages, put the .zip files in your gnuwin32
directory and install them like so:
NOTES:
You need the binaries and the developer files, but you do not
need the source to these packages. The installer gives you the
choice.
<cygwin shell>
$ cd d:/gnuwin32
$ unzip bzip2-1.0.2-bin.zip
[lots of inflating...]
$ unzip bzip2-1.0.2-lib.zip
[lots of inflating...]
$ unzip zlib-1.1.4-bin.zip
[lots of inflating...]
$ unzip zlib-1.1.4-lib.zip
[lots of inflating...]
Done.
After you are done installing the gnuwin32 tools, you should add the
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
your Windows path. The msys shell will pick up your Windows path.
* Unpack Icarus Verilog source
Unpack the compressed tar file (.tar.gz) of the source with a command
like this:
$ gunzip -d verilog-20030303.tar.gz | tar xvf -
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
This will create a directory "verilog-20030303" that contains all the
This will create a directory "verilog-xxxxxxxx" that contains all the
source for Icarus Verilog. Descend into that directory, as that is
where we will work from now on.
$ cd verilog-20030303
$ cd verilog-xxxxxxxx
NOTE:
NOTES:
The exact name of the file will vary according to the
snapshot. The 20030303 name is only an example.
* Select the mingw compilers
Unpack the source into a directory that has no spaces. The
makefiles included in the source get confused by white space in
directory names.
In your cygwin window, if you type "which c++" you might get the
response path "/usr/bin/c++" which is the cygwin compiler. This is not
the one we want to use, however. Tell the shell where the mingw
compilers are by setting the search path like so:
* Preconfigure Icarus Verilog (Not normally needed)
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH
Under certain cases, you may need to "preconfigure" the Icarus Verilog
source tree. You should only need to do this if you are getting the
Icarus Verilog source tree from CVS, or you are using an existing
source tree that you've patched to cause configure.in files to change.
This assumes that you installed mingw in D:\mingw-2.0.0. The actual
programs are in the bin directory under the root. After this command,
check that you are now getting the right compilers with this "which"
command:
NOTE: If you are building from a fresh, bundled source tree that
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
the "Configure Icarus Verilog" step below.
$ which c++
/cygdrive/d/mingw-2.0.0/bin/c++
First, remove any autom4te.cache directories that may exist in your
source tree. These can make a mess of autoconf runs. Then, generate
configure scripts with this command:
Good!
$ sh autoconf.sh
This script will run the "autoconf" command (part of the msysDTK) to
generate all the necessary "configure" scripts. This will take a few
minutes. This should go smoothly.
* Configure Icarus Verilog
@@ -215,10 +216,10 @@ without white space.
Now, configure the source to make the makefiles and configuration
details. Run these commands:
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
$ export CPPFLAGS LDFLAGS
$ ./configure --prefix=d:/iverilog
$ ./configure --prefix=c:/iverilog
NOTES:
The CPPFLAGS and LDFLAGS variables tell configure where
@@ -267,10 +268,10 @@ directory you chose) and away you go.
You may find that you need to put some of the prerequisite DLLs into
the d:\iverilog\bin directory. These include:
d:\mingw-2.0.0\bin\mingw10.dll
d:\mingw-packages\bin\libreadline.dll
d:\gnuwin32\bin\bzip2.dll
d:\gnuwin32\bin\zlib.dll
c:\mingw\bin\mingw10.dll
c:\mingw-packages\bin\libreadline.dll
c:\gnuwin32\bin\bzip2.dll
c:\gnuwin32\bin\zlib.dll
If you already have these in your Windows path (i.e. your system32
directory) then you do not need to copy them into the iverilog
@@ -279,14 +280,14 @@ files.
* Running Icarus Verilog
Finally, put the D:\iverilog\bin directory in your Windows path, and
Finally, put the C:\iverilog\bin directory in your Windows path, and
you should be able to run the iverilog and vvp commands to your
heart's content.
Currently, the iverilog.exe uses the path to itself to locate the
libraries and modules associated with itself. In other words, if you
execute the D:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the D:\iverilog directory and subdirectories below
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the C:\iverilog directory and subdirectories below
that. This means you can move the Icarus Verilog installation by
simply moving the root directory and all its contents.
+73 -90
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.18 2004/08/28 15:08:31 steve Exp $"
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -39,30 +39,13 @@ unsigned count_lval_width(const NetAssign_*idx)
}
NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), var_(0), bmux_(0)
: sig_(s), word_(0), base_(0)
{
loff_ = 0;
lwid_ = sig_->pin_count();
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
}
NetAssign_::NetAssign_(NetMemory*s)
: sig_(0), mem_(s), var_(0), bmux_(0)
{
loff_ = 0;
lwid_ = mem_->width();
more = 0;
}
NetAssign_::NetAssign_(NetVariable*s)
: sig_(0), mem_(0), var_(s), bmux_(0)
{
loff_ = 0;
lwid_ = 0;
more = 0;
}
NetAssign_::~NetAssign_()
{
if (sig_) {
@@ -72,38 +55,39 @@ NetAssign_::~NetAssign_()
}
assert( more == 0 );
if (bmux_) delete bmux_;
if (word_) delete word_;
}
void NetAssign_::set_bmux(NetExpr*r)
void NetAssign_::set_word(NetExpr*r)
{
assert(bmux_ == 0);
bmux_ = r;
assert(word_ == 0);
word_ = r;
}
NetExpr* NetAssign_::bmux()
NetExpr* NetAssign_::word()
{
return bmux_;
return word_;
}
const NetExpr* NetAssign_::bmux() const
const NetExpr* NetAssign_::word() const
{
return bmux_;
return word_;
}
const NetExpr* NetAssign_::get_base() const
{
return base_;
}
unsigned NetAssign_::lwidth() const
{
if (mem_) return lwid_;
else if (bmux_) return 1;
else return lwid_;
return lwid_;
}
perm_string NetAssign_::name() const
{
if (sig_) {
return sig_->name();
} else if (mem_) {
return mem_->name();
} else {
return perm_string::literal("");
}
@@ -114,32 +98,10 @@ NetNet* NetAssign_::sig() const
return sig_;
}
NetMemory* NetAssign_::mem() const
void NetAssign_::set_part(NetExpr*base, unsigned wid)
{
return mem_;
}
NetVariable* NetAssign_::var() const
{
return var_;
}
void NetAssign_::set_part(unsigned lo, unsigned lw)
{
loff_ = lo;
lwid_ = lw;
if (sig_) {
assert(sig_->pin_count() >= (lo + lw));
} else {
assert(mem_);
assert(lwid_ == mem_->width());
}
}
unsigned NetAssign_::get_loff() const
{
return loff_;
base_ = base;
lwid_ = wid;
}
/*
@@ -259,8 +221,61 @@ NetAssignNB::~NetAssignNB()
{
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetCAssign::~NetCAssign()
{
}
NetDeassign::NetDeassign(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetDeassign::~NetDeassign()
{
}
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetForce::~NetForce()
{
}
NetRelease::NetRelease(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.22 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*
@@ -270,37 +285,5 @@ NetAssignNB::~NetAssignNB()
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.15 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2002/08/04 18:28:15 steve
* Do not use hierarchical names of memories to
* generate vvp labels. -tdll target does not
* used hierarchical name string to look up the
* memory objects in the design.
*
* Revision 1.13 2002/07/02 03:02:57 steve
* Change the signal to a net when assignments go away.
*
* Revision 1.12 2002/06/08 23:42:46 steve
* Add NetRamDq synthsesis from memory l-values.
*
* Revision 1.11 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.10 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*
* Revision 1.9 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*/
+35 -76
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.45 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: net_design.cc,v 1.50 2006/08/08 05:11:37 steve Exp $"
#endif
# include "config.h"
@@ -67,8 +67,8 @@ int Design::get_precision() const
return des_precision_;
}
unsigned long Design::scale_to_precision(unsigned long val,
const NetScope*scope) const
uint64_t Design::scale_to_precision(uint64_t val,
const NetScope*scope) const
{
int units = scope->time_unit();
assert( units >= des_precision_ );
@@ -173,71 +173,6 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
return find_scope(path);
}
/*
* Find a parameter from within a specified context. If the name is
* not here, keep looking up until I run out of up to look at. The
* method works by scanning scopes, starting with the passed scope and
* working up towards the root, looking for the named parameter. The
* name in this case can be hierarchical, so there is an inner loop to
* follow the scopes of the name down to to key.
*
* The expression value of the parameter is returned as the result,
* and the scope that contains the parameter is returned in the out
* argument found_in.
*/
const NetExpr* Design::find_parameter(NetScope*scope,
const hname_t&path,
NetScope*&found_in) const
{
for ( ; scope ; scope = scope->parent()) {
unsigned hidx = 0;
NetScope*cur = scope;
while (path.peek_name(hidx+1)) {
cur = cur->child(path.peek_name(hidx));
if (cur == 0)
break;
hidx += 1;
}
if (cur == 0)
continue;
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx))) {
found_in = cur;
return res;
}
}
return 0;
}
const NetExpr* Design::find_parameter(const NetScope*scope,
const hname_t&path) const
{
for ( ; scope ; scope = scope->parent()) {
unsigned hidx = 0;
const NetScope*cur = scope;
while (path.peek_name(hidx+1)) {
cur = cur->child(path.peek_name(hidx));
if (cur == 0)
break;
hidx += 1;
}
if (cur == 0)
continue;
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx)))
return res;
}
return 0;
}
/*
* This method runs through the scope, noticing the defparam
* statements that were collected during the elaborate_scope pass and
@@ -390,18 +325,27 @@ void NetScope::evaluate_parameters(Design*des)
assert(expr);
switch (expr->expr_type()) {
case NetExpr::ET_REAL:
case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
"unable to evaluate real parameter values: " <<
*expr << endl;
des->errors += 1;
continue;
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate real parameter value: "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
}
break;
case NetExpr::ET_VECTOR:
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
if (! dynamic_cast<const NetEConst*>(expr)) {
// Try to evaluate the expression.
@@ -618,6 +562,21 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.50 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.49 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.48 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.47 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.46 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.45 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
+89 -33
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_expr.cc,v 1.23 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
#endif
# include "config.h"
@@ -25,9 +25,12 @@
# include "compiler.h"
# include <iostream>
NetExpr::TYPE NetExpr::expr_type() const
/*
* the grand default data type is a logic vector.
*/
ivl_variable_type_t NetExpr::expr_type() const
{
return ET_VECTOR;
return IVL_VT_LOGIC;
}
/*
@@ -96,15 +99,15 @@ NetEBAdd* NetEBAdd::dup_expr() const
return result;
}
NetExpr::TYPE NetEBAdd::expr_type() const
ivl_variable_type_t NetEBAdd::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
return ET_VECTOR;
return IVL_VT_LOGIC;
}
/*
@@ -161,6 +164,21 @@ bool NetEBComp::has_width() const
return true;
}
ivl_variable_type_t NetEBComp::expr_type() const
{
// Case compare always returns BOOL
if (op() == 'E' || op() == 'N')
return IVL_VT_BOOL;
if (left()->expr_type() == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
if (right()->expr_type() == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
return IVL_VT_BOOL;
}
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
@@ -183,15 +201,15 @@ NetEBDiv* NetEBDiv::dup_expr() const
return result;
}
NetExpr::TYPE NetEBDiv::expr_type() const
ivl_variable_type_t NetEBDiv::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
return ET_VECTOR;
return IVL_VT_LOGIC;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
@@ -219,15 +237,49 @@ NetEBMult* NetEBMult::dup_expr() const
return result;
}
NetExpr::TYPE NetEBMult::expr_type() const
ivl_variable_type_t NetEBMult::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
return ET_VECTOR;
return IVL_VT_LOGIC;
}
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
assert(op == 'p');
expr_width(l->expr_width());
cast_signed(l->has_sign() || r->has_sign());
}
NetEBPow::~NetEBPow()
{
}
NetEBPow* NetEBPow::dup_expr() const
{
NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
right_->dup_expr());
result->set_line(*this);
return result;
}
ivl_variable_type_t NetEBPow::expr_type() const
{
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
@@ -372,9 +424,9 @@ NetECReal* NetECReal::dup_expr() const
return tmp;
}
NetExpr::TYPE NetECReal::expr_type() const
ivl_variable_type_t NetECReal::expr_type() const
{
return ET_REAL;
return IVL_VT_REAL;
}
NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
@@ -450,15 +502,7 @@ bool NetESelect::has_width() const
return true;
}
bool NetESelect::set_width(unsigned w)
{
if (expr_width() == 1)
return true;
else
return false;
}
NetESFunc::NetESFunc(const char*n, NetExpr::TYPE t,
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
unsigned width, unsigned np)
: name_(0), type_(t)
{
@@ -509,13 +553,25 @@ NetExpr* NetESFunc::parm(unsigned idx)
return parms_[idx];
}
NetExpr::TYPE NetESFunc::expr_type() const
ivl_variable_type_t NetESFunc::expr_type() const
{
return type_;
}
/*
* $Log: net_expr.cc,v $
* Revision 1.27 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.26 2005/11/26 00:35:43 steve
* More precise about r-value width of constants.
*
* Revision 1.25 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.24 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.23 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
+6 -102
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@@ -33,110 +33,14 @@
# include "netlist.h"
# include <assert.h>
/*
* Construct the procedural continuous assignment statement. This is a
* bit different from a normal assignment because the the lval is only
* intermittently connected. The deassign in particular disconnects
* the signals when they are not being assigned anymore. Because of
* this, there is no other reference to the lval to make it stay put
* so we increment the eref.
*
* XXXX I'm not sure this is the right way. Perhaps I should create
* output pins to connect to the netlist? But that would cause the
* link ring to grow, and that is not quite correct either. Hmm...
*/
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetCAssign::~NetCAssign()
{
lval_->decr_eref();
}
const NetNet* NetCAssign::lval() const
{
return lval_;
}
const Link& NetCAssign::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
NetDeassign::NetDeassign(NetNet*l)
: lval_(l)
{
lval_->incr_eref();
}
NetDeassign::~NetDeassign()
{
lval_->decr_eref();
}
const NetNet*NetDeassign::lval() const
{
return lval_;
}
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetForce::~NetForce()
{
lval_->decr_eref();
}
const Link& NetForce::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
const NetNet* NetForce::lval() const
{
return lval_;
}
NetRelease::NetRelease(NetNet*l)
: lval_(l)
{
/* Put myself into a release list that the net is
keeping. This is so that the NetNet can detach itself if
and when it is deleted by the optimizer. */
release_next_ = lval_->release_list_;
lval_->release_list_ = this;
}
NetRelease::~NetRelease()
{
assert(lval_ == 0);
}
const NetNet*NetRelease::lval() const
{
return lval_;
}
/*
* $Log: net_force.cc,v $
* Revision 1.13 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
+58 -67
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $"
#ident "$Id: net_func.cc,v 1.8 2006/06/18 04:15:50 steve Exp $"
#endif
# include "config.h"
@@ -26,42 +26,25 @@
# include "PExpr.h"
# include <iostream>
static unsigned count_def_pins(const NetFuncDef*def)
{
assert(def->return_sig());
unsigned sum = def->return_sig()->pin_count();
for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1)
sum += def->port(idx)->pin_count();
return sum;
}
/*
* To make a NetUserFunc device, make as many pins as there are ports
* in the function. Get the port count from the function definition,
* which accounts for all the inputs, plus one for the phantom output
* that is the result.
*/
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
: NetNode(s, n, count_def_pins(d->func_def())),
: NetNode(s, n, d->func_def()->port_count()+1),
def_(d)
{
NetFuncDef*def = def_->func_def();
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
unsigned port_wid = port_width(0);
for (unsigned idx = 0 ; idx < port_wid ; idx += 1) {
pin(idx).set_dir(Link::OUTPUT);
pin(idx).set_name(def_->basename(), idx);
}
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
unsigned pin_base = port_wid;
for (unsigned idx = 1 ; idx < port_count() ; idx += 1) {
const NetNet*port_sig = def->port(idx-1);
unsigned bits = port_width(idx);
for (unsigned bit = 0; bit < bits; bit += 1) {
pin(pin_base+bit).set_dir(Link::INPUT);
pin(pin_base+bit).set_name(port_sig->name(), bit);
pin(pin_base+bit).drive0(Link::HIGHZ);
pin(pin_base+bit).drive1(Link::HIGHZ);
}
pin_base += bits;
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
}
@@ -69,11 +52,6 @@ NetUserFunc::~NetUserFunc()
{
}
unsigned NetUserFunc::port_count() const
{
return def_->func_def()->port_count() + 1;
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*def = def_->func_def();
@@ -82,44 +60,16 @@ unsigned NetUserFunc::port_width(unsigned port) const
if (port == 0) {
const NetNet*sig = def->return_sig();
assert(sig);
return sig->pin_count();
return sig->vector_width();
}
port -= 1;
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
return port_sig->pin_count();
return port_sig->vector_width();
}
Link& NetUserFunc::port_pin(unsigned port, unsigned idx)
{
NetFuncDef*def = def_->func_def();
unsigned pin_base = 0;
const NetNet*port_sig;
if (port == 0)
return pin(idx);
port_sig = def->return_sig();
pin_base += port_sig->pin_count();
port -= 1;
assert(port < def->port_count());
for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) {
port_sig = def->port(port_idx);
pin_base += port_sig->pin_count();
}
port_sig = def->port(port);
assert(idx < port_sig->pin_count());
assert((pin_base+idx) < pin_count());
return pin(pin_base+idx);
}
const NetScope* NetUserFunc::def() const
{
return def_;
@@ -162,8 +112,49 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
return true;
}
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
const struct sfunc_return_type*def,
unsigned ports)
: NetNode(s, n, ports)
{
def_ = def;
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
}
NetSysFunc::~NetSysFunc()
{
}
const char*NetSysFunc::func_name() const
{
return def_->name;
}
unsigned NetSysFunc::vector_width() const
{
return def_->wid;
}
/*
* $Log: net_func.cc,v $
* Revision 1.8 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.7 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.6 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
+53 -12
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.14 2004/02/18 17:11:56 steve Exp $"
#ident "$Id: net_link.cc,v 1.19 2006/02/02 02:43:58 steve Exp $"
#endif
# include "config.h"
@@ -58,7 +58,10 @@ void connect(Nexus*l, Link&r)
void connect(Link&l, Link&r)
{
assert(&l != &r);
connect(l.nexus_, r);
if (r.is_linked() && !l.is_linked())
connect(r.nexus_, l);
else
connect(l.nexus_, r);
}
Link::Link()
@@ -313,6 +316,30 @@ void* Nexus::t_cookie(void*val)const
return tmp;
}
unsigned Nexus::vector_width() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
if (sig == 0)
continue;
return sig->vector_width();
}
return 0;
}
NetNet* Nexus::pick_any_net()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNet*sig = dynamic_cast<NetNet*>(cur->get_obj());
if (sig != 0)
return sig;
}
return 0;
}
const char* Nexus::name() const
{
if (name_)
@@ -364,7 +391,7 @@ const char* Nexus::name() const
}
assert(sig);
ostringstream tmp;
tmp << sig->name();
tmp << sig->scope()->name() << "." << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
@@ -407,13 +434,14 @@ void NexusSet::add(Nexus*that)
}
unsigned ptr = bsearch_(that);
if ((ptr < nitems_) && (items_[ptr] == that))
if (ptr < nitems_) {
assert(items_[ptr] == that);
return;
}
assert(ptr == nitems_);
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
items_[idx] = items_[idx-1];
items_[ptr] = that;
nitems_ += 1;
}
@@ -430,7 +458,7 @@ void NexusSet::rem(Nexus*that)
return;
unsigned ptr = bsearch_(that);
if ((ptr >= nitems_) || (items_[ptr] != that))
if (ptr >= nitems_)
return;
if (nitems_ == 1) {
@@ -462,10 +490,8 @@ Nexus* NexusSet::operator[] (unsigned idx) const
unsigned NexusSet::bsearch_(Nexus*that) const
{
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
if (items_[idx] < that)
continue;
return idx;
if (items_[idx] == that)
return idx;
}
return nitems_;
@@ -499,6 +525,21 @@ bool NexusSet::intersect(const NexusSet&that) const
/*
* $Log: net_link.cc,v $
* Revision 1.19 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.18 2005/09/25 23:40:11 steve
* Simplify NexusSet set handling.
*
* Revision 1.17 2005/06/13 23:22:37 steve
* Fix compile errors.
*
* Revision 1.16 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.15 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
+32 -35
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_modulo.cc,v 1.7 2004/02/18 17:11:56 steve Exp $"
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
#endif
# include "config.h"
@@ -30,25 +30,22 @@
# include "netlist.h"
# include "compiler.h"
/*
* 0 -- Result
* 1 -- DataA
* 2 -- DataB
*/
NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
unsigned wa, unsigned wb)
: NetNode(s, n, wr+wa+wb),
: NetNode(s, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb)
{
unsigned p = 0;
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::OUTPUT);
pin(p).set_name(perm_string::literal("Result"), idx);
}
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataA"), idx);
}
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataB"), idx);
}
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetModulo::~NetModulo()
@@ -70,44 +67,44 @@ unsigned NetModulo::width_b() const
return width_b_;
}
Link& NetModulo::pin_Result(unsigned idx)
Link& NetModulo::pin_Result()
{
assert(idx < width_r_);
return pin(idx);
return pin(0);
}
const Link& NetModulo::pin_Result(unsigned idx) const
const Link& NetModulo::pin_Result() const
{
assert(idx < width_r_);
return pin(idx);
return pin(0);
}
Link& NetModulo::pin_DataA(unsigned idx)
Link& NetModulo::pin_DataA()
{
assert(idx < width_a_);
return pin(idx+width_r_);
return pin(1);
}
const Link& NetModulo::pin_DataA(unsigned idx) const
const Link& NetModulo::pin_DataA() const
{
assert(idx < width_a_);
return pin(idx+width_r_);
return pin(1);
}
Link& NetModulo::pin_DataB(unsigned idx)
Link& NetModulo::pin_DataB()
{
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
return pin(2);
}
const Link& NetModulo::pin_DataB(unsigned idx) const
const Link& NetModulo::pin_DataB() const
{
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
return pin(2);
}
/*
* $Log: net_modulo.cc,v $
* Revision 1.9 2005/09/15 22:54:47 steve
* Fix bug configuring NetModulo pins.
*
* Revision 1.8 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.7 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
+31 -25
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.12 2004/09/04 04:24:15 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -54,15 +54,6 @@ NexusSet* NetEBinary::nex_input()
return result;
}
NexusSet* NetEBitSel::nex_input()
{
NexusSet*result = sig_->nex_input();
NexusSet*tmp = idx_->nex_input();
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEConcat::nex_input()
{
NexusSet*result = parms_[0]->nex_input();
@@ -87,12 +78,6 @@ NexusSet* NetECReal::nex_input()
return new NexusSet;
}
NexusSet* NetEMemory::nex_input()
{
NexusSet*result = idx_->nex_input();
return result;
}
/*
* A parameter by definition has no inputs. It represents a constant
* value, even if that value is a constant expression.
@@ -177,17 +162,21 @@ NexusSet* NetEUnary::nex_input()
return expr_->nex_input();
}
NexusSet* NetEVariable::nex_input()
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input()
{
if (bmux_ == 0)
return new NexusSet;
else
return bmux_->nex_input();
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input();
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input();
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetAssignBase::nex_input()
@@ -398,6 +387,23 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.16 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.15 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.14 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.13 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.12 2004/09/04 04:24:15 steve
* PR1026: assignment statements can have sensitivities in the l-values.
*
+5 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_output.cc,v 1.11 2004/09/16 03:17:33 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.12 2005/02/14 04:58:50 steve Exp $"
#endif
# include "config.h"
@@ -47,10 +47,7 @@ void NetAssignBase::nex_output(NexusSet&out)
{
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
if (NetNet*lsig = cur->sig()) {
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = cur->get_loff() + idx;
out.add(lsig->pin(off).nexus());
}
out.add(lsig->pin(0).nexus());
} else {
/* Quoting from netlist.h comments for class NetMemory:
* "This is not a node because memory objects can only be
@@ -122,6 +119,9 @@ void NetWhile::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.12 2005/02/14 04:58:50 steve
* l-value input may be a vector.
*
* Revision 1.11 2004/09/16 03:17:33 steve
* net_output handles l-value concatenations.
*
+6 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_proc.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_proc.cc,v 1.7 2006/08/08 05:11:37 steve Exp $"
#endif
# include "config.h"
@@ -131,7 +131,7 @@ NetForever::~NetForever()
delete statement_;
}
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
: delay_(d), expr_(0), statement_(st)
{
}
@@ -146,7 +146,7 @@ NetPDelay::~NetPDelay()
if (expr_) delete expr_;
}
unsigned long NetPDelay::delay() const
uint64_t NetPDelay::delay() const
{
assert(expr_ == 0);
return delay_;
@@ -177,6 +177,9 @@ const NetExpr* NetRepeat::expr() const
/*
* $Log: net_proc.cc,v $
* Revision 1.7 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.6 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+24 -67
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.33 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: net_scope.cc,v 1.36 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -38,10 +38,8 @@
NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
memories_ = 0;
signals_ = 0;
events_ = 0;
vars_ = 0;
lcounter_ = 0;
if (up) {
@@ -133,17 +131,25 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
* perm_string::literal method to fake the compiler into doing the
* compare without actually creating a perm_string.
*/
const NetExpr* NetScope::get_parameter(const char* key) const
const NetExpr* NetScope::get_parameter(const char* key,
const NetExpr*&msb,
const NetExpr*&lsb) const
{
map<perm_string,param_expr_t>::const_iterator idx;
idx = parameters.find(perm_string::literal(key));
if (idx != parameters.end())
if (idx != parameters.end()) {
msb = (*idx).second.msb;
lsb = (*idx).second.lsb;
return (*idx).second.expr;
}
idx = localparams.find(perm_string::literal(key));
if (idx != localparams.end())
if (idx != localparams.end()) {
msb = (*idx).second.msb;
lsb = (*idx).second.lsb;
return (*idx).second.expr;
}
return 0;
}
@@ -283,15 +289,6 @@ NetEvent* NetScope::find_event(const char*name)
return 0;
}
NetVariable* NetScope::find_variable(const char*name)
{
for (NetVariable*cur = vars_; cur ; cur = cur->snext_)
if (strcmp(cur->basename(), name) == 0)
return cur;
return 0;
}
void NetScope::add_signal(NetNet*net)
{
if (signals_ == 0) {
@@ -360,58 +357,6 @@ NetNet* NetScope::find_signal_in_child(const hname_t&path)
return cur->find_signal(path.peek_name(idx));
}
void NetScope::add_memory(NetMemory*mem)
{
if (memories_ == 0) {
mem->snext_ = mem;
mem->sprev_ = mem;
} else {
mem->snext_ = memories_->snext_;
mem->sprev_ = memories_;
mem->snext_->sprev_ = mem;
mem->sprev_->snext_ = mem;
}
memories_ = mem;
mem->scope_ = this;
}
void NetScope::rem_memory(NetMemory*mem)
{
assert(mem->scope_ == this);
if (memories_ == mem)
memories_ = mem->sprev_;
if (memories_ == mem) {
memories_ = 0;
} else {
mem->sprev_->snext_ = mem->snext_;
mem->snext_->sprev_ = mem->sprev_;
}
mem->scope_ = 0;
}
NetMemory* NetScope::find_memory(const string&key)
{
if (memories_ == 0)
return 0;
NetMemory*cur = memories_;
do {
if (cur->name() == key.c_str())
return cur;
cur = cur->sprev_;
} while (cur != memories_);
return 0;
}
void NetScope::add_variable(NetVariable*var)
{
assert(var->scope_ == 0);
var->scope_ = this;
var->snext_ = vars_;
vars_ = var;
}
/*
* This method locates a child scope by name. The name is the simple
* name of the child, no hierarchy is searched.
@@ -467,6 +412,18 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.36 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.35 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.34 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.33 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
-82
View File
@@ -1,82 +0,0 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_variable.cc,v 1.3 2004/02/19 07:06:57 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
NetVariable::NetVariable(perm_string name)
{
name_ = name;
scope_ = 0;
snext_ = 0;
}
NetVariable::~NetVariable()
{
}
perm_string NetVariable::basename() const
{
return name_;
}
NetScope* NetVariable::scope()
{
return scope_;
}
const NetScope* NetVariable::scope() const
{
return scope_;
}
NetEVariable::NetEVariable(NetVariable*v)
: var_(v)
{
}
NetEVariable::~NetEVariable()
{
}
NetExpr::TYPE NetEVariable::expr_type() const
{
return NetExpr::ET_REAL;
}
const NetVariable* NetEVariable::variable() const
{
return var_;
}
/*
* $Log: net_variable.cc,v $
* Revision 1.3 2004/02/19 07:06:57 steve
* LPM, logic and Variables have perm_string names.
*
* Revision 1.2 2003/03/06 00:28:42 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.1 2003/01/28 16:23:27 steve
* Add missing net_variable.cc to CVS.
*
*/
+738 -735
View File
File diff suppressed because it is too large Load Diff
+760 -494
View File
File diff suppressed because it is too large Load Diff
+74 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
#ident "$Id: netmisc.cc,v 1.12 2006/06/02 04:48:50 steve Exp $"
#endif
# include "config.h"
@@ -30,7 +30,7 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
{
if (val == 0)
return sig;
#if 0
NetScope*scope = sig->scope();
unsigned long abs_val = (val >= 0)? val : (-val);
unsigned width = sig->pin_count();
@@ -70,12 +70,63 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
des->add_node(val_c);
return res;
#else
cerr << sig->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl;
return 0;
#endif
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made
* from the constant value.
*/
NetExpr* make_add_expr(NetExpr*expr, long val)
{
NetExpr*tmp = pe->elaborate_expr(des, scope);
if (val == 0)
return expr;
// If the value to be added is <0, then instead generate a
// SUBTRACT node and turn the value positive.
char add_op = '+';
if (val < 0) {
add_op = '-';
val = -val;
}
verinum val_v (val);
val_v.has_sign(true);
if (expr->has_width()) {
val_v = verinum(val_v, expr->expr_width());
}
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
NetEBAdd*res = new NetEBAdd(add_op, expr, val_c);
res->set_line(*expr);
return res;
}
NetExpr* make_sub_expr(long val, NetExpr*expr)
{
verinum val_v (val, expr->expr_width());
val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
NetEBAdd*res = new NetEBAdd('-', val_c, expr);
res->set_line(*expr);
return res;
}
NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid)
{
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
if (tmp == 0)
return 0;
@@ -90,6 +141,24 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* $Log: netmisc.cc,v $
* Revision 1.12 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.11 2005/04/08 04:50:31 steve
* Don not give to make_add express an unwanted width.
*
* Revision 1.10 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.9 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.8 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
+82 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.19 2004/03/07 20:04:11 steve Exp $"
#ident "$Id: netmisc.h,v 1.27 2007/01/16 05:44:15 steve Exp $"
#endif
# include "netlist.h"
@@ -33,13 +33,28 @@
* If the symbol was not found, return 0. The output arguments
* get 0 except for the pointer to the object that represents
* the located symbol.
*
* The ex1 and ex2 output arguments are extended results. If the
* symbol is a parameter (par!=0) then ex1 is the msb expression and
* ex2 is the lsb expression for the range. If there is no range, then
* these values are set to 0.
*/
extern NetScope* symbol_search(Design*des, NetScope*start, hname_t path,
extern NetScope* symbol_search(const Design*des,
NetScope*start, hname_t path,
NetNet*&net, /* net/reg */
NetMemory*&mem, /* memory */
NetVariable*&var, /* real/realtime */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */);
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(const Design*des,
NetScope*start, const hname_t&path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(des, start, path, net, /*mem,*/ par, eve, ex1, ex2);
}
/*
* This function transforms an expression by padding the high bits
@@ -50,6 +65,15 @@ extern NetScope* symbol_search(Design*des, NetScope*start, hname_t path,
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
/*
* This function transforms an expression by cropping the high bits
* off with a part select. The result has the width w passed in. This
* function does not pad, use pad_to_width if padding is desired.
*/
extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
/*
* This function takes as input a NetNet signal and adds a constant
* value to it. If the val is 0, then simply return sig. Otherwise,
@@ -57,6 +81,23 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
*/
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
/*
* These functions make various sorts of expressions, given operands
* of certain type. The order of the operands is preserved in cases
* where order matters.
*
* make_add_expr
* Make a NetEBAdd expresion with <expr> the first argument and
* <val> the second. This may get turned into a subtract if <val> is
* less then zero. If val is exactly zero, then return <expr> as is.
*
* make_sub_expr
* Make a NetEBAdd(subtract) node that subtracts the given
* expression from the integer value.
*/
extern NetExpr*make_add_expr(NetExpr*expr, long val);
extern NetExpr*make_sub_expr(long val, NetExpr*expr);
/*
* In some cases the lval is accessible as a pointer to the head of
* a list of NetAssign_ objects. This function returns the width of
@@ -69,12 +110,47 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* right away. If the expression can be evaluated, this returns a
* constant expression. If it cannot be evaluated, it returns whatever
* it can. If the expression cannot be elaborated, return 0.
*
* The expr_width is the width of the context where the expression is
* being elaborated, or -1 if the expression is self-determinted width.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid);
/*
* $Log: netmisc.h,v $
* Revision 1.27 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.26 2006/09/28 00:29:49 steve
* Allow specparams as constants in expressions.
*
* Revision 1.25 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.24 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.23 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.22 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.21 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.20 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.19 2004/03/07 20:04:11 steve
* MOre thorough use of elab_and_eval function.
*
+92 -23
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pad_to_width.cc,v 1.15 2004/02/18 17:11:57 steve Exp $"
#ident "$Id: pad_to_width.cc,v 1.20 2005/12/22 15:43:47 steve Exp $"
#endif
# include "config.h"
@@ -56,47 +56,116 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
return tmp;
}
/* Do it the hard way, with a concatenation. */
verinum pad(verinum::V0, wid - expr->expr_width());
NetEConst*co = new NetEConst(pad);
co->set_line(*expr);
NetEConcat*cc = new NetEConcat(2);
cc->set_line(*expr);
cc->set(0, co);
cc->set(1, expr);
cc->set_width(wid);
expr = cc;
return expr;
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->set_line(*expr);
tmp->cast_signed(expr->has_sign());
return tmp;
}
/*
* Pad a NetNet to the desired vector width by concatenating a
* NetConst of constant zeros. Use a NetConcat node to do the
* concatenation.
*/
NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
{
NetScope*scope = net->scope();
const string path = scope->name();
assert(scope);
if (net->pin_count() >= wid)
if (net->vector_width() >= wid)
return net;
verinum pad(verinum::V0, wid - net->pin_count());
// Make the NetConcat and connect the input net to the lsb input.
NetConcat*cc = new NetConcat(scope, scope->local_symbol(), wid, 2);
des->add_node(cc);
connect(cc->pin(1), net->pin(0));
// Make a NetConst of the desired width and connect in to the
// lsb input of the NetConcat.
verinum pad(verinum::V0, wid - net->vector_width());
NetConst*con = new NetConst(scope, scope->local_symbol(), pad);
des->add_node(con);
connect(cc->pin(2), con->pin(0));
// Make a NetNet for the NetConst to NetConcat link.
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid - net->vector_width());
tmp->data_type( net->data_type() );
tmp->local_flag(true);
connect(cc->pin(2), tmp->pin(0));
// Create a NetNet of the output width and connect it to the
// NetConcat node output pin.
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->data_type( net->data_type() );
tmp->local_flag(true);
connect(cc->pin(0), tmp->pin(0));
return tmp;
}
NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid)
{
NetScope*scope = net->scope();
if (net->vector_width() >= wid)
return net;
NetSignExtend*se
= new NetSignExtend(scope, scope->local_symbol(), wid);
se->set_line(*net);
des->add_node(se);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
tmp->set_line(*net);
tmp->local_flag(true);
tmp->data_type(net->data_type());
tmp->set_signed(true);
connect(tmp->pin(0), se->pin(0));
connect(se->pin(1), net->pin(0));
return tmp;
}
NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
{
NetScope*scope = net->scope();
if (net->vector_width() <= wid)
return net;
NetPartSelect*ps = new NetPartSelect(net, 0, wid, NetPartSelect::VP);
des->add_node(ps);
ps->set_line(*net);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->data_type(net->data_type());
tmp->local_flag(true);
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
connect(tmp->pin(idx), net->pin(idx));
for (unsigned idx = net->pin_count() ; idx < wid ; idx += 1)
connect(tmp->pin(idx), con->pin(idx-net->pin_count()));
tmp->set_line(*tmp);
connect(ps->pin(0), tmp->pin(0));
return tmp;
}
/*
* $Log: pad_to_width.cc,v $
* Revision 1.20 2005/12/22 15:43:47 steve
* pad_to_width handles signed expressions.
*
* Revision 1.19 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.18 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.17 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.16 2005/01/12 03:17:37 steve
* Properly pad vector widths in pgassign.
*
* Revision 1.15 2004/02/18 17:11:57 steve
* Use perm_strings for named langiage items.
*
+741 -248
View File
File diff suppressed because it is too large Load Diff
+251 -72
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: pform.cc,v 1.138 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -26,9 +26,10 @@
# include "pform.h"
# include "parse_misc.h"
# include "parse_api.h"
# include "PData.h"
# include "PEvent.h"
# include "PUdp.h"
# include "PGenerate.h"
# include "PSpec.h"
# include <list>
# include <map>
# include <assert.h>
@@ -45,7 +46,17 @@ string vl_file = "";
extern int VLparse();
/* This tracks the current module being processed. There can only be
exactly one module currently being parsed, since verilog does not
allow nested module definitions. */
static Module*pform_cur_module = 0;
/* increment this for generate schemes within a module, and set it
to zero when a new module starts. */
static unsigned scope_generate_counter = 1;
/* This tracks the current generate scheme being processed. This is
always within a module. */
static PGenerate*pform_cur_generate = 0;
static NetNet::Type pform_default_nettype = NetNet::WIRE;
@@ -64,10 +75,13 @@ static unsigned pform_timescale_line = 0;
* of scope. As I enter a scope, the push function is called, and as I
* leave a scope the pop function is called. Entering tasks, functions
* and named blocks causes scope to be pushed and popped. The module
* name is not included it this scope stack.
* name is not included in this scope stack.
*
* The hier_name function, therefore, returns the name path of a
* function relative the current function.
* The hier_name function, therefore, converts the name to the scope
* of the module currently in progress.
*
* The scope stack does not include any scope created by a generate
* scheme.
*/
static hname_t scope_stack;
@@ -91,6 +105,18 @@ static hname_t hier_name(const char*tail)
return name;
}
static PWire*get_wire_in_module(const hname_t&name)
{
/* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes
cannot be within sub-scopes. Only directly in
modules. */
if (pform_cur_generate)
return pform_cur_generate->get_wire(name);
return pform_cur_module->get_wire(name);
}
void pform_set_default_nettype(NetNet::Type type,
const char*file, unsigned lineno)
{
@@ -217,6 +243,10 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
pform_cur_module->set_file(file);
pform_cur_module->set_lineno(lineno);
/* The generate scheme numbering starts with *1*, not
zero. That's just the way it is, thanks to the standard. */
scope_generate_counter = 1;
if (warn_timescale && pform_timescale_file
&& (strcmp(pform_timescale_file,file) != 0)) {
@@ -293,6 +323,58 @@ void pform_endmodule(const char*name)
pform_cur_module = 0;
}
void pform_genvars(list<perm_string>*names)
{
list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) {
pform_cur_module->genvars.push_back( *cur );
}
delete names;
}
void pform_start_generate_for(const struct vlltype&li,
char*ident1, PExpr*init,
PExpr*test,
char*ident2, PExpr*next)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
gen->set_file(li.text);
gen->set_lineno(li.first_line);
// For now, assume that generates do not nest.
assert(pform_cur_generate == 0);
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
pform_cur_generate->loop_index = lex_strings.make(ident1);
pform_cur_generate->loop_init = init;
pform_cur_generate->loop_test = test;
pform_cur_generate->loop_step = next;
delete[]ident1;
delete[]ident2;
}
void pform_generate_block_name(char*name)
{
assert(pform_cur_generate != 0);
assert(pform_cur_generate->scope_name == 0);
pform_cur_generate->scope_name = lex_strings.make(name);
delete[]name;
}
void pform_endgenerate()
{
assert(pform_cur_generate != 0);
assert(pform_cur_module);
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
pform_cur_generate = 0;
}
bool pform_expression_is_constant(const PExpr*ex)
{
return ex->is_constant(pform_cur_module);
@@ -614,7 +696,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
/* Make the PWire for the output port. */
pins[0] = new PWire(hier_name(out_name),
synchronous_flag? NetNet::REG : NetNet::WIRE,
NetNet::POUTPUT);
NetNet::POUTPUT,
IVL_VT_LOGIC);
pins[0]->set_file(file);
pins[0]->set_lineno(lineno);
@@ -627,7 +710,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
assert(idx < pins.count());
pins[idx] = new PWire(hier_name(*cur),
NetNet::WIRE,
NetNet::PINPUT);
NetNet::PINPUT,
IVL_VT_LOGIC);
pins[idx]->set_file(file);
pins[idx]->set_lineno(lineno);
}
@@ -691,10 +775,10 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
*/
static void pform_set_net_range(const char* name,
const svector<PExpr*>*range,
bool signed_flag)
bool signed_flag,
ivl_variable_type_t dt)
{
PWire*cur = pform_cur_module->get_wire(hier_name(name));
PWire*cur = get_wire_in_module(hier_name(name));
if (cur == 0) {
VLerror("error: name is not a valid net.");
return;
@@ -712,11 +796,15 @@ static void pform_set_net_range(const char* name,
cur->set_range((*range)[0], (*range)[1]);
}
cur->set_signed(signed_flag);
if (dt != IVL_VT_NO_TYPE)
cur->set_data_type(dt);
}
void pform_set_net_range(list<perm_string>*names,
svector<PExpr*>*range,
bool signed_flag)
bool signed_flag,
ivl_variable_type_t dt)
{
assert((range == 0) || (range->count() == 2));
@@ -724,7 +812,7 @@ void pform_set_net_range(list<perm_string>*names,
; cur != names->end()
; cur ++ ) {
perm_string txt = *cur;
pform_set_net_range(txt, range, signed_flag);
pform_set_net_range(txt, range, signed_flag, dt);
}
delete names;
@@ -755,26 +843,6 @@ void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
delete names;
}
static void pform_make_datum(perm_string name, const char*fn, unsigned ln)
{
hname_t hname = hier_name(name);
PData*datum = new PData(hname);
datum->set_file(fn);
datum->set_lineno(ln);
pform_cur_module->datum[hname] = datum;
}
void pform_make_reals(list<perm_string>*names, const char*fn, unsigned ln)
{
list<perm_string>::iterator cur;
for (cur = names->begin() ; cur != names->end() ; cur++) {
perm_string txt = *cur;
pform_make_datum(txt, fn, ln);
}
delete names;
}
/*
* pform_makegates is called when a list of gates (with the same type)
* are ready to be instantiated. The function runs through the list of
@@ -810,7 +878,10 @@ void pform_makegate(PGBuiltin::Type type,
cur->set_file(info.file);
cur->set_lineno(info.lineno);
pform_cur_module->add_gate(cur);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur);
}
void pform_makegates(PGBuiltin::Type type,
@@ -868,7 +939,10 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order);
}
pform_cur_module->add_gate(cur);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur);
}
static void pform_make_modgate(perm_string type,
@@ -952,7 +1026,7 @@ void pform_make_modgates(perm_string type,
delete gates;
}
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
svector<PExpr*>*del,
struct str_pair_t str)
{
@@ -970,7 +1044,11 @@ PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
cur->strength0(str.str0);
cur->strength1(str.str1);
pform_cur_module->add_gate(cur);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur);
return cur;
}
@@ -1060,7 +1138,7 @@ void pform_module_define_port(const struct vlltype&li,
}
cur = new PWire(name, type, port_type);
cur = new PWire(name, type, port_type, IVL_VT_LOGIC);
cur->set_file(li.text);
cur->set_lineno(li.first_line);
@@ -1103,36 +1181,43 @@ void pform_module_define_port(const struct vlltype&li,
* do check to see if the name has already been declared, as this
* function is called for every declaration.
*/
/*
* this is the basic form of pform_makwire. This takes a single simple
* name, port type, net type, data type, and attributes, and creates
* the variable/net. Other forms of pform_makewire ultimately call
* this one to create the wire and stash it.
*/
void pform_makewire(const vlltype&li, const char*nm,
NetNet::Type type, NetNet::PortType pt,
ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr)
{
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
PWire*cur = get_wire_in_module(name);
// If this is not implicit ("implicit" meaning we don't know
// what the type is yet) then set thay type now.
if (cur && type != NetNet::IMPLICIT) {
bool rc = cur->set_wire_type(type);
if (rc == false) {
ostringstream msg;
msg << name << " previously defined at " <<
cur->get_line() << ".";
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< ".";
VLerror(msg.str().c_str());
} else {
bool rc = cur->set_wire_type(type);
if (rc == false) {
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< ".";
VLerror(msg.str().c_str());
}
cerr << "XXXX type=" << type <<", curtype=" << cur->get_wire_type() << endl;
}
}
if (cur) {
cur->set_file(li.text);
cur->set_lineno(li.first_line);
return;
}
cur = new PWire(name, type, pt);
cur = new PWire(name, type, pt, dt);
cur->set_file(li.text);
cur->set_lineno(li.first_line);
@@ -1143,23 +1228,32 @@ void pform_makewire(const vlltype&li, const char*nm,
}
}
pform_cur_module->add_wire(cur);
if (pform_cur_generate)
pform_cur_generate->add_wire(cur);
else
pform_cur_module->add_wire(cur);
}
/*
* This form takes a list of names and some type information, and
* generates a bunch of variables/nets. We hse the basic
* pform_makewire above.
*/
void pform_makewire(const vlltype&li,
svector<PExpr*>*range,
bool signed_flag,
list<perm_string>*names,
NetNet::Type type,
NetNet::PortType pt,
ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end()
; cur ++ ) {
perm_string txt = *cur;
pform_makewire(li, txt, type, pt, attr);
pform_set_net_range(txt, range, signed_flag);
pform_makewire(li, txt, type, pt, dt, attr);
pform_set_net_range(txt, range, signed_flag, dt);
}
delete names;
@@ -1167,13 +1261,17 @@ void pform_makewire(const vlltype&li,
delete range;
}
/*
* This form makes nets with delays and continuous assignments.
*/
void pform_makewire(const vlltype&li,
svector<PExpr*>*range,
bool signed_flag,
svector<PExpr*>*delay,
str_pair_t str,
net_decl_assign_t*decls,
NetNet::Type type)
NetNet::Type type,
ivl_variable_type_t dt)
{
net_decl_assign_t*first = decls->next;
decls->next = 0;
@@ -1181,16 +1279,19 @@ void pform_makewire(const vlltype&li,
while (first) {
net_decl_assign_t*next = first->next;
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, 0);
pform_set_net_range(first->name, range, signed_flag);
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
pform_set_net_range(first->name, range, signed_flag, dt);
hname_t name = hier_name(first->name);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = get_wire_in_module(name);
if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first->name));
lval->set_file(li.text);
lval->set_lineno(li.first_line);
pform_make_pgassign(lval, first->expr, delay, str);
PGAssign*ass = pform_make_pgassign(lval, first->expr,
delay, str);
ass->set_file(li.text);
ass->set_lineno(li.first_line);
}
free(first->name);
@@ -1205,7 +1306,7 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT);
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC);
cur->set_file(file);
cur->set_lineno(lineno);
pform_cur_module->add_wire(cur);
@@ -1274,6 +1375,7 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
* no output or inout ports.
*/
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
svector<PExpr*>*range,
list<perm_string>*names,
@@ -1294,7 +1396,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
if (curw) {
curw->set_port_type(pt);
} else {
curw = new PWire(name, NetNet::IMPLICIT_REG, pt);
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
curw->set_file(file);
curw->set_lineno(lineno);
pform_cur_module->add_wire(curw);
@@ -1431,13 +1533,52 @@ void pform_set_defparam(const hname_t&name, PExpr*expr)
}
/*
* XXXX Not implemented yet.
* Specify paths.
*/
extern void pform_make_specify_path(list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst)
extern PSpecPath* pform_make_specify_path(const struct vlltype&li,
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst)
{
PSpecPath*path = new PSpecPath(src->size(), dst->size());
path->set_file(li.text);
path->set_lineno(li.first_line);
unsigned idx;
list<perm_string>::const_iterator cur;
idx = 0;
for (idx = 0, cur = src->begin() ; cur != src->end() ; idx++, cur++) {
path->src[idx] = *cur;
}
assert(idx == path->src.size());
delete src;
for (idx = 0, cur = dst->begin() ; cur != dst->end() ; idx++, cur++) {
path->dst[idx] = *cur;
}
assert(idx == path->dst.size());
delete dst;
return path;
}
extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
{
assert(path->delays.size() == 0);
path->delays.resize(del->count());
for (unsigned idx = 0 ; idx < path->delays.size() ; idx += 1)
path->delays[idx] = (*del)[idx];
delete del;
return path;
}
extern void pform_module_specify_path(PSpecPath*obj)
{
pform_cur_module->specify_paths.push_back(obj);
}
void pform_set_port_type(const struct vlltype&li,
@@ -1452,7 +1593,7 @@ void pform_set_port_type(const struct vlltype&li,
perm_string txt = *cur;
pform_set_port_type(txt, pt, li.text, li.first_line);
if (range)
pform_set_net_range(txt, range, signed_flag);
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE);
}
delete names;
@@ -1465,18 +1606,21 @@ static void pform_set_reg_integer(const char*nm)
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER, NetNet::NOT_A_PORT);
cur = new PWire(name, NetNet::INTEGER,
NetNet::NOT_A_PORT,
IVL_VT_LOGIC);
cur->set_signed(true);
pform_cur_module->add_wire(cur);
} else {
bool rc = cur->set_wire_type(NetNet::INTEGER);
assert(rc);
cur->set_data_type(IVL_VT_LOGIC);
cur->set_signed(true);
}
assert(cur);
cur->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)),
new PENumber(new verinum(0UL, INTEGER_WIDTH)));
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
cur->set_signed(true);
}
@@ -1496,16 +1640,18 @@ static void pform_set_reg_time(const char*nm)
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT);
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
pform_cur_module->add_wire(cur);
} else {
bool rc = cur->set_wire_type(NetNet::REG);
assert(rc);
rc = cur->set_data_type(IVL_VT_LOGIC);
assert(rc);
}
assert(cur);
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, INTEGER_WIDTH)),
new PENumber(new verinum(0UL, INTEGER_WIDTH)));
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
}
void pform_set_reg_time(list<perm_string>*names)
@@ -1530,7 +1676,8 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
perm_string txt = *cur;
PWire*pp = new PWire(hname_t(txt),
NetNet::IMPLICIT,
NetNet::PINPUT);
NetNet::PINPUT,
IVL_VT_LOGIC);
(*out)[idx] = pp;
idx += 1;
}
@@ -1597,6 +1744,38 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.138 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.137 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.136 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.135 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.134 2006/03/30 05:22:34 steve
* task/function ports can have types.
*
* Revision 1.133 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.132 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.131 2005/05/06 00:25:13 steve
* Handle synthesis of concatenation expressions.
*
* Revision 1.130 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.129 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*
+60 -10
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $"
#ident "$Id: pform.h,v 1.87 2006/09/23 04:57:19 steve Exp $"
#endif
# include "netlist.h"
@@ -57,6 +57,7 @@
*/
class PGate;
class PExpr;
class PSpecPath;
struct vlltype;
/*
@@ -77,7 +78,8 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max);
/* This is information about port name information for named port
connections. */
typedef struct named<PExpr*> named_pexpr_t;
//typedef struct named<PExpr*> named_pexpr_t;
typedef named<PExpr*> named_pexpr_t;
struct parmvalue_t {
svector<PExpr*>*by_order;
@@ -166,28 +168,52 @@ extern void pform_pop_scope();
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
const char*file, unsigned loneno);
/*
* This function takes the list of names as new genvars to declare in
* the current module scope.
*/
extern void pform_genvars(list<perm_string>*names);
extern void pform_start_generate_for(const struct vlltype&li,
char*ident1,
PExpr*init,
PExpr*test,
char*ident2,
PExpr*next);
extern void pform_generate_block_name(char*name);
extern void pform_endgenerate();
/*
* The makewire functions announce to the pform code new wires. These
* go into a module that is currently opened.
*/
extern void pform_makewire(const struct vlltype&li, const char*name,
NetNet::Type type, NetNet::PortType pt,
NetNet::Type type,
NetNet::PortType pt,
ivl_variable_type_t,
svector<named_pexpr_t*>*attr);
/* This form handles simple declarations */
extern void pform_makewire(const struct vlltype&li,
svector<PExpr*>*range,
bool signed_flag,
list<perm_string>*names,
NetNet::Type type,
NetNet::PortType,
ivl_variable_type_t,
svector<named_pexpr_t*>*attr);
/* This form handles assignment declarations. */
extern void pform_makewire(const struct vlltype&li,
svector<PExpr*>*range,
bool signed_flag,
svector<PExpr*>*delay,
str_pair_t str,
net_decl_assign_t*assign_list,
NetNet::Type type);
NetNet::Type type,
ivl_variable_type_t);
extern void pform_make_reginit(const struct vlltype&li,
const char*name, PExpr*expr);
@@ -203,7 +229,9 @@ extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno);
extern void pform_set_net_range(list<perm_string>*names,
svector<PExpr*>*, bool);
svector<PExpr*>*,
bool signed_flag,
ivl_variable_type_t);
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names);
@@ -233,8 +261,12 @@ extern void pform_set_defparam(const hname_t&name, PExpr*expr);
* Functions related to specify blocks.
*/
extern void pform_set_specparam(perm_string name, PExpr*expr);
extern void pform_make_specify_path(list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst);
extern PSpecPath*pform_make_specify_path(const struct vlltype&li,
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst);
extern PSpecPath*pform_assign_path_delay(PSpecPath*obj, svector<PExpr*>*delays);
extern void pform_module_specify_path(PSpecPath*obj);
/*
* pform_make_behavior creates processes that are declared with always
@@ -270,9 +302,6 @@ extern void pform_make_modgates(perm_string type,
svector<lgate>*gates);
/* Make a continuous assignment node, with optional bit- or part- select. */
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
svector<PExpr*>*delays,
struct str_pair_t str);
extern void pform_make_pgassign_list(svector<PExpr*>*alist,
svector<PExpr*>*del,
struct str_pair_t str,
@@ -281,6 +310,7 @@ extern void pform_make_pgassign_list(svector<PExpr*>*alist,
/* Given a port type and a list of names, make a list of wires that
can be used as task port information. */
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
svector<PExpr*>*range,
list<perm_string>*names,
@@ -298,6 +328,26 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.87 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.86 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.85 2006/03/30 05:22:34 steve
* task/function ports can have types.
*
* Revision 1.84 2005/12/05 21:21:18 steve
* Fixes for stubborn compilers.
*
* Revision 1.83 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.82 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.81 2004/08/26 04:02:04 steve
* Add support for localparam ranges.
*
+150 -34
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.88 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.94 2006/09/23 04:57:19 steve Exp $"
#endif
# include "config.h"
@@ -29,8 +29,9 @@
* module in question.
*/
# include "pform.h"
# include "PData.h"
# include "PEvent.h"
# include "PGenerate.h"
# include "PSpec.h"
# include <iostream>
# include <iomanip>
# include <typeinfo>
@@ -146,11 +147,27 @@ void PEIdent::dump(ostream&out) const
out << path_;
if (msb_) {
out << "[" << *msb_;
if (lsb_) {
if (lsb_) switch (sel_) {
case SEL_IDX_UP:
out << "+:" << *lsb_;
break;
case SEL_IDX_DO:
out << "-:" << *lsb_;
break;
case SEL_PART:
out << ":" << *lsb_;
break;
default:
out << ":?:" << *lsb_;
break;
}
out << "]";
}
typedef std::vector<PExpr*>::const_iterator vector_it_t;
for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) {
out << "[" << *(*cur) << "]";
}
}
void PEString::dump(ostream&out) const
@@ -201,27 +218,29 @@ void PEBinary::dump(ostream&out) const
}
void PWire::dump(ostream&out) const
void PWire::dump(ostream&out, unsigned ind) const
{
out << " " << type_;
out << setw(ind) << "" << type_;
switch (port_type_) {
case NetNet::PIMPLICIT:
out << " (implicit input)";
out << " implicit input";
break;
case NetNet::PINPUT:
out << " (input)";
out << " input";
break;
case NetNet::POUTPUT:
out << " (output)";
out << " output";
break;
case NetNet::PINOUT:
out << " (input output)";
out << " inout";
break;
case NetNet::NOT_A_PORT:
break;
}
out << " " << data_type_;
if (signed_) {
out << " signed";
}
@@ -291,9 +310,9 @@ void PGate::dump_delays(ostream&out) const
delay_.dump_delays(out);
}
void PGate::dump(ostream&out) const
void PGate::dump(ostream&out, unsigned ind) const
{
out << " " << typeid(*this).name() << " ";
out << setw(ind) << "" << typeid(*this).name() << " ";
delay_.dump_delays(out);
out << " " << get_name() << "(";
dump_pins(out);
@@ -301,45 +320,47 @@ void PGate::dump(ostream&out) const
}
void PGAssign::dump(ostream&out) const
void PGAssign::dump(ostream&out, unsigned ind) const
{
out << " assign (" << strength0() << "0 " << strength1() << "1) ";
out << setw(ind) << "";
out << "assign (" << strength0() << "0 " << strength1() << "1) ";
dump_delays(out);
out << " " << *pin(0) << " = " << *pin(1) << ";" << endl;
}
void PGBuiltin::dump(ostream&out) const
void PGBuiltin::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "";
switch (type()) {
case PGBuiltin::BUFIF0:
out << " bufif0 ";
out << "bufif0 ";
break;
case PGBuiltin::BUFIF1:
out << " bufif1 ";
out << "bufif1 ";
break;
case PGBuiltin::NOTIF0:
out << " bufif0 ";
out << "bufif0 ";
break;
case PGBuiltin::NOTIF1:
out << " bufif1 ";
out << "bufif1 ";
break;
case PGBuiltin::NAND:
out << " nand ";
out << "nand ";
break;
case PGBuiltin::NMOS:
out << " nmos ";
out << "nmos ";
break;
case PGBuiltin::RNMOS:
out << " rnmos ";
out << "rnmos ";
break;
case PGBuiltin::RPMOS:
out << " rpmos ";
out << "rpmos ";
break;
case PGBuiltin::PMOS:
out << " pmos ";
out << "pmos ";
break;
default:
out << " builtin gate ";
out << "builtin gate ";
}
out << "(" << strength0() << "0 " << strength1() << "1) ";
@@ -355,9 +376,9 @@ void PGBuiltin::dump(ostream&out) const
out << ");" << endl;
}
void PGModule::dump(ostream&out) const
void PGModule::dump(ostream&out, unsigned ind) const
{
out << " " << type_ << " ";
out << setw(ind) << "" << type_ << " ";
// If parameters are overridden by order, dump them.
if (overrides_) {
@@ -719,6 +740,71 @@ void PProcess::dump(ostream&out, unsigned ind) const
statement_->dump(out, ind+2);
}
void PSpecPath::dump(std::ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "specify path (";
for (unsigned idx = 0 ; idx < src.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(src[idx]);
out << src[idx];
}
out << " => ";
for (unsigned idx = 0 ; idx < dst.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(dst[idx]);
out << dst[idx];
}
out << ") = (";
for (unsigned idx = 0 ; idx < delays.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(delays[idx]);
out << *delays[idx];
}
out << ");" << endl;
}
void PGenerate::dump(ostream&out) const
{
out << " generate(" << id_number << ")";
switch (scheme_type) {
case GS_NONE:
break;
case GS_LOOP:
out << " for ("
<< loop_index
<< "=" << *loop_init
<< "; " << *loop_test
<< "; " << loop_index
<< "=" << *loop_step << ")";
break;
case GS_CONDIT:
break;
}
if (scope_name)
out << " : " << scope_name;
out << endl;
for (map<hname_t,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) {
(*idx).second->dump(out, 6);
}
for (list<PGate*>::const_iterator idx = gates.begin()
; idx != gates.end() ; idx++) {
(*idx)->dump(out, 6);
}
out << " endgenerate" << endl;
}
void Module::dump(ostream&out) const
{
if (attributes.begin() != attributes.end()) {
@@ -784,6 +870,18 @@ void Module::dump(ostream&out) const
out << "/* ERROR */;" << endl;
}
typedef list<perm_string>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
; cur != genvars.end() ; cur++) {
out << " genvar " << (*cur) << ";" << endl;
}
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
for (genscheme_iter_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur++) {
(*cur)->dump(out);
}
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
for (specparm_iter_t cur = specparams.begin()
; cur != specparams.end() ; cur ++) {
@@ -807,13 +905,6 @@ void Module::dump(ostream&out) const
<< ev->get_line() << endl;
}
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
; cur != datum.end() ; cur ++ ) {
PData*tmp = (*cur).second;
out << " real " << tmp->name() << "; // "
<< tmp->get_line() << endl;
}
// Iterate through and display all the wires.
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end()
@@ -857,6 +948,13 @@ void Module::dump(ostream&out) const
(*behav)->dump(out, 4);
}
for (list<PSpecPath*>::const_iterator spec = specify_paths.begin()
; spec != specify_paths.end()
; spec ++ ) {
(*spec)->dump(out, 4);
}
out << "endmodule" << endl;
}
@@ -909,6 +1007,24 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.94 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.93 2006/04/28 04:19:31 steve
* Dump indexes of ident expressions
*
* Revision 1.92 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.91 2005/10/04 04:09:26 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.90 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.89 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.88 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*
+104 -43
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2006 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.34 2003/08/28 04:11:19 steve Exp $"
#ident "$Id: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -33,10 +33,11 @@
*/
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <typeinfo>
bool NetExpr::set_width(unsigned w)
bool NetExpr::set_width(unsigned w, bool)
{
cerr << get_line() << ": internal warning: "
<<typeid(*this).name() << ": set_width(unsigned) "
@@ -45,7 +46,7 @@ bool NetExpr::set_width(unsigned w)
return false;
}
bool NetEBinary::set_width(unsigned w)
bool NetEBinary::set_width(unsigned w, bool)
{
bool flag = true;
switch (op_) {
@@ -80,7 +81,7 @@ bool NetEBinary::set_width(unsigned w)
* The bitwise logical operators have operands the same size as the
* result. Anything else is a mess.
*/
bool NetEBAdd::set_width(unsigned w)
bool NetEBAdd::set_width(unsigned w, bool)
{
unsigned wid = w;
@@ -113,7 +114,7 @@ bool NetEBAdd::set_width(unsigned w)
* result. Anything else is a mess. I first try to get the operands to
* shrink to the desired size. I then expand operands that are too small.
*/
bool NetEBBits::set_width(unsigned w)
bool NetEBBits::set_width(unsigned w, bool)
{
/* First, give the operands a chance to adjust themselves to
the requested width. */
@@ -153,7 +154,7 @@ bool NetEBBits::set_width(unsigned w)
* their own natural width, but the comparison operator result has a
* fixed width of 1.
*/
bool NetEBComp::set_width(unsigned w)
bool NetEBComp::set_width(unsigned w, bool)
{
return (w == 1);
}
@@ -162,12 +163,12 @@ bool NetEBComp::set_width(unsigned w)
* There is nothing we can do to the operands of a division to make it
* confirm to the requested width. Force the context to pad or truncate.
*/
bool NetEBDiv::set_width(unsigned w)
bool NetEBDiv::set_width(unsigned w, bool)
{
return w == expr_width();
}
bool NetEBLogic::set_width(unsigned w)
bool NetEBLogic::set_width(unsigned w, bool)
{
bool flag;
flag = left_->set_width(right_->expr_width());
@@ -180,17 +181,23 @@ bool NetEBLogic::set_width(unsigned w)
* There is nothing we can do to the operands of a multiply to make it
* confirm to the requested width. Force the context to pad or truncate.
*/
bool NetEBMult::set_width(unsigned w)
bool NetEBMult::set_width(unsigned w, bool)
{
return w == expr_width();
}
bool NetEBPow::set_width(unsigned w, bool last_chance)
{
bool flag = left_->set_width(w, last_chance);
return flag;
}
/*
* The shift operator allows the shift amount to have its own
* natural width. The width of the operator result is the width of the
* left operand, the value that is to be shifted.
*/
bool NetEBShift::set_width(unsigned w)
bool NetEBShift::set_width(unsigned w, bool)
{
bool flag = true;
@@ -228,7 +235,7 @@ bool NetEBShift::set_width(unsigned w)
* matter because the null expression is indication of an error and
* the compiler will not go beyond elaboration.
*/
bool NetEConcat::set_width(unsigned w)
bool NetEConcat::set_width(unsigned w, bool)
{
unsigned sum = 0;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
@@ -241,7 +248,7 @@ bool NetEConcat::set_width(unsigned w)
return true;
}
bool NetEConst::set_width(unsigned w)
bool NetEConst::set_width(unsigned w, bool last_chance)
{
if (w == value_.len()) {
expr_width(w);
@@ -289,17 +296,19 @@ bool NetEConst::set_width(unsigned w)
? value_[value_.len() - 1]
: verinum::V0;
// Don't reduce a number too small to hold all the
// significant bits.
for (unsigned idx = w ; idx < value_.len() ; idx += 1)
if (value_[idx] != pad_bit)
use_w = idx+1;
if (! last_chance) {
// Don't reduce a number too small to hold all the
// significant bits.
for (unsigned idx = w ; idx < value_.len() ; idx += 1)
if (value_[idx] != pad_bit)
use_w = idx+1;
// Correct for the special case of signed value. We
// cannot have the result change sign on us.
if (value_.has_sign() && (use_w < value_.len())
&& (value_[use_w-1] != pad_bit))
use_w += 1;
// Correct for the special case of signed value. We
// cannot have the result change sign on us.
if (value_.has_sign() && (use_w < value_.len())
&& (value_[use_w-1] != pad_bit))
use_w += 1;
}
verinum tmp (verinum::V0, use_w, has_width());
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
@@ -312,18 +321,27 @@ bool NetEConst::set_width(unsigned w)
}
}
/*
* Parameter vectors cannot be resized because they refer to a common
* value.
*/
bool NetEConstParam::set_width(unsigned w, bool)
{
return w == expr_width();
}
/*
* Real constants can have whatever width the environment wants,
* because it isn't really a vector. The environment will convert this
* to a vector at the right time.
*/
bool NetECReal::set_width(unsigned w)
bool NetECReal::set_width(unsigned w, bool)
{
expr_width(w);
return true;
}
bool NetEMemory::set_width(unsigned w)
#if 0
bool NetEMemory::set_width(unsigned w, bool)
{
if (w != mem_->width())
return false;
@@ -331,13 +349,21 @@ bool NetEMemory::set_width(unsigned w)
expr_width(w);
return true;
}
bool NetEParam::set_width(unsigned)
#endif
bool NetEParam::set_width(unsigned, bool)
{
return false;
}
bool NetESFunc::set_width(unsigned w)
bool NetESelect::set_width(unsigned w, bool)
{
if (expr_width() == 1)
return true;
else
return false;
}
bool NetESFunc::set_width(unsigned w, bool)
{
return w == expr_width();
}
@@ -346,25 +372,29 @@ bool NetESFunc::set_width(unsigned w)
* The signal should automatically pad with zeros to get to the desired
* width. Do not allow signal bits to be truncated, however.
*/
bool NetESignal::set_width(unsigned w)
bool NetESignal::set_width(unsigned w, bool)
{
if (w != bit_count())
if (w != vector_width())
return false;
return true;
}
bool NetEBitSel::set_width(unsigned w)
{
if (w != 1) return false;
return true;
}
bool NetETernary::set_width(unsigned w)
bool NetETernary::set_width(unsigned w, bool last_chance)
{
bool flag = true;
flag = flag && true_val_->set_width(w);
flag = flag && false_val_->set_width(w);
flag = flag && true_val_->set_width(w, last_chance);
flag = flag && false_val_->set_width(w, last_chance);
/* The ternary really insists that the true and false clauses
have the same width. Even if we fail to make the width that
the user requests, at least pad the smaller width to suit
the larger. */
if (true_val_->expr_width() < false_val_->expr_width())
true_val_ = pad_to_width(true_val_, false_val_->expr_width());
if (false_val_->expr_width() < true_val_->expr_width())
false_val_ = pad_to_width(false_val_, true_val_->expr_width());
expr_width(true_val_->expr_width());
return flag;
}
@@ -374,13 +404,13 @@ bool NetETernary::set_width(unsigned w)
* width. What I really need to do is note the width of the output
* parameter of the function definition and take that into account.
*/
bool NetEUFunc::set_width(unsigned wid)
bool NetEUFunc::set_width(unsigned wid, bool)
{
expr_width(wid);
return true;
}
bool NetEUnary::set_width(unsigned w)
bool NetEUnary::set_width(unsigned w, bool)
{
bool flag = true;
switch (op_) {
@@ -403,7 +433,7 @@ bool NetEUnary::set_width(unsigned w)
* Unary reduction operators allow its operand to have any width. The
* result is defined to be 1.
*/
bool NetEUReduce::set_width(unsigned w)
bool NetEUReduce::set_width(unsigned w, bool)
{
return w == 1;
}
@@ -411,6 +441,37 @@ bool NetEUReduce::set_width(unsigned w)
/*
* $Log: set_width.cc,v $
* Revision 1.42 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.41 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.40 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.39 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.38 2006/05/02 04:29:42 steve
* Be more stubborn about widths.
*
* Revision 1.37 2005/11/26 00:35:44 steve
* More precise about r-value width of constants.
*
* Revision 1.36 2005/05/17 20:56:55 steve
* Parameters cannot have their width changed.
*
* Revision 1.35 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.34 2003/08/28 04:11:19 steve
* Spelling patch.
*
+6 -3
View File
@@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: svector.h,v 1.9 2003/07/23 02:35:44 steve Exp $"
#ident "$Id: svector.h,v 1.10 2005/06/14 19:13:43 steve Exp $"
#endif
# include "config.h"
@@ -101,14 +101,17 @@ template <class TYPE> class svector {
* Override the implementation of the above template for the string
* type parameter. The initialization to nil works different here.
*/
inline svector<string>::svector<string>(unsigned size)
: nitems_(size), items_(new string[size])
template <> inline svector<std::string>::svector(unsigned size)
: nitems_(size), items_(new std::string[size])
{
}
/*
* $Log: svector.h,v $
* Revision 1.10 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.9 2003/07/23 02:35:44 steve
* Inline the svector<string> constructor.
*
+17 -18
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: symbol_search.cc,v 1.1 2003/09/19 03:30:05 steve Exp $"
#ident "$Id: symbol_search.cc,v 1.4 2007/01/16 05:44:15 steve Exp $"
#endif
# include "netlist.h"
@@ -27,12 +27,11 @@
/*
* Search for the hierarchical name.
*/
NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
NetNet*&net,
NetMemory*&mem,
NetVariable*&var,
const NetExpr*&par,
NetEvent*&eve)
NetEvent*&eve,
const NetExpr*&ex1, const NetExpr*&ex2)
{
assert(scope);
@@ -41,8 +40,6 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
/* Initialize output argument to cleared. */
net = 0;
mem = 0;
var = 0;
par = 0;
eve = 0;
@@ -57,22 +54,12 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
return scope;
}
if ( (mem = scope->find_memory(key)) ) {
delete key;
return scope;
}
if ( (var = scope->find_variable(key)) ) {
delete key;
return scope;
}
if ( (eve = scope->find_event(key)) ) {
delete key;
return scope;
}
if ( (par = scope->get_parameter(key)) ) {
if ( (par = scope->get_parameter(key, ex1, ex2)) ) {
delete key;
return scope;
}
@@ -89,6 +76,18 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
/*
* $Log: symbol_search.cc,v $
* Revision 1.4 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.3 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.2 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.1 2003/09/19 03:30:05 steve
* Fix name search in elab_lval.
*
+6 -55
View File
@@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 2000 Stephen Williams ([email protected])
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: syn-rules.y,v 1.31 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: syn-rules.y,v 1.34 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -118,11 +118,8 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
// where lval is really a "reg [7:0]". In other words, part
// selects in the l-value are handled by loff and the lwidth().
int loff = a->get_loff();
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
connect(ff->pin_Data(idx), d->bit(idx+rval_pinoffset));
connect(ff->pin_Q(idx), a->sig()->pin(idx+loff));
}
connect(ff->pin_Data(), d->sig()->pin(0));
connect(ff->pin_Q(), a->sig()->pin(0));
connect(ff->pin_Clock(), pclk->pin(0));
if (ce) connect(ff->pin_Enable(), ce->pin(0));
@@ -140,45 +137,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
a->turn_sig_to_wire_on_release();
}
static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
NetEvProbe*pclk, NetNet*ce,
NetAssign_*a, unsigned rval_pinoffset)
{
assert(d);
assert(a);
/* Connect the input Data bits of the RAM, from the r-value of
the assignment. */
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
connect(ram->pin_Data(idx), d->bit(idx+rval_pinoffset));
}
/* Connect the Address pins from the addr net discovered by the
caller. */
for (unsigned idx = 0 ; idx < ram->awidth() ; idx += 1) {
connect(ram->pin_Address(idx), adr->pin(idx));
}
/* Connect the input clock and the WE of the RAM. */
assert(pclk);
connect(ram->pin_InClock(), pclk->pin(0));
if (ce) {
connect(ram->pin_WE(), ce->pin(0));
} /* XXX does ram CE default to true if not connected? */
/* This notices any other NetRamDq objects connected to the
same NetMemory, that have the same address pins and are
otherwise compatible. This absorbs them into this object. */
ram->absorb_partners();
/* This lval_ represents a reg that is a WIRE in the
synthesized results. This function signals the destructor
to change the REG that this l-value refers to into a
WIRE. It is done then, at the last minute, so that pending
synthesis can continue to work with it as a WIRE. */
a->turn_sig_to_wire_on_release();
}
static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
NetEvent*eclk, NetExpr*cexp, NetAssignBase*asn)
{
@@ -211,16 +169,9 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
if (a->sig()) {
// cerr << "new NetFF named " << a->name() << endl;
NetFF*ff = new NetFF(top->scope(), a->name(),
a->lwidth());
a->sig()->vector_width());
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
des->add_node(ff);
} else if (a->mem()) {
NetMemory *m=a->mem();
NetNet *adr = a->bmux()->synthesize(des);
NetRamDq*ram = new NetRamDq(top->scope(), m->name(),
m, adr->pin_count());
hookup_RAMDQ(ram, d, adr, pclk, ce, a, rval_pinoffset);
des->add_node(ram);
}
rval_pinoffset += a->lwidth();
}
@@ -240,7 +191,7 @@ static void make_initializer(Design*des, NetProcTop*top, NetAssignBase*asn)
for (unsigned idx = 0 ; idx < asn->l_val(0)->lwidth() ; idx += 1) {
verinum::V bit = rsig->bit(idx).nexus()->driven_value();
verinum::V bit = rsig->sig()->pin(idx).nexus()->driven_value();
Nexus*nex = asn->l_val(0)->sig()->pin(idx).nexus();
for (Link*cur = nex->first_nlink()
+251 -286
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,42 +17,28 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.39 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: synth2.cc,v 1.45 2005/08/27 04:32:08 steve Exp $"
#endif
# include "config.h"
# include "functor.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <assert.h>
static int debug_synth2=0;
#ifdef __FUNCTION__
#define DEBUG_SYNTH2_ENTRY(class) if (debug_synth2) { cerr << "Enter " << class << "::" \
<< __FUNCTION__ << endl; dump(cerr, 4); }
#define DEBUG_SYNTH2_EXIT(class,val) if (debug_synth2) { cerr << "Exit " << class << "::" \
<< __FUNCTION__ << ", result " << val << endl; }
#else
#define DEBUG_SYNTH2_ENTRY(class)
#define DEBUG_SYNTH2_EXIT(class,val)
#endif
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
return false;
}
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events)
{
DEBUG_SYNTH2_ENTRY("NetProc")
if (events.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
@@ -63,15 +49,17 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
return synth_async(des, scope, nex_map, nex_out);
}
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
#if 0
static unsigned find_nexus_in_set(const NetBus&nset, const Nexus*nex)
{
unsigned idx = 0;
for (idx = 0 ; idx < nset->pin_count() ; idx += 1)
if (nset->pin(idx).nexus() == nex)
for (idx = 0 ; idx < nset.pin_count() ; idx += 1)
if (nset.pin(idx).nexus() == nex)
return idx;
return idx;
}
#endif
/*
* Async synthesis of assignments is done by synthesizing the rvalue
@@ -84,36 +72,42 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
* r-value.
*/
bool NetAssignBase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
DEBUG_SYNTH2_ENTRY("NetAssignBase")
NetNet*rsig = rval_->synthesize(des);
assert(rsig);
NetNet*lsig = lval_->sig();
if (!lsig) {
cerr << get_line() << ": error: NetAssignBase::synth_async on unsupported lval ";
cerr << get_line() << ": error: "
<< "NetAssignBase::synth_async on unsupported lval ";
dump_lval(cerr);
cerr << endl;
DEBUG_SYNTH2_EXIT("NetAssignBase",false)
return false;
}
assert(lval_->more == 0);
if (lval_->lwidth() != nex_map->pin_count()) {
cerr << get_line() << ": error: NetAssignBase::synth_async pin count mismatch, "
<< lval_->lwidth() << " != " << nex_map->pin_count() << endl;
DEBUG_SYNTH2_EXIT("NetAssignBase",false)
if (debug_synth2) {
cerr << get_line() << ": debug: l-value signal is "
<< lsig->vector_width() << " bits, r-value signal is "
<< rsig->vector_width() << " bits." << endl;
}
#if 0
/* The l-value and r-value map must have the same width. */
if (lval_->lwidth() != nex_map->vector_width()) {
cerr << get_line() << ": error: Assignment synthesis: "
<< "vector width mismatch, "
<< lval_->lwidth() << " bits != "
<< nex_map->vector_width() << " bits." << endl;
return false;
}
assert(nex_map->pin_count() <= rsig->pin_count());
#else
/* For now, assume there is exactly one output. */
assert(nex_out.pin_count() == 1);
#endif
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
unsigned off = lval_->get_loff()+idx;
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
connect(nex_out->pin(ptr), rsig->pin(idx));
}
connect(nex_out.pin(0), rsig->pin(0));
/* This lval_ represents a reg that is a WIRE in the
synthesized results. This function signals the destructor
@@ -122,7 +116,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
synthesis can continue to work with it as a WIRE. */
lval_->turn_sig_to_wire_on_release();
DEBUG_SYNTH2_EXIT("NetAssignBase",true)
return true;
}
@@ -133,191 +126,144 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
* substatements.
*/
bool NetBlock::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
DEBUG_SYNTH2_ENTRY("NetBlock")
if (last_ == 0) {
DEBUG_SYNTH2_EXIT("NetBlock",true)
return true;
}
const perm_string tmp1 = perm_string::literal("tmp1");
const perm_string tmp2 = perm_string::literal("tmp2");
bool flag = true;
NetProc*cur = last_;
do {
cur = cur->next_;
/* Create a temporary nex_map for the substatement. */
/* Create a temporary map of the output only from this
statement. */
NexusSet tmp_set;
cur->nex_output(tmp_set);
NetNet*tmp_map = new NetNet(scope, tmp1, NetNet::WIRE,
tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_map->pin(idx));
NetBus tmp_map (scope, tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1)
connect(tmp_set[idx], tmp_map.pin(idx));
/* Create also a temporary net_out to collect the
output. */
NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE,
tmp_set.count());
/* Create also a temporary NetBus to collect the
output from the synthesis. */
NetBus tmp_out (scope, tmp_set.count());
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out);
flag = flag && ok_flag;
flag = flag && ok_flag;
if (ok_flag == false)
continue;
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(nex_out->pin(ptr), tmp_out->pin(idx));
}
/* Now find the tmp_map pins in the nex_map global map,
and use that to direct the connection to the nex_out
output bus. Look for the nex_map pin that is linked
to the tmp_map.pin(idx) pin, and link that to the
tmp_out.pin(idx) output link. */
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
unsigned ptr = 0;
while (ptr < nex_map.pin_count()
&& ! nex_map.pin(ptr).is_linked(tmp_map.pin(idx)))
ptr += 1;
delete tmp_map;
delete tmp_out;
assert(ptr < nex_out.pin_count());
connect(nex_out.pin(ptr), tmp_out.pin(idx));
}
} while (cur != last_);
DEBUG_SYNTH2_EXIT("NetBlock",flag)
return flag;
}
bool NetCase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
DEBUG_SYNTH2_ENTRY("NetCase")
unsigned cur;
/* Synthesize the select expression. */
NetNet*esig = expr_->synthesize(des);
/* Scan the select vector looking for constant bits. The
constant bits will be elided from the select input connect,
but we still need to keep track of them. */
unsigned sel_pins = 0;
unsigned long sel_mask = 0;
unsigned long sel_ref = 0;
for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) {
unsigned sel_width = esig->vector_width();
assert(sel_width > 0);
if (esig->pin(idx).nexus()->drivers_constant()) {
verinum::V bit = esig->pin(idx).nexus()->driven_value();
if (bit == verinum::V1)
sel_ref |= 1 << idx;
unsigned mux_width = 0;
for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1)
mux_width += nex_out.pin(idx).nexus()->vector_width();
} else {
sel_pins += 1;
sel_mask |= 1 << idx;
}
}
/* Collect all the statements into a map of index to
statement. The guard expression it evaluated to be the
index of the mux value, and the statement is bound to that
index. */
/* Build a map of guard values to mux select values. This
helps account for constant select bits that are being
elided. */
map<unsigned long,unsigned long>guard2sel;
cur = 0;
for (unsigned idx = 0 ; idx < (1U<<esig->pin_count()) ; idx += 1) {
if ((idx & ~sel_mask) == sel_ref) {
guard2sel[idx] = cur;
cur += 1;
}
}
assert(cur == (1U << sel_pins));
unsigned long max_guard_value = 0;
map<unsigned long,NetProc*>statement_map;
NetProc*statement_default = 0;
NetMux*mux = new NetMux(scope, scope->local_symbol(),
nex_out->pin_count(),
1U << sel_pins, sel_pins);
/* Connect the non-constant select bits to the select input of
the mux device. */
cur = 0;
for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) {
/* skip bits that are known to be constant. */
if ((sel_mask & (1U << idx)) == 0)
continue;
connect(mux->pin_Sel(cur), esig->pin(idx));
cur += 1;
}
assert(cur == sel_pins);
/* Hook up the output of the mux to the mapped output pins. */
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
connect(nex_out->pin(idx), mux->pin_Result(idx));
NetProc**statement_map = new NetProc*[1 << sel_pins];
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1)
statement_map[item] = 0;
/* Assign the input statements to MUX inputs. This involves
calculating the guard value, passing that through the
guard2sel map, then saving the statement in the
statement_map. If I find a default case, then save that for
use later. */
NetProc*default_statement = 0;
for (unsigned item = 0 ; item < nitems_ ; item += 1) {
/* Skip the default case this pass. */
if (items_[item].guard == 0) {
default_statement = items_[item].statement;
statement_default = items_[item].statement;
continue;
}
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
assert(ge);
verinum gval = ge->value();
unsigned sel_idx = guard2sel[gval.as_ulong()];
unsigned sel_idx = gval.as_ulong();
assert(items_[item].statement);
statement_map[sel_idx] = items_[item].statement;
if (sel_idx > max_guard_value)
max_guard_value = sel_idx;
}
/* Now that statements match with mux inputs, synthesize the
sub-statements. If I get to an input that has no statement,
then use the default statement there. */
NetNet*default_sig = 0;
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1) {
unsigned mux_size = max_guard_value + 1;
/* Detect the case that this is a default input, and I
have a precalculated default_sig. */
if ((statement_map[item] == 0) && (default_sig != 0)) {
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
connect(mux->pin_Data(idx, item), default_sig->pin(idx));
continue;
}
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, nex_map->pin_count());
sig->local_flag(true);
if (statement_map[item] == 0) {
statement_map[item] = default_statement;
default_statement = 0;
default_sig = sig;
}
if (statement_map[item] == 0) {
/* Missing case and no default; this could still be
* synthesizable with synchronous logic, but not here. */
DEBUG_SYNTH2_EXIT("NetCase", false)
return false;
}
statement_map[item]->synth_async(des, scope, nex_map, sig);
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
connect(mux->pin_Data(idx, item), sig->pin(idx));
}
delete[]statement_map;
NetMux*mux = new NetMux(scope, scope->local_symbol(),
mux_width, mux_size, sel_width);
des->add_node(mux);
DEBUG_SYNTH2_EXIT("NetCase", true)
/* The select signal is already synthesized. Simply hook it up. */
connect(mux->pin_Sel(), esig->pin(0));
/* For now, assume that the output is only 1 signal. */
assert(nex_out.pin_count() == 1);
connect(mux->pin_Result(), nex_out.pin(0));
/* For now, only support logic types. */
ivl_variable_type_t mux_data_type = IVL_VT_LOGIC;
/* Forgot to support default statements? */
assert(statement_default == 0);
NetNet*isig;
for (unsigned idx = 0 ; idx < mux_size ; idx += 1) {
NetProc*stmt = statement_map[idx];
if (stmt == 0) {
cerr << get_line() << ": error: case " << idx
<< " is not accounted for in asynchronous mux." << endl;
continue;
}
isig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, mux_width);
isig->local_flag(true);
isig->data_type(mux_data_type);
connect(mux->pin_Data(idx), isig->pin(0));
NetBus tmp (scope, 1);
connect(tmp.pin(0), isig->pin(0));
stmt->synth_async(des, scope, tmp, tmp);
}
return true;
}
bool NetCondit::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
DEBUG_SYNTH2_ENTRY("NetCondit")
#if 0
NetNet*ssig = expr_->synthesize(des);
assert(ssig);
@@ -360,50 +306,56 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
}
NetMux*mux = new NetMux(scope, scope->local_symbol(),
nex_out->pin_count(), 2, 1);
nex_out->vector_width(), 2, 1);
connect(mux->pin_Sel(0), ssig->pin(0));
for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
connect(mux->pin_Data(idx, 1), asig->pin(idx));
for (unsigned idx = 0 ; idx < bsig->pin_count() ; idx += 1)
connect(mux->pin_Data(idx, 0), bsig->pin(idx));
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
connect(nex_out->pin(idx), mux->pin_Result(idx));
connect(mux->pin_Sel(), ssig->pin(0));
connect(mux->pin_Data(1), asig->pin(0));
connect(mux->pin_Data(0), bsig->pin(0));
connect(nex_out->pin(0), mux->pin_Result());
des->add_node(mux);
DEBUG_SYNTH2_EXIT("NetCondit",true)
return true;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetCondit::synth_async" << endl;
return false;
#endif
}
bool NetEvWait::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
const NetBus&nex_map, NetBus&nex_out)
{
DEBUG_SYNTH2_ENTRY("NetEvWait")
bool flag = statement_->synth_async(des, scope, nex_map, nex_out);
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
return flag;
}
/*
* This method is called when the process is shown to be
* asynchronous. Figure out the nexus set of outputs from this
* process, and pass that to the synth_async method for the statement
* of the process. The statement will connect its output to the
* nex_out set, using the nex_map as a guide. Starting from the top,
* the nex_map is the same as the nex_map.
*/
bool NetProcTop::synth_async(Design*des)
{
DEBUG_SYNTH2_ENTRY("NetProcTop")
NexusSet nex_set;
statement_->nex_output(nex_set);
const perm_string tmp1 = perm_string::literal("tmp");
NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
connect(nex_set[idx], nex_out->pin(idx));
if (debug_synth2) {
cerr << get_line() << ": debug: Process has "
<< nex_set.count() << " outputs." << endl;
}
bool flag = statement_->synth_async(des, scope(), nex_out, nex_out);
NetBus nex_q (scope(), nex_set.count());
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_set[idx], nex_q.pin(idx));
}
delete nex_out;
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
bool flag = statement_->synth_async(des, scope(), nex_q, nex_q);
return flag;
}
@@ -422,15 +374,14 @@ bool NetProcTop::synth_async(Design*des)
* the statements may each infer different reset and enable signals.
*/
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in)
{
DEBUG_SYNTH2_ENTRY("NetBlock")
if (last_ == 0) {
DEBUG_SYNTH2_EXIT("NetBlock",true)
return true;
}
#if 0
bool flag = true;
const perm_string tmp1 = perm_string::literal("tmp1");
@@ -572,8 +523,14 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
taken up by the smaller NetFF devices. */
delete ff;
DEBUG_SYNTH2_EXIT("NetBlock",flag)
return flag;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetBlock::synth_sync"
<< endl;
return false;
#endif
}
/*
@@ -583,10 +540,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
* expression is connected to an event, or not.
*/
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in)
{
DEBUG_SYNTH2_ENTRY("NetCondit")
#if 0
/* First try to turn the condition expression into an
asynchronous set/reset. If the condition expression has
inputs that are included in the sensitivity list, then it
@@ -768,7 +725,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (ff->pin_Enable().is_linked()) {
NetLogic*ce_and = new NetLogic(scope,
scope->local_symbol(), 3,
NetLogic::AND);
NetLogic::AND, 1);
des->add_node(ce_and);
connect(ff->pin_Enable(), ce_and->pin(1));
connect(ce->pin(0), ce_and->pin(2));
@@ -788,15 +745,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
DEBUG_SYNTH2_EXIT("NetCondit",flag)
return flag;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetCondit::synth_sync" << endl;
return false;
#endif
}
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in)
{
DEBUG_SYNTH2_ENTRY("NetEvWait")
if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
@@ -814,7 +775,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
svector<NetEvProbe*>events (ev->nprobe() - 1);
/* Get the input set from the substatement. This will be used
to figure out which of the probes in the clock. */
to figure out which of the probes is the clock. */
NexusSet*statement_input = statement_ -> nex_input();
/* Search for a clock input. The clock input is the edge event
@@ -848,62 +809,117 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
<< " are valid clock inputs." << endl;
cerr << get_line() << ": : Perhaps the clock"
<< " is read by a statement or expression?" << endl;
DEBUG_SYNTH2_EXIT("NetEvWait",false)
return false;
}
connect(ff->pin_Clock(), pclk->pin(0));
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
if (pclk->edge() == NetEvProbe::NEGEDGE) {
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
ff->attribute(polarity, verinum("INVERT"));
if (debug_synth2) {
cerr << get_line() << ": debug: "
<< "Detected a NEGEDGE clock for the synthesized ff."
<< endl;
}
}
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope, ff,
nex_map, nex_out, events);
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
return flag;
}
/*
* This method is called for a process that is determined to be
* synchronous. Create a NetFF device to hold the output from the
* statement, and synthesize that statement in place.
*/
bool NetProcTop::synth_sync(Design*des)
{
DEBUG_SYNTH2_ENTRY("NetProcTop")
if (debug_synth2) {
cerr << get_line() << ": debug: "
<< "Process is apparently synchronous. Making NetFFs."
<< endl;
}
NexusSet nex_set;
statement_->nex_output(nex_set);
/* Make a model FF that will connect to the first item in the
set, and will also take the initial connection of clocks
and resets. */
if (debug_synth2) {
cerr << get_line() << ": debug: "
<< "Top level making a "
<< nex_set[0]->vector_width() << "-wide "
<< "NetFF device." << endl;
}
NetFF*ff = new NetFF(scope(), scope()->local_symbol(),
nex_set.count());
nex_set[0]->vector_width());
des->add_node(ff);
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
/* The D inputs to the DFF device will receive the output from
the statements of the process. */
NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(),
NetNet::WIRE, nex_set.count());
nex_d->local_flag(true);
NetBus nex_d (scope(), nex_set.count());
NetBus nex_q (scope(), nex_set.count());
/* The Q of the NetFF devices is connected to the output that
we are. The nex_q is a bundle of the outputs. We will also
pass the nex_q as a map to the statement's synth_sync
method to map it to the correct nex_d pin. */
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_d->pin(idx), ff->pin_Data(idx));
connect(nex_set[idx], nex_q.pin(idx));
}
/* The Q outputs of the DFF will connect to the actual outputs
of the process. Thus, the DFF will be between the outputs
of the process and the outputs of the substatement. */
const perm_string tmpq = perm_string::literal("tmpq");
NetNet*nex_q = new NetNet(scope(), tmpq, NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_set[idx], nex_q->pin(idx));
connect(nex_q->pin(idx), ff->pin_Q(idx));
}
// Connect the input later.
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope(), ff,
nex_q, nex_d,
svector<NetEvProbe*>());
if (! flag) {
delete ff;
return false;
}
delete nex_q;
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
return flag;
NetNet*tmp = nex_d.pin(0).nexus()->pick_any_net();
assert(tmp);
tmp = crop_to_width(des, tmp, ff->width());
connect(tmp->pin(0), ff->pin_Data());
connect(nex_q.pin(0), ff->pin_Q());
for (unsigned idx = 1 ; idx < nex_set.count() ; idx += 1) {
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
nex_set[idx]->vector_width());
des->add_node(ff2);
tmp = nex_d.pin(idx).nexus()->pick_any_net();
assert(tmp);
tmp = crop_to_width(des, tmp, ff2->width());
connect(nex_q.pin(idx), ff2->pin_Q());
connect(tmp->pin(0), ff2->pin_Data());
connect(ff->pin_Clock(), ff2->pin_Clock());
if (ff->pin_Enable().is_linked())
connect(ff->pin_Enable(), ff2->pin_Enable());
if (ff->pin_Aset().is_linked())
connect(ff->pin_Aset(), ff2->pin_Aset());
if (ff->pin_Aclr().is_linked())
connect(ff->pin_Aclr(), ff2->pin_Aclr());
if (ff->pin_Sset().is_linked())
connect(ff->pin_Sset(), ff2->pin_Sset());
if (ff->pin_Sclr().is_linked())
connect(ff->pin_Sclr(), ff2->pin_Sclr());
}
return true;
}
class synth2_f : public functor_t {
@@ -978,74 +994,23 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
void synth2(Design*des)
{
debug_synth2 = atoi(des->get_flag("ivl-synth2-debug"));
synth2_f synth_obj;
des->functor(&synth_obj);
}
/*
* $Log: synth2.cc,v $
* Revision 1.39 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
* Revision 1.45 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
* Revision 1.38 2004/08/28 15:08:32 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
* Revision 1.44 2005/05/15 04:45:50 steve
* Debug text.
*
* Revision 1.37 2004/03/15 18:40:12 steve
* Only include DEBUG_SYNTH2 if __FUNCTION__ defined.
* Revision 1.43 2005/04/25 01:35:58 steve
* Reimplement basic asynchronous processes.
*
* Revision 1.36 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
* Revision 1.42 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.35 2004/02/18 17:11:58 steve
* Use perm_strings for named langiage items.
*
* Revision 1.34 2003/12/20 00:59:31 steve
* Synthesis debug messages.
*
* Revision 1.33 2003/12/17 16:52:39 steve
* Debug dumps for synth2.
*
* Revision 1.32 2003/10/27 02:18:04 steve
* Handle special case of FF with enable and constant data.
*
* Revision 1.31 2003/08/28 04:11:19 steve
* Spelling patch.
*
* Revision 1.30 2003/08/15 02:23:53 steve
* Add synthesis support for synchronous reset.
*
* Revision 1.29 2003/08/14 02:41:05 steve
* Fix dangling pointer in NexusSet handling blocks.
*
* Revision 1.28 2003/08/10 17:04:23 steve
* Detect asynchronous FF inputs that are expressions.
*
* Revision 1.27 2003/06/23 00:14:44 steve
* ivl_synthesis_cell cuts off synthesis within a module.
*
* Revision 1.26 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
*
* Revision 1.25 2003/04/03 04:30:00 steve
* Prevent overrun comparing verinums to zero.
*
* Revision 1.24 2003/03/25 04:04:29 steve
* Handle defaults in synthesized case statements.
*
* Revision 1.23 2003/03/06 00:28:42 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.22 2003/02/26 01:29:24 steve
* LPM objects store only their base names.
*
* Revision 1.21 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.20 2002/11/09 23:29:29 steve
* Handle nested-if chip enables.
*
* Revision 1.19 2002/11/09 20:22:57 steve
* Detect synthesis conflicts blocks statements share outputs.
*/
+15 -12
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_funcs.cc,v 1.6 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: sys_funcs.cc,v 1.7 2005/07/11 16:56:51 steve Exp $"
#endif
# include "config.h"
@@ -31,14 +31,14 @@
*/
static const struct sfunc_return_type sfunc_table[] = {
{ "$realtime", NetExpr::ET_REAL, 0, 0 },
{ "$bitstoreal", NetExpr::ET_REAL, 0, 0 },
{ "$itor", NetExpr::ET_REAL, 0, 0 },
{ "$realtobits", NetExpr::ET_VECTOR, 64, 0 },
{ "$time", NetExpr::ET_VECTOR, 64, 0 },
{ "$stime", NetExpr::ET_VECTOR, 32, 0 },
{ "$simtime", NetExpr::ET_VECTOR, 64, 0 },
{ 0, NetExpr::ET_VECTOR, 32, 0 }
{ "$realtime", IVL_VT_REAL, 0, 0 },
{ "$bitstoreal", IVL_VT_REAL, 0, 0 },
{ "$itor", IVL_VT_REAL, 0, 0 },
{ "$realtobits", IVL_VT_LOGIC, 64, 0 },
{ "$time", IVL_VT_LOGIC, 64, 0 },
{ "$stime", IVL_VT_LOGIC, 32, 0 },
{ "$simtime", IVL_VT_LOGIC, 64, 0 },
{ 0, IVL_VT_LOGIC, 32, 0 }
};
struct sfunc_return_type_cell : sfunc_return_type {
@@ -124,7 +124,7 @@ int load_sys_func_table(const char*path)
if (strcmp(stype,"vpiSysFuncReal") == 0) {
cell = new struct sfunc_return_type_cell;
cell->name = lex_strings.add(name);
cell->type = NetExpr::ET_REAL;
cell->type = IVL_VT_REAL;
cell->wid = 0;
cell->signed_flag = true;
cell->next = sfunc_stack;
@@ -135,7 +135,7 @@ int load_sys_func_table(const char*path)
if (strcmp(stype,"vpiSysFuncInt") == 0) {
cell = new struct sfunc_return_type_cell;
cell->name = lex_strings.add(name);
cell->type = NetExpr::ET_VECTOR;
cell->type = IVL_VT_LOGIC;
cell->wid = 32;
cell->signed_flag = true;
cell->next = sfunc_stack;
@@ -176,7 +176,7 @@ int load_sys_func_table(const char*path)
cell = new struct sfunc_return_type_cell;
cell->name = lex_strings.add(name);
cell->type = NetExpr::ET_VECTOR;
cell->type = IVL_VT_LOGIC;
cell->wid = width;
cell->signed_flag = signed_flag;
cell->next = sfunc_stack;
@@ -193,6 +193,9 @@ int load_sys_func_table(const char*path)
/*
* $Log: sys_funcs.cc,v $
* Revision 1.7 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.6 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*
+438 -329
View File
File diff suppressed because it is too large Load Diff
+48 -158
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-expr.cc,v 1.39 2004/06/17 16:06:19 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.44 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -38,18 +38,7 @@
*/
static ivl_variable_type_t get_expr_type(const NetExpr*net)
{
switch (net->expr_type()) {
case NetExpr::ET_VOID:
return IVL_VT_VOID;
case NetExpr::ET_REAL:
return IVL_VT_REAL;
case NetExpr::ET_VECTOR:
return IVL_VT_VECTOR;
}
return IVL_VT_VOID;
return net->expr_type();
}
/*
@@ -211,34 +200,13 @@ void dll_target::expr_concat(const NetEConcat*net)
expr_ = cur;
}
void dll_target::expr_memory(const NetEMemory*net)
{
assert(expr_ == 0);
if (net->index()) {
net->index()->expr_scan(this);
assert(expr_);
}
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(cur);
cur->type_ = IVL_EX_MEMORY;
cur->value_ = IVL_VT_VECTOR;
cur->width_= net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
cur->u_.memory_.idx_ = expr_;
expr_ = cur;
}
void dll_target::expr_const(const NetEConst*net)
{
assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
expr_->value_= IVL_VT_VECTOR;
expr_->value_= net->expr_type();
if (net->value().is_string()) {
expr_->type_ = IVL_EX_STRING;
@@ -369,18 +337,7 @@ void dll_target::expr_sfunc(const NetESFunc*net)
assert(expr);
expr->type_ = IVL_EX_SFUNC;
switch (net->expr_type()) {
case NetExpr::ET_VECTOR:
expr->value_= IVL_VT_VECTOR;
break;
case NetExpr::ET_REAL:
expr->value_= IVL_VT_REAL;
break;
case NetExpr::ET_VOID:
assert(0);
expr->value_= IVL_VT_VECTOR;
break;
}
expr->value_= net->expr_type();
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
/* system function names are lex_strings strings. */
@@ -432,116 +389,41 @@ void dll_target::expr_ternary(const NetETernary*net)
void dll_target::expr_signal(const NetESignal*net)
{
ivl_signal_t sig = find_signal(des_, net->sig());
assert(expr_ == 0);
/* If there is a word expression, generate it. */
ivl_expr_t word_expr = 0;
if (const NetExpr*word = net->word_index()) {
word->expr_scan(this);
assert(expr_);
word_expr = expr_;
expr_ = 0;
}
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
expr_->type_ = IVL_EX_SIGNAL;
expr_->value_= IVL_VT_VECTOR;
expr_->value_= net->expr_type();
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->u_.signal_.sig = find_signal(des_, net->sig());
expr_->u_.signal_.lsi = net->lsi();
expr_->u_.signal_.msi = net->msi();
}
void dll_target::expr_subsignal(const NetEBitSel*net)
{
assert(expr_ == 0);
ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr);
expr->type_ = IVL_EX_BITSEL;
expr->value_= IVL_VT_VECTOR;
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
expr->u_.bitsel_.sig = find_signal(des_, net->sig());
assert(expr->u_.bitsel_.sig->lsb_index == net->sig()->lsb());
net->index()->expr_scan(this);
assert(expr_);
expr->u_.bitsel_.bit = expr_;
/* If the lsb of the signal is not 0, then we are about to
lose the proper offset to the normalized vector. Modify the
expression to subtract the offset:
reg [7:4] a;
... = a[x];
becomes
reg [3:0] a;
... = a[x-4];
to reflect the normalizing of vectors that is done by the
compiler. */
if (expr->u_.bitsel_.sig->lsb_index != 0) {
/* Create in tmpc the constant offset (4 in the above
example) to be subtracted from the index. */
char*bits;
long lsb = expr->u_.bitsel_.sig->lsb_index;
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->width_ = expr->u_.bitsel_.bit->width_;
tmpc->signed_ = net->index()->has_sign()? 1 : 0;
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
bits[idx] = (lsb & 1)? '1' : '0';
lsb >>= 1;
}
/* Now make the subtractor (x-4 in the above example)
that has as input A the index expression and input B
the constant to subtract. */
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->width_ = tmpc->width_;
tmps->signed_ = net->index()->has_sign()? 1 : 0;
tmps->u_.binary_.op_ = '-';
tmps->u_.binary_.lef_ = expr->u_.bitsel_.bit;
tmps->u_.binary_.rig_ = tmpc;
/* Replace (x) with (x-4) */
expr->u_.bitsel_.bit = tmps;
/* If the index item distance (the distance to the next
most significant bit) is not 1, then multiply the
previous result to convert the index. */
if (expr->u_.bitsel_.sig->lsb_dist != 1) {
long dist = expr->u_.bitsel_.sig->lsb_dist;
tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->width_ = expr->u_.bitsel_.bit->width_;
tmpc->signed_ = 1;
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
bits[idx] = (dist & 1)? '1' : '0';
dist >>= 1;
}
tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->width_ = tmpc->width_;
tmps->signed_ = 1;
tmps->u_.binary_.op_ = '*';
tmps->u_.binary_.lef_ = expr->u_.bitsel_.bit;
tmps->u_.binary_.rig_ = tmpc;
expr->u_.bitsel_.bit = tmps;
}
expr_->u_.signal_.word = word_expr;
expr_->u_.signal_.sig = sig;
/* Make account for the special case that this is a reference
to an array as a whole. We detect this case by noting that
this is an array (more then 1 word) and there is no word
select expression. In that case, this is an IVL_EX_ARRAY
expression instead of a SIGNAL expression. */
if (sig->array_words > 1 && word_expr == 0) {
expr_->type_ = IVL_EX_ARRAY;
expr_->width_ = 0; // Doesn't make much sense for arrays.
}
expr_ = expr;
}
void dll_target::expr_ufunc(const NetEUFunc*net)
{
assert(expr_ == 0);
@@ -550,7 +432,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
assert(expr);
expr->type_ = IVL_EX_UFUNC;
expr->value_= IVL_VT_VECTOR;
expr->value_= net->expr_type();
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
@@ -590,20 +472,28 @@ void dll_target::expr_unary(const NetEUnary*net)
expr_->u_.unary_.sub_ = sub;
}
void dll_target::expr_variable(const NetEVariable*net)
{
assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_VARIABLE;
expr_->value_ = IVL_VT_REAL;
expr_->width_ = 0;
expr_->signed_= net->has_sign()? 1 : 0;
expr_->u_.variable_.var = find_variable(des_, net->variable());
}
/*
* $Log: t-dll-expr.cc,v $
* Revision 1.44 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.43 2005/09/14 02:53:15 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.42 2005/07/13 04:51:36 steve
* Functions get type from their output signal.
*
* Revision 1.41 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.40 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.39 2004/06/17 16:06:19 steve
* Help system function signedness survive elaboration.
*
+78 -201
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-proc.cc,v 1.65 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: t-dll-proc.cc,v 1.69 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -130,13 +130,6 @@ bool dll_target::func_def(const NetScope*net)
return true;
}
if (const NetVariable*ret_var = def->return_var()) {
cerr << ret_var->get_line() << ": internal error: "
<< "Function " << net->name() << " has an unsupported "
<< "return type." << endl;
return false;
}
cerr << "?:0" << ": internal error: "
<< "Function " << net->name() << " has a return type"
<< " that I do not understand." << endl;
@@ -145,65 +138,73 @@ bool dll_target::func_def(const NetScope*net)
}
/*
* This private function makes the assignment lvals for the various
* kinds of assignment statements.
*/
void dll_target::proc_assign(const NetAssign*net)
void dll_target::make_assign_lvals_(const NetAssignBase*net)
{
unsigned cnt;
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN;
unsigned cnt = net->l_val_count();
stmt_cur_->u_.assign_.lvals_ = cnt = net->l_val_count();
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0;
stmt_cur_->u_.assign_.lvals_ = cnt;
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0;
/* The assignment may have multiple concatenated
l-values. Scan them and accumulate an ivl_lval_t list. */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
const NetAssign_*asn = net->l_val(idx);
const NetExpr*loff = asn->get_base();
if (loff == 0) {
cur->loff = 0;
} else {
loff->expr_scan(this);
cur->loff = expr_;
expr_ = 0;
}
cur->width_ = asn->lwidth();
cur->loff_ = asn->get_loff();
if (asn->sig()) {
cur->type_ = IVL_LVAL_REG;
cur->n.sig = find_signal(des_, asn->sig());
cur->type_ = IVL_LVAL_REG;
cur->n.sig = find_signal(des_, asn->sig());
cur->idx = 0;
if (asn->bmux()) {
// If there is a word select expression, it is
// really an array index.
if (asn->word()) {
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
asn->word()->expr_scan(this);
if (cur->n.sig->lsb_index != 0)
sub_off_from_expr_(asn->sig()->lsb());
if (cur->n.sig->lsb_dist != 1)
mul_expr_by_const_(cur->n.sig->lsb_dist);
cur->type_ = IVL_LVAL_MUX;
cur->type_ = IVL_LVAL_ARR;
cur->idx = expr_;
expr_ = 0;
}
} else if (asn->var()) {
cur->type_ = IVL_LVAL_VAR;
cur->idx = 0;
cur->n.var = find_variable(des_, asn->var());
} else {
assert(asn->mem());
cur->type_ = IVL_LVAL_MEM;
cur->n.mem = find_memory(des_, asn->mem());
assert(cur->n.mem);
cur->width_ = ivl_memory_width(cur->n.mem);
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
cur->idx = expr_;
expr_ = 0;
assert(0);
}
}
}
/*
*/
void dll_target::proc_assign(const NetAssign*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN;
stmt_cur_->u_.assign_.delay = 0;
/* Make the lval fields. */
make_assign_lvals_(net);
assert(expr_ == 0);
net->rval()->expr_scan(this);
@@ -221,62 +222,17 @@ void dll_target::proc_assign(const NetAssign*net)
void dll_target::proc_assign_nb(const NetAssignNB*net)
{
unsigned cnt = net->l_val_count();
const NetExpr* delay_exp = net->get_delay();
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
stmt_cur_->u_.assign_.lvals_ = cnt;
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0;
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
const NetAssign_*asn = net->l_val(idx);
cur->width_ = asn->lwidth();
cur->loff_ = asn->get_loff();
if (asn->sig()) {
cur->type_ = IVL_LVAL_REG;
cur->n.sig = find_signal(des_, asn->sig());
cur->idx = 0;
if (asn->bmux()) {
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
if (cur->n.sig->lsb_index != 0)
sub_off_from_expr_(asn->sig()->lsb());
if (cur->n.sig->lsb_dist != 1)
mul_expr_by_const_(cur->n.sig->lsb_dist);
cur->type_ = IVL_LVAL_MUX;
cur->idx = expr_;
expr_ = 0;
}
} else if (asn->mem()) {
assert(asn->mem());
cur->type_ = IVL_LVAL_MEM;
cur->n.mem = find_memory(des_, asn->mem());
assert(cur->n.mem);
cur->width_ = ivl_memory_width(cur->n.mem);
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
cur->idx = expr_;
expr_ = 0;
} else {
assert(asn->var());
cur->type_ = IVL_LVAL_VAR;
cur->idx = 0;
cur->n.var = find_variable(des_, asn->var());
}
}
/* Make the lval fields. */
make_assign_lvals_(net);
/* Make the rval field. */
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
@@ -428,27 +384,13 @@ bool dll_target::proc_cassign(const NetCAssign*net)
stmt_cur_->type_ = IVL_ST_CASSIGN;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
/* Make the l-value fields. */
make_assign_lvals_(net);
const NetNet*lsig = net->lval();
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
stmt_cur_->u_.cassign_.npins = net->pin_count();
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
assert(ntmp[idx]);
}
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
return true;
}
@@ -485,19 +427,9 @@ bool dll_target::proc_deassign(const NetDeassign*net)
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_DEASSIGN;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
const NetNet*lsig = net->lval();
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
stmt_cur_->u_.cassign_.npins = 0;
stmt_cur_->u_.cassign_.pins = 0;
/* Make the l-value fields. */
make_assign_lvals_(net);
return true;
}
@@ -554,52 +486,19 @@ bool dll_target::proc_disable(const NetDisable*net)
bool dll_target::proc_force(const NetForce*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_FORCE;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
/* Make the l-value fields. */
make_assign_lvals_(net);
const NetNet*lsig = net->lval();
assert(lsig);
ivl_signal_t sig = find_signal(des_, lsig);
assert(sig);
ivl_lval_type_t ltype;
switch (sig->type_) {
case IVL_SIT_REG:
ltype = IVL_LVAL_REG;
break;
case IVL_SIT_TRI:
case IVL_SIT_TRI0:
case IVL_SIT_TRI1:
ltype = IVL_LVAL_NET;
break;
default:
cerr << net->get_line() << ": internal error: Sorry, "
<< "force to nets not supported by this target."
<< endl;
return false;
}
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
stmt_cur_->u_.cassign_.npins = net->pin_count();
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
assert(ntmp[idx]);
}
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
return true;
}
@@ -630,47 +529,8 @@ bool dll_target::proc_release(const NetRelease*net)
stmt_cur_->type_ = IVL_ST_RELEASE;
/* If there is no signal attached to the release, then it is
the victim of an elided net. In that case, simply state
that there are no lvals, and that's all. */
const NetNet*lsig = net->lval();
if (lsig == 0) {
stmt_cur_->u_.cassign_.lvals = 0;
return true;
}
assert(lsig);
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
ivl_signal_t sig = find_signal(des_, lsig);
assert(sig);
ivl_lval_type_t ltype;
switch (sig->type_) {
case IVL_SIT_REG:
ltype = IVL_LVAL_REG;
break;
case IVL_SIT_TRI:
case IVL_SIT_TRI0:
case IVL_SIT_TRI1:
ltype = IVL_LVAL_NET;
break;
default:
cerr << net->get_line() << ": internal error: Sorry, "
<< "force/release to nets not supported by this target."
<< endl;
return false;
}
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
/* Make the l-value fields. */
make_assign_lvals_(net);
return true;
}
@@ -872,6 +732,23 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.69 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.68 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.67 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.66 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.65 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*
+767 -652
View File
File diff suppressed because it is too large Load Diff
+160 -98
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: t-dll.h,v 1.137 2007/01/17 05:00:12 steve Exp $"
#endif
# include "target.h"
@@ -69,11 +69,12 @@ struct dll_target : public target_t, public expr_scan_t {
bool bufz(const NetBUFZ*);
void event(const NetEvent*);
void variable(const NetVariable*);
void logic(const NetLogic*);
bool ureduce(const NetUReduce*);
void net_case_cmp(const NetCaseCmp*);
void udp(const NetUDP*);
void lpm_add_sub(const NetAddSub*);
bool lpm_array_dq(const NetArrayDq*);
void lpm_clshift(const NetCLShift*);
void lpm_compare(const NetCompare*);
void lpm_divide(const NetDivide*);
@@ -81,19 +82,21 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_modulo(const NetModulo*);
void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*);
void lpm_ram_dq(const NetRamDq*);
bool concat(const NetConcat*);
bool part_select(const NetPartSelect*);
bool replicate(const NetReplicate*);
void net_assign(const NetAssign_*);
bool net_cassign(const NetCAssign*);
bool net_force(const NetForce*);
bool net_sysfunction(const NetSysFunc*);
bool net_function(const NetUserFunc*);
bool net_const(const NetConst*);
bool net_literal(const NetLiteral*);
void net_probe(const NetEvProbe*);
bool sign_extend(const NetSignExtend*);
bool process(const NetProcTop*);
void scope(const NetScope*);
void signal(const NetNet*);
void memory(const NetMemory*);
bool signal_paths(const NetNet*);
ivl_dll_t dll_;
ivl_design_s des_;
@@ -129,7 +132,6 @@ struct dll_target : public target_t, public expr_scan_t {
struct ivl_expr_s*expr_;
void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*);
void expr_memory(const NetEMemory*);
void expr_const(const NetEConst*);
void expr_creal(const NetECReal*);
void expr_param(const NetEConstParam*);
@@ -137,12 +139,10 @@ struct dll_target : public target_t, public expr_scan_t {
void expr_scope(const NetEScope*);
void expr_select(const NetESelect*);
void expr_sfunc(const NetESFunc*);
void expr_subsignal(const NetEBitSel*);
void expr_ternary(const NetETernary*);
void expr_ufunc(const NetEUFunc*);
void expr_unary(const NetEUnary*);
void expr_signal(const NetESignal*);
void expr_variable(const NetEVariable*);
ivl_scope_t lookup_scope_(const NetScope*scope);
@@ -154,17 +154,16 @@ struct dll_target : public target_t, public expr_scan_t {
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
static ivl_variable_t find_variable(ivl_design_s &des, const NetVariable*net);
static ivl_parameter_t scope_find_param(ivl_scope_t scope,
const char*name);
void add_root(ivl_design_s &des_, const NetScope *s);
void make_assign_lvals_(const NetAssignBase*net);
void sub_off_from_expr_(long);
void mul_expr_by_const_(long);
void make_logic_delays_(struct ivl_net_logic_s*obj, const NetObj*net);
void make_scope_parameters(ivl_scope_t scope, const NetScope*net);
static ivl_expr_t expr_from_value_(const verinum&that);
@@ -174,6 +173,11 @@ struct dll_target : public target_t, public expr_scan_t {
* These are various private declarations used by the t-dll target.
*/
struct ivl_delaypath_s {
ivl_nexus_t src;
uint64_t delay[12];
};
struct ivl_event_s {
perm_string name;
ivl_scope_t scope;
@@ -201,11 +205,6 @@ struct ivl_expr_s {
ivl_expr_t rig_;
} binary_;
struct {
ivl_signal_t sig;
ivl_expr_t bit;
} bitsel_;
struct {
unsigned rept;
unsigned parms;
@@ -227,7 +226,7 @@ struct ivl_expr_s {
struct {
ivl_signal_t sig;
unsigned lsi, msi;
ivl_expr_t word;
} signal_;
struct {
@@ -272,9 +271,6 @@ struct ivl_expr_s {
ivl_expr_t sub_;
} unary_;
struct {
ivl_variable_t var;
} variable_;
} u_;
};
@@ -289,11 +285,11 @@ struct ivl_lpm_s {
ivl_lpm_type_t type;
ivl_scope_t scope;
perm_string name;
// Value returned by ivl_lpm_width;
unsigned width;
union {
struct ivl_lpm_ff_s {
unsigned width;
unsigned swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
@@ -308,49 +304,64 @@ struct ivl_lpm_s {
ivl_nexus_t*pins;
ivl_nexus_t pin;
} d;
union { // ram only
ivl_nexus_t*pins;
ivl_nexus_t pin;
} s;
ivl_memory_t mem; // ram only
ivl_expr_t aset_value;
ivl_expr_t sset_value;
} ff;
struct ivl_lpm_mux_s {
unsigned width;
unsigned size;
unsigned swid;
ivl_nexus_t*d;
union {
ivl_nexus_t*pins;
ivl_nexus_t pin;
} q;
union {
ivl_nexus_t*pins;
ivl_nexus_t pin;
} s;
ivl_nexus_t q, s;
} mux;
struct ivl_lpm_shift_s {
unsigned width;
unsigned select;
unsigned signed_flag :1;
ivl_nexus_t*q;
ivl_nexus_t*d;
ivl_nexus_t*s;
ivl_nexus_t q, d, s;
} shift;
struct ivl_lpm_arith_s {
unsigned width;
unsigned signed_flag :1;
ivl_nexus_t*q, *a, *b;
ivl_nexus_t q, a, b;
} arith;
struct ivl_lpm_array_s {
ivl_signal_t sig;
unsigned swid;
ivl_nexus_t q, a;
} array;
struct ivl_concat_s {
unsigned inputs;
ivl_nexus_t*pins;
} concat;
struct ivl_part_s {
unsigned base;
unsigned signed_flag :1;
ivl_nexus_t q, a, s;
} part;
// IVL_LPM_RE_* and IVL_LPM_SIGN_EXT use this.
struct ivl_lpm_reduce_s {
ivl_nexus_t q, a;
} reduce;
struct ivl_lpm_repeat_s {
unsigned count;
ivl_nexus_t q, a;
} repeat;
struct ivl_lpm_sfunc_s {
const char* fun_name;
unsigned ports;
ivl_nexus_t*pins;
} sfunc;
struct ivl_lpm_ufunc_s {
ivl_scope_t def;
unsigned ports;
unsigned *port_wid;
ivl_nexus_t*pins;
} ufunc;
} u_;
@@ -365,40 +376,38 @@ struct ivl_lpm_s {
enum ivl_lval_type_t {
IVL_LVAL_REG = 0,
IVL_LVAL_MUX = 1,
IVL_LVAL_MEM = 2,
/* IVL_LVAL_MEM = 2, / Deprecated in favor of LVAL_ARR? */
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
IVL_LVAL_VAR = 4
IVL_LVAL_ARR = 4
};
struct ivl_lval_s {
unsigned width_;
unsigned loff_;
unsigned type_ : 8;
ivl_expr_t loff;
ivl_expr_t idx;
unsigned width_;
unsigned type_ : 8;
union {
ivl_signal_t sig;
ivl_memory_t mem;
ivl_variable_t var;
} n;
};
/*
* This object represents a vector constant, possibly signed, in a
* This object represents a literal constant, possibly signed, in a
* structural context.
*/
struct ivl_net_const_s {
ivl_variable_type_t type;
unsigned width_;
unsigned signed_ : 1;
union {
double real_value;
char bit_[sizeof(char*)];
char *bits_;
} b;
union {
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
ivl_nexus_t pin_;
};
/*
@@ -407,6 +416,7 @@ struct ivl_net_const_s {
*/
struct ivl_net_logic_s {
ivl_logic_t type_;
unsigned width_;
ivl_udp_t udp;
perm_string name_;
@@ -418,7 +428,7 @@ struct ivl_net_logic_s {
struct ivl_attribute_s*attr;
unsigned nattr;
unsigned delay[3];
ivl_expr_t delay[3];
};
@@ -428,7 +438,7 @@ struct ivl_net_logic_s {
struct ivl_udp_s {
perm_string name;
unsigned nin;
unsigned sequ;
int sequ; /* boolen */
char init;
unsigned nrows;
typedef const char*ccharp_t;
@@ -471,19 +481,6 @@ struct ivl_nexus_s {
void*private_data;
};
/*
* Memory.
*/
struct ivl_memory_s {
perm_string basename_;
ivl_scope_t scope_;
unsigned width_;
unsigned signed_ : 1;
unsigned size_;
int root_;
};
/*
* This is the implementation of a parameter. Each scope has a list of
* these.
@@ -534,12 +531,6 @@ struct ivl_scope_s {
unsigned nlpm_;
ivl_lpm_t* lpm_;
unsigned nmem_;
ivl_memory_t* mem_;
unsigned nvar_;
ivl_variable_t* var_;
unsigned nparam_;
ivl_parameter_t param_;
@@ -564,6 +555,7 @@ struct ivl_scope_s {
struct ivl_signal_s {
ivl_signal_type_t type_;
ivl_signal_port_t port_;
ivl_variable_type_t data_type;
unsigned width_;
unsigned signed_ : 1;
@@ -578,10 +570,15 @@ struct ivl_signal_s {
perm_string name_;
ivl_scope_t scope_;
unsigned array_words;
int array_base;
union {
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
ivl_nexus_t pin;
ivl_nexus_t*pins;
};
ivl_delaypath_s*path;
unsigned npath;
struct ivl_attribute_s*attr;
unsigned nattr;
@@ -595,7 +592,8 @@ struct ivl_signal_s {
struct ivl_statement_s {
enum ivl_statement_type_e type_;
union {
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB */
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB
IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
unsigned lvals_;
struct ivl_lval_s*lval_;
ivl_expr_t rval_;
@@ -615,13 +613,6 @@ struct ivl_statement_s {
struct ivl_statement_s*case_st;
} case_;
struct { /* IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
unsigned lvals;
struct ivl_lval_s*lval;
unsigned npins;
ivl_nexus_t*pins;
} cassign_;
struct { /* IVL_ST_CONDIT */
/* This is the condition expression */
ivl_expr_t cond_;
@@ -630,7 +621,7 @@ struct ivl_statement_s {
} condit_;
struct { /* IVL_ST_DELAY */
unsigned long delay_;
uint64_t delay_;
ivl_statement_t stmt_;
} delay_;
@@ -673,17 +664,88 @@ struct ivl_statement_s {
} u_;
};
/*
* This holds the details about a variable object.
*/
struct ivl_variable_s {
ivl_variable_type_t type;
perm_string name;
ivl_scope_t scope;
};
/*
* $Log: t-dll.h,v $
* Revision 1.137 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.136 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.135 2007/01/16 05:44:16 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.134 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.133 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.132 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.131 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.130 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.129 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.128 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.127 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.126 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.125 2005/05/08 23:44:08 steve
* Add support for variable part select.
*
* Revision 1.124 2005/04/01 06:04:30 steve
* Clean up handle of UDPs.
*
* Revision 1.123 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.122 2005/02/19 02:43:39 steve
* Support shifts and divide.
*
* Revision 1.121 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.120 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.119 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.118 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.117 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.116 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.115 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space.
*
+97 -43
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $"
#ident "$Id: target.cc,v 1.80 2007/01/16 05:44:16 steve Exp $"
#endif
# include "config.h"
@@ -41,18 +41,10 @@ void target_t::event(const NetEvent*ev)
<< "): Unhandled event <" << ev->full_name() << ">." << endl;
}
void target_t::memory(const NetMemory*)
bool target_t::signal_paths(const NetNet*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled memory." << endl;
return true;
}
void target_t::variable(const NetVariable*that)
{
cerr << that->get_line() << ": error: target (" << typeid(*this).name()
<< "): Unhandled variable <" << that->basename() << ">." << endl;
}
bool target_t::func_def(const NetScope*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -68,6 +60,8 @@ void target_t::task_def(const NetScope*)
void target_t::logic(const NetLogic*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled logic gate" << endl;
}
bool target_t::bufz(const NetBUFZ*)
@@ -83,12 +77,26 @@ void target_t::udp(const NetUDP*)
"Unhandled UDP." << endl;
}
bool target_t::ureduce(const NetUReduce*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled unary reduction logic gate." << endl;
return false;
}
void target_t::lpm_add_sub(const NetAddSub*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetAddSub." << endl;
}
bool target_t::lpm_array_dq(const NetArrayDq*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetArrayDq." << endl;
return false;
}
void target_t::lpm_clshift(const NetCLShift*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -130,11 +138,25 @@ void target_t::lpm_mux(const NetMux*)
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetMux." << endl;
}
void target_t::lpm_ram_dq(const NetRamDq*)
bool target_t::concat(const NetConcat*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetRamDq." << endl;
"Unhandled NetConcat." << endl;
return false;
}
bool target_t::part_select(const NetPartSelect*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetPartSelect." << endl;
return false;
}
bool target_t::replicate(const NetReplicate*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetReplicate." << endl;
return false;
}
void target_t::net_case_cmp(const NetCaseCmp*)
@@ -143,14 +165,6 @@ void target_t::net_case_cmp(const NetCaseCmp*)
"Unhandled case compare node." << endl;
}
bool target_t::net_cassign(const NetCAssign*dev)
{
cerr << "target (" << typeid(*this).name() << "): ";
cerr << dev->get_line();
cerr << ": Target does not support procedural continuous assignment." << endl;
return false;
}
bool target_t::net_const(const NetConst*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -158,10 +172,10 @@ bool target_t::net_const(const NetConst*)
return false;
}
bool target_t::net_force(const NetForce*dev)
bool target_t::net_sysfunction(const NetSysFunc*net)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetForce node." << endl;
"Unhandled NetSysFunc node." << endl;
return false;
}
@@ -172,6 +186,13 @@ bool target_t::net_function(const NetUserFunc*net)
return false;
}
bool target_t::net_literal(const NetLiteral*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled LITERAL node." << endl;
return false;
}
void target_t::net_probe(const NetEvProbe*net)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -179,6 +200,13 @@ void target_t::net_probe(const NetEvProbe*net)
net->dump_node(cerr, 4);
}
bool target_t::sign_extend(const NetSignExtend*net)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetSignExtend node." << endl;
return false;
}
bool target_t::process(const NetProcTop*top)
{
return top->statement()->emit_proc(this);
@@ -345,13 +373,6 @@ void expr_scan_t::expr_concat(const NetEConcat*that)
cerr << that->get_line() << ": expr_scan_t (" <<
typeid(*this).name() << "): unhandled expr_concat." << endl;
}
void expr_scan_t::expr_memory(const NetEMemory*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_memory." << endl;
}
void expr_scan_t::expr_event(const NetEEvent*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
@@ -382,12 +403,6 @@ void expr_scan_t::expr_signal(const NetESignal*)
"unhandled expr_signal." << endl;
}
void expr_scan_t::expr_subsignal(const NetEBitSel*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled bit select expression." << endl;
}
void expr_scan_t::expr_ternary(const NetETernary*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
@@ -406,12 +421,6 @@ void expr_scan_t::expr_unary(const NetEUnary*)
"unhandled expr_unary." << endl;
}
void expr_scan_t::expr_variable(const NetEVariable*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_variable." << endl;
}
void expr_scan_t::expr_binary(const NetEBinary*ex)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
@@ -420,6 +429,51 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.80 2007/01/16 05:44:16 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.79 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.78 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.77 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.76 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.75 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.74 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.73 2005/02/03 04:56:21 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.72 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.71 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.70 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.69 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
+60 -14
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $"
#ident "$Id: target.h,v 1.77 2007/01/16 05:44:16 steve Exp $"
#endif
# include "netlist.h"
@@ -64,12 +64,7 @@ struct target_t {
/* Output a signal (called for each signal) */
virtual void signal(const NetNet*) =0;
/* Output a memory (called for each memory object) */
virtual void memory(const NetMemory*);
/* Output an event object. Called for each named event in the scope. */
virtual void variable(const NetVariable*);
virtual bool signal_paths(const NetNet*);
/* Output a defined task. */
virtual void task_def(const NetScope*);
@@ -77,6 +72,7 @@ struct target_t {
/* LPM style components are handled here. */
virtual void lpm_add_sub(const NetAddSub*);
virtual bool lpm_array_dq(const NetArrayDq*);
virtual void lpm_clshift(const NetCLShift*);
virtual void lpm_compare(const NetCompare*);
virtual void lpm_divide(const NetDivide*);
@@ -84,18 +80,23 @@ struct target_t {
virtual void lpm_ff(const NetFF*);
virtual void lpm_mult(const NetMult*);
virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*);
virtual bool concat(const NetConcat*);
virtual bool part_select(const NetPartSelect*);
virtual bool replicate(const NetReplicate*);
/* Output a gate (called for each gate) */
virtual void logic(const NetLogic*);
virtual bool ureduce(const NetUReduce*); /* unary reduction operator */
virtual bool bufz(const NetBUFZ*);
virtual void udp(const NetUDP*);
virtual void net_case_cmp(const NetCaseCmp*);
virtual bool net_cassign(const NetCAssign*);
virtual bool net_const(const NetConst*);
virtual bool net_force(const NetForce*);
virtual bool net_sysfunction(const NetSysFunc*);
virtual bool net_function(const NetUserFunc*);
virtual bool net_literal(const NetLiteral*);
virtual void net_probe(const NetEvProbe*);
virtual bool sign_extend(const NetSignExtend*);
/* Output a process (called for each process). It is up to the
target to recurse if desired. */
@@ -135,17 +136,14 @@ struct expr_scan_t {
virtual void expr_rparam(const NetECRealParam*);
virtual void expr_creal(const NetECReal*);
virtual void expr_concat(const NetEConcat*);
virtual void expr_memory(const NetEMemory*);
virtual void expr_event(const NetEEvent*);
virtual void expr_scope(const NetEScope*);
virtual void expr_select(const NetESelect*);
virtual void expr_sfunc(const NetESFunc*);
virtual void expr_signal(const NetESignal*);
virtual void expr_subsignal(const NetEBitSel*);
virtual void expr_ternary(const NetETernary*);
virtual void expr_ufunc(const NetEUFunc*);
virtual void expr_unary(const NetEUnary*);
virtual void expr_variable(const NetEVariable*);
virtual void expr_binary(const NetEBinary*);
};
@@ -153,7 +151,7 @@ struct expr_scan_t {
/* The emit functions take a design and emit it to the output stream
using the specified target. If the target is given by name, it is
located in the target_table and used. */
extern bool emit(const Design*des, const char*type);
extern int emit(const Design*des, const char*type);
/* This function takes a fully qualified verilog name (which may have,
for example, dots in it) and produces a mangled version that can be
@@ -170,6 +168,54 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.77 2007/01/16 05:44:16 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.76 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.75 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.74 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.73 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.72 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.71 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.70 2005/02/03 04:56:21 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.69 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.68 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.66 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.65 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
+10 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: targets.cc,v 1.11 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@@ -25,17 +25,25 @@
# include "target.h"
extern const struct target tgt_dll;
#ifdef WITH_T_XNF
extern const struct target tgt_xnf;
#endif
const struct target *target_table[] = {
&tgt_dll,
#ifdef WITH_T_XNF
&tgt_xnf,
#endif
0
};
/*
* $Log: targets.cc,v $
* Revision 1.12 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.11 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+5 -2
View File
@@ -2,7 +2,7 @@
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
Copyright 2001 Stephen Williams
$Id: fpga.txt,v 1.11 2003/08/07 05:17:34 steve Exp $
$Id: fpga.txt,v 1.12 2005/09/19 21:45:36 steve Exp $
The FPGA code generator supports a variety of FPGA devices, writing
XNF or EDIF depending on the target. You can select the architecture
@@ -44,7 +44,7 @@ map to target gates if desired.
If this is selected, then the output is formatted as an XNF file,
suitable for most any type of device. The devices that it emits
are generic devices from the unified library. Some devices are macros,
youmay need to further resolve the generated XNF to get working
you may need to further resolve the generated XNF to get working
code for your part.
* arch=virtex
@@ -188,6 +188,9 @@ Compile a single-file design with command line tools like so:
---
$Log: fpga.txt,v $
Revision 1.12 2005/09/19 21:45:36 steve
Spelling patches from Larry.
Revision 1.11 2003/08/07 05:17:34 steve
Add arch=lpm to the documentation.

Some files were not shown because too many files have changed in this diff Show More