packages feed

sv2v 0.0.9 → 0.0.10

raw patch · 33 files changed

+1570/−695 lines, 33 filesdep ~basedep ~containersdep ~githash

Dependency ranges changed: base, containers, githash, vector

Files

CHANGELOG.md view
@@ -1,3 +1,46 @@+## v0.0.10++### Breaking Changes++* `--write adjacent` no longer forbids overwriting existing generated files++### New Features++* Added support for assignments within expressions (e.g., `x = ++y;`)+* Added support for excluding the conversion of unbased unsized literals (e.g.,+  `'1`, `'x`) via `--exclude UnbasedUniszed`+* Added support for enumerated type ranges (e.g., `enum { X[3:5] }`)+* Added support for complex event expressions (e.g., `@(x ^ y)`)+* Added support for the SystemVerilog `edge` event+* Added support for cycle delay ranges in assertion sequence expressions+* Added support for procedural continuous assignments (`assign`/`deassign` and+  `force`/`release`)+* Added conversion for `do` `while` loops+* Added support for hierarchical calls to functions with no inputs+* Added support for passing through DPI imports and exports+* Added support for passing through functions with output ports+* Extended applicability of simplified Yosys-compatible `for` loop elaboration++### Other Enhancements++* Certain errors raised during conversion now also provide hierarchical and+  approximate source location information to help locate the error++### Bug Fixes++* Fixed inadvertent design behavior changes caused by constant folding removing+  intentional width-extending operations such as `+ 0` and `* 1`+* Fixed forced conversion to `reg` of data sensed in an edge-controlled+  procedural assignment+* `always_comb` and `always_latch` now generate explicit sensitivity lists where+  necessary because of calls to functions which reference non-local data+* Fixed signed `struct` fields being converted to unsigned expressions when+  accessed directly+* Fixed conversion of casts using structs containing multi-dimensional fields+* Fixed incorrect name resolution conflicts raised during interface inlining+* Fixed handling of interface instances which shadow other declarations+* Fixed names like `<pkg>_<name>` being shadowed by elaborated packages+ ## v0.0.9  ### Breaking Changes
LICENSE view
@@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright 2019-2021 Zachary Snow+Copyright 2019-2022 Zachary Snow Copyright 2011-2015 Tom Hawkins  All rights reserved.
NOTICE view
@@ -1,26 +1,26 @@ ================================================================================-Dependency: alex-3.2.6+Dependency: alex-3.2.7.1 ================================================================================    Copyright (c) 1995-2011, Chris Dornan and Simon Marlow   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are   met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of the copyright holders, nor the names of the         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -38,43 +38,43 @@ ================================================================================    This library (libraries/base) is derived from code from several-  sources: -  +  sources:+     * Code from the GHC project which is largely (c) The University of       Glasgow, and distributable under a BSD-style license (see below),-  +     * Code from the Haskell 98 Report which is (c) Simon Peyton Jones       and freely redistributable (but see the full license for       restrictions).-  +     * Code from the Haskell Foreign Function Interface specification,       which is (c) Manuel M. T. Chakravarty and freely redistributable       (but see the full license for restrictions).-  +   The full text of these licenses is reproduced below.  All of the   licenses are BSD-style or compatible.-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -87,14 +87,14 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "Report on the Programming Language   Haskell 98", is distributed under the following license:-  +     Copyright (c) 2002 Simon Peyton Jones-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -102,15 +102,15 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Language.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "The Haskell 98 Foreign Function   Interface, An Addendum to the Haskell 98 Report" is distributed under   the following license:-  +     Copyright (c) 2002 Manuel M. T. Chakravarty-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -118,52 +118,52 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Foreign Function Interface.-  +   ------------------------------------------------------------------------------   + ================================================================================-Dependency: base-4.14.1.0+Dependency: base-4.14.3.0 ================================================================================    This library (libraries/base) is derived from code from several-  sources: -  +  sources:+     * Code from the GHC project which is largely (c) The University of       Glasgow, and distributable under a BSD-style license (see below),-  +     * Code from the Haskell 98 Report which is (c) Simon Peyton Jones       and freely redistributable (but see the full license for       restrictions).-  +     * Code from the Haskell Foreign Function Interface specification,       which is (c) Manuel M. T. Chakravarty and freely redistributable       (but see the full license for restrictions).-  +   The full text of these licenses is reproduced below.  All of the   licenses are BSD-style or compatible.-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -176,14 +176,14 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "Report on the Programming Language   Haskell 98", is distributed under the following license:-  +     Copyright (c) 2002 Simon Peyton Jones-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -191,15 +191,15 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Language.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "The Haskell 98 Foreign Function   Interface, An Addendum to the Haskell 98 Report" is distributed under   the following license:-  +     Copyright (c) 2002 Manuel M. T. Chakravarty-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -207,7 +207,7 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Foreign Function Interface.-  +   -----------------------------------------------------------------------------  ================================================================================@@ -215,24 +215,24 @@ ================================================================================    Copyright (c) Lennart Kolmodin-  +   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions   are met:-  +   1. Redistributions of source code must retain the above copyright      notice, this list of conditions and the following disclaimer.-  +   2. Redistributions in binary form must reproduce the above copyright      notice, this list of conditions and the following disclaimer in the      documentation and/or other materials provided with the distribution.-  +   3. Neither the name of the author nor the names of his contributors      may be used to endorse or promote products derived from this software      without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE@@ -253,9 +253,9 @@             (c) Duncan Coutts 2006-2015             (c) David Roundy 2003-2005             (c) Simon Meier 2010-2011-  +   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions   are met:@@ -267,7 +267,7 @@   3. Neither the name of the author nor the names of his contributors      may be used to endorse or promote products derived from this software      without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE@@ -286,23 +286,23 @@    Copyright Neil Mitchell 2009-2021.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are   met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of Neil Mitchell nor the names of other         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -316,28 +316,28 @@   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  ================================================================================-Dependency: containers-0.6.2.1+Dependency: containers-0.6.5.1 ================================================================================    The Glasgow Haskell Compiler License-  +   Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-  +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-  +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without   specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -358,28 +358,28 @@   This library (deepseq) is derived from code from the GHC project which   is largely (c) The University of Glasgow, and distributable under a   BSD-style license (see below).-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2001-2009, The University Court of the University of Glasgow. ++  Copyright 2001-2009, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -392,7 +392,7 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   -----------------------------------------------------------------------------  ================================================================================@@ -400,39 +400,39 @@ ================================================================================    This library (libraries/base) is derived from code from two-  sources: -  +  sources:+     * Code from the GHC project which is largely (c) The University of       Glasgow, and distributable under a BSD-style license (see below),-  +     * Code from the Haskell 98 Report which is (c) Simon Peyton Jones       and freely redistributable (but see the full license for       restrictions).-  +   The full text of these licenses is reproduced below.  Both of the   licenses are BSD-style or compatible.-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -445,14 +445,14 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "Report on the Programming Language   Haskell 98", is distributed under the following license:-  +     Copyright (c) 2002 Simon Peyton Jones-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -460,7 +460,7 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Language.-  +   -----------------------------------------------------------------------------  ================================================================================@@ -469,23 +469,23 @@    Copyright Neil Mitchell 2005-2018.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are   met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of Neil Mitchell nor the names of other         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -503,39 +503,39 @@ ================================================================================    This library (libraries/ghc-prim) is derived from code from several-  sources: -  +  sources:+     * Code from the GHC project which is largely (c) The University of       Glasgow, and distributable under a BSD-style license (see below),-  +     * Code from the Haskell 98 Report which is (c) Simon Peyton Jones       and freely redistributable (but see the full license for       restrictions).-  +   The full text of these licenses is reproduced below.  All of the   licenses are BSD-style or compatible.-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -548,14 +548,14 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "Report on the Programming Language   Haskell 98", is distributed under the following license:-  +     Copyright (c) 2002 Simon Peyton Jones-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -563,29 +563,29 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Language.-   + ================================================================================-Dependency: githash-0.1.6.1+Dependency: githash-0.1.6.2 ================================================================================    Copyright (c) 2018, Michael Snoyman, 2015, Adam C. Foltzer   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   * Redistributions of source code must retain the above copyright notice, this     list of conditions and the following disclaimer.-  +   * Redistributions in binary form must reproduce the above copyright notice,     this list of conditions and the following disclaimer in the documentation     and/or other materials provided with the distribution.-  +   * Neither the name of githash nor the names of its     contributors may be used to endorse or promote products derived from     this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE@@ -603,23 +603,23 @@    The Happy License   ------------------  +   Copyright 2001, Simon Marlow and Andy Gill.  All rights reserved.-  +   Extensions to implement Tomita's Generalized LR parsing:     Copyright 2004, University of Durham, Paul Callaghan and Ben Medlock.     All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR@@ -637,24 +637,24 @@ ================================================================================    Copyright Milan Straka 2010-  +   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of Milan Straka nor the names of other         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -672,24 +672,24 @@ ================================================================================    Copyright (c) 2014, Herbert Valerio Riedel-  +   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of Herbert Valerio Riedel nor the names of other         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -707,24 +707,24 @@ ================================================================================    The Glasgow Haskell Compiler License-  +   Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-  +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-  +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without   specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -745,28 +745,28 @@   This library (libraries/pretty) is derived from code from   the GHC project which is largely (c) The University of   Glasgow, and distributable under a BSD-style license (see below).-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -779,30 +779,30 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   -----------------------------------------------------------------------------  ================================================================================-Dependency: primitive-0.7.1.0+Dependency: primitive-0.7.3.0 ================================================================================    Copyright (c) 2008-2009, Roman Leshchinskiy   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -815,46 +815,46 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-   + ================================================================================-Dependency: process-1.6.9.0+Dependency: process-1.6.13.2 ================================================================================    This library (libraries/process) is derived from code from two-  sources: -  +  sources:+     * Code from the GHC project which is largely (c) The University of       Glasgow, and distributable under a BSD-style license (see below),-  +     * Code from the Haskell 98 Report which is (c) Simon Peyton Jones       and freely redistributable (but see the full license for       restrictions).-  +   The full text of these licenses is reproduced below.  Both of the   licenses are BSD-style or compatible.-  +   ------------------------------------------------------------------------------  +   The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -867,14 +867,14 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  +   ------------------------------------------------------------------------------  +   Code derived from the document "Report on the Programming Language   Haskell 98", is distributed under the following license:-  +     Copyright (c) 2002 Simon Peyton Jones-  +     The authors intend this Report to belong to the entire Haskell     community, and so we grant permission to copy and distribute it for     any purpose, provided that it is reproduced in its entirety,@@ -882,33 +882,33 @@     copied and distributed for any purpose, provided that the modified     version is clearly presented as such, and that it does not claim to     be a definition of the Haskell 98 Language.-  +   -----------------------------------------------------------------------------  ================================================================================ Dependency: template-haskell-2.16.0.0 ================================================================================ -  +   The Glasgow Haskell Compiler License-  +   Copyright 2002-2007, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-  +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-  +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without   specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -921,27 +921,27 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-   + ================================================================================ Dependency: text-1.2.4.1 ================================================================================    Copyright (c) 2008-2009, Tom Harper   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions   are met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -955,28 +955,28 @@   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  ================================================================================-Dependency: th-compat-0.1.2+Dependency: th-compat-0.1.3 ================================================================================    Copyright (c) 2020, Ryan Scott-  +   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +       * Redistributions of source code must retain the above copyright         notice, this list of conditions and the following disclaimer.-  +       * Redistributions in binary form must reproduce the above         copyright notice, this list of conditions and the following         disclaimer in the documentation and/or other materials provided         with the distribution.-  +       * Neither the name of Ryan Scott nor the names of other         contributors may be used to endorse or promote products derived         from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR@@ -995,13 +995,13 @@    TimeLib is Copyright (c) Ashley Yakeley, 2004-2014. All rights reserved.   Certain sections are Copyright 2004, The University Court of the University of Glasgow. All rights reserved.-  +   Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.-  +   - Neither name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  ================================================================================@@ -1009,24 +1009,24 @@ ================================================================================    The Glasgow Haskell Compiler License-  +   Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-  +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-  +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without   specific prior written permission.-  +   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -1045,24 +1045,24 @@ ================================================================================    The Glasgow Haskell Compiler License-  -  Copyright 2004, The University Court of the University of Glasgow. ++  Copyright 2004, The University Court of the University of Glasgow.   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -1077,26 +1077,26 @@   DAMAGE.  ================================================================================-Dependency: vector-0.12.3.0+Dependency: vector-0.12.3.1 ================================================================================    Copyright (c) 2008-2012, Roman Leshchinskiy   All rights reserved.-  +   Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions are met:-  +   - Redistributions of source code must retain the above copyright notice,   this list of conditions and the following disclaimer.-   +   - Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution.-   +   - Neither name of the University nor the names of its contributors may be   used to endorse or promote products derived from this software without-  specific prior written permission. -  +  specific prior written permission.+   THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF   GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND@@ -1109,5 +1109,5 @@   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   DAMAGE.-  + 
README.md view
@@ -94,8 +94,8 @@      --skip-preprocessor    Disable preprocessor Conversion:      --pass-through         Dump input without converting-  -E --exclude=CONV         Exclude a particular conversion (always, assert,-                            interface, or logic)+  -E --exclude=CONV         Exclude a particular conversion (Always, Assert,+                            Interface, Logic, or UnbasedUnsized)   -v --verbose              Retain certain conversion artifacts   -w --write=MODE/FILE      How to write output; default is 'stdout'; use                             'adjacent' to create a .v file next to each input;
src/Convert.hs view
@@ -17,9 +17,12 @@ import qualified Convert.BlockDecl import qualified Convert.Cast import qualified Convert.DimensionQuery+import qualified Convert.DoWhile import qualified Convert.DuplicateGenvar import qualified Convert.EmptyArgs import qualified Convert.Enum+import qualified Convert.EventEdge+import qualified Convert.ExprAsgn import qualified Convert.ForAsgn import qualified Convert.Foreach import qualified Convert.FuncRet@@ -64,6 +67,7 @@     [ Convert.NamedBlock.convert     , Convert.DuplicateGenvar.convert     , Convert.AsgnOp.convert+    , Convert.EmptyArgs.convert     , Convert.FuncRet.convert     , Convert.TFBlock.convert     ]@@ -76,7 +80,7 @@     , Convert.Inside.convert     , Convert.IntTypes.convert     , Convert.MultiplePacked.convert-    , Convert.UnbasedUnsized.convert+    , selectExclude Job.UnbasedUnsized Convert.UnbasedUnsized.convert     , Convert.Cast.convert     , Convert.ParamType.convert     , Convert.HierConst.convert@@ -99,10 +103,12 @@ initialPhases selectExclude =     [ Convert.ForAsgn.convert     , Convert.Jump.convert+    , Convert.ExprAsgn.convert     , Convert.KWArgs.convert     , Convert.Unique.convert+    , Convert.EventEdge.convert     , Convert.LogOp.convert-    , Convert.EmptyArgs.convert+    , Convert.DoWhile.convert     , Convert.Foreach.convert     , Convert.FuncRoutine.convert     , selectExclude Job.Assert Convert.Assertion.convert
src/Convert/AlwaysKW.hs view
@@ -3,24 +3,224 @@  -  - Conversion for `always_latch`, `always_comb`, and `always_ff`  -- - `always_latch` -> `always @*`- - `always_comb` -> `always @*`- - `always_ff` -> `always`+ - `always_comb` and `always_latch` become `always @*`, or produce an explicit+ - sensitivity list if they need to pick up sensitivities from the functions+ - they call. `always_ff` simply becomes `always`.+ -+ - TODO: `always_comb` blocks do not run at time zero  -}  module Convert.AlwaysKW (convert) where +import Control.Monad.State.Strict+import Control.Monad.Writer.Strict+import Data.Maybe (fromMaybe, mapMaybe)++import Convert.Scoper import Convert.Traverse import Language.SystemVerilog.AST  convert :: [AST] -> [AST]-convert = map $ traverseDescriptions $ traverseModuleItems replaceAlwaysKW+convert = map $ traverseDescriptions traverseDescription -replaceAlwaysKW :: ModuleItem -> ModuleItem-replaceAlwaysKW (AlwaysC AlwaysLatch stmt) =-    AlwaysC Always $ Timing (Event SenseStar) stmt-replaceAlwaysKW (AlwaysC AlwaysComb stmt) =-    AlwaysC Always $ Timing (Event SenseStar) stmt-replaceAlwaysKW (AlwaysC AlwaysFF stmt) =-    AlwaysC Always stmt-replaceAlwaysKW other = other+traverseDescription :: Description -> Description+traverseDescription description@Part{} =+    evalState (evalScoperT $ scopePart op description) mempty+    where op = traverseModuleItem >=> scoper+traverseDescription description = description++type SC = ScoperT Kind (State (Any, [Expr]))++type PortDir = (Identifier, Direction)++data Kind+    = Const Expr+    | Var+    | Proc [Expr] [PortDir]+    deriving Eq++scoper :: ModuleItem -> SC ModuleItem+scoper = scopeModuleItem traverseDecl return traverseGenItem traverseStmt++-- track declarations and visit expressions they contain+traverseDecl :: Decl -> SC Decl+traverseDecl decl = do+    case decl of+        Param    s _ x e   -> do+            -- handle references to local constants+            e' <- if s == Localparam+                    then scopeExpr e+                    else return Nil+            insertElem x $ Const e'+        ParamType  _ x _   -> insertElem x $ Const Nil+        Variable _ _ x _ _ -> do+            -- don't let the second visit of a function or task overwrite the+            -- Proc entry that was just generated+            details <- lookupLocalIdentM x+            case details of+                Just (_, _, Proc{}) -> return ()+                _ -> insertElem x Var+        Net  _ _ _ _ x _ _ -> insertElem x Var+        CommentDecl{} -> return ()+    traverseDeclExprsM traverseExpr decl++-- track expressions and subroutines in a statement+traverseStmt :: Stmt -> SC Stmt+traverseStmt (Subroutine expr args) =+    traverseCall Subroutine expr args+traverseStmt stmt = traverseStmtExprsM traverseExpr stmt++-- visit tasks, functions, and always blocks in generate scopes+traverseGenItem :: GenItem -> SC GenItem+traverseGenItem (GenModuleItem item) =+    traverseModuleItem item >>= return . GenModuleItem+traverseGenItem other = return other++-- identify variables referenced within an expression+traverseExpr :: Expr -> SC Expr+traverseExpr (Call expr args) =+    traverseCall Call expr args+traverseExpr expr = do+    prefix <- embedScopes longestStaticPrefix expr+    case prefix of+        Just expr' -> push (Any False, [expr']) >> return expr+        _ -> traverseSinglyNestedExprsM traverseExpr expr++-- turn a reference to a variable into a canonicalized longest static prefix, if+-- possible, per IEEE 1800-2017 Section 11.5.3+longestStaticPrefix :: Scopes Kind -> Expr -> Maybe Expr+longestStaticPrefix scopes expr@Ident{} =+    asVar scopes expr+longestStaticPrefix scopes (Range expr mode (l, r)) = do+    expr' <- longestStaticPrefix scopes expr+    l' <- asConst scopes l+    r' <- asConst scopes r+    Just $ Range expr' mode (l', r')+longestStaticPrefix scopes (Bit expr idx) = do+    expr' <- longestStaticPrefix scopes expr+    idx' <- asConst scopes idx+    Just $ Bit expr' idx'+longestStaticPrefix scopes orig@(Dot expr field) =+    case asVar scopes orig of+        Just orig' -> Just orig'+        _ -> do+            expr' <- longestStaticPrefix scopes expr+            Just $ Dot expr' field+longestStaticPrefix _ _ =+    Nothing++-- lookup an expression as an outwardly-visible variable+asVar :: Scopes Kind -> Expr -> Maybe Expr+asVar scopes expr = do+    (accesses, _, Var) <- lookupElem scopes expr+    if visible accesses+        then Just $ accessesToExpr accesses+        else Nothing++visible :: [Access] -> Bool+visible = not . elem (Access "" Nil)++-- lookup an expression as a hoist-able constant+asConst :: Scopes Kind -> Expr -> Maybe Expr+asConst scopes expr =+    case runWriter $ asConstRaw scopes expr of+        (expr', Any False) -> Just expr'+        _ -> Nothing++asConstRaw :: Scopes Kind -> Expr -> Writer Any Expr+asConstRaw scopes expr =+    case lookupElem scopes expr of+        Just (_, _, Const Nil) -> recurse+        Just (_, _, Const expr') -> asConstRaw scopes expr'+        Just{} -> tell (Any True) >> return Nil+        Nothing -> recurse+    where+        recurse = traverseSinglyNestedExprsM (asConstRaw scopes) expr++-- special handling for subroutine invocations and function calls+traverseCall :: (Expr -> Args -> a) -> Expr -> Args -> SC a+traverseCall constructor expr args = do+    details <- lookupElemM expr+    expr' <- traverseExpr expr+    args' <- case details of+        Just (_, _, Proc exprs ps) -> do+            when (not $ null exprs) $+                push (Any True, exprs)+            traverseArgs ps args+        _ -> traverseArgs [] args+    return $ constructor expr' args'++-- treats output ports as assignment-like contexts+traverseArgs :: [PortDir] -> Args -> SC Args+traverseArgs ps (Args pnArgs kwArgs) = do+    pnArgs' <- zipWithM usingPN [0..] pnArgs+    kwArgs' <- mapM usingKW kwArgs+    return (Args pnArgs' kwArgs')+    where++        usingPN :: Int -> Expr -> SC Expr+        usingPN key val = do+            if dir == Output+                then return val+                else traverseExpr val+            where dir = if key < length ps+                            then snd $ ps !! key+                            else Input++        usingKW :: (Identifier, Expr) -> SC (Identifier, Expr)+        usingKW (key, val) = do+            val' <- if dir == Output+                        then return val+                        else traverseExpr val+            return (key, val')+            where dir = fromMaybe Input $ lookup key ps++-- append to the non-local expression state+push :: (Any, [Expr]) -> SC ()+push x = lift $ modify' (x <>)++-- custom traversal which converts SystemVerilog `always` keywords and tracks+-- information about task and functions+traverseModuleItem :: ModuleItem -> SC ModuleItem+traverseModuleItem (AlwaysC AlwaysLatch stmt) = do+    e <- fmap toEvent $ findNonLocals $ Initial stmt+    return $ AlwaysC Always $ Timing (Event e) stmt+traverseModuleItem (AlwaysC AlwaysComb stmt) = do+    e <- fmap toEvent $ findNonLocals $ Initial stmt+    return $ AlwaysC Always $ Timing (Event e) stmt+traverseModuleItem (AlwaysC AlwaysFF stmt) =+    return $ AlwaysC Always stmt+traverseModuleItem item@(MIPackageItem (Function _ _ x decls _)) = do+    (_, s) <- findNonLocals item+    insertElem x $ Proc s (ports decls)+    return item+traverseModuleItem item@(MIPackageItem (Task _ x decls _)) = do+    insertElem x $ Proc [] (ports decls)+    return item+traverseModuleItem other = return other++toEvent :: (Bool, [Expr]) -> Event+toEvent (False, _) = EventStar+toEvent (True, exprs) =+    EventExpr $ foldl1 EventExprOr $ map (EventExprEdge NoEdge) exprs++-- turn a list of port declarations into a port direction map+ports :: [Decl] -> [PortDir]+ports = filter ((/= Local) . snd) . map port++port :: Decl -> PortDir+port (Variable d _ x _ _) = (x, d)+port (Net  d _ _ _ x _ _) = (x, d)+port _ = ("", Local)++-- get a list of non-local variables referenced within a module item, and+-- whether or not this module item references any functions which themselves+-- reference non-local variables+findNonLocals :: ModuleItem -> SC (Bool, [Expr])+findNonLocals item = do+    scopes <- get+    lift $ put mempty+    _ <- scoper item+    (anys, exprs) <- lift get+    let nonLocals = mapMaybe (longestStaticPrefix scopes) exprs+    return (getAny anys, nonLocals)
src/Convert/Cast.hs view
@@ -115,7 +115,8 @@     where         maybeInt = numberToInteger size         Just int = maybeInt-        illegal s = error $ "size cast width " ++ show size ++ " is not " ++ s+        illegal = scopedErrorM . msg+        msg s = "size cast width " ++ show size ++ " is not " ++ s convertCastM (Number size) (Number value) signed =     return $ Number $         numberCast signed (fromIntegral size') value
+ src/Convert/DoWhile.hs view
@@ -0,0 +1,31 @@+{- sv2v+ - Author: Zachary Snow <zach@zachjs.com>+ -+ - Conversion for `do` `while` loops.+ -+ - These are converted into while loops with an extra condition which is+ - initially true and immediately set to false in the body. This strategy is+ - preferrable to simply duplicating the loop body as it could contain jumps.+ -}++module Convert.DoWhile (convert) where++import Convert.Traverse+import Language.SystemVerilog.AST++convert :: [AST] -> [AST]+convert =+    map $ traverseDescriptions $ traverseModuleItems $+    traverseStmts $ traverseNestedStmts convertStmt++convertStmt :: Stmt -> Stmt+convertStmt (DoWhile cond body) =+    Block Seq "" [decl] [While cond' body']+    where+        ident = "sv2v_do_while"+        typ = IntegerVector TLogic Unspecified []+        decl = Variable Local typ ident [] (RawNum 1)+        cond' = BinOp LogOr (Ident ident) cond+        asgn = Asgn AsgnOpEq Nothing (LHSIdent ident) (RawNum 0)+        body' = Block Seq "" [] [asgn, body]+convertStmt other = other
src/Convert/EmptyArgs.hs view
@@ -8,48 +8,77 @@  module Convert.EmptyArgs (convert) where -import Control.Monad.Writer.Strict-import qualified Data.Set as Set-+import Convert.Scoper import Convert.Traverse import Language.SystemVerilog.AST -type Idents = Set.Set Identifier+type SC = Scoper ()  convert :: [AST] -> [AST]-convert = map $ traverseDescriptions convertDescription+convert = map $ traverseDescriptions traverseDescription -convertDescription :: Description -> Description-convertDescription description@Part{} =-    traverseModuleItems-        (traverseExprs $ traverseNestedExprs $ convertExpr functions)-        description'-    where-        (description', functions) =-            runWriter $ traverseModuleItemsM traverseFunctionsM description-convertDescription other = other+traverseDescription :: Description -> Description+traverseDescription =+    evalScoper . scopePart scoper .+    traverseModuleItems addDummyArg+    where scoper = scopeModuleItem+            traverseDecl traverseModuleItem traverseGenItem traverseStmt -traverseFunctionsM :: ModuleItem -> Writer Idents ModuleItem-traverseFunctionsM (MIPackageItem (Function ml t f decls stmts)) = do-    decls' <--        if any isInput decls-            then return decls-            else do-                tell $ Set.singleton f-                return $ dummyDecl : decls-    return $ MIPackageItem $ Function ml t f decls' stmts-    where-        dummyType = IntegerVector TReg Unspecified []-        dummyDecl = Variable Input dummyType "_sv2v_unused" [] Nil-        isInput :: Decl -> Bool-        isInput (Variable Input _ _ _ _) = True-        isInput _ = False-traverseFunctionsM other = return other+-- add a dummy argument to functions with no input ports+addDummyArg :: ModuleItem -> ModuleItem+addDummyArg (MIPackageItem (Function l t f decls stmts))+    | all (not . isInput) decls =+        MIPackageItem $ Function l t f (dummyDecl : decls) stmts+addDummyArg other = other -convertExpr :: Idents -> Expr -> Expr-convertExpr functions (Call (Ident func) (Args [] [])) =-    Call (Ident func) (Args args [])-    where args = if Set.member func functions-            then [RawNum 0]-            else []-convertExpr _ other = other+isInput :: Decl -> Bool+isInput (Variable Input _ _ _ _) = True+isInput _ = False++-- write down all declarations so we can look up the dummy arg+traverseDecl :: Decl -> SC Decl+traverseDecl decl = do+    decl' <- case decl of+        Param    _ _ x _   -> insertElem x () >> return decl+        ParamType  _ x _   -> insertElem x () >> return decl+        Variable d t x a e -> do+            insertElem x ()+            -- new dummy args have a special name for idempotence+            return $ if x == dummyIdent+                then Variable d t dummyIdentFinal a e+                else decl+        Net  _ _ _ _ x _ _ -> insertElem x () >> return decl+        CommentDecl{} -> return decl+    traverseDeclExprsM traverseExpr decl'++traverseModuleItem :: ModuleItem -> SC ModuleItem+traverseModuleItem = traverseExprsM traverseExpr++traverseGenItem :: GenItem -> SC GenItem+traverseGenItem = traverseGenItemExprsM traverseExpr++traverseStmt :: Stmt -> SC Stmt+traverseStmt = traverseStmtExprsM traverseExpr++-- pass a dummy value to functions which had no inputs+traverseExpr :: Expr -> SC Expr+traverseExpr (Call func (Args args [])) = do+    details <- lookupElemM $ Dot func dummyIdent+    let args' = if details /= Nothing+                    then RawNum 0 : args+                    else args+    return $ Call func (Args args' [])+traverseExpr expr =+    traverseSinglyNestedExprsM traverseExpr expr++dummyIdent :: Identifier+dummyIdent = '?' : dummyIdentFinal++dummyIdentFinal :: Identifier+dummyIdentFinal = "_sv2v_unused"++dummyType :: Type+dummyType = IntegerVector TReg Unspecified []++dummyDecl :: Decl+dummyDecl = Variable Input dummyType dummyIdent [] Nil
src/Convert/Enum.hs view
@@ -94,7 +94,7 @@     -- check for obviously duplicate values     if noDuplicates         then zipWithM_ insertEnumItem keys vals-        else error $ "enum conversion has duplicate vals: "+        else scopedErrorM $ "enum conversion has duplicate vals: "                 ++ show (zip keys vals)     where         insertEnumItem :: Identifier -> Expr -> SC ()
+ src/Convert/EventEdge.hs view
@@ -0,0 +1,41 @@+{- sv2v+ - Author: Zachary Snow <zach@zachjs.com>+ -+ - Conversion for `edge` sensitivity+ -+ - IEEE 1800-2017 Section 9.4.2 defines `edge` as either `posedge` or `negedge`.+ - This does not convert senses in assertions as they are likely either removed+ - or fully supported downstream.+ -}++module Convert.EventEdge (convert) where++import Convert.Traverse+import Language.SystemVerilog.AST++convert :: [AST] -> [AST]+convert =+    map $ traverseDescriptions $ traverseModuleItems $ traverseStmts $+        traverseNestedStmts convertStmt++convertStmt :: Stmt -> Stmt+convertStmt (Asgn op (Just timing) lhs expr) =+    Asgn op (Just $ convertTiming timing) lhs expr+convertStmt (Timing timing stmt) =+    Timing (convertTiming timing) stmt+convertStmt other = other++convertTiming :: Timing -> Timing+convertTiming (Event event) = Event $ convertEvent event+convertTiming other = other++convertEvent :: Event -> Event+convertEvent EventStar = EventStar+convertEvent (EventExpr e) = EventExpr $ convertEventExpr e++convertEventExpr :: EventExpr -> EventExpr+convertEventExpr (EventExprOr v1 v2) =+    EventExprOr (convertEventExpr v1) (convertEventExpr v2)+convertEventExpr (EventExprEdge Edge lhs) =+    EventExprOr (EventExprEdge Posedge lhs) (EventExprEdge Negedge lhs)+convertEventExpr other@EventExprEdge{} = other
+ src/Convert/ExprAsgn.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE PatternSynonyms #-}+{- sv2v+ - Author: Zachary Snow <zach@zachjs.com>+ -+ - Conversion for assignments within expressions+ -+ - IEEE 1800-2017 Section 11.3.6 states that assignments within expressions can+ - only appear in procedural statements, though some tools support them in other+ - contexts. We do not currently raise an error for assignments within+ - expressions in unsupported contexts.+ -+ - Assignment expressions are replaced with the LHS, with the LHS being updated+ - in a preceding statement. For post-increment operations, a pre-increment is+ - performed and then the increment is reversed in the expression.+ -+ - This conversion occurs after the elaboration of `do` `while` loops and+ - `foreach` loops, but before the elaboration of jumps and extra `for` loop+ - initializations.+ -}++module Convert.ExprAsgn (convert) where++import Control.Monad.Writer.Strict+import Data.Bitraversable (bimapM)++import Convert.Traverse+import Language.SystemVerilog.AST++convert :: [AST] -> [AST]+convert = map $ traverseDescriptions $ traverseModuleItems $+    traverseStmts convertStmt++convertStmt :: Stmt -> Stmt++-- assignment expressions in a loop guard+convertStmt (While cond stmt) =+    if null add+        then While cond stmt'+        else block $ add ++ [While cond' $ injectLoopIter add stmt']+    where+        (cond', add) = runWriter $ convertExpr cond+        stmt' = convertStmt stmt++-- assignment expressions can appear in any part of the for loop+convertStmt (For inits cond incrs stmt) =+    if null initsAdd && null condAdd && null incrsAdd+        then For inits cond incrs stmt'+        else For initsCombined cond' incrs' $+            injectLoopIter (incrsAdd ++ condAdd) stmt'+    where+        (inits', initsAdd) = runWriter $ mapM convertInit inits+        (cond', condAdd) = runWriter $ convertExpr cond+        (incrs', incrsAdd) = runWriter $ mapM convertIncr incrs+        stmt' = convertStmt stmt+        initsCombined = map toInit initsAdd ++ inits' ++ map toInit condAdd++-- assignment expressions in other statements are added in front+convertStmt stmt =+    traverseSinglyNestedStmts convertStmt $+        if null add+            then stmt+            else block $ add ++ [stmt']+    where (stmt', add) = runWriter $ traverseStmtExprsM convertExpr stmt++-- helper for creating simple blocks+block :: [Stmt] -> Stmt+block = Block Seq "" []++-- add statements before the loop guard is checked+injectLoopIter :: [Stmt] -> Stmt -> Stmt+injectLoopIter add stmt = block $ beforeContinue add stmt : add++-- add statements before every `continue` in the loop+beforeContinue :: [Stmt] -> Stmt -> Stmt+beforeContinue _ stmt@While{} = stmt+beforeContinue _ stmt@For{} = stmt+beforeContinue add Continue =+    block $ add ++ [Continue]+beforeContinue add stmt =+    traverseSinglyNestedStmts (beforeContinue add) stmt++-- reversible pattern to unwrap in for loops+pattern AsgnStmt :: LHS -> Expr -> Stmt+pattern AsgnStmt lhs expr = Asgn AsgnOpEq Nothing lhs expr++toInit :: Stmt -> (LHS, Expr)+toInit stmt = (lhs, expr)+    where AsgnStmt lhs expr = stmt++-- functions which convert and collect assignment expressions+type Converter t = t -> Writer [Stmt] t++convertExpr :: Converter Expr+convertExpr (ExprAsgn l r) = do+    l' <- convertExpr l+    r' <- convertExpr r+    let Just lhs = exprToLHS l' -- checked by parser+    tell [AsgnStmt lhs r']+    return l'+convertExpr expr =+    traverseSinglyNestedExprsM convertExpr expr++convertLHS :: Converter LHS+convertLHS = traverseNestedLHSsM $ traverseLHSExprsM convertExpr++convertInit :: Converter (LHS, Expr)+convertInit = bimapM convertLHS convertExpr++convertIncr :: Converter (LHS, AsgnOp, Expr)+convertIncr (lhs, op, expr) = do+    lhs' <- convertLHS lhs+    expr' <- convertExpr expr+    return (lhs', op, expr')
src/Convert/ExprUtils.hs view
@@ -76,14 +76,10 @@  simplifyBinOp :: BinOp -> Expr -> Expr -> Expr -simplifyBinOp Add (Dec 0) e = e-simplifyBinOp Add e (Dec 0) = e simplifyBinOp Sub e (Dec 0) = e simplifyBinOp Sub (Dec 0) e = UniOp UniSub e simplifyBinOp Mul (Dec 0) _ = toDec 0-simplifyBinOp Mul (Dec 1) e = e simplifyBinOp Mul _ (Dec 0) = toDec 0-simplifyBinOp Mul e (Dec 1) = e simplifyBinOp Mod _ (Dec 1) = toDec 0  simplifyBinOp Add e1 (UniOp UniSub e2) = BinOp Sub e1 e2
src/Convert/FuncRet.hs view
@@ -1,7 +1,8 @@ {- sv2v  - Author: Zachary Snow <zach@zachjs.com>  -- - Conversion which makes function `logic` and `reg` return types implicit+ - Conversion which makes function `logic` and `reg` return types implicit and+ - converts `void` functions to tasks  -  - Verilog-2005 restricts function return types to `integer`, `real`,  - `realtime`, `time`, and implicit signed/dimensioned types.@@ -16,6 +17,8 @@ convert = map $ traverseDescriptions $ traverseModuleItems convertFunction  convertFunction :: ModuleItem -> ModuleItem+convertFunction (MIPackageItem (Function ml Void f decls stmts)) =+    MIPackageItem $ Task ml f decls stmts convertFunction (MIPackageItem (Function ml t f decls stmts)) =     MIPackageItem $ Function ml t' f decls stmts     where
src/Convert/FuncRoutine.hs view
@@ -32,6 +32,7 @@ convertDescription other = other  collectFunctionsM :: ModuleItem -> Writer Idents ()+collectFunctionsM (MIPackageItem (Function _ Void _ _ _)) = return () collectFunctionsM (MIPackageItem (Function _ _ f _ _)) =     tell $ Set.singleton f collectFunctionsM _ = return ()
src/Convert/Interface.hs view
@@ -7,6 +7,7 @@  module Convert.Interface (convert) where +import Data.List (intercalate, (\\)) import Data.Maybe (isJust, isNothing, mapMaybe) import Control.Monad.Writer.Strict import qualified Data.Map.Strict as Map@@ -57,7 +58,7 @@ convertDescription _ (Part _ _ Interface _ name _ _) =     PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name convertDescription parts (Part attrs extern Module lifetime name ports items) =-    if null $ extractModportInstances $ PartInfo Module ports items then+    if null $ extractModportInstances name $ PartInfo Module ports items then         Part attrs extern Module lifetime name ports items'     else         PackageItem $ Decl $ CommentDecl $@@ -99,12 +100,12 @@             else do                 -- inline instantiation of a module                 let modportBindings = getModportBindings modports-                if length modportInstances /= length modportBindings-                    then-                        error $ "instance " ++ instanceName ++ " of " ++ part-                            ++ " has interface ports "-                            ++ showKeys modportInstances ++ ", but only "-                            ++ showKeys modportBindings ++ " are connected"+                let unconnected = map fst modportInstances \\+                                    map fst modportBindings+                if not (null unconnected)+                    then scopedErrorM $ "instance " ++ instanceName ++ " of "+                            ++ part ++ " has unconnected interface ports: "+                            ++ intercalate ", " unconnected                     else scoper $ Generate $ map GenModuleItem $                             inlineInstance modports rs modportBindings partItems                             part instanceName paramBindings portBindings@@ -115,12 +116,11 @@                 Just partInfo = maybePartInfo                 PartInfo partKind _ partItems = partInfo -                modportInstances = extractModportInstances partInfo+                modportInstances = extractModportInstances part partInfo                 getModportBindings modports = mapMaybe                     (inferModportBinding modports modportInstances) $                     map (second $ addImpliedSlice modports) portBindings                 second f = \(a, b) -> (a, f b)-                showKeys = show . map fst          traverseModuleItemM other = return other @@ -195,8 +195,8 @@                 -- given entire interface, but just bound to a modport                 foundModport $ Dot expr modportName             else if modportInstance /= Nothing then-                error $ "could not resolve modport binding " ++ show expr-                    ++ " for port " ++ portName ++ " of type "+                scopedError modports $ "could not resolve modport binding "+                    ++ show expr ++ " for port " ++ portName ++ " of type "                     ++ showModportType interfaceName modportName             else                 Nothing@@ -208,14 +208,15 @@                 (interfaceName, modportName) =                     case modportInstance of                         Just x -> x-                        Nothing -> error $ "can't deduce modport for interface "-                            ++ show expr ++ " bound to port " ++ portName+                        Nothing -> scopedError modports $+                            "can't deduce modport for interface " ++ show expr+                            ++ " bound to port " ++ portName                  foundModport modportE =                     if (null interfaceName || bInterfaceName == interfaceName)                         && (null modportName || bModportName == modportName)                         then Just (instanceE, qualifyModport modportE)-                        else error msg+                        else scopedError modports msg                     where                         bModportName =                             case modportE of@@ -246,8 +247,8 @@                         Nothing ->                             case lookupIntfElem modports (Dot e "") of                                 Just (accesses, _, _) -> init accesses-                                Nothing ->-                                    error $ "could not find modport " ++ show e+                                Nothing -> scopedError modports $+                                    "could not find modport " ++ show e          showModportType :: Identifier -> Identifier -> String         showModportType "" "" = "generic interface"@@ -271,23 +272,26 @@                         e' = replaceInExpr replacements e          -- association list of modport instances in the given module body-        extractModportInstances :: PartInfo -> ModportInstances-        extractModportInstances partInfo =-            execWriter $ mapM (collectDeclsM collectDecl) (pItems partInfo)+        extractModportInstances :: Identifier -> PartInfo -> ModportInstances+        extractModportInstances part partInfo =+            execWriter $ runScoperT $ scopeModuleItems collector part decls             where-                collectDecl :: Decl -> Writer ModportInstances ()-                collectDecl (Variable _ t x _ _) =+                collector = scopeModuleItem checkDecl return return return+                decls = filter isDecl $ pItems partInfo+                checkDecl :: Decl -> ScoperT () (Writer ModportInstances) Decl+                checkDecl decl@(Variable _ t x _ _) =                     if maybeInfo == Nothing then-                        return ()+                        return decl                     else if elem x (pPorts partInfo) then-                        tell [(x, info)]+                        tell [(x, info)] >> return decl                     else-                        error $ "Modport not in port list: " ++ show (t, x)+                        scopedErrorM $+                            "Modport not in port list: " ++ show t ++ " " ++ x                             ++ ". Is this an interface missing a port list?"                     where                         maybeInfo = extractModportInfo t                         Just info = maybeInfo-                collectDecl _ = return ()+                checkDecl decl = return decl          extractModportInfo :: Type -> Maybe (Identifier, Identifier)         extractModportInfo (InterfaceT "" "" _) = Just ("", "")@@ -309,6 +313,10 @@  convertDescription _ other = other +isDecl :: ModuleItem -> Bool+isDecl (MIPackageItem Decl{}) = True+isDecl _ = False+ -- produce the implicit modport decls for an interface bundle impliedModport :: [ModuleItem] -> [ModportDecl] impliedModport =@@ -338,8 +346,10 @@         items' = evalScoper $ scopeModuleItems scoper partName $             map (traverseNestedModuleItems rewriteItem) $             if null modportBindings-                then items ++ [typeModport, dimensionModport, bundleModport]-                else items+                then itemsChecked ++ infoModports+                else itemsChecked+        itemsChecked = checkBeforeInline global partName items checkErrMsg+        infoModports = [typeModport, dimensionModport, bundleModport]         scoper = scopeModuleItem             traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM @@ -422,8 +432,8 @@         -- LHSs are replaced using simple substitutions         traverseLHSM :: LHS -> Scoper () LHS         traverseLHSM =-            embedScopes tagLHS >=>-            embedScopes replaceLHS+            fmap replaceLHS .+            embedScopes tagLHS         tagLHS :: Scopes () -> LHS -> LHS         tagLHS scopes lhs             | lookupElem scopes lhs /= Nothing =@@ -438,25 +448,24 @@                 then LHSDot scopedInstanceLHS y                 else LHSDot (LHSIdent x) y         renamePartLHS lhs = traverseSinglyNestedLHSs renamePartLHS lhs-        replaceLHS :: Scopes () -> LHS -> LHS-        replaceLHS _ (LHSDot lhs "@") = lhs-        replaceLHS local (LHSDot (LHSBit lhs elt) field) =+        replaceLHS :: LHS -> LHS+        replaceLHS (LHSDot lhs "@") = lhs+        replaceLHS (LHSDot (LHSBit lhs elt) field) =             case lookup (LHSDot (LHSBit lhs Tag) field) lhsReplacements of                 Just resolved -> replaceLHSArrTag elt resolved-                Nothing -> LHSDot (replaceLHS local $ LHSBit lhs elt) field-        replaceLHS local lhs =+                Nothing -> LHSDot (replaceLHS $ LHSBit lhs elt) field+        replaceLHS lhs =             case lookup lhs lhsReplacements of                 Just lhs' -> lhs'-                Nothing -> checkExprResolution local (lhsToExpr lhs) $-                    traverseSinglyNestedLHSs (replaceLHS local) lhs+                Nothing -> traverseSinglyNestedLHSs replaceLHS lhs         replaceLHSArrTag :: Expr -> LHS -> LHS         replaceLHSArrTag =             traverseNestedLHSs . (traverseLHSExprs . replaceArrTag)         -- top-level expressions may be modports bound to other modports         traverseExprM :: Expr -> Scoper () Expr         traverseExprM =-            embedScopes tagExpr >=>-            embedScopes replaceExpr+            fmap replaceExpr .+            embedScopes tagExpr         tagExpr :: Scopes () -> Expr -> Expr         tagExpr scopes expr             | lookupElem scopes expr /= Nothing =@@ -471,38 +480,35 @@                 then Dot scopedInstanceExpr y                 else Dot (Ident x) y         renamePartExpr expr = visitExprsStep renamePartExpr expr-        replaceExpr :: Scopes () -> Expr -> Expr-        replaceExpr _ (Dot expr "@") = expr-        replaceExpr local (Ident x) =+        replaceExpr :: Expr -> Expr+        replaceExpr (Dot expr "@") = expr+        replaceExpr (Ident x) =             case lookup x modportBindings of                 Just (_, m) -> m-                Nothing -> checkExprResolution local (Ident x) (Ident x)-        replaceExpr local expr =-            replaceExpr' local expr-        replaceExpr' :: Scopes () -> Expr -> Expr-        replaceExpr' _ (Dot expr "@") = expr-        replaceExpr' local (Dot (Bit expr elt) field) =+                Nothing -> Ident x+        replaceExpr expr =+            replaceExpr' expr+        replaceExpr' :: Expr -> Expr+        replaceExpr' (Dot expr "@") = expr+        replaceExpr' (Dot (Bit expr elt) field) =             case lookup (Dot (Bit expr Tag) field) exprReplacements of-                Just resolved -> replaceArrTag (replaceExpr' local elt) resolved-                Nothing -> Dot (replaceExpr' local $ Bit expr elt) field-        replaceExpr' local (Bit expr elt) =+                Just resolved -> replaceArrTag (replaceExpr' elt) resolved+                Nothing -> Dot (replaceExpr' $ Bit expr elt) field+        replaceExpr' (Bit expr elt) =             case lookup (Bit expr Tag) exprReplacements of-                Just resolved -> replaceArrTag (replaceExpr' local elt) resolved-                Nothing -> Bit (replaceExpr' local expr) (replaceExpr' local elt)-        replaceExpr' local expr@(Dot Ident{} _) =+                Just resolved -> replaceArrTag (replaceExpr' elt) resolved+                Nothing -> Bit (replaceExpr' expr) (replaceExpr' elt)+        replaceExpr' expr@(Dot Ident{} _) =             case lookup expr exprReplacements of                 Just expr' -> expr'-                Nothing -> checkExprResolution local expr $-                    visitExprsStep (replaceExprAny local) expr-        replaceExpr' local (Ident x) =-            checkExprResolution local (Ident x) (Ident x)-        replaceExpr' local expr = replaceExprAny local expr-        replaceExprAny :: Scopes () -> Expr -> Expr-        replaceExprAny local expr =+                Nothing -> visitExprsStep replaceExprAny expr+        replaceExpr' (Ident x) = Ident x+        replaceExpr' expr = replaceExprAny expr+        replaceExprAny :: Expr -> Expr+        replaceExprAny expr =             case lookup expr exprReplacements of                 Just expr' -> expr'-                Nothing -> checkExprResolution local expr $-                    visitExprsStep (replaceExpr' local) expr+                Nothing -> visitExprsStep replaceExpr' expr         replaceArrTag :: Expr -> Expr -> Expr         replaceArrTag replacement Tag = replacement         replaceArrTag replacement expr =@@ -521,22 +527,11 @@             . traverseExprTypes (traverseNestedTypes typeMapper)             where typeMapper = traverseTypeExprs exprMapper -        checkExprResolution :: Scopes () -> Expr -> a -> a-        checkExprResolution local expr =-            if not (exprResolves local expr) && exprResolves global expr-                then-                    error $ "inlining instance \"" ++ instanceName ++ "\" of "-                        ++ inlineKind ++ " \"" ++ partName-                        ++ "\" would make expression \"" ++ show expr-                        ++ "\" used in \"" ++ instanceName-                        ++ "\" resolvable when it wasn't previously"-                else id--        exprResolves :: Scopes a -> Expr -> Bool-        exprResolves local (Ident x) =-            isJust (lookupElem local x) || isLoopVar local x-        exprResolves local expr =-            isJust (lookupElem local expr)+        checkErrMsg :: String -> String+        checkErrMsg exprStr = "inlining instance \"" ++ instanceName+            ++ "\" of " ++ inlineKind ++ " \"" ++ partName+            ++ "\" would make expression \"" ++ exprStr ++ "\" used in \""+            ++ instanceName ++ "\" resolvable when it wasn't previously"          -- unambiguous reference to the current instance         scopedInstanceRaw = accessesToExpr $ localAccesses global instanceName@@ -715,3 +710,74 @@ sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l sliceLo IndexedPlus (base, _) = base sliceLo IndexedMinus (base, len) = BinOp Add (BinOp Sub base len) (RawNum 1)++-- check for cases where an expression in an inlined part only resolves after+-- inlining, potentially hiding a design error+checkBeforeInline :: Scopes a -> Identifier -> [ModuleItem]+    -> (String -> String) -> [ModuleItem]+checkBeforeInline global partName items checkErrMsg =+    evalScoper $ scopeModuleItems scoper partName $ items+    where+        scoper = scopeModuleItem+            checkDecl checkModuleItem checkGenItem checkStmt++        checkDecl :: Decl -> Scoper () Decl+        checkDecl decl = do+            case decl of+                Variable  _ _ x _ _ -> insertElem x ()+                Net   _ _ _ _ x _ _ -> insertElem x ()+                Param     _ _ x _   -> insertElem x ()+                ParamType _   x _   -> insertElem x ()+                CommentDecl{} -> return ()+            traverseDeclExprsM checkExpr decl++        checkModuleItem :: ModuleItem -> Scoper () ModuleItem+        checkModuleItem item@(Instance _ _ x _ _) =+            insertElem x () >> traverseExprsM checkExpr item+        checkModuleItem item =+            traverseExprsM checkExpr item >>=+            traverseLHSsM  checkLHS++        checkGenItem :: GenItem -> Scoper () GenItem+        checkGenItem = traverseGenItemExprsM checkExpr++        checkStmt :: Stmt -> Scoper () Stmt+        checkStmt =+            traverseStmtExprsM checkExpr >=>+            traverseStmtLHSsM  checkLHS++        checkExpr :: Expr -> Scoper () Expr+        checkExpr = embedScopes checkExprResolutionId++        checkLHS :: LHS -> Scoper () LHS+        checkLHS = embedScopes checkLHSResolutionId++        checkLHSResolutionId :: Scopes () -> LHS -> LHS+        checkLHSResolutionId local lhs = checkExprResolution local expr lhs+            where expr = lhsToExpr lhs++        checkExprResolutionId :: Scopes () -> Expr -> Expr+        checkExprResolutionId local expr = checkExprResolution local expr expr++        -- error if the given expression resolves globally but not locally+        checkExprResolution :: Scopes () -> Expr -> a -> a+        checkExprResolution local expr =+            if exprResolves global expr && not (anyPrefixResolves local expr)+                then scopedError local $ checkErrMsg $ show expr+                else id++        -- check if hierarchical prefix of an expr exists in the given scope+        anyPrefixResolves :: Scopes () -> Expr -> Bool+        anyPrefixResolves local expr =+            exprResolves local expr ||+            case expr of+                Dot inner _ -> anyPrefixResolves local inner+                Bit inner _ -> anyPrefixResolves local inner+                _ -> False++        -- check if expr exists in the given scope+        exprResolves :: Scopes a -> Expr -> Bool+        exprResolves local (Ident x) =+            isJust (lookupElem local x) || isLoopVar local x+        exprResolves local expr =+            isJust (lookupElem local expr)
src/Convert/Jump.hs view
@@ -121,12 +121,25 @@ pattern SimpleLoopInits :: Identifier -> [(LHS, Expr)] pattern SimpleLoopInits var <- [(LHSIdent var, _)] -pattern SimpleLoopGuard :: Identifier -> Expr-pattern SimpleLoopGuard var <- BinOp _ (Ident var) _- pattern SimpleLoopIncrs :: Identifier -> [(LHS, AsgnOp, Expr)] pattern SimpleLoopIncrs var <- [(LHSIdent var, _, _)] +-- check if an expression contains a reference to the given identifier+usesIdent :: Identifier -> Expr -> Writer Any ()+usesIdent x (Ident y)+    | x == y = tell $ Any True+    | otherwise = return ()+usesIdent x expr =+    collectSinglyNestedExprsM (usesIdent x) expr++-- identifies loops which could likely be statically unrolled, and so may+-- benefit from avoiding complicating the loop guard with jump state, assuming+-- the guard and incrementation do not have side effects+simpleLoopVar :: [(LHS, Expr)] -> Expr -> [(LHS, AsgnOp, Expr)] -> Identifier+simpleLoopVar (SimpleLoopInits var1) comp (SimpleLoopIncrs var3)+    | var1 == var3, getAny $ execWriter $ usesIdent var1 comp = var1+simpleLoopVar _ _ _ = ""+ -- rewrites the given statement, and returns the type of any unfinished jump convertStmt :: Stmt -> State Info Stmt @@ -140,20 +153,12 @@  convertStmt (Block Seq ""     decls@[CommentDecl{}, Variable Local _ var0 [] Nil]-    [ comment@CommentStmt{}-    , For-        inits@(SimpleLoopInits var1)-        comp@(SimpleLoopGuard var2)-        incr@(SimpleLoopIncrs var3)-        stmt-    ]) =-    convertLoop localInfo loop comp incr stmt+    [comment@CommentStmt{}, For inits comp incr stmt])+    | var1@(_ : _) <- simpleLoopVar inits comp incr, var0 == var1 =+    convertLoop (Just var1) loop comp incr stmt         >>= return . Block Seq "" decls . (comment :) . pure     where         loop c i s = For inits c i s-        localInfo = if var0 /= var1 || var1 /= var2 || var2 /= var3-                        then Nothing-                        else Just ""  convertStmt (Block Seq x decls stmts) =     step stmts >>= return . Block Seq x decls@@ -192,25 +197,17 @@     modify $ \s -> s { sHasJump = hasJump }     return $ Case unique kw expr cases' -convertStmt (For-    inits@(SimpleLoopInits var1)-    comp@(SimpleLoopGuard var2)-    incr@(SimpleLoopIncrs var3) stmt) =-    convertLoop localInfo loop comp incr stmt+convertStmt (For inits comp incr stmt)+    | var@(_ : _) <- simpleLoopVar inits comp incr =+    convertLoop (Just var) loop comp incr stmt     where         loop c i s = For inits c i s-        localInfo = if var1 /= var2 || var2 /= var3-                        then Nothing-                        else Just var1 convertStmt (For inits comp incr stmt) =     convertLoop Nothing loop comp incr stmt     where loop c i s = For inits c i s convertStmt (While comp stmt) =     convertLoop Nothing loop comp [] stmt     where loop c _ s = While c s-convertStmt (DoWhile comp stmt) =-    convertLoop Nothing loop comp [] stmt-    where loop c _ s = DoWhile c s  convertStmt (Continue) = do     loopDepth <- gets sLoopDepth
src/Convert/Logic.hs view
@@ -94,7 +94,7 @@                         Just (_, _, t) -> tell [isRegType t]                         _ -> tell [False] -        always_comb = AlwaysC Always . Timing (Event SenseStar)+        always_comb = AlwaysC Always . Timing (Event EventStar)          fixModuleItem :: ModuleItem -> ModuleItem         -- rewrite bad continuous assignments to use procedural assignments@@ -141,12 +141,7 @@                         items =                             [ MIPackageItem $ Decl decl                             , always_comb $ Asgn AsgnOpEq Nothing lhs tmpExpr]-                        lhs = case exprToLHS expr of-                            Just l -> l-                            Nothing ->-                                error $ "bad non-lhs, non-net expr "-                                    ++ show expr ++ " connected to output port "-                                    ++ portName ++ " of " ++ instanceName+                        Just lhs = exprToLHS expr                 maybeModulePorts = Map.lookup moduleName ports         fixModuleItem other = other @@ -188,9 +183,9 @@ rewriteDeclM _ decl = return decl  traverseStmtM :: Stmt -> ST Stmt-traverseStmtM stmt@Timing{} =+traverseStmtM (Asgn op Just{} lhs expr) =     -- ignore the timing LHSs-    return stmt+    traverseStmtM $ Asgn op Nothing lhs expr traverseStmtM stmt@(Subroutine (Ident f) (Args (_ : Ident x : _) [])) =     when (f == "$readmemh" || f == "$readmemb") (collectLHSM $ LHSIdent x)         >> return stmt
src/Convert/MultiplePacked.hs view
@@ -5,7 +5,7 @@  - Conversion for flattening variables with multiple packed dimensions  -  - This removes one packed dimension per identifier per pass. This works fine- - because all conversions are repeatedly applied.+ - because this conversion is repeatedly applied.  -  - We previously had a very complex conversion which used `generate` to make  - flattened and unflattened versions of the array as necessary. This has now@@ -28,6 +28,7 @@  import Convert.ExprUtils import Control.Monad ((>=>))+import Data.Bifunctor (first) import Data.Tuple (swap) import Data.Maybe (isJust) import qualified Data.Map.Strict as Map@@ -59,31 +60,35 @@     traverseDeclExprsM traverseExprM $ Param s t' ident e traverseDeclM other = traverseDeclExprsM traverseExprM other +-- write down the given declaration and then flatten it traverseTypeM :: Type -> [Range] -> Identifier -> Scoper TypeInfo Type traverseTypeM t a ident = do     tScoped <- scopeType t     insertElem ident (tScoped, a)-    t' <- case t of-        Struct pk fields rs -> do-            fields' <- flattenFields fields-            return $ Struct pk fields' rs-        Union  pk fields rs -> do-            fields' <- flattenFields fields-            return $ Union  pk fields' rs-        _ -> return t-    let (tf, rs) = typeRanges t'-    if length rs <= 1-        then return t'-        else do-            let r1 : r2 : rest = rs-            let rs' = (combineRanges r1 r2) : rest-            return $ tf rs'+    return $ flattenType t++-- flatten the innermost dimension of the given type, and any types it contains+flattenType :: Type -> Type+flattenType t =+    tf $ if length ranges <= 1+        then ranges+        else rangesFlat     where-        flattenFields fields = do-            let (fieldTypes, fieldNames) = unzip fields-            fieldTypes' <- mapM (\x -> traverseTypeM x [] "") fieldTypes-            return $ zip fieldTypes' fieldNames+        (tf, ranges) = case t of+            Struct pk fields rs ->+                (Struct pk fields', rs)+                where fields' = flattenFields fields+            Union  pk fields rs ->+                (Union  pk fields', rs)+                where fields' = flattenFields fields+            _ -> typeRanges t+        r1 : r2 : rest = ranges+        rangesFlat = combineRanges r1 r2 : rest +-- flatten the types in a given list of struct/union fields+flattenFields :: [Field] -> [Field]+flattenFields = map $ first flattenType+ traverseModuleItemM :: ModuleItem -> Scoper TypeInfo ModuleItem traverseModuleItemM (Instance m p x rs l) = do     -- converts multi-dimensional instances@@ -118,9 +123,9 @@             where                 size1 = rangeSizeHiLo (s1, e1)                 size2 = rangeSizeHiLo (s2, e2)-                lower = BinOp Add e2 (BinOp Mul e1 size2)-                upper = BinOp Add (BinOp Mul size1 size2)-                            (BinOp Sub lower (RawNum 1))+                lower = binOp Add e2 (binOp Mul e1 size2)+                upper = binOp Add (binOp Mul size1 size2)+                            (binOp Sub lower (RawNum 1))  traverseStmtM :: Stmt -> Scoper TypeInfo Stmt traverseStmtM =@@ -144,10 +149,8 @@         traverseLHSSingleM lhs = do             let expr = lhsToExpr lhs             expr' <- convertExprM expr-            case exprToLHS expr' of-                Just lhs' -> return lhs'-                Nothing -> error $ "multi-packed conversion created non-LHS from "-                    ++ (show expr) ++ " to " ++ (show expr')+            let Just lhs' = exprToLHS expr'+            return lhs'  convertExprM :: Expr -> Scoper TypeInfo Expr convertExprM = embedScopes convertExpr@@ -158,9 +161,9 @@     where         -- removes the innermost dimensions of the given type information, and         -- applies the given transformation to the expression-        dropLevel :: (Expr -> Expr) -> (TypeInfo, Expr) -> (TypeInfo, Expr)-        dropLevel nest ((t, a), expr) =-            ((tf rs', a'), nest expr)+        dropLevel :: TypeInfo -> TypeInfo+        dropLevel (t, a) =+            (tf rs', a')             where                 (tf, rs) = typeRanges t                 (rs', a') = case (rs, a) of@@ -168,48 +171,46 @@                     (packed, []) -> (tail packed, [])                     (packed, unpacked) -> (packed, tail unpacked) -        -- given an expression, returns its type information and a tagged-        -- version of the expression, if possible-        levels :: Expr -> Maybe (TypeInfo, Expr)+        -- given an expression, returns its type information, if possible+        levels :: Expr -> Maybe TypeInfo         levels (Bit expr a) =             case levels expr of-                Just info -> Just $ dropLevel (\expr' -> Bit expr' a) info+                Just info -> Just $ dropLevel info                 Nothing -> fallbackLevels $ Bit expr a-        levels (Range expr a b) =-            fmap (dropLevel $ \expr' -> Range expr' a b) (levels expr)+        levels (Range expr _ _) =+            fmap dropLevel $ levels expr         levels (Dot expr x) =             case levels expr of-                Just ((Struct _ fields [], []), expr') -> dropDot fields expr'-                Just ((Union  _ fields [], []), expr') -> dropDot fields expr'+                Just (Struct _ fields [], []) -> dropDot fields+                Just (Union  _ fields [], []) -> dropDot fields                 _ -> fallbackLevels $ Dot expr x             where-                dropDot :: [Field] -> Expr -> Maybe (TypeInfo, Expr)-                dropDot fields expr' =+                dropDot :: [Field] -> Maybe TypeInfo+                dropDot fields =                     if Map.member x fieldMap-                        then Just ((fieldType, []), Dot expr' x)+                        then Just (fieldType, [])                         else Nothing                     where                         fieldMap = Map.fromList $ map swap fields                         fieldType = fieldMap Map.! x         levels expr = fallbackLevels expr -        fallbackLevels :: Expr -> Maybe (TypeInfo, Expr)+        fallbackLevels :: Expr -> Maybe TypeInfo         fallbackLevels expr =-            fmap ((, expr) . thd3) res+            fmap thd3 res             where                 res = lookupElem scopes expr                 thd3 (_, _, c) = c          -- given an expression, returns the two most significant (innermost,-        -- leftmost) packed dimensions and a tagged version of the expression,-        -- if possible-        dims :: Expr -> Maybe (Range, Range, Expr)+        -- leftmost) packed dimensions+        dims :: Expr -> Maybe (Range, Range)         dims expr =             case levels expr of-                Just ((t, []), expr') ->+                Just (t, []) ->                     case snd $ typeRanges t of                         dimInner : dimOuter : _ ->-                            Just (dimInner, dimOuter, expr')+                            Just (dimInner, dimOuter)                         _ -> Nothing                 _ -> Nothing @@ -219,31 +220,26 @@         orientIdx r e =             endianCondExpr r e eSwapped             where-                eSwapped = BinOp Sub (snd r) (BinOp Sub e (fst r))+                eSwapped = binOp Sub (snd r) (binOp Sub e (fst r))          -- Converted idents are prefixed with an invalid character to ensure         -- that are not converted twice when the traversal steps downward. When         -- the prefixed identifier is encountered at the lowest level, it is         -- removed. -        tag = ':'-         rewriteExpr :: Expr -> Expr-        rewriteExpr (Ident x) =-            if head x == tag-                then Ident $ tail x-                else Ident x+        rewriteExpr expr@Ident{} = expr         rewriteExpr orig@(Bit (Bit expr idxInner) idxOuter) =             if isJust maybeDims && expr == rewriteExpr expr-                then Bit expr' idx'+                then Bit expr idx'                 else rewriteExprLowPrec orig             where                 maybeDims = dims expr-                Just (dimInner, dimOuter, expr') = maybeDims+                Just (dimInner, dimOuter) = maybeDims                 idxInner' = orientIdx dimInner idxInner                 idxOuter' = orientIdx dimOuter idxOuter-                base = BinOp Mul idxInner' (rangeSize dimOuter)-                idx' = simplify $ BinOp Add base idxOuter'+                base = binOp Mul idxInner' (rangeSize dimOuter)+                idx' = simplify $ binOp Add base idxOuter'         rewriteExpr orig@(Range (Bit expr idxInner) NonIndexed rangeOuter) =             if isJust maybeDims && expr == rewriteExpr expr                 then rewriteExpr $ Range exprOuter IndexedMinus range@@ -252,44 +248,46 @@                 maybeDims = dims expr                 exprOuter = Bit expr idxInner                 baseDec = fst rangeOuter-                baseInc = BinOp Sub (BinOp Add baseDec len) (RawNum 1)+                baseInc = binOp Sub (binOp Add baseDec len) (RawNum 1)                 base = endianCondExpr rangeOuter baseDec baseInc                 len = rangeSize rangeOuter                 range = (base, len)         rewriteExpr orig@(Range (Bit expr idxInner) modeOuter rangeOuter) =             if isJust maybeDims && expr == rewriteExpr expr-                then Range expr' modeOuter range'+                then Range expr modeOuter range'                 else rewriteExprLowPrec orig             where                 maybeDims = dims expr-                Just (dimInner, dimOuter, expr') = maybeDims+                Just (dimInner, dimOuter) = maybeDims                 idxInner' = orientIdx dimInner idxInner                 (baseOuter, lenOuter) = rangeOuter                 baseOuter' = orientIdx dimOuter baseOuter-                start = BinOp Mul idxInner' (rangeSize dimOuter)-                baseDec = BinOp Add start baseOuter'+                start = binOp Mul idxInner' (rangeSize dimOuter)+                baseDec = binOp Add start baseOuter'                 baseInc = if modeOuter == IndexedPlus-                    then BinOp Add (BinOp Sub baseDec len) one-                    else BinOp Sub (BinOp Add baseDec len) one+                    then binOp Add (binOp Sub baseDec len) one+                    else binOp Sub (binOp Add baseDec len) one                 base = endianCondExpr dimOuter baseDec baseInc                 len = lenOuter                 range' = (base, len)                 one = RawNum 1+        rewriteExpr (Cast (Left t) expr) =+            Cast (Left $ flattenType t) expr         rewriteExpr other =             rewriteExprLowPrec other          rewriteExprLowPrec :: Expr -> Expr         rewriteExprLowPrec orig@(Bit expr idx) =             if isJust maybeDims && expr == rewriteExpr expr-                then Range expr' mode' range'+                then Range expr mode' range'                 else orig             where                 maybeDims = dims expr-                Just (dimInner, dimOuter, expr') = maybeDims+                Just (dimInner, dimOuter) = maybeDims                 mode' = IndexedPlus                 idx' = orientIdx dimInner idx                 len = rangeSize dimOuter-                base = BinOp Add (endianCondExpr dimOuter (snd dimOuter) (fst dimOuter)) (BinOp Mul idx' len)+                base = binOp Add (endianCondExpr dimOuter (snd dimOuter) (fst dimOuter)) (binOp Mul idx' len)                 range' = (simplify base, simplify len)         rewriteExprLowPrec orig@(Range expr NonIndexed range) =             if isJust maybeDims && expr == rewriteExpr expr@@ -298,34 +296,55 @@             where                 maybeDims = dims expr                 baseDec = fst range-                baseInc = BinOp Sub (BinOp Add baseDec len) (RawNum 1)+                baseInc = binOp Sub (binOp Add baseDec len) (RawNum 1)                 base = endianCondExpr range baseDec baseInc                 len = rangeSize range                 range' = (base, len)         rewriteExprLowPrec orig@(Range expr mode range) =             if isJust maybeDims && expr == rewriteExpr expr-                then Range expr' mode' range'+                then Range expr mode' range'                 else orig             where                 maybeDims = dims expr-                Just (dimInner, dimOuter, expr') = maybeDims+                Just (dimInner, dimOuter) = maybeDims                 sizeOuter = rangeSize dimOuter                 offsetOuter = uncurry (endianCondExpr dimOuter) $ swap dimOuter                 (baseOrig, lenOrig) = range-                lenOrigMinusOne = BinOp Sub lenOrig (RawNum 1)+                lenOrigMinusOne = binOp Sub lenOrig (RawNum 1)                 baseSwapped =                     orientIdx dimInner $                     if mode == IndexedPlus                         then                             endianCondExpr dimInner                             baseOrig-                            (BinOp Add baseOrig lenOrigMinusOne)+                            (binOp Add baseOrig lenOrigMinusOne)                         else                             endianCondExpr dimInner-                            (BinOp Sub baseOrig lenOrigMinusOne)+                            (binOp Sub baseOrig lenOrigMinusOne)                             baseOrig-                base = BinOp Add offsetOuter (BinOp Mul sizeOuter baseSwapped)+                base = binOp Add offsetOuter (binOp Mul sizeOuter baseSwapped)                 mode' = IndexedPlus-                len = BinOp Mul sizeOuter lenOrig+                len = binOp Mul sizeOuter lenOrig                 range' = (base, len)         rewriteExprLowPrec other = other++-- Traditional identity operations like `+ 0` and `* 1` are not no-ops in+-- SystemVerilog because they may implicitly extend the width of the other+-- operand. Encouraged by the official language specifications (e.g., Section+-- 11.6.2 of IEEE 1800-2017), these operations are used in real designs as+-- workarounds for the standard expression evaluation semantics.+--+-- The process of flattening arrays in this conversion can naturally lead to+-- unnecessary identity operations. Previously, `simplifyStep` was responsible+-- for cleaning up the below unnecessary operations produced by this conversion,+-- but it inadvertently changed the behavior of legitimate input designs.+--+-- Rather than applying these specific simplifications to all expressions, they+-- are now only considered when constructing a new binary operation expression+-- as part of array flattening.+binOp :: BinOp -> Expr -> Expr -> Expr+binOp Add (RawNum 0) e = e+binOp Add e (RawNum 0) = e+binOp Mul (RawNum 1) e = e+binOp Mul e (RawNum 1) = e+binOp op a b = BinOp op a b
src/Convert/Package.hs view
@@ -26,7 +26,7 @@  import Control.Monad.State.Strict import Control.Monad.Writer.Strict-import Data.List (insert, intercalate)+import Data.List (insert, intercalate, isPrefixOf) import Data.Maybe (mapMaybe) import qualified Data.Map.Strict as Map import qualified Data.Set as Set@@ -74,7 +74,7 @@ prefixItems :: Identifier -> [ModuleItem] -> [ModuleItem] prefixItems prefix items =     snd $ evalState (processItems "" prefix items) initialState-    where initialState = ([], Map.empty, Map.empty)+    where initialState = PK [] Map.empty Map.empty Set.empty  -- collect packages and global package items collectPackageM :: Description -> Writer (Packages, Classes, [PackageItem]) ()@@ -107,14 +107,55 @@ convertPackages files =     (files', packages')     where-        (files', ([], packages', _)) = runState op ([], packages, classes)+        (files', PK [] packages' _ _) = runState op initialState+        initialState = PK [] packages classes conflicts         op = mapM (traverseDescriptionsM traverseDescriptionM) files         packages = Map.insert "" (Map.empty, globalItems) realPackages         (realPackages, classes, globalItems) =             execWriter $ mapM (collectDescriptionsM collectPackageM) files+        prefixes = Set.union (Map.keysSet classes) (Map.keysSet realPackages)+        conflicts =+            if Set.null prefixes+                then Set.empty+                else execWriter $ mapM (collectIdentConflicts prefixes) files -type PackagesState = State ([Identifier], Packages, Classes)+-- write down identifiers that might conflict with the generated names for+-- injected package items+collectIdentConflicts :: Idents -> AST -> Writer Idents ()+collectIdentConflicts prefixes =+    mapM_ $ collectModuleItemsM collectModuleItem+    where+        collectModuleItem =+            evalScoperT . scoper >=>+            collectify traverseIdentsM ident+        scoper = scopeModuleItem collectDecl return return return+        collectDecl decl = do+            case decl of+                Variable _ _ x _ _ -> lift $ ident x+                Net  _ _ _ _ x _ _ -> lift $ ident x+                Param    _ _ x   _ -> lift $ ident x+                ParamType  _ x   _ -> lift $ ident x+                CommentDecl{} -> return ()+            return decl+        ident = collectIdent prefixes +-- write down identifiers that have a package name as a prefix+collectIdent :: Idents -> Identifier -> Writer Idents ()+collectIdent prefixes ident =+    case Set.lookupLE ident prefixes of+        Just prefix -> when (prefix `isPrefixOf` ident) found+            where found = tell $ Set.singleton ident+        Nothing -> return ()++data PK = PK+    { pkStack :: [Identifier]+    , pkPackages :: Packages+    , pkClasses :: Classes+    , pkConflicts :: Idents+    }++type PackagesState = State PK+ traverseDescriptionM :: Description -> PackagesState Description traverseDescriptionM (PackageItem item) = do     return $ PackageItem $ case piNames item of@@ -264,7 +305,7 @@                     insertElem x Declared                     if inProcedure || null packageName                         then return x-                        else return $ packageName ++ '_' : x+                        else lift $ makeIdent packageName x          -- check the global scope for declarations or imports         resolveGlobalIdent :: Identifier -> Scope Identifier@@ -293,13 +334,13 @@                 Just ([_, _], _, Declared) ->                     if null packageName                         then return x-                        else return $ packageName ++ '_' : x+                        else lift $ makeIdent packageName x                 Just (_, _, Declared) -> return x                 Just (_, _, Imported rootPkg) ->-                    return $ rootPkg ++ '_' : x+                    lift $ makeIdent rootPkg x                 Just (accesses, _, Available [rootPkg]) -> do                     insertElem accesses $ Imported rootPkg-                    return $ rootPkg ++ '_' : x+                    lift $ makeIdent rootPkg x                 Just (_, _, Available rootPkgs) ->                     error $ "identifier " ++ show x                         ++ " ambiguously refers to the definitions in any of "@@ -404,9 +445,11 @@                 lift $ resolvePSIdent p x             else do                 details <- lookupElemM $ Dot (Ident p) x-                return $ case details of-                    Just ([_, _], _, Declared) -> p ++ '_' : x-                    Just ([_, _], _, Imported rootPkg) -> rootPkg ++ '_' : x+                case details of+                    Just ([_, _], _, Declared) ->+                        lift $ makeIdent p x+                    Just ([_, _], _, Imported rootPkg) ->+                        lift $ makeIdent rootPkg x                     _ -> error $ "package " ++ show p ++ " references"                             ++ " undeclared local \"" ++ p ++ "::" ++ x ++ "\"" @@ -425,7 +468,7 @@         -- inject the given class item and its dependencies into the local scope         classScopeInject :: Identifier -> Identifier -> Scope ()         classScopeInject rootPkg fullName = do-            (_, packages, _) <- lift get+            packages <- lift $ gets pkPackages             let (_, packageItems) = packages Map.! rootPkg             let localPIs = Map.fromList $ concatMap toPIElem packageItems             mapM_ injectIfMissing $@@ -451,7 +494,7 @@ -- locate a package by name, processing its contents if necessary findPackage :: Identifier -> PackagesState Package findPackage packageName = do-    (stack, packages, classes) <- get+    PK { pkStack = stack, pkPackages = packages } <- get     let maybePackage = Map.lookup packageName packages     assertMsg (maybePackage /= Nothing) $         "could not find package " ++ show packageName@@ -465,10 +508,12 @@     if Map.null exports         then do             -- process and resolve this package-            put (packageName : stack, packages, classes)+            modify' $ \pk -> pk { pkStack = packageName : pkStack pk }             package' <- processPackage packageName $ snd package-            (_, packages', _) <- get-            put (stack, Map.insert packageName package' packages', classes)+            pk <- get+            let stack' = tail $ pkStack pk+            let packages' = Map.insert packageName package' $ pkPackages pk+            put $ pk { pkStack = stack', pkPackages = packages' }             return package'         else return package @@ -490,11 +535,11 @@ -- resolve a package scoped identifier to its unique global name resolvePSIdent :: Identifier -> Identifier -> PackagesState Identifier resolvePSIdent packageName itemName = do-    (_, _, classes) <- get+    classes <- gets pkClasses     case Map.lookup packageName classes of         Nothing -> do             rootPkg <- resolveRootPackage packageName itemName-            return $ rootPkg ++ '_' : itemName+            makeIdent rootPkg itemName         Just ([], _) -> resolveCSIdent packageName [] Set.empty itemName         Just _ -> error $ "reference to " ++ show itemName             ++ " in parameterized class " ++ show packageName@@ -532,7 +577,7 @@ resolveCSIdent :: Identifier -> [ParamBinding] -> Idents -> Identifier -> PackagesState Identifier resolveCSIdent className paramBindings scopeKeys itemName = do     -- find the specified class-    (_, _, classes) <- get+    classes <- gets pkClasses     let maybeClass = Map.lookup className classes     assertMsg (maybeClass /= Nothing) $         "could not find class " ++ show className@@ -550,13 +595,13 @@     let classItems'' = map overrider classItems'     -- add the synthetic package to the state     let package = (exports, classItems'')-    (stack, packages, _) <- get-    put (stack, Map.insert packageName package packages, classes)+    packages' <- gets $ Map.insert packageName package . pkPackages+    modify' $ \pk -> pk { pkPackages = packages' }     -- ensure the item actually exists     let maybeIdentState = Map.lookup itemName exports     assertMsg (maybeIdentState /= Nothing) $         "could not find " ++ show itemName ++ " in class " ++ show className-    return $ packageName ++ '_' : itemName+    makeIdent packageName itemName     where         extractParameterName :: Decl -> Maybe Identifier         extractParameterName (Param Parameter _ x _) = Just x@@ -600,6 +645,19 @@             where x' = drop (1 + length packageName) x         overrideParam _ _ other = other +-- construct a new identifier for a package scoped identifier+makeIdent :: Identifier -> Identifier -> PackagesState Identifier+makeIdent x y = do+    conflicts <- gets pkConflicts+    return $ uniqueIdent conflicts $ x ++ '_' : y++-- prepend underscores until the name is unique+uniqueIdent :: Idents -> Identifier -> Identifier+uniqueIdent conflicts ident =+    if Set.member ident conflicts+        then uniqueIdent conflicts $ '_' : ident+        else ident+ -- errors with the given message when the check is false assertMsg :: Monad m => Bool -> String -> m () assertMsg check msg = when (not check) $ error msg@@ -652,7 +710,7 @@ -- iteratively inserts missing package items exactly where they are needed addItems :: PIs -> Idents -> [(ModuleItem, Idents)] -> [ModuleItem] addItems pis existingPIs ((item, usedPIs) : items) =-    if not $ Set.disjoint existingPIs thisPI then+    if not $ forceKeep || Set.disjoint existingPIs thisPI then         -- this item was re-imported earlier in the module         addItems pis existingPIs items     else if Map.null itemsToAdd then@@ -666,7 +724,11 @@         thisPI = case item of             MIPackageItem packageItem ->                 Set.fromList $ piNames packageItem+            Instance _ _ x _ _ -> Set.singleton x             _ -> Set.empty+        forceKeep = case item of+            Instance{} -> True+            _ -> False         neededPIs = Set.difference (Set.difference usedPIs existingPIs) thisPI         itemsToAdd = Map.restrictKeys pis neededPIs         (chosenName, chosenPI) = Map.findMin itemsToAdd@@ -778,6 +840,8 @@ piNames (Decl (Param    _ _ ident   _)) = [ident] piNames (Decl (ParamType  _ ident   _)) = [ident] piNames (Decl (CommentDecl          _)) = []-piNames (Import x y) = [show $ Import x y]-piNames (Export x y) = [show $ Export x y]+piNames item@DPIImport{} = [show item]+piNames item@DPIExport{} = [show item]+piNames item@Import{} = [show item]+piNames item@Export{} = [show item] piNames (Directive _) = []
src/Convert/RemoveComments.hs view
@@ -39,6 +39,9 @@     where         decls' = convertDecls decls         stmts' = convertStmts stmts+convertPackageItem (DPIImport spec prop alias typ name decls) =+    DPIImport spec prop alias typ name decls'+    where decls' = convertDecls decls convertPackageItem other = other  convertStmt :: Stmt -> Stmt
src/Convert/Scoper.hs view
@@ -57,6 +57,8 @@     , withinProcedureM     , procedureLoc     , procedureLocM+    , scopedError+    , scopedErrorM     , isLoopVar     , isLoopVarM     , loopVarDepth@@ -68,7 +70,7 @@     ) where  import Control.Monad.State.Strict-import Data.List (findIndices, partition)+import Data.List (findIndices, intercalate, isPrefixOf, partition) import Data.Maybe (isNothing) import qualified Data.Map.Strict as Map @@ -105,6 +107,7 @@     , sProcedureLoc :: [Access]     , sInjectedItems :: [(Bool, ModuleItem)]     , sInjectedDecls :: [Decl]+    , sLatestTrace :: String     } deriving Show  extractMapping :: Scopes a -> Map.Map Identifier a@@ -353,6 +356,26 @@ procedureLoc :: Scopes a -> [Access] procedureLoc = sProcedureLoc +debugLocation :: Scopes a -> String+debugLocation s =+    hierarchy +++    if null latestTrace+        then " (use -v to get approximate source location)"+        else ", near " ++ latestTrace+    where+        hierarchy = intercalate "." $ map tierToStr $ sCurrent s+        latestTrace = sLatestTrace s+        tierToStr :: Tier -> String+        tierToStr (Tier "" _) = "<unnamed_block>"+        tierToStr (Tier x "") = x+        tierToStr (Tier x y) = x ++ '[' : y ++ "]"++scopedErrorM :: Monad m => String -> ScoperT a m x+scopedErrorM msg = get >>= flip scopedError msg++scopedError :: Scopes a -> String -> x+scopedError scopes = error . (++ ", within scope " ++ debugLocation scopes)+ isLoopVar :: Scopes a -> Identifier -> Bool isLoopVar scopes x = any matches $ sCurrent scopes     where matches = (== x) . tierIndex@@ -411,8 +434,11 @@ runScoperT = flip runStateT initialState  initialState :: Scopes a-initialState = Scopes [] Map.empty [] [] []+initialState = Scopes [] Map.empty [] [] [] "" +tracePrefix :: String+tracePrefix = "Trace: "+ scopeModuleItem     :: forall a m. Monad m     => MapperM (ScoperT a m) Decl@@ -420,7 +446,7 @@     -> MapperM (ScoperT a m) GenItem     -> MapperM (ScoperT a m) Stmt     -> MapperM (ScoperT a m) ModuleItem-scopeModuleItem declMapper moduleItemMapper genItemMapper stmtMapper =+scopeModuleItem declMapperRaw moduleItemMapper genItemMapper stmtMapperRaw =     wrappedModuleItemMapper     where         fullStmtMapper :: Stmt -> ScoperT a m Stmt@@ -438,6 +464,21 @@                 then traverseSinglyNestedStmtsM fullStmtMapper stmt'                 else fullStmtMapper $ Block Seq "" injected [stmt'] +        declMapper :: Decl -> ScoperT a m Decl+        declMapper decl@(CommentDecl c) =+            consumeComment c >> return decl+        declMapper decl = declMapperRaw decl++        stmtMapper :: Stmt -> ScoperT a m Stmt+        stmtMapper stmt@(CommentStmt c) =+            consumeComment c >> return stmt+        stmtMapper stmt = stmtMapperRaw stmt++        consumeComment :: String -> ScoperT a m ()+        consumeComment c =+            when (tracePrefix `isPrefixOf` c) $+                modify' $ \s -> s { sLatestTrace = drop (length tracePrefix) c }+         -- converts a decl and adds decls injected during conversion         declMapper' :: Decl -> ScoperT a m [Decl]         declMapper' decl = do@@ -479,7 +520,11 @@         redirectTFDecl :: Type -> Identifier -> ScoperT a m (Type, Identifier)         redirectTFDecl typ ident = do             res <- declMapper $ Variable Local typ ident [] Nil-            let Variable Local newType newName newRanges Nil = res+            (newType, newName, newRanges) <-+                return $ case res of+                    Variable Local t x r Nil -> (t, x, r)+                    Net Local TWire DefaultStrength t x r Nil -> (t, x, r)+                    _ -> error "redirectTFDecl invariant violated"             return $ if null newRanges                 then (newType, newName)                 else@@ -516,6 +561,14 @@             return $ MIPackageItem $ Task ml x' decls' stmts'         fullModuleItemMapper (MIPackageItem (Decl decl)) =             declMapper decl >>= return . MIPackageItem . Decl+        fullModuleItemMapper (MIPackageItem item@DPIImport{}) = do+            let DPIImport spec prop alias typ name decls = item+            (typ', name') <- redirectTFDecl typ name+            decls' <- mapM declMapper decls+            let item' = DPIImport spec prop alias typ' name' decls'+            return $ MIPackageItem item'+        fullModuleItemMapper (MIPackageItem (DPIExport spec alias kw name)) =+            return $ MIPackageItem $ DPIExport spec alias kw name         fullModuleItemMapper (AlwaysC kw stmt) = do             enterProcedure             stmt' <- fullStmtMapper stmt
src/Convert/Struct.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TupleSections #-} {- sv2v  - Author: Zachary Snow <zach@zachjs.com>@@ -8,6 +9,7 @@ module Convert.Struct (convert) where  import Control.Monad ((>=>), when)+import Control.Monad.State.Strict (get) import Data.Either (isLeft) import Data.List (elemIndex, find, partition, (\\)) import Data.Maybe (fromJust)@@ -111,12 +113,14 @@             let (tf, rs) = typeRanges t             when (isRangeable t) $                 scopeType (tf $ a ++ rs) >>= insertElem x-            let e' = convertExpr t e+            scopes <- get+            let e' = convertExpr scopes t e             let t' = convertType t             return $ Variable d t' x a e'         Param s t x e -> do             scopeType t >>= insertElem x-            let e' = convertExpr t e+            scopes <- get+            let e' = convertExpr scopes t e             let t' = convertType t             return $ Param s t' x e'         _ -> return decl@@ -182,24 +186,27 @@     (typ, lhs') <- convertLHS lhs     -- convert the RHS using the LHS type information, and then the innermost     -- type information on the resulting RHS-    (_, expr') <- embedScopes convertSubExpr $ convertExpr typ expr+    scopes <- get+    let (_, expr') =+            convertSubExpr scopes $+            convertExpr scopes typ expr     return (lhs', expr')  structIsntReady :: Type -> Bool structIsntReady = (Nothing ==) . convertStruct  -- try expression conversion by looking at the *outermost* type first-convertExpr :: Type -> Expr -> Expr-convertExpr _ Nil = Nil-convertExpr t (Mux c e1 e2) =+convertExpr :: Scopes a -> Type -> Expr -> Expr+convertExpr _ _ Nil = Nil+convertExpr scopes t (Mux c e1 e2) =     Mux c e1' e2'     where-        e1' = convertExpr t e1-        e2' = convertExpr t e2+        e1' = convertExpr scopes t e1+        e2' = convertExpr scopes t e2 -convertExpr struct@(Struct _ fields []) (Pattern itemsOrig) =+convertExpr scopes struct@(Struct _ fields []) (Pattern itemsOrig) =     if not (null extraNames) then-        error $ "pattern " ++ show (Pattern itemsOrig) +++        scopedError scopes $ "pattern " ++ show (Pattern itemsOrig) ++             " has extra named fields " ++ show extraNames ++             " that are not in " ++ show struct     else if structIsntReady struct then@@ -215,7 +222,8 @@                 itemsOrig             -- position-based patterns should cover every field             else if length itemsOrig /= length fields then-                error $ "struct pattern " ++ show (Pattern itemsOrig) +++                scopedError scopes $ "struct pattern " +++                    show (Pattern itemsOrig) ++                     " doesn't have the same number of items as " ++ show struct             -- if the pattern does not use identifiers, use the             -- identifiers from the struct type definition in order@@ -229,9 +237,9 @@         isNumbered :: TypeOrExpr -> Bool         isNumbered (Right (Number n)) =             if maybeIndex == Nothing-                then error msgNonInteger+                then scopedError scopes msgNonInteger                 else 0 <= index && index < length fieldNames-                        || error msgOutOfBounds+                        || scopedError scopes msgOutOfBounds             where                 maybeIndex = fmap fromIntegral $ numberToInteger n                 Just index = maybeIndex@@ -245,7 +253,7 @@         right = \(Right x) -> x         getName :: Expr -> Identifier         getName (Ident x) = x-        getName e = error $ "invalid pattern key " ++ show e+        getName e = scopedError scopes $ "invalid pattern key " ++ show e                         ++ " is not a type, field name, or index"          items = zip@@ -253,7 +261,7 @@             (map resolveField fieldNames)         resolveField :: Identifier -> Expr         resolveField fieldName =-            convertExpr fieldType $+            convertExpr scopes fieldType $             -- look up by name             if valueByName /= Nothing then                 fromJust valueByName@@ -269,7 +277,7 @@             else if valueByIndex /= Nothing then                 fromJust valueByIndex             else-                error $ "couldn't find field '" ++ fieldName +++                scopedError scopes $ "couldn't find field '" ++ fieldName ++                     "' from struct definition " ++ show struct ++                     " in struct pattern " ++ show (Pattern itemsOrig)             where@@ -292,21 +300,21 @@                         Just value = numberToInteger n                         Right (Number n) = item -convertExpr _ (Cast (Left t) expr) =-    Cast (Left t') $ convertExpr t expr+convertExpr scopes _ (Cast (Left t) expr) =+    Cast (Left t') $ convertExpr scopes t expr     where t' = convertType t -convertExpr (Implicit _ []) expr =-    traverseSinglyNestedExprs (convertExpr UnknownType) expr-convertExpr (Implicit sg rs) expr =-    convertExpr (IntegerVector TBit sg rs) expr+convertExpr scopes (Implicit _ []) expr =+    traverseSinglyNestedExprs (convertExpr scopes UnknownType) expr+convertExpr scopes (Implicit sg rs) expr =+    convertExpr scopes (IntegerVector TBit sg rs) expr  -- TODO: This is a conversion for concat array literals with elements -- that are unsized numbers. This probably belongs somewhere else.-convertExpr t@IntegerVector{} (Concat exprs) =+convertExpr scopes t@IntegerVector{} (Concat exprs) =     if all isUnsizedNumber exprs         then Concat $ map (Cast $ Left t') exprs-        else Concat $ map (convertExpr t') exprs+        else Concat $ map (convertExpr scopes t') exprs     where         t' = dropInnerTypeRange t         isUnsizedNumber :: Expr -> Bool@@ -318,35 +326,35 @@  -- TODO: This is really a conversion for using default patterns to -- populate arrays. Maybe this should be somewhere else?-convertExpr t orig@(Pattern [(Left UnknownType, expr)]) =+convertExpr scopes t orig@(Pattern [(Left UnknownType, expr)]) =     if null rs         then orig         else Repeat count [expr']     where         count = rangeSize $ head rs-        expr' = Cast (Left t') $ convertExpr t' expr+        expr' = Cast (Left t') $ convertExpr scopes t' expr         (_, rs) = typeRanges t         t' = dropInnerTypeRange t  -- pattern syntax used for simple array literals-convertExpr t (Pattern items) =+convertExpr scopes t (Pattern items) =     if all (== Right Nil) names-        then convertExpr t $ Concat exprs'+        then convertExpr scopes t $ Concat exprs'         else Pattern items     where         (names, exprs) = unzip items         t' = dropInnerTypeRange t-        exprs' = map (convertExpr t') exprs+        exprs' = map (convertExpr scopes t') exprs  -- propagate types through concatenation expressions-convertExpr t (Concat exprs) =+convertExpr scopes t (Concat exprs) =     Concat exprs'     where         t' = dropInnerTypeRange t-        exprs' = map (convertExpr t') exprs+        exprs' = map (convertExpr scopes t') exprs -convertExpr _ expr =-    traverseSinglyNestedExprs (convertExpr UnknownType) expr+convertExpr scopes _ expr =+    traverseSinglyNestedExprs (convertExpr scopes UnknownType) expr  fallbackType :: Scopes Type -> Expr -> (Type, Expr) fallbackType scopes e =@@ -356,12 +364,19 @@                 Nothing -> UnknownType                 Just (_, _, typ) -> typ +pattern MakeSigned :: Expr -> Expr+pattern MakeSigned e = Call (Ident "$signed") (Args [e] [])+ -- converting LHSs by looking at the innermost types first convertLHS :: LHS -> Scoper Type (Type, LHS) convertLHS l = do     let e = lhsToExpr l     (t, e') <- embedScopes convertSubExpr e-    let Just l' = exprToLHS e'+    -- per IEEE 1800-2017 sections 10.7 and 11.8, the signedness of the LHS does+    -- not affect the evaluation and sign-extension of the RHS+    let Just l' = exprToLHS $ case e' of+                        MakeSigned e'' -> e''+                        _ -> e'     return (t, l')  -- try expression conversion by looking at the *innermost* type first@@ -372,23 +387,32 @@     else if structIsntReady subExprType then         (fieldType, Dot e' x)     else-        (fieldType, undotted)+        (fieldType, undottedWithSign)     where         (subExprType, e') = convertSubExpr scopes e-        (fieldType, bounds, dims) = lookupFieldInfo subExprType x+        (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x         base = fst bounds         len = rangeSize bounds         undotted = if null dims || rangeSize (head dims) == RawNum 1             then Bit e' (fst bounds)             else Range e' IndexedMinus (base, len)+        -- retain signedness of fields which would otherwise be lost via the+        -- resulting bit or range selection+        IntegerVector _ fieldSg _ = fieldType+        undottedWithSign =+            if fieldSg == Signed+                then MakeSigned undotted+                else undotted+ convertSubExpr scopes (Range (Dot e x) NonIndexed rOuter) =     if isntStruct subExprType then         (UnknownType, orig')     else if structIsntReady subExprType then         (replaceInnerTypeRange NonIndexed rOuter' fieldType, orig')     else if null dims then-        error $ "illegal access to range " ++ show (Range Nil NonIndexed rOuter)-            ++ " of " ++ show (Dot e x) ++ ", which has type " ++ show fieldType+        scopedError scopes $ "illegal access to range "+            ++ show (Range Nil NonIndexed rOuter) ++ " of " ++ show (Dot e x)+            ++ ", which has type " ++ show fieldType     else         (replaceInnerTypeRange NonIndexed rOuter' fieldType, undotted)     where@@ -398,7 +422,7 @@         (_, roRight') = convertSubExpr scopes roRight         rOuter' = (roLeft', roRight')         orig' = Range (Dot e' x) NonIndexed rOuter'-        (fieldType, bounds, dims) = lookupFieldInfo subExprType x+        (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x         [dim] = dims         rangeLeft = ( BinOp Sub (fst bounds) $ BinOp Sub (fst dim) roLeft'                     , BinOp Sub (fst bounds) $ BinOp Sub (fst dim) roRight' )@@ -412,8 +436,9 @@     else if structIsntReady subExprType then         (replaceInnerTypeRange mode (baseO', lenO') fieldType, orig')     else if null dims then-        error $ "illegal access to range " ++ show (Range Nil mode (baseO, lenO))-            ++ " of " ++ show (Dot e x) ++ ", which has type " ++ show fieldType+        scopedError scopes $ "illegal access to range "+            ++ show (Range Nil mode (baseO, lenO)) ++ " of " ++ show (Dot e x)+            ++ ", which has type " ++ show fieldType     else         (replaceInnerTypeRange mode (baseO', lenO') fieldType, undotted)     where@@ -421,7 +446,7 @@         (_, baseO') = convertSubExpr scopes baseO         (_, lenO') = convertSubExpr scopes lenO         orig' = Range (Dot e' x) mode (baseO', lenO')-        (fieldType, bounds, dims) = lookupFieldInfo subExprType x+        (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x         [dim] = dims         baseLeft  = BinOp Sub (fst bounds) $ BinOp Sub (fst dim) baseO'         baseRight = BinOp Add (snd bounds) $ BinOp Sub (snd dim) baseO'@@ -445,8 +470,8 @@     else if structIsntReady subExprType then         (dropInnerTypeRange fieldType, orig')     else if null dims then-        error $ "illegal access to bit " ++ show i ++ " of " ++ show (Dot e x)-            ++ ", which has type " ++ show fieldType+        scopedError scopes $ "illegal access to bit " ++ show i ++ " of "+            ++ show (Dot e x) ++ ", which has type " ++ show fieldType     else         (dropInnerTypeRange fieldType, Bit e' iFlat)     where@@ -454,7 +479,7 @@         (_, i') = convertSubExpr scopes i         (backupType, _) = fallbackType scopes $ Dot e' x         orig' = Bit (Dot e' x) i'-        (fieldType, bounds, dims) = lookupFieldInfo subExprType x+        (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x         [dim] = dims         left  = BinOp Sub (fst bounds) $ BinOp Sub (fst dim) i'         right = BinOp Add (snd bounds) $ BinOp Sub (snd dim) i'@@ -508,11 +533,14 @@ isntStruct :: Type -> Bool isntStruct = (== Nothing) . getFields --- get the field type, flattended bounds, and original type dimensions-lookupFieldInfo :: Type -> Identifier -> (Type, Range, [Range])-lookupFieldInfo struct fieldName =+-- get the field type, flattened bounds, and original type dimensions+lookupFieldInfo :: Scopes Type -> Type -> Expr -> Identifier+    -> (Type, Range, [Range])+lookupFieldInfo scopes struct base fieldName =     if maybeFieldType == Nothing-        then error $ "field '" ++ fieldName ++ "' not found in " ++ show struct+        then scopedError scopes $ "field '" ++ fieldName ++ "' not found in "+                ++ show struct ++ ", in expression "+                ++ show (Dot base fieldName)         else (fieldType, bounds, dims)     where         Just fields = getFields struct@@ -538,4 +566,4 @@                 details = lookupElem scopes $ LHSDot lhs x                 typ = maybe UnknownType thd3 details                 thd3 (_, _, c) = c-                (_, e') = convertSubExpr scopes $ convertExpr typ e+                (_, e') = convertSubExpr scopes $ convertExpr scopes typ e
src/Convert/Traverse.hs view
@@ -255,6 +255,7 @@         cs (Return expr) = return $ Return expr         cs (Subroutine expr exprs) = return $ Subroutine expr exprs         cs (Trigger blocks x) = return $ Trigger blocks x+        cs stmt@Force{} = return stmt         cs (Assertion a) =             traverseAssertionStmtsM fullMapper a >>= return . Assertion         cs (Continue) = return Continue@@ -300,13 +301,13 @@             e' <- mapper e             s' <- seqExprMapper s             return $ SeqExprThroughout e' s'-        seqExprMapper (SeqExprDelay ms e s) = do+        seqExprMapper (SeqExprDelay ms r s) = do             ms' <- case ms of                 Nothing -> return Nothing                 Just x -> seqExprMapper x >>= return . Just-            e' <- mapper e+            r' <- mapBothM mapper r             s' <- seqExprMapper s-            return $ SeqExprDelay ms' e' s'+            return $ SeqExprDelay ms' r' s'         seqExprMapper (SeqExprFirstMatch s items) = do             s' <- seqExprMapper s             items' <- mapM seqMatchItemMapper items@@ -343,10 +344,11 @@             spMapper PropExprFollowsNO se pe         propExprMapper (PropExprIff p1 p2) =             ppMapper PropExprIff p1 p2-        propSpecMapper (PropertySpec ms e pe) = do+        propSpecMapper (PropertySpec mv e pe) = do+            mv' <- mapM (traverseEventExprsM mapper) mv             e' <- mapper e             pe' <- propExprMapper pe-            return $ PropertySpec ms e' pe'+            return $ PropertySpec mv' e' pe'         assertionExprMapper (Concurrent e) =             propSpecMapper e >>= return . Concurrent         assertionExprMapper (Immediate d e) =@@ -365,13 +367,6 @@ traverseStmtLHSsM mapper = stmtMapper     where         fullMapper = mapper-        stmtMapper (Timing (Event sense) stmt) = do-            sense' <- senseMapper sense-            return $ Timing (Event sense') stmt-        stmtMapper (Asgn op (Just (Event sense)) lhs expr) = do-            lhs' <- fullMapper lhs-            sense' <- senseMapper sense-            return $ Asgn op (Just $ Event sense') lhs' expr         stmtMapper (Asgn op mt lhs expr) =             fullMapper lhs >>= \lhs' -> return $ Asgn op mt lhs' expr         stmtMapper (For inits me incrs stmt) = do@@ -380,30 +375,9 @@             lhss' <- mapM fullMapper lhss             let incrs' = zip3 lhss' asgnOps exprs             return $ For inits' me incrs' stmt-        stmtMapper (Assertion a) =-            assertionMapper a >>= return . Assertion+        stmtMapper (Force kw l e) =+            fullMapper l >>= \l' -> return $ Force kw l' e         stmtMapper other = return other-        senseMapper (Sense        lhs) = fullMapper lhs >>= return . Sense-        senseMapper (SensePosedge lhs) = fullMapper lhs >>= return . SensePosedge-        senseMapper (SenseNegedge lhs) = fullMapper lhs >>= return . SenseNegedge-        senseMapper (SenseOr    s1 s2) = do-            s1' <- senseMapper s1-            s2' <- senseMapper s2-            return $ SenseOr s1' s2'-        senseMapper (SenseStar       ) = return SenseStar-        assertionExprMapper (Concurrent (PropertySpec (Just sense) me pe)) = do-            sense' <- senseMapper sense-            return $ Concurrent $ PropertySpec (Just sense') me pe-        assertionExprMapper other = return other-        assertionMapper (Assert e ab) = do-            e' <- assertionExprMapper e-            return $ Assert e' ab-        assertionMapper (Assume e ab) = do-            e' <- assertionExprMapper e-            return $ Assume e' ab-        assertionMapper (Cover e stmt) = do-            e' <- assertionExprMapper e-            return $ Cover e' stmt  traverseStmtLHSs :: Mapper LHS -> Mapper Stmt traverseStmtLHSs = unmonad traverseStmtLHSsM@@ -496,6 +470,10 @@             e2' <- exprMapper e2             e3' <- exprMapper e3             return $ MinTypMax e1' e2' e3'+        em (ExprAsgn e1 e2) = do+            e1' <- exprMapper e1+            e2' <- exprMapper e2+            return $ ExprAsgn e1' e2'         em (Nil) = return Nil  traverseSinglyNestedExprs :: Mapper Expr -> Mapper Expr@@ -618,6 +596,14 @@         return $ MIPackageItem $ Import x y     moduleItemMapper (MIPackageItem (Export x y)) =         return $ MIPackageItem $ Export x y+    moduleItemMapper (MIPackageItem item@DPIImport{}) = do+        let DPIImport spec prop alias typ name decls = item+        typ' <- typeMapper typ+        decls' <- mapM declMapper decls+        let item' = DPIImport spec prop alias typ' name decls'+        return $ MIPackageItem item'+    moduleItemMapper (MIPackageItem (DPIExport spec alias kw name)) =+        return $ MIPackageItem $ DPIExport spec alias kw name     moduleItemMapper (AssertionItem (mx, a)) = do         a' <- traverseAssertionStmtsM stmtMapper a         a'' <- traverseAssertionExprsM exprMapper a'@@ -659,7 +645,6 @@     caseMapper (exprs, stmt) = do         exprs' <- mapM exprMapper exprs         return (exprs', stmt)-    stmtMapper = traverseNestedStmtsM flatStmtMapper     flatStmtMapper (StmtAttr attr stmt) =         -- note: we exclude expressions in attributes from conversion         return $ StmtAttr attr stmt@@ -689,7 +674,8 @@     flatStmtMapper (Foreach x vars stmt) = return $ Foreach x vars stmt     flatStmtMapper (If u cc s1 s2) =         exprMapper cc >>= \cc' -> return $ If u cc' s1 s2-    flatStmtMapper (Timing event stmt) = return $ Timing event stmt+    flatStmtMapper (Timing timing stmt) =+        timingMapper timing >>= \timing' -> return $ Timing timing' stmt     flatStmtMapper (Subroutine e (Args l p)) = do         e' <- exprMapper e         l' <- mapM exprMapper l@@ -699,10 +685,12 @@     flatStmtMapper (Return expr) =         exprMapper expr >>= return . Return     flatStmtMapper (Trigger blocks x) = return $ Trigger blocks x-    flatStmtMapper (Assertion a) = do-        a' <- traverseAssertionStmtsM stmtMapper a-        a'' <- traverseAssertionExprsM exprMapper a'-        return $ Assertion a''+    flatStmtMapper (Force kw l e) = do+        l' <- lhsMapper l+        e' <- exprMapper e+        return $ Force kw l' e'+    flatStmtMapper (Assertion a) =+        traverseAssertionExprsM exprMapper a >>= return . Assertion     flatStmtMapper (Continue) = return Continue     flatStmtMapper (Break) = return Break     flatStmtMapper (Null) = return Null@@ -710,6 +698,22 @@      asgnMapper (l, op, e) = exprMapper e >>= \e' -> return $ (l, op, e') +    timingMapper (Event e) = eventMapper e >>= return . Event+    timingMapper (Delay e) = exprMapper e >>= return . Delay+    timingMapper (Cycle e) = exprMapper e >>= return . Cycle++    eventMapper EventStar = return EventStar+    eventMapper (EventExpr e) =+        traverseEventExprsM exprMapper e >>= return . EventExpr++traverseEventExprsM :: Monad m => MapperM m Expr -> MapperM m EventExpr+traverseEventExprsM mapper (EventExprEdge edge expr) =+    mapper expr >>= return . EventExprEdge edge+traverseEventExprsM mapper (EventExprOr e1 e2) = do+    e1' <- traverseEventExprsM mapper e1+    e2' <- traverseEventExprsM mapper e2+    return $ EventExprOr e1' e2'+ traverseStmtExprs :: Mapper Expr -> Mapper Stmt traverseStmtExprs = unmonad traverseStmtExprsM collectStmtExprsM :: Monad m => CollectorM m Expr -> CollectorM m Stmt@@ -837,6 +841,7 @@         tm (UnpackedType t r) = do             t' <- mapper t             return $ UnpackedType t' r+        tm Void = return Void  traverseSinglyNestedTypes :: Mapper Type -> Mapper Type traverseSinglyNestedTypes = unmonad traverseSinglyNestedTypesM@@ -1077,6 +1082,9 @@         stmtMapper (Asgn op mt lhs expr) = do             (lhs', expr') <- mapper (lhs, expr)             return $ Asgn op mt lhs' expr'+        stmtMapper (Force kw lhs expr) | expr /= Nil = do+            (lhs', expr') <- mapper (lhs, expr)+            return $ Force kw lhs' expr'         stmtMapper other = return other  traverseStmtAsgns :: Mapper (LHS, Expr) -> Mapper Stmt
src/Convert/TypeOf.hs view
@@ -130,7 +130,8 @@ elaborateSizeCast :: Expr -> Expr -> ST Expr elaborateSizeCast (Number size) _ | Just 0 == numberToInteger size =     -- special case because zero-width ranges cannot be represented-    error $ "size cast width " ++ show size ++ " is not a positive integer"+    scopedErrorM $ "size cast width " ++ show size+        ++ " is not a positive integer" elaborateSizeCast size value = do     t <- typeof value     force <- isStringParam value
src/Job.hs view
@@ -24,6 +24,7 @@     | Interface     | Logic     | Succinct+    | UnbasedUnsized     deriving (Typeable, Data, Eq)  data Write@@ -65,8 +66,8 @@     , passThrough = nam_ "pass-through" &= help "Dump input without converting"         &= groupname "Conversion"     , exclude = nam_ "exclude" &= name "E" &= typ "CONV"-        &= help ("Exclude a particular conversion (always, assert, interface,"-            ++ " or logic)")+        &= help ("Exclude a particular conversion (Always, Assert, Interface,"+            ++ " Logic, or UnbasedUnsized)")     , verbose = nam "verbose" &= help "Retain certain conversion artifacts"     , write = Stdout &= ignore -- parsed from the flexible flag below     , writeRaw = "s" &= name "write" &= name "w" &= explicit &= typ "MODE/FILE"@@ -85,7 +86,7 @@     &= summary ("sv2v " ++ version)     &= details [ "sv2v converts SystemVerilog to Verilog."                , "More info: https://github.com/zachjs/sv2v"-               , "(C) 2019-2021 Zachary Snow, 2011-2015 Tom Hawkins" ]+               , "(C) 2019-2022 Zachary Snow, 2011-2015 Tom Hawkins" ]     &= helpArg [explicit, name "help"]     &= versionArg [explicit, name "version"]     &= verbosityArgs [ignore] [ignore]
src/Language/SystemVerilog/AST/Description.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE PatternSynonyms #-} {- sv2v  - Author: Zachary Snow <zach@zachjs.com>  - Initial Verilog AST Author: Tom Hawkins <tomahawkins@gmail.com>@@ -12,6 +13,8 @@     , Lifetime    (..)     , Qualifier   (..)     , ClassItem+    , DPIImportProperty (..)+    , DPIExportKW (..)     ) where  import Data.List (intercalate)@@ -22,7 +25,7 @@ import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Decl (Decl(CommentDecl)) import Language.SystemVerilog.AST.Stmt (Stmt)-import Language.SystemVerilog.AST.Type (Type, Identifier)+import Language.SystemVerilog.AST.Type (Type, Identifier, pattern UnknownType) import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem)  data Description@@ -82,6 +85,8 @@     | Export Identifier Identifier     | Decl Decl     | Directive String+    | DPIImport String DPIImportProperty Identifier Type Identifier [Decl]+    | DPIExport String Identifier DPIExportKW Identifier     deriving Eq  instance Show PackageItem where@@ -95,6 +100,22 @@     show (Export x y) = printf "export %s::%s;" (showWildcard x) (showWildcard y)     show (Decl decl) = show decl     show (Directive str) = str+    show (DPIImport spec prop alias typ name decls) =+        printf "import %s %s%s %s %s(%s);"+            (show spec) (showPad prop) aliasStr protoStr name declsStr+        where+            aliasStr = if null alias then "" else alias ++ " = "+            protoStr =+                if typ == UnknownType+                    then "task"+                    else "function " ++ show typ+            declsStr =+                if null decls+                    then ""+                    else "\n\t" ++ showDecls decls ++ "\n"+    show (DPIExport spec alias kw name) =+        printf "export %s %s%s %s;" (show spec) aliasStr (show kw) name+        where aliasStr = if null alias then "" else alias ++ " = "  showWildcard :: Identifier -> String showWildcard "" = "*"@@ -137,3 +158,23 @@     show QStatic    = "static"     show QLocal     = "local"     show QProtected = "protected"++data DPIImportProperty+    = DPIContext+    | DPIPure+    | DPINone+    deriving Eq++instance Show DPIImportProperty where+    show DPIContext = "context"+    show DPIPure    = "pure"+    show DPINone    = ""++data DPIExportKW+    = DPIExportTask+    | DPIExportFunction+    deriving Eq++instance Show DPIExportKW where+    show DPIExportTask     = "task"+    show DPIExportFunction = "function"
src/Language/SystemVerilog/AST/Expr.hs view
@@ -15,6 +15,7 @@     , DimsFn (..)     , DimFn (..)     , showAssignment+    , showRange     , showRanges     , ParamBinding     , showParams@@ -60,6 +61,7 @@     | Pattern [(TypeOrExpr, Expr)]     | Inside  Expr [Expr]     | MinTypMax Expr Expr Expr+    | ExprAsgn Expr Expr     | Nil     deriving Eq @@ -91,6 +93,7 @@             showPatternItem (Left t, v) = printf "%s: %s" tStr (show v)                 where tStr = if null (show t) then "default" else show t     show (MinTypMax a b c) = printf "(%s : %s : %s)" (show a) (show b) (show c)+    show (ExprAsgn l r) = printf "(%s = %s)" (show l) (show r)     show e@UniOp{} = showsPrec 0 e ""     show e@BinOp{} = showsPrec 0 e ""     show e@Dot  {} = showsPrec 0 e ""
src/Language/SystemVerilog/AST/Stmt.hs view
@@ -8,7 +8,9 @@ module Language.SystemVerilog.AST.Stmt     ( Stmt   (..)     , Timing (..)-    , Sense  (..)+    , Event        (..)+    , EventExpr    (..)+    , Edge         (..)     , CaseKW (..)     , Case     , ActionBlock  (..)@@ -29,7 +31,7 @@ import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad, showBlock) import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Decl (Decl)-import Language.SystemVerilog.AST.Expr (Expr(Call, Ident, Nil), Args(..))+import Language.SystemVerilog.AST.Expr (Expr(Call, Ident, Nil), Args(..), Range, showRange, showAssignment) import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.Op (AsgnOp(AsgnOpEq)) import Language.SystemVerilog.AST.Type (Identifier)@@ -51,6 +53,7 @@     | Subroutine Expr Args     | Trigger Bool Identifier     | Assertion Assertion+    | Force Bool LHS Expr     | Continue     | Break     | Null@@ -96,6 +99,13 @@     show (Timing    t s) = printf "%s%s" (show t) (showShortBranch s)     show (Trigger   b x) = printf "->%s %s;" (if b then "" else ">") x     show (Assertion   a) = show a+    show (Force  kw l e) = printf "%s %s%s;" kwStr (show l) (showAssignment e)+        where+            kwStr = case (kw, e /= Nil) of+                (True , True ) -> "force"+                (True , False) -> "release"+                (False, True ) -> "assign"+                (False, False) -> "deassign"     show (Continue     ) = "continue;"     show (Break        ) = "break;"     show (Null         ) = ";"@@ -160,31 +170,47 @@ type Case = ([Expr], Stmt)  data Timing-    = Event Sense+    = Event Event     | Delay Expr     | Cycle Expr     deriving Eq  instance Show Timing where-    show (Event s) = printf  "@(%s)" (show s)+    show (Event e) = printf  "@(%s)" (show e)     show (Delay e) = printf  "#(%s)" (show e)     show (Cycle e) = printf "##(%s)" (show e) -data Sense-    = Sense        LHS-    | SenseOr      Sense Sense-    | SensePosedge LHS-    | SenseNegedge LHS-    | SenseStar+data Event+    = EventStar+    | EventExpr EventExpr     deriving Eq -instance Show Sense where-    show (Sense        a  ) = show a-    show (SenseOr      a b) = printf "%s or %s" (show a) (show b)-    show (SensePosedge a  ) = printf "posedge %s" (show a)-    show (SenseNegedge a  ) = printf "negedge %s" (show a)-    show (SenseStar       ) = "*"+instance Show Event where+    show EventStar = "*"+    show (EventExpr e) = show e +data EventExpr+    = EventExprEdge Edge Expr+    | EventExprOr EventExpr EventExpr+    deriving Eq++instance Show EventExpr where+    show (EventExprEdge g e) = printf "%s%s" (showPad g) (show e)+    show (EventExprOr   a b) = printf "%s or %s" (show a) (show b)++data Edge+    = Posedge+    | Negedge+    | Edge+    | NoEdge+    deriving Eq++instance Show Edge where+    show Posedge = "posedge"+    show Negedge = "negedge"+    show Edge    = "edge"+    show NoEdge  = ""+ data ActionBlock     = ActionBlock Stmt Stmt     deriving Eq@@ -222,7 +248,7 @@     | SeqExprIntersect  SeqExpr SeqExpr     | SeqExprThroughout Expr    SeqExpr     | SeqExprWithin     SeqExpr SeqExpr-    | SeqExprDelay (Maybe SeqExpr) Expr SeqExpr+    | SeqExprDelay (Maybe SeqExpr) Range SeqExpr     | SeqExprFirstMatch SeqExpr [SeqMatchItem]     deriving Eq instance Show SeqExpr where@@ -232,9 +258,14 @@     show (SeqExprIntersect  a b) = printf "(%s %s %s)" (show a) "intersect"  (show b)     show (SeqExprThroughout a b) = printf "(%s %s %s)" (show a) "throughout" (show b)     show (SeqExprWithin     a b) = printf "(%s %s %s)" (show a) "within"     (show b)-    show (SeqExprDelay   me e s) = printf "%s##%s %s" (maybe "" showPad me) (show e) (show s)+    show (SeqExprDelay   me r s) = printf "%s##%s %s" (maybe "" showPad me) (showCycleDelayRange r) (show s)     show (SeqExprFirstMatch e a) = printf "first_match(%s, %s)" (show e) (commas $ map show a) +showCycleDelayRange :: Range -> String+showCycleDelayRange (Nil, e) = printf "(%s)" (show e)+showCycleDelayRange (e, Nil) = printf "[%s:$]" (show e)+showCycleDelayRange r = showRange r+ type AssertionItem = (Identifier, Assertion)  data Assertion@@ -266,15 +297,15 @@     show FinalDeferred = "final"  data PropertySpec-    = PropertySpec (Maybe Sense) Expr PropExpr+    = PropertySpec (Maybe EventExpr) Expr PropExpr     deriving Eq instance Show PropertySpec where-    show (PropertySpec ms e pe) =-        printf "%s%s\n\t%s" msStr eStr (show pe)+    show (PropertySpec mv e pe) =+        printf "%s%s\n\t%s" mvStr eStr (show pe)         where-            msStr = case ms of+            mvStr = case mv of                 Nothing -> ""-                Just s -> printf "@(%s) " (show s)+                Just v -> printf "@(%s) " (show v)             eStr = case e of                 Nil -> ""                 _ -> printf "disable iff (%s)" (show e)
src/Language/SystemVerilog/AST/Type.hs view
@@ -9,6 +9,7 @@  module Language.SystemVerilog.AST.Type     ( Identifier+    , EnumItem     , Field     , Type               (..)     , Signing            (..)@@ -33,7 +34,7 @@  type Identifier = String -type Item = (Identifier, Expr)+type EnumItem = (Identifier, Expr) type Field = (Type, Identifier)  data Type@@ -44,13 +45,14 @@     | Alias               Identifier           [Range]     | PSAlias  Identifier Identifier           [Range]     | CSAlias  Identifier [ParamBinding] Identifier [Range]-    | Enum     Type         [Item]             [Range]+    | Enum     Type         [EnumItem]         [Range]     | Struct   Packing      [Field]            [Range]     | Union    Packing      [Field]            [Range]     | InterfaceT Identifier Identifier         [Range]     | TypeOf Expr     | TypedefRef Expr     | UnpackedType Type [Range] -- used internally+    | Void     deriving Eq  instance Show Type where@@ -66,13 +68,14 @@     show (Enum t vals r) = printf "enum %s{%s}%s" tStr (commas $ map showVal vals) (showRanges r)         where             tStr = showPad t-            showVal :: (Identifier, Expr) -> String+            showVal :: EnumItem -> String             showVal (x, e) = x ++ (showAssignment e)     show (Struct p items r) = printf "struct %s{\n%s\n}%s" (showPad p) (showFields items) (showRanges r)     show (Union  p items r) = printf  "union %s{\n%s\n}%s" (showPad p) (showFields items) (showRanges r)     show (TypeOf expr) = printf "type(%s)" (show expr)     show (UnpackedType t rs) = printf "UnpackedType(%s, %s)" (show t) (showRanges rs)     show (TypedefRef e) = show e+    show Void = "void"  showFields :: [Field] -> String showFields items = itemsStr@@ -101,6 +104,7 @@         NonInteger    kw       -> (nullRange $ NonInteger  kw   , [])         TypeOf            expr -> (nullRange $ TypeOf       expr, [])         TypedefRef        expr -> (nullRange $ TypedefRef   expr, [])+        Void                   -> (nullRange Void               , [])  nullRange :: Type -> ([Range] -> Type) nullRange t [] = t@@ -180,6 +184,7 @@     | TRealtime     | TString     | TEvent+    | TChandle     deriving Eq  instance Show NetType where@@ -212,6 +217,7 @@     show TRealtime  = "realtime"     show TString    = "string"     show TEvent     = "event"+    show TChandle   = "chandle"  data Packing     = Unpacked
src/Language/SystemVerilog/Parser/Parse.y view
@@ -406,7 +406,7 @@ %nonassoc "else" %right  "|->" "|=>" "#-#" "#=#" %right "iff"-%left "or"+%left "or" "," %left "and" %left "intersect" %left "within"@@ -518,9 +518,19 @@   | "realtime"  { withPos $1 TRealtime  }   | "string"    { withPos $1 TString    }   | "event"     { withPos $1 TEvent     }+  | "chandle"   { withPos $1 TChandle   } -EnumItems :: { [(Identifier, Expr)] }-  : VariablePortIdentifiers { $1 }+EnumItems :: { [EnumItem] }+  : EnumItem               { $1 }+  | EnumItem "," EnumItems { $1 ++ $3 }+EnumItem :: { [EnumItem] }+  : Identifier                    OptAsgn { [($1, $2)] }+  | IdentifierP IntegralDimension OptAsgn {% makeEnumItems $1 $2 $3 }+IntegralDimension :: { (Integer, Integer) }+  : "[" IntegralNumber                    "]" { ( 0, $2 - 1) }+  | "[" IntegralNumber ":" IntegralNumber "]" { ($2,     $4) }+IntegralNumber :: { Integer }+  : number {% readIntegralNumber (tokenPosition $1) (tokenString $1) }  StructItems :: { [(Type, Identifier)] }   : StructItem             { $1 }@@ -672,12 +682,6 @@   | "type" IdentifierP { [DTTypeDecl (tokenPosition $1), uncurry DTIdent $2] }   | ParameterDeclKW    { [uncurry DTParamKW $1] } -VariablePortIdentifiers :: { [(Identifier, Expr)] }-  : VariablePortIdentifier                             { [$1] }-  | VariablePortIdentifiers "," VariablePortIdentifier { $1 ++ [$3] }-VariablePortIdentifier :: { (Identifier, Expr) }-  : Identifier OptAsgn { ($1,$2) }- Direction :: { Direction }   : DirectionP { snd $1 } DirectionP :: { (Position, Direction) }@@ -762,7 +766,7 @@ PropertySpec :: { PropertySpec }   : OptClockingEvent "disable" "iff" "(" Expr ")" PropExpr { PropertySpec $1 $5  $7 }   | OptClockingEvent                              PropExpr { PropertySpec $1 Nil $2 }-OptClockingEvent :: { Maybe Sense }+OptClockingEvent :: { Maybe EventExpr }   : ClockingEvent { Just $1 }   | {- empty -}   { Nothing } @@ -786,8 +790,8 @@   | SeqExpr "intersect"  SeqExpr { SeqExprIntersect  $1 $3 }   | Expr    "throughout" SeqExpr { SeqExprThroughout $1 $3 }   | SeqExpr "within"     SeqExpr { SeqExprWithin     $1 $3 }-  | SeqExpr "##" Number  SeqExpr { SeqExprDelay (Just $1) (Number $3) $4 }-  |         "##" Number  SeqExpr { SeqExprDelay (Nothing) (Number $2) $3 }+  | SeqExpr "##" CycleDelayRange SeqExpr { SeqExprDelay (Just $1) $3 $4 }+  |         "##" CycleDelayRange SeqExpr { SeqExprDelay (Nothing) $2 $3 }   | "first_match" "(" SeqExpr SeqMatchItems ")" { SeqExprFirstMatch $3 $4 } SeqMatchItems :: { [SeqMatchItem] }   : "," SeqMatchItem               { [$2] }@@ -796,6 +800,16 @@   : ForStepAssignment   { SeqMatchAsgn $1 }   | Identifier CallArgs { SeqMatchCall $1 $2 } +CycleDelayRange :: { Range }+  : Range { $1 }+  | Number       { (Nil, Number $1) }+  | Identifier   { (Nil, Ident  $1) }+  | "(" Expr ")" { (Nil,        $2) }+  | "[" "+" "]"  { (RawNum 1, Nil) }+  | "[" "*" "]"  { (RawNum 0, Nil) }+  | "[*"    "]"  { (RawNum 0, Nil) }+  | "[" Expr ":" "$" "]" { ($2, Nil) }+ ActionBlock :: { ActionBlock }   : Stmt %prec NoElse { ActionBlock $1 Null }   |      "else" Stmt  { ActionBlock Null $2 }@@ -901,6 +915,7 @@   | ImportOrExport       { $1 }   | ForwardTypedef ";"   { $1 }   | TimeunitsDeclaration { $1 }+  | DPIImportExport      { [$1] }   | Directive            { [Directive $1] }  ImportOrExport :: { [PackageItem] }@@ -909,7 +924,6 @@   | "export" "*" "::" "*" ";"       { [Export "" ""] } TaskOrFunction :: { PackageItem }   : "function" Lifetime FuncRetAndName    TFItems DeclsAndStmts endfunction StrTag {% checkTag (snd $3) $7 $ Function $2 (fst $3) (snd $3) (map makeInput $4 ++ fst $5) (snd $5) }-  | "function" Lifetime "void" Identifier TFItems DeclsAndStmts endfunction StrTag {% checkTag $4       $8 $ Task     $2 $4                ($5 ++ fst $6) (snd $6) }   | "task"     Lifetime Identifier        TFItems DeclsAndStmts endtask     StrTag {% checkTag $3       $7 $ Task     $2 $3                ($4 ++ fst $5) (snd $5) } Typedef :: { Decl }   : "typedef" Type Identifier ";" { ParamType Localparam $3 $2 }@@ -928,6 +942,30 @@   | "timeunit" Time "/" Time ";" { [] }   | "timeprecision" Time     ";" { [] } +DPIImportExport :: { PackageItem }+  : "import" DPISpecString OptDPIImportProperty OptDPIAlias DPITFProto     { makeDPIImport $2 $3 $4 $5 }+  | "export" DPISpecString OptDPIAlias          DPIExportKW Identifier ";" { DPIExport $2 $3 $4 $5 }++DPIExportKW :: { DPIExportKW }+  : "task"     { DPIExportTask }+  | "function" { DPIExportFunction }++DPISpecString :: { String }+  : String { $1 }++OptDPIAlias :: { Identifier }+  : Identifier "=" { $1 }+  | {- empty -}    { "" }++OptDPIImportProperty :: { DPIImportProperty }+  : "context"   { DPIContext }+  | "pure"      { DPIPure }+  | {- empty -} { DPINone }++DPITFProto :: { (Type, Identifier, [Decl]) }+  : "function" FuncRetAndName    TFItems { (fst $2     , snd $2, $3) }+  | "task"     Identifier        TFItems { (UnknownType,     $2, $3) }+ Directive :: { String }   : "`celldefine"          { tokenString $1 }   | "`endcelldefine"       { tokenString $1 }@@ -955,6 +993,7 @@   | Signing                    Identifier { (Implicit $1          [], $2) }   |         DimensionsNonEmpty Identifier { (Implicit Unspecified $1, $2) }   | Signing DimensionsNonEmpty Identifier { (Implicit $1          $2, $3) }+  | "void"                     Identifier { (Void                   , $2) }  AlwaysKW :: { AlwaysKW }   : "always"       { Always      }@@ -1095,6 +1134,10 @@   | AttributeInstance Stmt                     { StmtAttr $1 $2 }   | ProceduralAssertionStatement               { Assertion $1 }   | "void" "'" "(" Expr CallArgs ")" ";"       { Subroutine $4 $5 }+  | "assign"   LHS "=" Expr ";"                { Force False $2  $4 }+  | "deassign" LHS          ";"                { Force False $2 Nil }+  | "force"    LHS "=" Expr ";"                { Force True  $2  $4 }+  | "release"  LHS          ";"                { Force True  $2 Nil }  OptDelayOrEvent :: { Maybe Timing }   : DelayOrEvent { Just $1 }@@ -1168,8 +1211,8 @@   | Identifier          { ($1, UnknownType) }  -- TODO: This does not allow for @identifier-ClockingEvent :: { Sense }-  : "@" "(" Senses ")" { $3 }+ClockingEvent :: { EventExpr }+  : "@" "(" EventExpr ")" { $3 }  TimingControl :: { Timing }   : DelayOrEvent { $1 }@@ -1188,26 +1231,27 @@   | "#" Identifier ParamBindings "::" Identifier { CSIdent $2 $3 $5 } CycleDelay :: { Expr }   : "##" Expr { $2 }-EventControl :: { Sense }-  : "@" "(" Senses ")" { $3 }-  | "@" "(*)"          { SenseStar }-  | "@" "(" "*" ")"    { SenseStar }-  | "@" "(*" ")"       { SenseStar }-  | "@" "(" "*)"       { SenseStar }-  | "@" "*"            { SenseStar }-  | "@*"               { SenseStar }-  | "@" Identifier     { Sense $ LHSIdent $2 }-Senses :: { Sense }-  : Sense             { $1 }-  | Senses "or" Sense { SenseOr $1 $3 }-  | Senses ","  Sense { SenseOr $1 $3 }-Sense :: { Sense }-  : "(" Sense ")"         {              $2 }-  |               LHS     { Sense        $1 }-  | "posedge"     LHS     { SensePosedge $2 }-  | "negedge"     LHS     { SenseNegedge $2 }-  | "posedge" "(" LHS ")" { SensePosedge $3 }-  | "negedge" "(" LHS ")" { SenseNegedge $3 }+EventControl :: { Event }+  : "@*"            { EventStar }+  | "@" "(*)"       { EventStar }+  | "@" "(" "*" ")" { EventStar }+  | "@" "(*" ")"    { EventStar }+  | "@" "(" "*)"    { EventStar }+  | "@" "*"         { EventStar }+  | "@" "(" EventExpr ")" { EventExpr $3 }+  | "@" Identifier        { EventExpr $ EventExprEdge NoEdge $ Ident $2 }+EventExpr :: { EventExpr }+  : Expr { EventExprEdge NoEdge $1 }+  | EventExprComplex { $1 }+EventExprComplex :: { EventExpr }+  : "(" EventExprComplex ")" { $2 }+  | Edge Expr { EventExprEdge $1 $2 }+  | EventExpr "or" EventExpr { EventExprOr $1 $3 }+  | EventExpr ","  EventExpr { EventExprOr $1 $3 }+Edge :: { Edge }+  : "posedge" { Posedge }+  | "negedge" { Negedge }+  | "edge"    { Edge    }  CaseKW :: { CaseKW }   : "case"  { CaseN }@@ -1343,6 +1387,11 @@   | "^"  Expr %prec REDUCE_OP { UniOp RedXor  $2 }   | "~^" Expr %prec REDUCE_OP { UniOp RedXnor $2 }   | "^~" Expr %prec REDUCE_OP { UniOp RedXnor $2 }+  -- assignments within expressions+  | "(" Expr "="        Expr ")" {% makeExprAsgn (tokenPosition $3, AsgnOpEq) $2 $4 }+  | "(" Expr AsgnBinOpP Expr ")" {% makeExprAsgn $3                           $2 $4 }+  | Expr IncOrDecOperatorP            {% makeIncrExprAsgn True  $2 $1 }+  | IncOrDecOperatorP Expr %prec "++" {% makeIncrExprAsgn False $1 $2 }  ExprOrNil :: { Expr }   : Expr        { $1 }@@ -1541,9 +1590,10 @@ makeInput :: Decl -> Decl makeInput (Variable Local t x a e) = Variable Input t x a e makeInput (Variable Input t x a e) = Variable Input t x a e+makeInput (Variable Output t x a e) = Variable Output t x a e makeInput (CommentDecl c) = CommentDecl c makeInput other =-  error $ "unexpected non-var or non-input decl: " ++ (show other)+  error $ "unexpected non-var or non-port function decl: " ++ (show other)  checkTag :: String -> String -> a -> ParseState a checkTag _ "" x = return x@@ -1713,5 +1763,54 @@     Decimal (-32) True 0 -> return a     _ -> parseError pos $ "expected 0 after #, but found " ++ str   where Token { tokenString = str, tokenPosition = pos } = tok++readIntegralNumber :: Position -> String -> ParseState Integer+readIntegralNumber pos str = do+  num <- readNumber pos str+  case numberToInteger num of+    Nothing ->+      parseError pos $ "expected an integral number, but found " ++ str+    Just integer | integer < 0 ->+      parseError pos $ "expected a non-negative number, but found " ++ str+    Just integer ->+      return integer++makeEnumItems :: (Position, Identifier) -> (Integer, Integer) -> Expr+  -> ParseState [EnumItem]+makeEnumItems (pos, _) (0, -1) _ =+  parseError pos "expected a positive number, but found zero"+makeEnumItems (_, root) (l, r) base =+  return $ (name, base) : map (, Nil) names+  where+    name : names =+      map (root ++) $+      map show $+      if l >= r+        then reverse [r..l]+        else [l..r]++makeDPIImport :: String -> DPIImportProperty -> Identifier+  -> (Type, Identifier, [Decl]) -> PackageItem+makeDPIImport a b c (d, e, f) = DPIImport a b c d e f++makeExprAsgn :: (Position, AsgnOp) -> Expr -> Expr -> ParseState Expr+makeExprAsgn (pos, AsgnOpEq) l r = do+  case exprToLHS l of+    Just{} -> return ()+    Nothing -> parseError pos $ "cannot convert expression to LHS: " ++ show l+  return $ ExprAsgn l r+makeExprAsgn (pos, op) l r =+  makeExprAsgn (pos, AsgnOpEq) l r'+  where+    AsgnOp binop = op+    r' = BinOp binop l r++makeIncrExprAsgn :: Bool -> (Position, BinOp) -> Expr -> ParseState Expr+makeIncrExprAsgn False (pos, op) expr =+  makeExprAsgn (pos, AsgnOp op) expr (RawNum 1)+makeIncrExprAsgn True (pos, op) expr = do+  expr' <- makeIncrExprAsgn False (pos, op) expr+  return $ BinOp op expr' minusOne+  where minusOne = Number $ Decimal 1 True 1  }
src/sv2v.hs view
@@ -4,13 +4,11 @@  - conversion entry point  -} -import System.Directory (doesFileExist) import System.IO (hPrint, hPutStrLn, stderr, stdout) import System.Exit (exitFailure, exitSuccess) -import Control.Monad (filterM, when, zipWithM_)+import Control.Monad (when, zipWithM_) import Control.Monad.Except (runExceptT)-import Data.List (intercalate)  import Convert (convert) import Job (readJob, Job(..), Write(..))@@ -63,11 +61,6 @@     writeFile f $ show $ concat asts writeOutput Adjacent inPaths asts = do     outPaths <- mapM rewritePath inPaths-    badPaths <- filterM doesFileExist outPaths-    when (not $ null badPaths) $ do-        hPutStrLn stderr $ "Refusing to write output because the following"-            ++ " files would be overwritten: " ++ intercalate ", " badPaths-        exitFailure     let results = map (++ "\n") $ map show asts     zipWithM_ writeFile outPaths results 
sv2v.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            sv2v-version:         0.0.9+version:         0.0.10 license:         BSD-3-Clause license-file:    LICENSE NOTICE maintainer:      Zachary Snow <zach@zachjs.com>@@ -55,9 +55,12 @@         Convert.BlockDecl         Convert.Cast         Convert.DimensionQuery+        Convert.DoWhile         Convert.DuplicateGenvar         Convert.EmptyArgs         Convert.Enum+        Convert.EventEdge+        Convert.ExprAsgn         Convert.ExprUtils         Convert.ForAsgn         Convert.Foreach@@ -106,12 +109,12 @@      build-depends:         array >=0.5.4.0 && <0.6,-        base >=4.14.1.0 && <4.15,+        base >=4.14.3.0 && <4.15,         cmdargs >=0.10.21 && <0.11,-        containers >=0.6.2.1 && <0.7,+        containers >=0.6.5.1 && <0.7,         directory >=1.3.6.0 && <1.4,         filepath >=1.4.2.1 && <1.5,-        githash >=0.1.6.1 && <0.2,+        githash >=0.1.6.2 && <0.2,         hashable >=1.3.0.0 && <1.4,         mtl >=2.2.2 && <2.3,-        vector >=0.12.3.0 && <0.13+        vector >=0.12.3.1 && <0.13