Compare commits

...
338 Commits
Author SHA1 Message Date
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
188 changed files with 26666 additions and 15253 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.
*
+12 -22
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.175 2006/04/10 00:37:42 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 tgt-verilog ; \
do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
@@ -90,8 +84,7 @@ 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 driver; \
do (cd $$dir ; $(MAKE) $@); done
rm -f *.o parse.cc parse.cc.output parse.h lexor.cc
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
@@ -99,27 +92,26 @@ clean:
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 driver; \
do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.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 \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -209,9 +201,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 +266,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; \
+18 -44
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.40 2006/04/10 00:37:42 steve Exp $"
#endif
# include <list>
@@ -30,11 +30,11 @@
# include "named.h"
# include "LineInfo.h"
# include "netlist.h"
class PData;
class PEvent;
class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PTask;
class PFunction;
class PWire;
@@ -108,15 +108,20 @@ 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;
perm_string mod_name() const { return name_; }
void add_gate(PGate*gate);
@@ -146,7 +151,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 +173,13 @@ 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.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.36 2004/05/25 19:21:06 steve
* More identifier lists use perm_strings.
* Revision 1.39 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
*
* Revision 1.35 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* 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
+37 -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: PDelays.cc,v 1.11 2003/06/21 01:21:42 steve Exp $"
#ident "$Id: PDelays.cc,v 1.13 2006/01/03 05:22:14 steve Exp $"
#endif
# include "config.h"
@@ -62,8 +62,7 @@ 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);
@@ -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,51 @@ 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);
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 +163,12 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
/*
* $Log: PDelays.cc,v $
* 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.
*
+16 -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.37 2005/10/04 04:09:25 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)
{
@@ -140,7 +148,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 +270,12 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* 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.
*
+187 -86
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.78 2006/03/25 02:36:26 steve Exp $"
#endif
# include <string>
# include <vector>
# include "netlist.h"
# include "verinum.h"
# include "LineInfo.h"
@@ -66,30 +67,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,25 +123,24 @@ 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_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;
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:
@@ -182,7 +189,7 @@ 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;
@@ -191,6 +198,14 @@ class PEFNumber : public PExpr {
bool sys_task_arg =false) 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:
@@ -205,22 +220,23 @@ class PEIdent : public PExpr {
virtual void dump(ostream&) const;
// Regs can be on the left of procedural continuous assignments
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) 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;
@@ -233,33 +249,62 @@ 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:
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) const;
NetExpr*elaborate_expr_net_part_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetNet*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_;
// 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_ram_(Design*des, NetScope*scope,
NetMemory*mem, 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_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;
@@ -267,6 +312,15 @@ class PEIdent : public PExpr {
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;
};
class PENumber : public PExpr {
@@ -280,17 +334,19 @@ class PENumber : public PExpr {
virtual void dump(ostream&) 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;
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;
@@ -316,15 +372,15 @@ class PEString : public PExpr {
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 NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) 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;
@@ -341,15 +397,15 @@ class PEUnary : public PExpr {
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;
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;
@@ -369,15 +425,15 @@ class PEBinary : public PExpr {
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 NetEBinary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) 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:
char op_;
@@ -388,44 +444,44 @@ class PEBinary : public PExpr {
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;
};
/*
@@ -443,15 +499,15 @@ class PETernary : public PExpr {
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 NetETernary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) 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_;
@@ -473,9 +529,9 @@ class PECallFunction : public PExpr {
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,
@@ -492,6 +548,51 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* 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
+30 -6
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.11 2005/07/07 16:22:49 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;
@@ -140,6 +161,9 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
/*
* $Log: PWire.cc,v $
* 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.
*
+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
+23 -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.30 2005/07/11 16:56:50 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,15 +94,21 @@ 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; }
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
@@ -126,7 +133,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 +143,18 @@ extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* 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)
+123 -180
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.54 2005/07/15 19:22:52 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,7 +732,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
}
break;
}
#endif
default:
break;
}
@@ -856,29 +754,53 @@ 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);
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF1, obj->width());
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);
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(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));
}
count += 1;
@@ -886,33 +808,29 @@ void cprop_functor::lpm_mux(Design*des, NetMux*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);
}
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF0, obj->width());
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(0), tmp->pin(1));
connect(obj->pin_Sel(), tmp->pin(2));
des->add_node(tmp);
count += 1;
delete obj;
@@ -1038,6 +956,31 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* 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.
*
+217 -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: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: design_dump.cc,v 1.165 2006/04/10 00:37:42 steve Exp $"
#endif
# include "config.h"
@@ -68,6 +68,28 @@ 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;
}
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
@@ -75,6 +97,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " " << data_type_;
if (signed_)
o << " signed";
switch (port_type_) {
@@ -96,8 +119,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();
@@ -117,13 +142,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
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_ << "] " <<
@@ -189,18 +207,13 @@ 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
{
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
<< name() << endl;
dump_node_pins(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@@ -216,6 +229,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 +246,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 +256,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 +267,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 +300,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,6 +382,26 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
{
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 NetRamDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
@@ -361,6 +410,58 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const
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 NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name() << "(";
@@ -436,8 +537,8 @@ void NetAssign_::dump_lval(ostream&o) const
if (bmux_) {
o << "[" << *bmux_ << "]";
} else {
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
} else if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
}
} else if (mem_) {
// Is there an obvious way to flag memories in the dump
@@ -447,8 +548,10 @@ void NetAssign_::dump_lval(ostream&o) const
if (bmux_) o << *bmux_;
else o << "**oops**";
o << "]";
} else if (var_) {
o << "<real " << var_->basename() << ">";
if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
}
} else {
o << "";
}
@@ -474,10 +577,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 +590,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 +660,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 +682,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 +737,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 +754,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 +779,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 +811,9 @@ void NetScope::dump(ostream&o) const
case TASK:
o << " task";
break;
case GENBLOCK:
o << " generate block";
break;
}
o << endl;
@@ -757,11 +859,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="
@@ -937,7 +1034,7 @@ void NetEConstParam::dump(ostream&o) const
{
o << "<" << name_ << "=";
NetEConst::dump(o);
o << ">";
o << ", wid=" << expr_width() << ">";
}
void NetECReal::dump(ostream&o) const
@@ -995,15 +1092,7 @@ 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 << "]";
o << name() << "[" << msi()<<":"<<lsi() << "]";
}
void NetEMemory::dump(ostream&o) const
@@ -1055,11 +1144,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 +1173,63 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* 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.
*
+4 -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: 2005/06/28 04:25:55 $" Version "$Date: 2005/06/28 04:25:55 $"
.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] [-Dmacro[=defn]] [-pflag=value]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
@@ -48,10 +48,10 @@ 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
+13 -7
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.67 2005/07/14 23:38:44 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,7 +107,7 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "3.0";
const char*generation = "2x";
char warning_flags[16] = "";
@@ -393,8 +393,8 @@ 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 {
fprintf(stderr, "Unknown/Unsupported Language generation "
@@ -402,7 +402,7 @@ 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");
return 1;
}
@@ -735,6 +735,12 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* 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.
*
+11 -13
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.20 2005/07/11 16:56:50 steve Exp $"
#endif
# include "config.h"
@@ -87,7 +87,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 +111,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 +131,16 @@ 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.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.
*
+5 -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.11 2005/07/11 16:56:50 steve Exp $"
#endif
# include "config.h"
@@ -109,11 +109,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 +166,9 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
/*
* $Log: elab_anet.cc,v $
* 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.
*
+667 -286
View File
File diff suppressed because it is too large Load Diff
+127 -131
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_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.33 2006/02/02 02:43:57 steve Exp $"
#endif
# include "config.h"
@@ -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,23 +144,28 @@ 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);
symbol_search(des, scope, path_, reg, mem, par, eve);
if (mem) {
return elaborate_mem_lval_(des, scope, mem);
}
if (is_force) {
cerr << get_line() << ": error: Memories "
<< "(" << path_ << " in this case)"
<< " are not allowed"
<< " as l-values to force statements." << endl;
des->errors += 1;
return 0;
}
if (var) {
NetAssign_*cur = new NetAssign_(var);
return cur;
return elaborate_mem_lval_(des, scope, mem);
}
if (reg == 0) {
@@ -171,8 +180,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
assert(reg);
/* 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;
@@ -185,7 +195,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
long msb, lsb;
NetExpr*mux;
if (msb_ && lsb_) {
if (msb_ || lsb_) {
assert(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
@@ -215,17 +227,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
lsb = vl->as_long();
mux = 0;
} else if (msb_) {
} else 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(msb_ == 0);
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);
assert(m);
msb = 0;
lsb = 0;
@@ -261,6 +275,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
lv->set_bmux(mux);
} 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 {
/* If the bit/part select is constant, then make the
@@ -283,7 +303,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,9 +312,7 @@ 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);
}
@@ -304,7 +322,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
{
if (msb_ == 0) {
if (idx_.empty()) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
@@ -312,37 +330,86 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
return 0;
}
if (msb_ && lsb_) {
cerr << get_line() << ": error: Cannot use part select on "
<< "memory \"" << mem->name() << ".\"" << endl;
if (idx_.size() != mem->dimensions()) {
cerr << get_line() << ": error: " << idx_.size()
<< " indices do not properly address a "
<< mem->dimensions() << "-dimension memory/array."
<< endl;
des->errors += 1;
return 0;
}
assert(msb_ && !lsb_);
// XXXX For now, require exactly 1 index.
assert(idx_.size() == 1);
NetExpr*ix = msb_->elaborate_expr(des, scope);
/* Elaborate the address expression. */
NetExpr*ix = elab_and_eval(des, scope, idx_[0]);
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;
}
}
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
lv->set_part(0, mem->width());
/* If there is no extra part select, then we are done. */
if (msb_ == 0 && lsb_ == 0) {
lv->set_part(0U, mem->width());
return lv;
}
assert(sel_ != SEL_NONE);
assert(msb_ && lsb_);
if (sel_ == SEL_PART) {
NetExpr*le = elab_and_eval(des, scope, lsb_);
NetExpr*me = elab_and_eval(des, scope, msb_);
NetEConst*lec = dynamic_cast<NetEConst*>(le);
NetEConst*mec = dynamic_cast<NetEConst*>(me);
if (lec == 0 || mec == 0) {
cerr << get_line() << ": error: Part select "
<< "expressions must be constant." << endl;
des->errors += 1;
delete le;
delete me;
return lv;
}
verinum wedv = mec->value() - lec->value();
unsigned wid = wedv.as_long() + 1;
lv->set_part(lec, wid);
return lv;
}
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
if (wid_ec == 0) {
cerr << lsb_->get_line() << ": error: "
<< "Second expression of indexed part select "
<< "most be constant." << endl;
des->errors += 1;
return lv;
}
unsigned wid = wid_ec->value().as_ulong();
NetExpr*base_ex = elab_and_eval(des, scope, msb_);
if (base_ex == 0) {
return 0;
}
if (sel_ == SEL_IDX_DO && wid > 1) {
base_ex = make_add_expr(base_ex, 1-(long)wid);
}
lv->set_part(base_ex, wid);
return lv;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
{
cerr << get_line() << ": error: Constant values not allowed "
<< "in l-value expressions." << endl;
@@ -352,6 +419,25 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* 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 +446,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.
*
*/
+1118 -1007
View File
File diff suppressed because it is too large Load Diff
+16 -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: elab_pexpr.cc,v 1.21 2004/02/20 06:22:56 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.23 2006/02/02 02:43:58 steve Exp $"
#endif
# include "config.h"
@@ -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);
}
@@ -231,6 +236,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* 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.
*
+176 -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.39 2006/04/10 00:37:42 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,102 @@ 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);
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;
verinum*test = loop_test->eval_const(des, container);
assert(test);
while (test->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.
verinum*step = loop_step->eval_const(des, container);
assert(step);
if (debug_elaborate)
cerr << get_line() << ": debug: genvar step from "
<< genvar << " to " << step->as_long() << endl;
genvar = step->as_long();
container->genvar_tmp_val = genvar;
delete step;
delete test;
test = loop_test->eval_const(des, container);
}
container->genvar_tmp = perm_string();
return true;
}
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
@@ -310,8 +442,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_) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
assert( (msb == 0) || (lsb != 0) );
@@ -322,12 +456,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 +512,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 +554,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 +565,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 +583,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 +742,18 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* 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.
*
+120 -6
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.41 2006/04/10 00:37:42 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. */
@@ -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);
@@ -609,13 +662,57 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
} else {
/* 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);
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);
}
@@ -623,6 +720,23 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
/*
* $Log: elab_sig.cc,v $
* 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.
*
+635 -289
View File
File diff suppressed because it is too large Load Diff
+86 -162
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.86 2005/07/11 16:56:50 steve Exp $"
#endif
# include "config.h"
@@ -63,12 +63,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
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 +75,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 +97,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,12 +120,33 @@ bool NetMux::emit_node(struct target_t*tgt) const
return true;
}
bool NetPartSelect::emit_node(struct target_t*tgt) const
{
return tgt->part_select(this);
}
bool NetRamDq::emit_node(struct target_t*tgt) const
{
tgt->lpm_ram_dq(this);
return true;
}
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 NetUserFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_function(this);
@@ -312,9 +331,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);
@@ -363,13 +379,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 +393,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;
}
@@ -474,11 +498,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 +508,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 +519,48 @@ 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.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 +586,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.
*/
+53 -10
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.40 2006/04/10 00:37:42 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,46 @@ 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);
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;
NetMemory*mem;
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, mem, expr, eve);
if (expr == 0)
return 0;
@@ -173,23 +204,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 +240,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)
@@ -240,6 +271,18 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/*
* $Log: eval.cc,v $
* 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.
*
+160 -100
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.68 2006/03/18 22:52:27 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;
@@ -1124,7 +1159,9 @@ NetExpr* NetEParam::eval_tree()
return 0;
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 +1212,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 +1230,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 "
@@ -1551,6 +1589,28 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* 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.
*
+308 -286
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.74 2006/01/03 05:15:33 steve Exp $"
#endif
# include "config.h"
@@ -45,14 +45,14 @@ 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);
@@ -60,11 +60,9 @@ NetNet* NetEBAdd::synthesize(Design*des)
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 +92,58 @@ 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);
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 +151,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 +182,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 +193,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_) {
@@ -338,25 +248,22 @@ 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->set_line(*this);
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 +277,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 +286,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;
}
@@ -449,7 +354,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 +376,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);
@@ -530,30 +435,40 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet::IMPLICIT, expr_width());
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));
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));
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());
connect(zcon->pin(0), zsig->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) {
connect(ccat->pin(1), zsig->pin(0));
connect(ccat->pin(2), lsig->pin(0));
} else {
connect(ccat->pin(1), lsig->pin(0));
connect(ccat->pin(2), zsig->pin(0));
}
return osig;
}
@@ -568,20 +483,18 @@ NetNet* NetEBShift::synthesize(Design*des)
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 +503,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 +521,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,12 +545,12 @@ 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;
@@ -659,28 +575,27 @@ 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->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;
}
@@ -702,32 +617,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:
@@ -744,39 +659,114 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
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;
}
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.
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
assert(bcon);
long bval = bcon->value().as_long();
off = sub->sb_to_idx(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);
sub = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
sub->local_flag(true);
sub->set_line(*this);
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());
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(0UL, 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->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 +786,27 @@ 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->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 +843,60 @@ 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.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.
*
+3 -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.15 2006/02/21 02:38:44 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,6 +63,7 @@ do
;;
*.cc) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cc`
fi
+1
View File
@@ -62,6 +62,7 @@ ivl_logic_udp
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_base
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
+700 -97
View File
File diff suppressed because it is too large Load Diff
+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.
+23 -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: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $"
#ident "$Id: lexor.lex,v 1.90 2006/03/30 05:44:36 steve Exp $"
#endif
# include "config.h"
@@ -154,7 +154,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 +179,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 +200,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 +293,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}?.* { }
+6
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,6 +43,8 @@ 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
@@ -51,6 +55,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 +115,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
+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.
*
+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.
*
+49 -9
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.92 2005/07/14 23:38:43 steve Exp $"
#endif
# include "config.h"
@@ -81,7 +81,13 @@ 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;
map<string,const char*> flags;
char*vpi_module_list = 0;
@@ -112,6 +118,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 +144,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 +158,9 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -181,8 +192,8 @@ static void process_generation_flag(const char*gen)
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;
@@ -314,6 +325,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,8 +554,8 @@ 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;
}
@@ -697,12 +711,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 +764,26 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* 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.
*
+59 -66
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.21 2006/02/02 02:43:58 steve Exp $"
#endif
# include "config.h"
@@ -39,30 +39,20 @@ unsigned count_lval_width(const NetAssign_*idx)
}
NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), var_(0), bmux_(0)
: sig_(s), mem_(0), bmux_(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)
: sig_(0), mem_(s), bmux_(0), base_(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_) {
@@ -91,6 +81,11 @@ const NetExpr* NetAssign_::bmux() const
return bmux_;
}
const NetExpr* NetAssign_::get_base() const
{
return base_;
}
unsigned NetAssign_::lwidth() const
{
if (mem_) return lwid_;
@@ -119,27 +114,10 @@ NetMemory* NetAssign_::mem() const
return mem_;
}
NetVariable* NetAssign_::var() const
void NetAssign_::set_part(NetExpr*base, unsigned wid)
{
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 +237,55 @@ 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.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 +295,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.
*/
+13 -68
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.48 2005/11/27 05:56:20 steve Exp $"
#endif
# include "config.h"
@@ -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,7 +325,7 @@ 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: "
@@ -401,7 +336,8 @@ void NetScope::evaluate_parameters(Design*des)
}
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 +554,15 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* 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.
*
+52 -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.26 2005/11/26 00:35:43 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,15 @@ 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;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
@@ -372,9 +390,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 +468,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 +519,22 @@ 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.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.
*
+20 -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.7 2005/03/18 02:56:03 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_;
@@ -164,6 +114,9 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
/*
* $Log: net_func.cc,v $
* 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.
*
+9 -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: net_nex_input.cc,v 1.12 2004/09/04 04:24:15 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.14 2005/07/11 16:56:50 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();
@@ -177,11 +168,6 @@ NexusSet* NetEUnary::nex_input()
return expr_->nex_input();
}
NexusSet* NetEVariable::nex_input()
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input()
{
if (bmux_ == 0)
@@ -398,6 +384,14 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* 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.
*
+18 -22
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.35 2005/11/27 05:56:20 steve Exp $"
#endif
# include "config.h"
@@ -41,7 +41,6 @@ NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
memories_ = 0;
signals_ = 0;
events_ = 0;
vars_ = 0;
lcounter_ = 0;
if (up) {
@@ -133,17 +132,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 +290,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) {
@@ -404,14 +402,6 @@ NetMemory* NetScope::find_memory(const string&key)
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 +457,12 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* 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.
*
*/
+553 -529
View File
File diff suppressed because it is too large Load Diff
+569 -343
View File
File diff suppressed because it is too large Load Diff
+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: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
#ident "$Id: netmisc.cc,v 1.11 2005/04/08 04:50:31 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,8 +70,58 @@ 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
}
/*
* 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)
{
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)
{
@@ -90,6 +140,19 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* $Log: netmisc.cc,v $
* 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.
*
+64 -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: netmisc.h,v 1.19 2004/03/07 20:04:11 steve Exp $"
#ident "$Id: netmisc.h,v 1.24 2005/11/27 05:56:20 steve Exp $"
#endif
# include "netlist.h"
@@ -33,13 +33,30 @@
* 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 */
NetMemory*&mem, /* memory */
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 +67,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 +83,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
@@ -75,6 +118,23 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
/*
* $Log: netmisc.h,v $
* 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.
*
+465 -207
View File
File diff suppressed because it is too large Load Diff
+183 -53
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.135 2006/04/10 00:37:42 steve Exp $"
#endif
# include "config.h"
@@ -26,9 +26,9 @@
# include "pform.h"
# include "parse_misc.h"
# include "parse_api.h"
# include "PData.h"
# include "PEvent.h"
# include "PUdp.h"
# include "PGenerate.h"
# include <list>
# include <map>
# include <assert.h>
@@ -45,7 +45,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 +74,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 +104,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 +242,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 +322,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 +695,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 +709,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 +774,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 +795,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 +811,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 +842,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 +877,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 +938,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 +1025,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 +1043,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 +1137,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,12 +1180,22 @@ 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);
PWire*cur = get_wire_in_module(name);
if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
@@ -1132,7 +1219,7 @@ void pform_makewire(const vlltype&li, const char*nm,
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 +1230,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 +1263,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 +1281,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 +1308,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 +1377,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 +1398,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);
@@ -1452,7 +1556,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,12 +1569,15 @@ 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);
@@ -1496,11 +1603,13 @@ 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);
@@ -1530,7 +1639,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 +1707,26 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* 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.
*
+50 -8
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.86 2006/04/10 00:37:42 steve Exp $"
#endif
# include "netlist.h"
@@ -77,7 +77,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 +167,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 +228,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);
@@ -270,9 +297,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 +305,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 +323,23 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* 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.
*
+104 -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.92 2006/04/10 00:37:42 steve Exp $"
#endif
# include "config.h"
@@ -29,8 +29,8 @@
* module in question.
*/
# include "pform.h"
# include "PData.h"
# include "PEvent.h"
# include "PGenerate.h"
# include <iostream>
# include <iomanip>
# include <typeinfo>
@@ -146,8 +146,19 @@ 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 << "]";
}
@@ -201,27 +212,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 +304,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 +314,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 +370,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 +734,44 @@ void PProcess::dump(ostream&out, unsigned ind) const
statement_->dump(out, ind+2);
}
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 +837,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 +872,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()
@@ -909,6 +967,18 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* 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.
*
+61 -37
View File
@@ -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.37 2005/11/26 00:35:44 steve Exp $"
#endif
# include "config.h"
@@ -36,7 +36,7 @@
# 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 +45,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 +80,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 +113,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 +153,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 +162,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,7 +180,7 @@ 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();
}
@@ -190,7 +190,7 @@ bool NetEBMult::set_width(unsigned w)
* 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 +228,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 +241,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 +289,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 +314,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)
bool NetEMemory::set_width(unsigned w, bool)
{
if (w != mem_->width())
return false;
@@ -332,12 +343,20 @@ bool NetEMemory::set_width(unsigned w)
return true;
}
bool NetEParam::set_width(unsigned)
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,7 +365,7 @@ 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())
return false;
@@ -354,13 +373,7 @@ bool NetESignal::set_width(unsigned w)
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)
{
bool flag = true;
flag = flag && true_val_->set_width(w);
@@ -374,13 +387,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 +416,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 +424,17 @@ bool NetEUReduce::set_width(unsigned w)
/*
* $Log: set_width.cc,v $
* 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.
*
+11 -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: symbol_search.cc,v 1.1 2003/09/19 03:30:05 steve Exp $"
#ident "$Id: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
#endif
# include "netlist.h"
@@ -27,12 +27,12 @@
/*
* 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);
@@ -42,7 +42,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;
@@ -62,17 +61,12 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
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 +83,12 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
/*
* $Log: symbol_search.cc,v $
* 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.
*
+7 -14
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.33 2005/04/24 23:44:02 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->bit(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));
@@ -149,15 +146,11 @@ static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
/* 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(ram->pin_Data(), d->bit(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(ram->pin_Address(), adr->pin(0));
/* Connect the input clock and the WE of the RAM. */
assert(pclk);
@@ -211,7 +204,7 @@ 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()) {
+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.
*
+375 -191
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-api.cc,v 1.108 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.133 2006/02/02 02:43:59 steve Exp $"
#endif
# include "config.h"
@@ -50,6 +50,9 @@ extern "C" int ivl_design_process(ivl_design_t des,
extern "C" ivl_scope_t ivl_design_root(ivl_design_t des)
{
cerr << "ANACHRONISM: ivl_design_root called. "
"Use ivl_design_roots instead." << endl;
assert (des->nroots_);
return des->roots_[0];
}
@@ -120,29 +123,39 @@ extern "C" unsigned ivl_memory_width(ivl_memory_t net)
}
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
{
assert(net);
return net->type;
}
extern "C" const char*ivl_const_bits(ivl_net_const_t net)
{
assert(net);
if (net->width_ <= sizeof(char*))
return net->b.bit_;
else
return net->b.bits_;
switch (net->type) {
case IVL_VT_LOGIC:
if (net->width_ <= sizeof(net->b.bit_))
return net->b.bit_;
else
return net->b.bits_;
default:
return 0;
}
}
extern "C" ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_const_nex(ivl_net_const_t net)
{
assert(net);
assert(idx < net->width_);
if (net->width_ == 1)
return net->n.pin_;
else
return net->n.pins_[idx];
return net->pin_;
}
extern "C" unsigned ivl_const_pins(ivl_net_const_t net)
extern "C" double ivl_const_real(ivl_net_const_t net)
{
assert(net);
return net->width_;
assert(net->type == IVL_VT_REAL);
return net->b.real_value;
}
extern "C" int ivl_const_signed(ivl_net_const_t net)
@@ -151,6 +164,12 @@ extern "C" int ivl_const_signed(ivl_net_const_t net)
return net->signed_;
}
extern "C" unsigned ivl_const_width(ivl_net_const_t net)
{
assert(net);
return net->width_;
}
extern "C" const char* ivl_event_name(ivl_event_t net)
{
static char*name_buffer = 0;
@@ -180,6 +199,10 @@ extern "C" const char* ivl_event_basename(ivl_event_t net)
return net->name;
}
extern "C" ivl_scope_t ivl_event_scope(ivl_event_t net)
{
return net->scope;
}
extern "C" unsigned ivl_event_nany(ivl_event_t net)
{
@@ -248,20 +271,6 @@ extern "C" double ivl_expr_dvalue(ivl_expr_t net)
return net->u_.real_.value;
}
extern "C" unsigned ivl_expr_lsi(ivl_expr_t net)
{
switch (net->type_) {
case IVL_EX_SIGNAL:
return net->u_.signal_.lsi;
default:
assert(0);
}
return 0;
}
extern "C" const char* ivl_expr_name(ivl_expr_t net)
{
switch (net->type_) {
@@ -272,9 +281,6 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
case IVL_EX_SIGNAL:
return net->u_.signal_.sig->name_;
case IVL_EX_VARIABLE:
return net->u_.variable_.var->name;
default:
assert(0);
}
@@ -305,9 +311,6 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
case IVL_EX_SELECT:
return net->u_.binary_.lef_;
case IVL_EX_BITSEL:
return net->u_.bitsel_.bit;
case IVL_EX_UNARY:
return net->u_.unary_.sub_;
@@ -438,8 +441,6 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
{
assert(net);
switch (net->type_) {
case IVL_EX_BITSEL:
return net->u_.bitsel_.sig;
case IVL_EX_SIGNAL:
return net->u_.signal_.sig;
@@ -503,12 +504,6 @@ extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
return net->u_.memory_.mem_;
}
extern "C" ivl_variable_t ivl_expr_variable(ivl_expr_t net)
{
assert(net->type_ == IVL_EX_VARIABLE);
return net->u_.variable_.var;
}
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
{
assert(net);
@@ -537,6 +532,40 @@ extern "C" ivl_attribute_t ivl_logic_attr_val(ivl_net_logic_t net,
return net->attr + idx;
}
extern "C" ivl_drive_t ivl_logic_drive0(ivl_net_logic_t net)
{
ivl_nexus_t nex = ivl_logic_pin(net, 0);
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
if (ivl_nexus_ptr_log(cur) != net)
continue;
if (ivl_nexus_ptr_pin(cur) != 0)
continue;
return ivl_nexus_ptr_drive0(cur);
}
assert(0);
return IVL_DR_STRONG;
}
extern "C" ivl_drive_t ivl_logic_drive1(ivl_net_logic_t net)
{
ivl_nexus_t nex = ivl_logic_pin(net, 0);
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
if (ivl_nexus_ptr_log(cur) != net)
continue;
if (ivl_nexus_ptr_pin(cur) != 0)
continue;
return ivl_nexus_ptr_drive1(cur);
}
assert(0);
return IVL_DR_STRONG;
}
extern "C" const char* ivl_logic_name(ivl_net_logic_t net)
{
assert(net);
@@ -579,14 +608,19 @@ extern "C" ivl_udp_t ivl_logic_udp(ivl_net_logic_t net)
return net->udp;
}
extern "C" unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
extern "C" ivl_expr_t ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
{
assert(transition < 3);
return net->delay[transition];
}
extern "C" unsigned ivl_logic_width(ivl_net_logic_t net)
{
assert(net);
return net->width_;
}
extern "C" unsigned ivl_udp_sequ(ivl_udp_t net)
extern "C" int ivl_udp_sequ(ivl_udp_t net)
{
return net->sequ;
}
@@ -673,6 +707,20 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
}
}
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
case IVL_LPM_PART_BI:
return net->u_.part.base;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
{
assert(net);
@@ -741,29 +789,73 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(net);
switch (net->type) {
case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.a[idx];
assert(idx <= 1);
if (idx == 0)
return net->u_.arith.a;
else
return net->u_.arith.b;
case IVL_LPM_MUX:
assert(idx < net->u_.mux.size);
return net->u_.mux.d[idx];
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT:
assert(idx == 0);
return net->u_.reduce.a;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width);
return net->u_.shift.d[idx];
assert(idx <= 1);
if (idx == 0)
return net->u_.shift.d;
else
return net->u_.shift.s;
case IVL_LPM_RAM:
assert(idx == 0);
return net->u_.ff.d.pin;
case IVL_LPM_FF:
case IVL_LPM_RAM:
assert(idx < net->u_.ff.width);
if (net->u_.ff.width == 1)
return net->u_.ff.d.pin;
assert(idx == 0);
return net->u_.ff.d.pin;
case IVL_LPM_CONCAT:
assert(idx < net->u_.concat.inputs);
return net->u_.concat.pins[idx+1];
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
case IVL_LPM_PART_BI:
assert(idx <= 1);
if (idx == 0)
return net->u_.part.a;
else
return net->u_.ff.d.pins[idx];
return net->u_.part.s;
case IVL_LPM_REPEAT:
assert(idx == 0);
return net->u_.repeat.a;
case IVL_LPM_UFUNC:
// Skip the return port.
assert(idx < (net->u_.ufunc.ports-1));
return net->u_.ufunc.pins[idx+1];
default:
assert(0);
@@ -773,6 +865,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
{
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_datab." << endl;
assert(net);
switch (net->type) {
@@ -785,8 +878,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.b[idx];
assert(idx == 0);
return net->u_.arith.b;
default:
assert(0);
@@ -794,14 +887,12 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
}
}
#if 0
extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
{
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_data2." << endl;
assert(net);
switch (net->type) {
case IVL_LPM_MUX:
assert(sdx < net->u_.mux.size);
assert(idx < net->u_.mux.width);
return net->u_.mux.d[sdx*net->u_.mux.width + idx];
case IVL_LPM_UFUNC: {
sdx += 1; /* skip the output port. */
@@ -818,7 +909,8 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
return 0;
}
}
#endif
#if 0
extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
{
assert(net);
@@ -832,6 +924,7 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
return 0;
}
}
#endif
/*
* This function returns the hierarchical name for the LPM device. The
@@ -873,39 +966,61 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.q[idx];
assert(idx == 0);
return net->u_.arith.q;
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_NEE:
assert(idx == 0);
return net->u_.arith.q[0];
return net->u_.arith.q;
case IVL_LPM_RAM:
assert(idx == 0);
return net->u_.ff.q.pin;
case IVL_LPM_FF:
case IVL_LPM_RAM:
assert(idx < net->u_.ff.width);
if (net->u_.ff.width == 1)
return net->u_.ff.q.pin;
else
return net->u_.ff.q.pins[idx];
assert(idx == 0);
return net->u_.ff.q.pin;
case IVL_LPM_MUX:
assert(idx < net->u_.mux.width);
if (net->u_.mux.width == 1)
return net->u_.mux.q.pin;
else
return net->u_.mux.q.pins[idx];
assert(idx == 0);
return net->u_.mux.q;
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT:
assert(idx == 0);
return net->u_.reduce.q;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width);
return net->u_.shift.q[idx];
assert(idx == 0);
return net->u_.shift.q;
case IVL_LPM_UFUNC:
assert(idx < net->u_.ufunc.port_wid[0]);
return net->u_.ufunc.pins[idx];
assert(idx == 0);
return net->u_.ufunc.pins[0];
case IVL_LPM_CONCAT:
return net->u_.concat.pins[0];
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
case IVL_LPM_PART_BI:
assert(idx == 0);
return net->u_.part.q;
case IVL_LPM_REPEAT:
assert(idx == 0);
return net->u_.repeat.q;
default:
assert(0);
@@ -919,27 +1034,14 @@ extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
return net->scope;
}
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
{
switch (net->type) {
case IVL_LPM_RAM:
assert(idx < net->u_.ff.swid);
if (net->u_.ff.swid == 1)
return net->u_.ff.s.pin;
else
return net->u_.ff.s.pins[idx];
return net->u_.ff.s.pin;
case IVL_LPM_MUX:
assert(idx < net->u_.mux.swid);
if (net->u_.mux.swid == 1)
return net->u_.mux.s.pin;
else
return net->u_.mux.s.pins[idx];
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.select);
return net->u_.shift.s[idx];
return net->u_.mux.s;
default:
assert(0);
@@ -954,9 +1056,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
return net->u_.ff.swid;
case IVL_LPM_MUX:
return net->u_.mux.swid;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.select;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
default:
assert(0);
return 0;
@@ -972,21 +1073,39 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_MUX:
return 0;
case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
return net->u_.arith.signed_flag;
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
return 0;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.signed_flag;
return 0;
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
return 1;
case IVL_LPM_UFUNC:
return 0;
case IVL_LPM_CONCAT: // Concatenations are always unsigned
return 0;
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
case IVL_LPM_PART_BI:
return net->u_.part.signed_flag;
case IVL_LPM_REPEAT:
return 0;
default:
assert(0);
return 0;
@@ -1000,6 +1119,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
return net->u_.mux.size;
case IVL_LPM_UFUNC:
return net->u_.ufunc.ports - 1;
case IVL_LPM_REPEAT:
return net->u_.repeat.count;
default:
assert(0);
return 0;
@@ -1021,20 +1142,39 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_MUX:
return net->u_.mux.width;
case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
return net->u_.arith.width;
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT:
return net->u_.reduce.width;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.width;
case IVL_LPM_UFUNC:
return net->u_.ufunc.port_wid[0];
return net->u_.ufunc.width;
case IVL_LPM_CONCAT:
return net->u_.concat.width;
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return net->u_.part.width;
case IVL_LPM_PART_BI:
return net->u_.part.width;
case IVL_LPM_REPEAT:
return net->u_.repeat.width;
default:
assert(0);
return 0;
@@ -1077,26 +1217,26 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
return 0x0;
}
extern "C" ivl_variable_t ivl_lval_var(ivl_lval_t net)
extern "C" ivl_expr_t ivl_lval_part_off(ivl_lval_t net)
{
assert(net);
if (net->type_ == IVL_LVAL_VAR)
return net->n.var;
return 0x0;
return net->loff;
}
extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
{
assert(net);
return net->loff_;
}
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
extern "C" unsigned ivl_lval_width(ivl_lval_t net)
{
assert(net);
return net->width_;
}
#if 0
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
{
assert(net);
return net->width_;
}
#endif
#if 0
extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
{
assert(net);
@@ -1104,11 +1244,19 @@ extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
assert(net->type_ != IVL_LVAL_MEM);
return ivl_signal_pin(net->n.sig, idx+net->loff_);
}
#endif
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
{
assert(net);
return net->n.sig;
switch (net->type_) {
case IVL_LVAL_REG:
case IVL_LVAL_NET:
case IVL_LVAL_MUX:
return net->n.sig;
default:
return 0;
}
}
extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
@@ -1293,19 +1441,6 @@ extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx)
return net->event_[idx];
}
extern "C" unsigned ivl_scope_vars(ivl_scope_t net)
{
assert(net);
return net->nvar_;
}
extern "C" ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(idx < net->nvar_);
return net->var_[idx];
}
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
{
assert(net);
@@ -1504,21 +1639,9 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
return name_buffer;
}
extern "C" ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
{
assert(net);
assert(idx < net->width_);
if (net->width_ == 1) {
return net->n.pin_;
} else {
return net->n.pins_[idx];
}
}
extern "C" unsigned ivl_signal_pins(ivl_signal_t net)
{
return net->width_;
return net->pin_;
}
extern "C" int ivl_signal_msb(ivl_signal_t net)
@@ -1532,6 +1655,11 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
return net->lsb_index;
}
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
{
return net->width_;
}
extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
{
return net->port_;
@@ -1552,6 +1680,11 @@ extern "C" int ivl_signal_integer(ivl_signal_t net)
return net->isint_;
}
extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net)
{
return net->data_type;
}
extern "C" ivl_signal_type_t ivl_signal_type(ivl_signal_t net)
{
return net->type_;
@@ -1760,15 +1893,12 @@ extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
assert(idx < net->u_.assign_.lvals_);
return net->u_.assign_.lval_ + idx;
case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN:
case IVL_ST_FORCE:
case IVL_ST_RELEASE:
assert(idx < net->u_.cassign_.lvals);
return net->u_.cassign_.lval + idx;
assert(idx < net->u_.assign_.lvals_);
return net->u_.assign_.lval_ + idx;
default:
assert(0);
@@ -1781,13 +1911,11 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
return net->u_.assign_.lvals_;
case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN:
case IVL_ST_FORCE:
case IVL_ST_RELEASE:
return net->u_.cassign_.lvals;
return net->u_.assign_.lvals_;
default:
assert(0);
@@ -1798,24 +1926,31 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
{
assert((net->type_ == IVL_ST_ASSIGN)
|| (net->type_ == IVL_ST_ASSIGN_NB));
|| (net->type_ == IVL_ST_ASSIGN_NB)
|| (net->type_ == IVL_ST_CASSIGN)
|| (net->type_ == IVL_ST_DEASSIGN)
|| (net->type_ == IVL_ST_FORCE)
|| (net->type_ == IVL_ST_RELEASE));
unsigned sum = 0;
for (unsigned idx = 0 ; idx < net->u_.assign_.lvals_ ; idx += 1) {
ivl_lval_t cur = net->u_.assign_.lval_ + idx;
unsigned nlvals;
struct ivl_lval_s*lvals;
nlvals = net->u_.assign_.lvals_;
lvals = net->u_.assign_.lval_;
for (unsigned idx = 0 ; idx < nlvals ; idx += 1) {
ivl_lval_t cur = lvals + idx;
switch(cur->type_) {
case IVL_LVAL_MUX:
sum += 1;
break;
case IVL_LVAL_REG:
sum += ivl_lval_pins(cur);
sum += ivl_lval_width(cur);
break;
case IVL_LVAL_MEM:
sum += ivl_memory_width(ivl_lval_mem(cur));
break;
case IVL_LVAL_VAR:
sum += 0;
break;
default:
assert(0);
}
@@ -1836,33 +1971,6 @@ extern "C" const char* ivl_stmt_name(ivl_statement_t net)
return 0;
}
extern "C" ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx)
{
switch (net->type_) {
case IVL_ST_CASSIGN:
case IVL_ST_FORCE:
assert(idx < net->u_.cassign_.npins);
return net->u_.cassign_.pins[idx];
default:
assert(0);
}
return 0;
}
extern "C" unsigned ivl_stmt_nexus_count(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_CASSIGN:
case IVL_ST_FORCE:
return net->u_.cassign_.npins;
default:
assert(0);
}
return 0;
}
extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx)
{
switch (net->type_) {
@@ -1892,6 +2000,8 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
case IVL_ST_CASSIGN:
case IVL_ST_FORCE:
return net->u_.assign_.rval_;
default:
assert(0);
@@ -1921,20 +2031,94 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
return 0;
}
extern "C" const char* ivl_variable_name(ivl_variable_t net)
{
assert(net);
return net->name;
}
extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
{
assert(net);
return net->type;
}
/*
* $Log: t-dll-api.cc,v $
* Revision 1.133 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.132 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.131 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.130 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.129 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.128 2005/06/13 23:22:37 steve
* Fix compile errors.
*
* Revision 1.127 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.126 2005/05/08 23:44:08 steve
* Add support for variable part select.
*
* Revision 1.125 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.124 2005/04/13 06:35:11 steve
* Make logic aware of strength.
*
* Revision 1.123 2005/04/06 05:29:08 steve
* Rework NetRamDq and IVL_LPM_RAM nodes.
*
* Revision 1.122 2005/04/01 06:04:30 steve
* Clean up handle of UDPs.
*
* Revision 1.121 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.120 2005/03/09 05:52:04 steve
* Handle case inequality in netlists.
*
* Revision 1.119 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.118 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.117 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.116 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.115 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.114 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.113 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.112 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.111 2004/12/18 18:56:18 steve
* Add ivl_event_scope, and better document ivl_event_X methods.
*
* Revision 1.110 2004/12/15 17:10:40 steve
* Fixup force statement elaboration.
*
* Revision 1.109 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.108 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*
+20 -137
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.43 2005/09/14 02:53: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();
}
/*
@@ -238,7 +227,7 @@ void dll_target::expr_const(const NetEConst*net)
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 +358,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. */
@@ -438,109 +416,12 @@ void dll_target::expr_signal(const NetESignal*net)
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_ = expr;
}
void dll_target::expr_ufunc(const NetEUFunc*net)
{
@@ -550,7 +431,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 +471,22 @@ 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.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.
*
+85 -205
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.68 2006/02/02 02:43:59 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,90 +138,15 @@ 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;
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;
/* 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);
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->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(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
const NetExpr*del = net->get_delay();
if (del) {
del->expr_scan(this);
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
}
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;
@@ -236,9 +154,18 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
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());
@@ -269,14 +196,52 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
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());
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);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
const NetExpr*del = net->get_delay();
if (del) {
del->expr_scan(this);
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
}
void dll_target::proc_assign_nb(const NetAssignNB*net)
{
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_.delay = 0;
/* 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 +393,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 +436,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 +495,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 +538,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 +741,17 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* 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.
*
+614 -543
View File
File diff suppressed because it is too large Load Diff
+109 -66
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.130 2006/02/02 02:43:59 steve Exp $"
#endif
# include "target.h"
@@ -69,8 +69,8 @@ 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*);
@@ -82,12 +82,15 @@ struct dll_target : public target_t, public expr_scan_t {
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_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*);
@@ -137,12 +140,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);
@@ -155,16 +156,17 @@ 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);
@@ -201,11 +203,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 +224,6 @@ struct ivl_expr_s {
struct {
ivl_signal_t sig;
unsigned lsi, msi;
} signal_;
struct {
@@ -272,9 +268,6 @@ struct ivl_expr_s {
ivl_expr_t sub_;
} unary_;
struct {
ivl_variable_t var;
} variable_;
} u_;
};
@@ -322,35 +315,51 @@ struct ivl_lpm_s {
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_concat_s {
unsigned width;
unsigned inputs;
ivl_nexus_t*pins;
} concat;
struct ivl_part_s {
unsigned width;
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 {
unsigned width;
ivl_nexus_t q, a;
} reduce;
struct ivl_lpm_repeat_s {
unsigned width;
unsigned count;
ivl_nexus_t q, a;
} repeat;
struct ivl_lpm_ufunc_s {
ivl_scope_t def;
unsigned ports;
unsigned *port_wid;
unsigned width;
ivl_nexus_t*pins;
} ufunc;
} u_;
@@ -366,39 +375,36 @@ enum ivl_lval_type_t {
IVL_LVAL_REG = 0,
IVL_LVAL_MUX = 1,
IVL_LVAL_MEM = 2,
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
IVL_LVAL_VAR = 4
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
};
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 +413,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 +425,7 @@ struct ivl_net_logic_s {
struct ivl_attribute_s*attr;
unsigned nattr;
unsigned delay[3];
ivl_expr_t delay[3];
};
@@ -428,7 +435,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;
@@ -537,9 +544,6 @@ struct ivl_scope_s {
unsigned nmem_;
ivl_memory_t* mem_;
unsigned nvar_;
ivl_variable_t* var_;
unsigned nparam_;
ivl_parameter_t param_;
@@ -564,6 +568,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 +583,7 @@ struct ivl_signal_s {
perm_string name_;
ivl_scope_t scope_;
union {
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
ivl_nexus_t pin_;
struct ivl_attribute_s*attr;
unsigned nattr;
@@ -595,7 +597,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 +618,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_;
@@ -673,17 +669,64 @@ 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.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.
*
+78 -34
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.77 2005/07/11 16:56:51 steve Exp $"
#endif
# include "config.h"
@@ -47,12 +47,6 @@ void target_t::memory(const NetMemory*)
"Unhandled memory." << endl;
}
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 +62,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,6 +79,13 @@ 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() << "): "
@@ -137,20 +140,33 @@ void target_t::lpm_ram_dq(const NetRamDq*)
"Unhandled NetRamDq." << endl;
}
bool target_t::concat(const NetConcat*)
{
cerr << "target (" << typeid(*this).name() << "): "
"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*)
{
cerr << "target (" << typeid(*this).name() << "): "
"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,13 +174,6 @@ bool target_t::net_const(const NetConst*)
return false;
}
bool target_t::net_force(const NetForce*dev)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetForce node." << endl;
return false;
}
bool target_t::net_function(const NetUserFunc*net)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -172,6 +181,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 +195,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);
@@ -382,12 +405,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 +423,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 +431,39 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* 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
+45 -9
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.74 2005/07/11 16:56:51 steve Exp $"
#endif
# include "netlist.h"
@@ -68,9 +68,6 @@ struct target_t {
/* 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*);
/* Output a defined task. */
virtual void task_def(const NetScope*);
virtual bool func_def(const NetScope*);
@@ -86,16 +83,21 @@ struct target_t {
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_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. */
@@ -141,11 +143,9 @@ struct expr_scan_t {
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 +153,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 +170,42 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* 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.
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.13 2004/02/10 19:25:01 steve Exp $"
#ident "$Id: Makefile.in,v 1.15 2005/03/03 04:34:42 steve Exp $"
#
#
SHELL = /bin/sh
@@ -52,7 +52,7 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = stub.o
O = stub.o memory.o statement.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
+11 -27
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 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,34 +17,18 @@
* 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: memory.c,v 1.1 2005/03/03 04:34:42 steve Exp $"
#endif
# include "config.h"
# include "PData.h"
# include "config.h"
# include "priv.h"
# include <assert.h>
PData::PData(const hname_t&h)
: hname_(h)
void show_memory(ivl_memory_t mem)
{
fprintf(out, " mem [%u] %s [%u] <root=%d>\n",
ivl_memory_width(mem),
ivl_memory_basename(mem),
ivl_memory_size(mem),
ivl_memory_root(mem));
}
PData::~PData()
{
}
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.
*
*/
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2004 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: priv.h,v 1.3 2005/03/05 05:47:42 steve Exp $"
#endif
# include <ivl_target.h>
# include <stdio.h>
/*
* This is the output file where the generated result should be
* written.
*/
extern FILE*out;
/*
* Keep a running count of errors that the stub detects. This will be
* the error count returned to the ivl_target environment.
*/
extern int stub_errors;
/*
* Show the details of the expression.
*/
extern void show_expression(ivl_expr_t net, unsigned ind);
extern void show_memory(ivl_memory_t mem);
/*
* Show the statement.
*/
extern void show_statement(ivl_statement_t net, unsigned ind);
+366
View File
@@ -0,0 +1,366 @@
/*
* Copyright (c) 2004 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: statement.c,v 1.9 2006/02/02 02:43:59 steve Exp $"
#endif
# include "config.h"
# include "priv.h"
# include <assert.h>
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
{
ivl_memory_t mem;
unsigned wid = 0;
if ( (mem = ivl_lval_mem(lval)) ) {
ivl_scope_t scope = ivl_memory_scope(mem);
fprintf(out, "%*s{ %s.%s width=%u }\n", ind, "",
ivl_scope_name(scope),
ivl_memory_basename(mem),
ivl_lval_width(lval));
fprintf(out, "%*sAddress-0 expression:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+8);
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sPart select base:\n", ind+4, "");
show_expression(ivl_lval_part_off(lval), ind+8);
}
/* When the l-value is a memory word, the lval_width
must exactly match the word width. */
if (ivl_lval_width(lval) != ivl_memory_width(mem)) {
fprintf(out, "%*sERROR: l-value width mismatch with "
" memory word width=%u\n", ind, "",
ivl_memory_width(mem));
stub_errors += 1;
}
} else {
ivl_signal_t sig = ivl_lval_sig(lval);
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
ind, "",
ivl_signal_name(sig),
ivl_signal_width(sig),
ivl_lval_width(lval));
if (ivl_lval_mux(lval)) {
fprintf(out, "%*sBit select expression:\n", ind+4, "");
show_expression(ivl_lval_mux(lval), ind+8);
}
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sPart select base:\n", ind+4, "");
show_expression(ivl_lval_part_off(lval), ind+8);
}
wid = ivl_lval_width(lval);
}
return wid;
}
static void show_stmt_cassign(ivl_statement_t net, unsigned ind)
{
unsigned idx;
unsigned lwid = 0;
fprintf(out, "%*sCONTINUOUS ASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
}
fprintf(out, "%*sTotal expected l-value width: %u bits\n",
ind+4, "", lwid);
show_expression(ivl_stmt_rval(net), ind+4);
}
static void show_stmt_delayx(ivl_statement_t net, unsigned ind)
{
fprintf(out, "%*s#(X) /* calculated delay */\n", ind, "");
show_expression(ivl_stmt_delay_expr(net), ind+4);
show_statement(ivl_stmt_sub_stmt(net), ind+2);
}
static void show_stmt_force(ivl_statement_t net, unsigned ind)
{
unsigned idx;
unsigned lwid = 0;
fprintf(out, "%*sforce <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
}
fprintf(out, "%*sTotal expected l-value width: %u bits\n",
ind+4, "", lwid);
show_expression(ivl_stmt_rval(net), ind+4);
}
static void show_stmt_release(ivl_statement_t net, unsigned ind)
{
unsigned idx;
unsigned lwid = 0;
fprintf(out, "%*srelease <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
}
fprintf(out, "%*sTotal l-value width: %u bits\n",
ind+4, "", lwid);
}
/*
* A trigger statement is the "-> name;" syntax in verilog, where a
* trigger signal is sent to a named event. The trigger statement is
* actually a very simple object.
*/
static void show_stmt_trigger(ivl_statement_t net, unsigned ind)
{
unsigned cnt = ivl_stmt_nevent(net);
unsigned idx;
fprintf(out, "%*s->", ind, "");
for (idx = 0 ; idx < cnt ; idx += 1) {
ivl_event_t event = ivl_stmt_events(net, idx);
fprintf(out, " %s", ivl_event_basename(event));
}
/* The compiler should make exactly one target event, so if we
find more or less, then print some error text. */
if (cnt != 1) {
fprintf(out, " /* ERROR: Expect one target event, got %u */", cnt);
}
fprintf(out, ";\n");
}
/*
* The wait statement contains simply an array of events to wait on,
* and a sub-statement to execute when an event triggers.
*/
void show_stmt_wait(ivl_statement_t net, unsigned ind)
{
unsigned idx;
const char*comma = "";
fprintf(out, "%*s@(", ind, "");
for (idx = 0 ; idx < ivl_stmt_nevent(net) ; idx += 1) {
ivl_event_t evnt = ivl_stmt_events(net, idx);
if (evnt == 0)
fprintf(out, "%s/*ERROR*/", comma);
else
fprintf(out, "%s%s.%s", comma,
ivl_scope_name(ivl_event_scope(evnt)),
ivl_event_basename(evnt));
comma = ", ";
}
fprintf(out, ")\n");
show_statement(ivl_stmt_sub_stmt(net), ind+4);
}
void show_statement(ivl_statement_t net, unsigned ind)
{
unsigned idx;
const ivl_statement_type_t code = ivl_statement_type(net);
switch (code) {
case IVL_ST_ASSIGN:
fprintf(out, "%*sASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
if (ivl_stmt_delay_expr(net))
show_expression(ivl_stmt_delay_expr(net), idx+4);
if (ivl_stmt_rval(net))
show_expression(ivl_stmt_rval(net), ind+4);
break;
case IVL_ST_ASSIGN_NB:
fprintf(out, "%*sASSIGN_NB <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
if (ivl_stmt_delay_expr(net)) {
fprintf(out, "%*s<internal delay>\n", ind+4, "");
show_expression(ivl_stmt_delay_expr(net), ind+6);
}
if (ivl_stmt_rval(net))
show_expression(ivl_stmt_rval(net), ind+4);
break;
case IVL_ST_BLOCK: {
unsigned cnt = ivl_stmt_block_count(net);
ivl_scope_t sscope = ivl_stmt_block_scope(net);
if (sscope)
fprintf(out, "%*sbegin : %s\n", ind, "",
ivl_scope_name(sscope));
else
fprintf(out, "%*sbegin\n", ind, "");
for (idx = 0 ; idx < cnt ; idx += 1) {
ivl_statement_t cur = ivl_stmt_block_stmt(net, idx);
show_statement(cur, ind+4);
}
fprintf(out, "%*send\n", ind, "");
break;
}
case IVL_ST_CASEX:
case IVL_ST_CASEZ:
case IVL_ST_CASER:
case IVL_ST_CASE: {
unsigned cnt = ivl_stmt_case_count(net);
unsigned idx;
fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt);
show_expression(ivl_stmt_cond_expr(net), ind+4);
for (idx = 0 ; idx < cnt ; idx += 1) {
ivl_expr_t ex = ivl_stmt_case_expr(net, idx);
ivl_statement_t st = ivl_stmt_case_stmt(net, idx);
if (ex == 0)
fprintf(out, "%*sdefault\n", ind+4, "");
else
show_expression(ex, ind+4);
show_statement(st, ind+4);
}
fprintf(out, "%*sendcase\n", ind, "");
break;
}
case IVL_ST_CASSIGN:
show_stmt_cassign(net, ind);
break;
case IVL_ST_CONDIT: {
ivl_expr_t ex = ivl_stmt_cond_expr(net);
ivl_statement_t t = ivl_stmt_cond_true(net);
ivl_statement_t f = ivl_stmt_cond_false(net);
fprintf(out, "%*sif (...)\n", ind, "");
show_expression(ex, ind+4);
if (t)
show_statement(t, ind+4);
else
fprintf(out, "%*s;\n", ind+4, "");
if (f) {
fprintf(out, "%*selse\n", ind, "");
show_statement(f, ind+4);
}
break;
}
case IVL_ST_DEASSIGN:
fprintf(out, "%*sDEASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
break;
case IVL_ST_DELAY:
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
show_statement(ivl_stmt_sub_stmt(net), ind+2);
break;
case IVL_ST_DELAYX:
show_stmt_delayx(net, ind);
break;
case IVL_ST_FORCE:
show_stmt_force(net, ind);
break;
case IVL_ST_FORK: {
unsigned cnt = ivl_stmt_block_count(net);
fprintf(out, "%*sfork\n", ind, "");
for (idx = 0 ; idx < cnt ; idx += 1) {
ivl_statement_t cur = ivl_stmt_block_stmt(net, idx);
show_statement(cur, ind+4);
}
fprintf(out, "%*sjoin\n", ind, "");
break;
}
case IVL_ST_NOOP:
fprintf(out, "%*s/* noop */;\n", ind, "");
break;
case IVL_ST_RELEASE:
show_stmt_release(net, ind);
break;
case IVL_ST_STASK: {
fprintf(out, "%*sCall %s(%u parameters);\n", ind, "",
ivl_stmt_name(net), ivl_stmt_parm_count(net));
for (idx = 0 ; idx < ivl_stmt_parm_count(net) ; idx += 1)
if (ivl_stmt_parm(net, idx))
show_expression(ivl_stmt_parm(net, idx), ind+4);
break;
}
case IVL_ST_TRIGGER:
show_stmt_trigger(net, ind);
break;
case IVL_ST_UTASK:
fprintf(out, "%*scall task ...\n", ind, "");
break;
case IVL_ST_WAIT:
show_stmt_wait(net, ind);
break;
case IVL_ST_WHILE:
fprintf(out, "%*swhile\n", ind, "");
show_expression(ivl_stmt_cond_expr(net), ind+4);
show_statement(ivl_stmt_sub_stmt(net), ind+2);
break;
default:
fprintf(out, "%*sunknown statement type (%u)\n", ind, "", code);
}
}
+6
View File
@@ -0,0 +1,6 @@
functor:synth2
functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
+1278 -504
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
functor:cprop
functor:nodangle
-t:dll
+2
View File
@@ -6,3 +6,5 @@ config.log
autom4te.cache
dep
vvp.tgt
vvp.conf
vvp-s.conf
+3 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.22 2004/02/10 19:25:01 steve Exp $"
#ident "$Id: Makefile.in,v 1.24 2005/09/14 02:53:15 steve Exp $"
#
#
SHELL = /bin/sh
@@ -51,7 +51,8 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vvp.o draw_mux.o draw_vpi.o eval_expr.o eval_real.o vector.o \
O = vvp.o draw_mux.o draw_ufunc.o draw_vpi.o eval_bool.o eval_expr.o \
eval_real.o vector.o \
vvp_process.o vvp_scope.o
ifeq (@WIN32@,yes)
+1 -1
View File
@@ -13,7 +13,7 @@ AC_CANONICAL_HOST
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(malloc.h stdint.h)
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
+94 -132
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_mux.c,v 1.7 2003/12/19 01:27:10 steve Exp $"
#ident "$Id: draw_mux.c,v 1.13 2005/10/12 17:26:17 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -28,163 +28,125 @@
# include <stdlib.h>
# include <string.h>
/*
* This draws a general mux, a slice at a time. Use MUXX so that
* unknows lead to unknown output.
*/
static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
{
unsigned sel = ivl_lpm_selects(net);
unsigned size = ivl_lpm_size(net);
unsigned sel_from_size;
unsigned seldx, idx;
ivl_nexus_t s;
sel_from_size = 0;
seldx = size - 1;
while (seldx > 0) {
seldx >>= 1;
sel_from_size += 1;
}
if (sel_from_size > sel) {
fprintf(stderr, "internal error: MUX size=%u, selects=%u\n",
size, sel);
}
assert(sel_from_size <= sel);
s = ivl_lpm_select(net, 0);
/* Draw the leaf mux devices that take inputs from the
net. These also use up the least significant bit of the
select vector. */
for (idx = 0 ; idx < size ; idx += 2) {
fprintf(vvp_out, "L_%s.%s/%u/%u/%u .functor MUXX, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), slice, sel, idx);
{
ivl_nexus_t a = ivl_lpm_data2(net, idx+0, slice);
draw_input_from_net(a);
fprintf(vvp_out, ", ");
}
if ((idx+1) < size) {
ivl_nexus_t b = ivl_lpm_data2(net, idx+1, slice);
draw_input_from_net(b);
fprintf(vvp_out, ", ");
} else {
fprintf(vvp_out, "C<x>, ");
}
draw_input_from_net(s);
fprintf(vvp_out, ", C<1>;\n");
}
/* Draw the tree of MUXX devices to connect the inner tree
nodes. */
for (seldx = 1 ; seldx < (sel-1) ; seldx += 1) {
unsigned level = sel - seldx;
unsigned span = 2 << seldx;
s = ivl_lpm_select(net, seldx);
for (idx = 0 ; idx < size ; idx += span) {
fprintf(vvp_out, "L_%s.%s/%u/%u/%u .functor MUXX, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)),
slice, level, idx);
fprintf(vvp_out, "L_%s.%s/%u/%u/%u, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)),
slice, level+1, idx);
if ((idx + span/2) < size) {
fprintf(vvp_out, "L_%s.%s/%u/%u/%u, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)),
slice, level+1, idx+span/2);
} else {
fprintf(vvp_out, "C<x>, ");
}
draw_input_from_net(s);
fprintf(vvp_out, ", C<1>;\n");
}
}
s = ivl_lpm_select(net, sel-1);
fprintf(vvp_out, "L_%s.%s/%u .functor MUXX, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), slice);
fprintf(vvp_out, "L_%s.%s/%u/2/0, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), slice);
if ((2U << (sel-1))/2 < size) {
fprintf(vvp_out, "L_%s.%s/%u/2/%u, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)),
slice, (2U << (sel-1))/2);
} else {
fprintf(vvp_out, "C<x>, ");
}
draw_input_from_net(s);
fprintf(vvp_out, ", C<1>;\n");
}
/*
* This draws a simple A/B mux. The mux can have any width, enough
* MUXZ nodes are created to support the vector.
*/
static void draw_lpm_mux_ab(ivl_lpm_t net)
static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
{
ivl_nexus_t s;
unsigned idx, width;
unsigned width = ivl_lpm_width(net);
/* Only support A-B muxes at this oint. */
/* Only support A-B muxes in this function. */
assert(ivl_lpm_size(net) == 2);
assert(ivl_lpm_selects(net) == 1);
width = ivl_lpm_width(net);
s = ivl_lpm_select(net, 0);
fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width);
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,0)));
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,1)));
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_select(net)));
fprintf(vvp_out, ", C4<>;\n");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t a = ivl_lpm_data2(net, 0, idx);
ivl_nexus_t b = ivl_lpm_data2(net, 1, idx);
fprintf(vvp_out, "L_%s.%s/%u .functor MUXZ, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
draw_input_from_net(a);
fprintf(vvp_out, ", ");
draw_input_from_net(b);
fprintf(vvp_out, ", ");
draw_input_from_net(s);
fprintf(vvp_out, ", C<1>;\n");
static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
{
int idx, level;
unsigned width = ivl_lpm_width(net);
unsigned swidth = ivl_lpm_selects(net);
char*select_input;
assert(ivl_lpm_size(net) == (1 << swidth));
select_input = strdup(draw_net_input(ivl_lpm_select(net)));
fprintf(vvp_out, "L_%p/0s .part %s, 0, 1; Bit 0 of the select\n",
net, select_input);
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 2) {
fprintf(vvp_out, "L_%p/0/%d .functor %s %u",
net, idx/2, muxz, width);
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+0)));
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+1)));
fprintf(vvp_out, ", L_%p/0s, C4<>;\n", net);
}
for (level = 1 ; level < swidth-1 ; level += 1) {
fprintf(vvp_out, "L_%p/%ds .part %s, %d, 1;\n",
net, level, select_input, level);
for (idx = 0 ; idx < (ivl_lpm_size(net) >> level); idx += 2) {
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
net, width, level, muxz, idx);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+0);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+1);
fprintf(vvp_out, ", L_%p/%ds", net, level);
fprintf(vvp_out, ", C4<>;\n");
}
}
fprintf(vvp_out, "L_%p/%ds .part %s, %d, 1; Bit %d of the select\n",
net, swidth-1, select_input, swidth-1, swidth-1);
fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width);
fprintf(vvp_out, ", L_%p/%d/0", net, swidth-2);
fprintf(vvp_out, ", L_%p/%d/1", net, swidth-2);
fprintf(vvp_out, ", L_%p/%ds", net, swidth-1);
fprintf(vvp_out, ", C4<>;\n");
free(select_input);
}
void draw_lpm_mux(ivl_lpm_t net)
{
unsigned idx;
const char*muxz = "MUXZ";
/* The output of the mux defines the type of the mux. the
ivl_target should guarantee that all the inputs are the
same type as the output. */
switch (data_type_of_nexus(ivl_lpm_q(net,0))) {
case IVL_VT_REAL:
muxz = "MUXR";
break;
default:
muxz = "MUXZ";
break;
}
if ((ivl_lpm_size(net) == 2) && (ivl_lpm_selects(net) == 1)) {
draw_lpm_mux_ab(net);
draw_lpm_mux_ab(net, muxz);
return;
}
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1)
draw_lpm_mux_bitslice(net, idx);
/* Here we are at the worst case, we generate a tree of MUXZ
devices to handle the arbitrary size. */
draw_lpm_mux_nest(net, muxz);
}
/*
* $Log: draw_mux.c,v $
* Revision 1.13 2005/10/12 17:26:17 steve
* MUX nodes get inputs from nets, not from net inputs,
* Detect and draw alias nodes to reduce net size and
* handle force confusion.
*
* Revision 1.12 2005/09/01 04:11:37 steve
* Generate code to handle real valued muxes.
*
* Revision 1.11 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
* Revision 1.10 2005/06/17 03:46:52 steve
* Make functors know their own width.
*
* Revision 1.9 2005/04/06 05:29:09 steve
* Rework NetRamDq and IVL_LPM_RAM nodes.
*
* Revision 1.8 2005/02/12 22:54:29 steve
* Implement a-b muxes as vector devices
*
* Revision 1.7 2003/12/19 01:27:10 steve
* Fix various unsigned compare warnings.
*
+158
View File
@@ -0,0 +1,158 @@
/*
* Copyright (c) 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
* 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: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $"
#endif
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <assert.h>
static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
{
struct vector_info res;
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
assert(res.wid <= ivl_signal_width(port));
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(port), res.base, res.wid);
clr_vector(res);
}
static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
{
int res = draw_eval_real(exp);
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
vvp_signal_label(port), res);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_LOGIC:
function_argument_logic(port, exp);
break;
case IVL_VT_REAL:
function_argument_real(port, exp);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype);
assert(0);
}
}
/*
* A call to a user defined function generates a result that is the
* result of this expression.
*
* The result of the function is placed by the function execution into
* a signal within the scope of the function that also has a basename
* the same as the function. The ivl_target API handled the result
* mapping already, and we get the name of the result signal as
* parameter 0 of the function definition.
*/
struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
{
unsigned idx;
unsigned swid = ivl_expr_width(exp);
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
/* evaluate the expressions and send the results to the
function ports. */
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(exp,idx));
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
res.base = allocate_vector(wid);
res.wid = wid;
{ unsigned load_wid = swid;
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(retval), load_wid);
if (load_wid < swid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+load_wid, swid-load_wid);
}
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
return res;
}
int draw_ufunc_real(ivl_expr_t exp)
{
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
int res = 0;
int idx;
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(exp,idx));
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Load the result into a word. */
res = allocate_word();
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
res, vvp_signal_label(retval));
return res;
}
+21 -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: draw_vpi.c,v 1.9 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: draw_vpi.c,v 1.13 2005/10/11 18:30:50 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -79,7 +79,6 @@ static void draw_vpi_taskfunc_args(const char*call_string,
case IVL_EX_STRING:
case IVL_EX_EVENT:
case IVL_EX_SCOPE:
case IVL_EX_VARIABLE:
continue;
case IVL_EX_SFUNC:
@@ -102,7 +101,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
it as I'll be passing the handle to the signal
itself. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
ivl_signal_width(ivl_expr_signal(expr))) {
break;
} else if (ivl_expr_signed(expr) !=
@@ -170,7 +169,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
calculated above. Otherwise, just pass the
signal. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
ivl_signal_width(ivl_expr_signal(expr))) {
break;
} else if (ivl_expr_signed(expr) !=
@@ -182,12 +181,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
vvp_signal_label(ivl_expr_signal(expr)));
continue;
}
case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr);
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
continue;
}
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
case IVL_EX_STRING:
if (( par = ivl_expr_parameter(expr) )) {
@@ -216,8 +212,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
fprintf(vvp_out, ", M_%s",
vvp_memory_label(ivl_expr_memory(expr)));
fprintf(vvp_out, ", M_%p", ivl_expr_memory(expr)) ;
continue;
}
break;
@@ -296,6 +291,20 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
/*
* $Log: draw_vpi.c,v $
* Revision 1.13 2005/10/11 18:30:50 steve
* Remove obsolete vvp_memory_label function.
*
* Revision 1.12 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.11 2005/06/18 15:55:21 steve
* Handle signed display of unsigned signals.
*
* Revision 1.10 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.9 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (c) 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
* 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
*/
#ident "$Id: eval_bool.c,v 1.4 2005/12/07 03:43:30 steve Exp $"
/*
* This file includes functions for evaluating REAL expressions.
*/
# include "vvp_config.h"
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
# include <math.h>
# include <assert.h>
/*
* Evaluate the bool64 the hard way, by evaluating the logic vector
* and converting it to a bool64.
*/
static int eval_bool64_logic(ivl_expr_t exp)
{
int res;
struct vector_info tmp;
tmp = draw_eval_expr(exp, STUFF_OK_XZ);
res = allocate_word();
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, tmp.base, tmp.wid);
clr_vector(tmp);
return res;
}
static int draw_number_bool64(ivl_expr_t exp)
{
int res;
const char*bits = ivl_expr_bits(exp);
uint64_t val = 0;
unsigned long idx;
for (idx = 0 ; idx < ivl_expr_width(exp) ; idx += 1) {
if (bits[idx] == '1')
val |= 1UL << idx;
}
res = allocate_word();
fprintf(vvp_out, " %%ix/load %d, %lu;\n", res, val);
return res;
}
int draw_eval_bool64(ivl_expr_t exp)
{
int res;
switch (ivl_expr_type(exp)) {
case IVL_EX_NUMBER:
res = draw_number_bool64(exp);
break;
default:
res = eval_bool64_logic(exp);
break;
}
return res;
}
/*
* $Log: eval_bool.c,v $
* Revision 1.4 2005/12/07 03:43:30 steve
* Include stdint.h if it is present.
*
* Revision 1.3 2005/12/05 21:20:55 steve
* Some systems donot have stding.h?
*
* Revision 1.2 2005/09/19 20:17:59 steve
* Include vvp_config.h instead of config.h
*
* Revision 1.1 2005/09/14 02:53:15 steve
* Support bool expressions and compares handle them optimally.
*
*/
+322 -186
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_expr.c,v 1.110 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: eval_expr.c,v 1.130 2006/02/02 02:43:59 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -57,7 +57,9 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
const char*bits;
unsigned idx;
assert(ivl_expr_type(ex) == IVL_EX_NUMBER);
if (ivl_expr_type(ex) != IVL_EX_NUMBER
&& ivl_expr_type(ex) != IVL_EX_ULONG)
return 0;
bits = ivl_expr_bits(ex);
for (idx = lim_wid ; idx < ivl_expr_width(ex) ; idx += 1)
@@ -99,6 +101,38 @@ unsigned long get_number_immediate(ivl_expr_t ex)
return imm;
}
/*
* This function, in addition to setting the value into index 0, sets
* bit 4 to 1 if the value is unknown.
*/
void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
{
struct vector_info vec;
int word;
switch (ivl_expr_value(expr)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, vec.base, vec.wid);
clr_vector(vec);
break;
case IVL_VT_REAL:
word = draw_eval_real(expr);
clr_word(word);
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
break;
default:
fprintf(stderr, "XXXX ivl_expr_value == %d\n",
ivl_expr_value(expr));
assert(0);
}
}
/*
* The STUFF_OK_XZ bit is true if the output is going to be further
* processed so that x and z values are equivilent. This may allow for
@@ -265,15 +299,17 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
&& number_is_immediate(re, 16))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|| ivl_expr_value(le) == IVL_VT_BOOL);
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|| ivl_expr_value(re) == IVL_VT_BOOL);
wid = ivl_expr_width(le);
if (ivl_expr_width(re) > wid)
wid = ivl_expr_width(re);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&~STUFF_OK_47);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&~STUFF_OK_47);
switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
@@ -556,6 +592,63 @@ static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp)
return res;
}
static struct vector_info draw_binary_expr_le_bool(ivl_expr_t exp,
unsigned wid)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
int lw, rw;
struct vector_info tmp;
char s_flag = (ivl_expr_signed(le) && ivl_expr_signed(re)) ? 's' : 'u';
assert(ivl_expr_value(le) == IVL_VT_BOOL);
assert(ivl_expr_value(re) == IVL_VT_BOOL);
lw = draw_eval_bool64(le);
rw = draw_eval_bool64(re);
switch (ivl_expr_opcode(exp)) {
case 'G':
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, rw, lw);
fprintf(vvp_out, " %%or 5, 4, 1;\n");
break;
case 'L':
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, lw, rw);
fprintf(vvp_out, " %%or 5, 4, 1;\n");
break;
case '<':
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, lw, rw);
break;
case '>':
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, rw, lw);
break;
default:
assert(0);
}
clr_word(lw);
clr_word(rw);
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
{ unsigned base = allocate_vector(wid);
fprintf(vvp_out, " %%mov %u, 5, 1;\n", base);
tmp.base = base;
tmp.wid = wid;
if (wid > 1)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, wid-1);
}
return tmp;
}
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
@@ -578,8 +671,17 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
if (ivl_expr_value(re) == IVL_VT_REAL)
return draw_binary_expr_le_real(exp);
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
/* Detect the special case that we can do this with integers. */
if (ivl_expr_value(le) == IVL_VT_BOOL
&& ivl_expr_value(re) == IVL_VT_BOOL
&& owid < 64) {
return draw_binary_expr_le_bool(exp, wid);
}
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|| ivl_expr_value(le) == IVL_VT_BOOL);
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|| ivl_expr_value(re) == IVL_VT_BOOL);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
@@ -989,7 +1091,7 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ|STUFF_OK_RO);
if (lv.wid != wid) {
fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c,"
@@ -1125,49 +1227,19 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp,
return rv;
}
static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
ivl_signal_t sig = ivl_expr_signal(exp);
ivl_expr_t sel = ivl_expr_oper1(exp);
/* Evaluate the bit select expression and save the result into
index register 0. */
res = draw_eval_expr(sel, 0);
fprintf(vvp_out, " %%ix/get 0, %u,%u;\n", res.base, res.wid);
clr_vector(res);
res.base = allocate_vector(wid);
res.wid = wid;
switch (ivl_signal_type(sig)) {
case IVL_SIT_TRI:
case IVL_SIT_TRI0:
case IVL_SIT_TRI1:
fprintf(vvp_out, " %%load/nx %u, V_%s, 0;\n", res.base,
vvp_signal_label(sig));
break;
default:
fprintf(vvp_out, " %%load/x %u, V_%s, 0;\n", res.base,
vvp_signal_label(sig));
break;
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
/*
* The concatenation operator is evaluated by evaluating each sub-
* expression, then copying it into the continguous vector of the
* result. Do this until the result vector is filled.
*/
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
unsigned off, rep;
struct vector_info res;
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
/* Allocate a vector to hold the result. */
res.base = allocate_vector(wid);
res.wid = wid;
@@ -1197,7 +1269,7 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
/* Try to locate the subexpression in the
lookaside map. */
avec.base = allocate_vector_exp(arg, awid);
avec.base = allocate_vector_exp(arg, awid, alloc_exclusive);
avec.wid = awid;
trans = awid;
@@ -1281,6 +1353,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
case 'z':
res.base = 3;
break;
default:
assert(0);
res.base = 0;
}
return res;
}
@@ -1457,29 +1532,15 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
{
unsigned idx;
unsigned lsi = ivl_expr_lsi(exp);
unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp);
if (swid > res.wid)
swid = res.wid;
if (ivl_signal_type(sig) == IVL_SIT_REG) {
/* If this is a REG (a variable) then I can do a vector
read. */
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
res.base, vvp_signal_label(sig), lsi, swid);
} else {
/* Vector reads of nets do not in general work because
they are not really functors but references to
scattered functors. So generate an array of loads. */
for (idx = 0 ; idx < swid ; idx += 1) {
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi);
}
}
/* If this is a REG (a variable) then I can do a vector read. */
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(sig), swid);
/* Pad the signal value with zeros. */
if (swid < res.wid) {
@@ -1496,15 +1557,21 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
}
}
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
struct vector_info res;
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
/* Already in the vector lookaside? */
res.base = allocate_vector_exp(exp, wid);
res.base = allocate_vector_exp(exp, wid, alloc_exclusive);
res.wid = wid;
if (res.base != 0)
if (res.base != 0) {
fprintf(vvp_out, "; Reuse signal base=%u wid=%u from lookaside.\n",
res.base, res.wid);
return res;
}
res.base = allocate_vector(wid);
res.wid = wid;
@@ -1514,11 +1581,14 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
return res;
}
/*
* Draw code to evaluate a memory word index expression and write the
* value into index register 3. This expression converts the run-time
* calculated value to canonical form that the %load/mv takes.
*/
void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
{
int root = ivl_memory_root(mem);
unsigned width = ivl_memory_width(mem);
width = (width+3) & ~3;
switch (ivl_expr_type(ae)) {
case IVL_EX_NUMBER: {
@@ -1540,14 +1610,14 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
unknown_flag = 1;
break;
}
fprintf(vvp_out, " %%ix/load 3, %lu;\n", (v-root)*width);
fprintf(vvp_out, " %%ix/load 3, %lu;\n", v-root);
fprintf(vvp_out, " %%mov 4, %c, 1;\n",
unknown_flag?'1':'0');
break;
}
case IVL_EX_ULONG: {
unsigned v = ivl_expr_uvalue(ae);
fprintf(vvp_out, " %%ix/load 3, %u;\n", (v-root)*width);
fprintf(vvp_out, " %%ix/load 3, %u;\n", v-root);
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
break;
}
@@ -1558,8 +1628,6 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
clr_vector(addr);
if (root>0)
fprintf(vvp_out, " %%ix/sub 3, %u;\n", root);
if (width>1)
fprintf(vvp_out, " %%ix/mul 3, %u;\n", width);
break;
}
}
@@ -1570,7 +1638,6 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
unsigned swid = ivl_expr_width(exp);
ivl_memory_t mem = ivl_expr_memory(exp);
struct vector_info res;
unsigned idx;
draw_memory_index_expr(mem, ivl_expr_oper1(exp));
@@ -1580,12 +1647,8 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
res.base = allocate_vector(wid);
res.wid = wid;
for (idx = 0 ; idx < swid ; idx += 1) {
if (idx)
fprintf(vvp_out, " %%ix/add 3, 1;\n");
fprintf(vvp_out, " %%load/m %u, M_%s;\n",
res.base+idx, vvp_memory_label(mem));
}
fprintf(vvp_out, " %%load/mv %u, M_%p, %u;\n",
res.base, mem, swid);
/* Pad the signal value with zeros. */
if (swid < wid)
@@ -1598,12 +1661,104 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
return res;
}
static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_select_signal(ivl_expr_t sube,
ivl_expr_t bit_idx,
unsigned bit_wid,
unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(sube);
struct vector_info shiv;
struct vector_info res;
unsigned idx;
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
if (shiv.base >= 8)
clr_vector(shiv);
/* Try the special case that the base is 0 and the width
exactly matches the signal. Just load the signal in one
instruction. */
if (shiv.base == 0 && ivl_expr_width(sube) == wid) {
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%load/v %u, V_%p, %u;\n",
res.base, sig, ivl_expr_width(sube));
return res;
}
/* Try the special case that hte part is at the beginning and
nearly the width of the signal. In this case, just load the
entire signal in one go then simply drop the excess bits. */
if (shiv.base == 0
&& (ivl_expr_width(sube) > wid)
&& (ivl_expr_width(sube) < (wid+wid/10))) {
res.base = allocate_vector(ivl_expr_width(sube));
res.wid = ivl_expr_width(sube);
fprintf(vvp_out, " %%load/v %u, V_%p, %u; Only need %u bits\n",
res.base, sig, ivl_expr_width(sube), wid);
save_signal_lookaside(res.base, sig, res.wid);
{
struct vector_info tmp;
tmp.base = res.base + wid;
tmp.wid = res.wid - wid;
clr_vector(tmp);
res.wid = wid;
}
return res;
}
/* Alas, do it the hard way. */
res.base = allocate_vector(wid);
res.wid = wid;
for (idx = 0 ; idx < res.wid ; idx += 1) {
if (idx >= bit_wid) {
fprintf(vvp_out, " %%mov %u, 0, %u; Pad from %u to %u\n",
res.base+idx, res.wid-idx,
ivl_expr_width(sube), wid);
break;
}
fprintf(vvp_out, " %%load/x.p %u, V_%p, 0;\n",
res.base+idx, sig);
}
return res;
}
static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
struct vector_info subv, shiv, res;
ivl_expr_t sube = ivl_expr_oper1(exp);
ivl_expr_t shift = ivl_expr_oper2(exp);
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
res.wid = wid;
/* First look for the self expression in the lookaside, and
allocate that if possible. If I find it, then immediatly
return that. */
if ( (res.base = allocate_vector_exp(exp, wid, alloc_exclusive)) != 0) {
fprintf(vvp_out, "; Reuse base=%u wid=%u from lookaside.\n",
res.base, wid);
return res;
}
if (ivl_expr_type(sube) == IVL_EX_SIGNAL) {
res = draw_select_signal(sube, shift, ivl_expr_width(exp), wid);
fprintf(vvp_out, "; Save base=%u wid=%u in lookaside.\n",
res.base, wid);
save_expression_lookaside(res.base, exp, wid);
return res;
}
/* Evaluate the sub-expression. */
subv = draw_eval_expr(sube, 0);
@@ -1617,6 +1772,16 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the bit select base expression and store the
result into index register 0. */
shiv = draw_eval_expr(shift, STUFF_OK_XZ);
/* Detect and handle the special case that the shift is a
constant 0. Skip the shift, and return the subexpression
with the width trimmed down to the desired width. */
if (shiv.base == 0) {
assert(subv.wid >= wid);
res.base = subv.base;
return res;
}
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
clr_vector(shiv);
@@ -1632,20 +1797,24 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
assert(subv.wid >= wid);
if (subv.wid > wid) {
res.base = subv.base;
res.wid = wid;
subv.base += wid;
subv.wid -= wid;
clr_vector(subv);
} else if (subv.wid == wid) {
} else {
assert(subv.wid == wid);
res = subv;
}
if (res.base >= 8)
if (res.base >= 8) {
fprintf(vvp_out, "; Save expression base=%u wid=%u in lookaside\n",
res.base, wid);
save_expression_lookaside(res.base, exp, wid);
}
return res;
}
@@ -1665,7 +1834,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the condition expression, and if necessary reduce
it to a single bit. */
tst = draw_eval_expr(cond, STUFF_OK_XZ);
tst = draw_eval_expr(cond, STUFF_OK_XZ|STUFF_OK_RO);
if ((tst.base >= 4) && (tst.wid > 1)) {
struct vector_info tmp;
@@ -1744,7 +1913,8 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
/* If the function has no parameters, then use this short-form
to draw the statement. */
if (parm_count == 0) {
assert(ivl_expr_value(exp) == IVL_VT_VECTOR);
assert(ivl_expr_value(exp) == IVL_VT_LOGIC
|| ivl_expr_value(exp) == IVL_VT_BOOL);
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%vpi_func \"%s\", %u, %u;\n",
@@ -1761,86 +1931,6 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
return res;
}
/*
* A call to a user defined function generates a result that is the
* result of this expression.
*
* The result of the function is placed by the function execution into
* a signal within the scope of the function that also has a basename
* the same as the function. The ivl_target API handled the result
* mapping already, and we get the name of the result signal as
* parameter 0 of the function definition.
*/
static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
{
unsigned idx;
unsigned swid = ivl_expr_width(exp);
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
/* evaluate the expressions and send the results to the
function ports. */
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
unsigned pin, bit;
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
ivl_signal_pins(port), 0);
bit = res.base;
assert(res.wid <= ivl_signal_pins(port));
for (pin = 0 ; pin < res.wid ; pin += 1) {
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
vvp_signal_label(port),
pin, bit);
if (bit >= 4)
bit += 1;
}
clr_vector(res);
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
res.base = allocate_vector(wid);
res.wid = wid;
{ unsigned load_wid = swid;
if (load_wid > ivl_signal_pins(retval))
load_wid = ivl_signal_pins(retval);
for (idx = 0 ; idx < load_wid ; idx += 1)
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx,
vvp_signal_label(retval), idx);
if (load_wid < swid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+load_wid, swid-load_wid);
}
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
return res;
}
static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
@@ -2007,18 +2097,6 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
return res;
}
static struct vector_info draw_variable_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
ivl_variable_t var = ivl_expr_variable(exp);
fprintf(vvp_out, " ; XXXX Read variable %s\n",
ivl_variable_name(var));
res.base = 0;
res.wid = wid;
return res;
}
/*
* Sometimes we know ahead of time where we want the expression value
* to go. In that case, call this function. It will check to see if
@@ -2077,12 +2155,8 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
res = draw_binary_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_BITSEL:
res = draw_bitsel_expr(exp, wid);
break;
case IVL_EX_CONCAT:
res = draw_concat_expr(exp, wid);
res = draw_concat_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_NUMBER:
@@ -2097,11 +2171,11 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
if (ivl_expr_oper2(exp) == 0)
res = draw_pad_expr(exp, wid);
else
res = draw_select_expr(exp, wid);
res = draw_select_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_SIGNAL:
res = draw_signal_expr(exp, wid);
res = draw_signal_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_TERNARY:
@@ -2123,10 +2197,6 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
case IVL_EX_UNARY:
res = draw_unary_expr(exp, wid);
break;
case IVL_EX_VARIABLE:
res = draw_variable_expr(exp, wid);
break;
}
return res;
@@ -2139,6 +2209,72 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* 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:20 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.128 2005/12/22 15:42:22 steve
* Pad part selects
*
* Revision 1.127 2005/10/11 18:54:10 steve
* Remove the $ from signal labels. They do not help.
*
* Revision 1.126 2005/10/11 18:30:50 steve
* Remove obsolete vvp_memory_label function.
*
* Revision 1.125 2005/09/19 21:45:36 steve
* Spelling patches from Larry.
*
* Revision 1.124 2005/09/19 20:18:20 steve
* Fix warnings about uninitialized variables.
*
* Revision 1.123 2005/09/17 04:01:32 steve
* Improve loading of part selects when easy.
*
* Revision 1.122 2005/09/17 01:01:00 steve
* More robust use of precalculated expressions, and
* Separate lookaside for written variables that can
* also be reused.
*
* Revision 1.121 2005/09/15 02:49:47 steve
* Better reuse of IVL_EX_SELECT expressions.
*
* Revision 1.120 2005/09/14 02:53:15 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.119 2005/07/13 04:52:31 steve
* Handle functions with real values.
*
* Revision 1.118 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.117 2005/03/12 23:45:33 steve
* Handle function/task port vectors.
*
* Revision 1.116 2005/03/03 04:34:42 steve
* Rearrange how memories are supported as vvp_vector4 arrays.
*
* Revision 1.115 2005/02/15 07:12:55 steve
* Support constant part select writes to l-values, and large part select reads from signals.
*
* Revision 1.114 2005/01/28 05:37:48 steve
* Special handling of constant shift 0.
*
* Revision 1.113 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.112 2005/01/24 05:08:02 steve
* Part selects are done in the compiler, not here.
*
* Revision 1.111 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.110 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

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