packages feed

verismith-0.4.0.0: test/Reduce.hs

{-|
Module      : Reduce
Description : Test reduction.
Copyright   : (c) 2019, Yann Herklotz Grave
License     : GPL-3
Maintainer  : yann [at] yannherklotz [dot] com
Stability   : experimental
Portability : POSIX

Test reduction.
-}

{-# LANGUAGE QuasiQuotes #-}

module Reduce
    ( reduceUnitTests
    )
where

import           Data.List        ((\\))
import           Test.Tasty
import           Test.Tasty.HUnit
import           Verismith
import           Verismith.Reduce

reduceUnitTests :: TestTree
reduceUnitTests = testGroup
    "Reducer tests"
    [ moduleReducerTest
    , modItemReduceTest
    , halveStatementsTest
    , statementReducerTest
    , activeWireTest
    , cleanTest
    , cleanAllTest
    , removeDeclTest
    ]

-- brittany-disable-next-binding
removeDeclTest :: TestTree
removeDeclTest = testCase "Remove declarations" $ do
    GenVerilog (removeDecl srcInfo1) @?= golden1
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top;
  wire a;
  wire b;
  wire c;
  reg d;
  reg e;
  reg f;
  reg g;
  reg h;
  wire i;
  wire j;
  wire clk;
  initial d <= a;

  always @* begin
    f <= e;
    g <= e;
    if (1) begin
      h <= h;
    end
  end

  always @(posedge clk);

  assign b = g;
endmodule
|]
        golden1 = GenVerilog $ SourceInfo "top" [verilog|
module top;
  wire a;
  wire b;
  reg d;
  reg e;
  reg f;
  reg g;
  reg h;
  wire clk;
  initial d <= a;

  always @* begin
    f <= e;
    g <= e;
    if (1) begin
      h <= h;
    end
  end

  always @(posedge clk);

  assign b = g;
endmodule
|]

-- brittany-disable-next-binding
cleanAllTest :: TestTree
cleanAllTest = testCase "Clean all" $ do
    GenVerilog (cleanSourceInfoAll srcInfo1) @?= golden1
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + c;
  assign b = c + d;
endmodule

module mod1;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + c;
  assign b = c + d;
endmodule

module mod2;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + c;
  assign b = c + d;
endmodule
|]
        golden1 = GenVerilog $ SourceInfo "top" [verilog|
module top;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + 1'b0;
  assign b = 1'b0 + 1'b0;
endmodule

module mod1;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + 1'b0;
  assign b = 1'b0 + 1'b0;
endmodule

module mod2;
  wire a;
  wire b;
  wire c;
  wire d;
  assign a = b + 1'b0;
  assign b = 1'b0 + 1'b0;
endmodule
|]

-- brittany-disable-next-binding
cleanTest :: TestTree
cleanTest = testCase "Clean expression" $ do
    clean ["wire1", "wire2"] srcInfo1 @?= golden1
    clean ["wire1", "wire3"] srcInfo2 @?= golden2
    where
        srcInfo1 = GenVerilog . SourceInfo "top" $ [verilog|
module top;
  wire wire1;
  wire wire2;
  wire wire3;
  assign wire1 = wire2[wire3];
endmodule
|]
        golden1 = GenVerilog . SourceInfo "top" $ [verilog|
module top;
  wire wire1;
  wire wire2;
  wire wire3;
  assign wire1 = wire2[1'b0];
endmodule
|]
        srcInfo2 = GenVerilog . SourceInfo "top" $ [verilog|
module top;
  wire wire1;
  wire wire2;
  wire wire3;
  assign wire1 = wire2[wire3:wire1];
endmodule
|]
        golden2 = GenVerilog . SourceInfo "top" $ [verilog|
module top;
  wire wire1;
  wire wire2;
  wire wire3;
  assign wire1 = 1'b0;
endmodule
|]


-- brittany-disable-next-binding
activeWireTest :: TestTree
activeWireTest = testCase "Active wires" $ do
    findActiveWires "top" verilog1 \\ ["x", "y", "z", "w"]          @?= []
    findActiveWires "top" verilog2 \\ ["x", "y", "z"]               @?= []
    findActiveWires "top" verilog3 \\ ["x", "y", "clk", "r1", "r2"] @?= []
    findActiveWires "top" verilog4 \\ ["x", "y", "w", "a", "b"]     @?= []
    where
        verilog1 = SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  assign z = 0;
  assign w = 2;
  assign y = w + z;
endmodule
|]
        verilog2 = SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  assign z = 0;
endmodule
|]
        verilog3 = SourceInfo "top" [verilog|
module top(clk, y, x);
  input clk;
  input x;
  output y;
  reg r1;
  reg r2;
  reg r3;
  wire w;
  always @(posedge clk) begin
    r1 <= r3;
    r2 <= r1;
  end

  always @(posedge clk) begin
    r1 <= r2;
  end
  random_inst inst(x, y, w);
  assign y = {r1, r2, r3};
endmodule
|]
        verilog4 = SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  wire a;
  wire b;
  wire c;
  m1 m1(w, z);
  m2 m2(.x(c), .z(a), .y(b));
endmodule

module m1(y, x);
  input x;
  output y;
endmodule

module m2(y, z, x);
  input x;
  output y;
  output z;
endmodule
|]

-- brittany-disable-next-binding
halveStatementsTest :: TestTree
halveStatementsTest = testCase "Statements" $ do
    GenVerilog <$> halveStatements "top" srcInfo1 @?= golden1
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top(clk, y, x);
  input clk;
  input x;
  output y;
  reg r1;
  reg r2;
  reg r3;
  always @(posedge clk) begin
    r1 <= r3;
    r2 <= r1;
    r3 <= r2;
  end

  always @(posedge clk) begin
    r1 <= r2;
    r2 <= r3;
    r3 <= r1;
  end
  assign y = {r1, r2, r3};
endmodule
|]
        golden1 = GenVerilog <$> Dual (SourceInfo "top" [verilog|
module top(clk, y, x);
  input clk;
  input x;
  output y;
  reg r1;
  reg r2;
  reg r3;
  always @(posedge clk) begin
    r1 <= 1'b0;
  end

  always @(posedge clk) begin
    r1 <= 1'b0;
  end
  assign y = {r1, 1'b0, 1'b0};
endmodule
|]) (SourceInfo "top" [verilog|
module top(clk, y, x);
  input clk;
  input x;
  output y;
  reg r1;
  reg r2;
  reg r3;
  always @(posedge clk) begin
    r2 <= 1'b0;
    r3 <= r2;
  end

  always @(posedge clk) begin
    r2 <= r3;
    r3 <= 1'b0;
  end
  assign y = {1'b0, r2, r3};
endmodule
|])

-- brittany-disable-next-binding
modItemReduceTest :: TestTree
modItemReduceTest = testCase "Module items" $ do
    GenVerilog <$> halveModItems "top" srcInfo1 @?= golden1
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  assign z = x;
  assign w = z;
  assign y = w;
endmodule
|]
        golden1 = GenVerilog <$> Dual (SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  assign y = 1'b0;
  assign z = x;
endmodule
|]) (SourceInfo "top" [verilog|
module top(y, x);
  input x;
  output y;
  wire z;
  wire w;
  assign y = w;
  assign w = 1'b0;
endmodule
|])

-- brittany-disable-next-binding
statementReducerTest :: TestTree
statementReducerTest = testCase "Statement reducer" $ do
    GenVerilog <$> halveStatements "top" srcInfo1 @?= fmap GenVerilog golden1
    GenVerilog <$> halveStatements "top" srcInfo2 @?= fmap GenVerilog golden2
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk) begin
    a <= 1;
    b <= 2;
    c <= 3;
    d <= 4;
  end

  always @(posedge clk) begin
    a <= 1;
    b <= 2;
    c <= 3;
    d <= 4;
  end
endmodule
|]
        golden1 = Dual (SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk) begin
    a <= 1;
    b <= 2;
  end

  always @(posedge clk) begin
    a <= 1;
    b <= 2;
  end
endmodule
|]) $ SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk) begin
    c <= 3;
    d <= 4;
  end

  always @(posedge clk) begin
    c <= 3;
    d <= 4;
  end
endmodule
|]
        srcInfo2 = SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk) begin
    if (x)
      y <= 2;
    else
      y <= 3;
  end
endmodule
|]
        golden2 = Dual (SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk)
      y <= 2;
endmodule
|]) $ SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;

  always @(posedge clk)
      y <= 3;
endmodule
|]

-- brittany-disable-next-binding
moduleReducerTest :: TestTree
moduleReducerTest = testCase "Module reducer" $ do
    halveModules srcInfo1 @?= golden1
    halveModules srcInfo2 @?= golden2
    where
        srcInfo1 = SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
  m m(y, x);
endmodule

module m(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule
|]
        golden1 = Single $ SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule
|]
        srcInfo2 = SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
  m m(y, x);
  m2 m2(y, x);
endmodule

module m(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule

module m2(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule
|]
        golden2 = Dual (SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
  m m(y, x);
endmodule

module m(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule
|]) $ SourceInfo "top" [verilog|
module top(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
  m2 m2(y, x);
endmodule

module m2(y, x);
  output wire [4:0] y;
  input wire [4:0] x;
endmodule
|]