Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLaSH compiler generates unused signed integers when converting from type Bit to Bool #329

Closed
Nrmize opened this issue Jul 19, 2018 · 2 comments

Comments

@Nrmize
Copy link

Nrmize commented Jul 19, 2018

Hi all,

I noticed something peculiar in a piece of code that I made to combine and invert two reset signals into one. Here is the code block I made:

module ResetEither where

import Clash.Prelude
import Clash.Signal.Internal

{-# ANN topEntityResEither
  (Synthesize
    { t_name   = "ResetEither"
    , t_inputs = [ PortName "A_RST"
                 , PortName "B_RST"
                 ]
    , t_output = PortName "RST_OUT"
    }) #-}
topEntityResEither
  :: Reset System Synchronous--A_RST
  -> Reset System Synchronous--B_RST
  -> Reset System Synchronous--RST_OUT
topEntityResEither = resetEither

resetEither
  :: Reset System Synchronous--A_RST
  -> Reset System Synchronous--B_RST
  -> Reset System Synchronous--RST_OUT
resetEither rsta rstb = reset_out
  where
    rstaBool = fromSyncReset rsta
    rstbBool = fromSyncReset rstb
    andA = ((.==.) (pure False) rstaBool) 
    andB = ((.==.) (pure False) rstbBool)

    reset_out = unsafeToSyncReset ((.||.) andA andB)

This code will generate the following VHDL:

-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.reseteither_types.all;

entity ResetEither is
  port(-- asynchronous reset: active high
       A_RST   : in std_logic;
       -- asynchronous reset: active high
       B_RST   : in std_logic;
       -- asynchronous reset: active high
       RST_OUT : out std_logic);
end;

architecture structural of ResetEither is
  signal ds1      : boolean;
  signal result   : boolean;
  signal ds1_0    : boolean;
  signal result_0 : boolean;
begin
  ds1 <= true when A_RST = '1' else false;

  result <= false when ds1 else
            true;

  ds1_0 <= true when B_RST = '1' else false;

  result_0 <= false when ds1_0 else
              true;

  RST_OUT <= '1' when (result or result_0) else '0';
end;

Now, if I were to change the following lines in my source Haskell code from:

    andA = ((.==.) (pure False) rstaBool) 
    andB = ((.==.) (pure False) rstbBool)

To:

    andA = ((.==.) (pure (bitToBool rst_val)) rstaBool) 
    andB = ((.==.) (pure (bitToBool rst_val)) rstbBool)

Where I use bitToBool to create my first Bool value and 'rst_val' is a Bit type that is equal to '0'. The functionality remains the same, however the following VHDL is generated instead:

-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.reseteither_types.all;

entity ResetEither is
  port(-- asynchronous reset: active high
       A_RST   : in std_logic;
       -- asynchronous reset: active high
       B_RST   : in std_logic;
       -- asynchronous reset: active high
       RST_OUT : out std_logic);
end;

architecture structural of ResetEither is
  signal \#case_alt\            : boolean;
  signal ds1                    : boolean;
  signal result                 : boolean;
  signal \#case_alt_0\          : boolean;
  signal ds1_0                  : boolean;
  signal result_0               : boolean;
  signal result_selection_res   : std_logic_vector(0 downto 0);
  signal \#i\                   : signed(63 downto 0);
  signal result_0_selection_res : std_logic_vector(0 downto 0);
  signal \#i_0\                 : signed(63 downto 0);
begin
  \#case_alt\ <= false when ds1 else
                 true;

  ds1 <= true when A_RST = '1' else false;

  \#i\ <= to_signed(0,64);

  result_selection_res <= std_logic_vector'(0 => '0');

  with (result_selection_res) select
    result <= ds1 when "1",
              \#case_alt\ when others;

  \#case_alt_0\ <= false when ds1_0 else
                   true;

  ds1_0 <= true when B_RST = '1' else false;

  \#i_0\ <= to_signed(0,64);

  result_0_selection_res <= std_logic_vector'(0 => '0');

  with (result_0_selection_res) select
    result_0 <= ds1_0 when "1",
                \#case_alt_0\ when others;

  RST_OUT <= '1' when (result or result_0) else '0';
end;

As, you can see, there are several instances where the compiler generated signed 64 bit integers in the VHDL that are not being used (signals #i\ and #i_0). Has anyone else had similar issues with the 'boolToBit' or 'bittoBool' functions found in Clash.Class.BitPack ?

I would prefer to have each signal be of Bit type rather than Bool for my particular application. But this issue tends to bloat the VHDL signal declarations on my other larger designs that use 'bitToBool' more often.

@Nrmize Nrmize changed the title CLaSH compiler generates unused signed integers when doing a Bit comparison CLaSH compiler generates unused signed integers when converting from type Bit to Bool Jul 19, 2018
@christiaanb
Copy link
Member

Ah, I see the 0.99 branch doesn't have fa6f55e that's in master which is what's causing this in case of calling bitToBool on constants.

@christiaanb
Copy link
Member

The latest version includes the above mentioned fix

leonschoorl pushed a commit that referenced this issue Jul 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants