hsverilog-0.1.0: tests/test.hs
{-#LANGUAGE TypeFamilies#-}
{-#LANGUAGE TemplateHaskell#-}
{-#LANGUAGE QuasiQuotes#-}
{-#LANGUAGE OverloadedStrings#-}
import qualified Data.Text as T
import qualified Data.Map as M
import Test.Hspec hiding (shouldBe,shouldReturn)
import Test.Hspec.Expectations.Lifted
import HsVerilog
import Text.Shakespeare.Text
import Control.Monad
trimSpace' :: T.Text -> String
trimSpace' x = dropWhile (== ' ') $ trimSpace $ T.unpack x
trimSpace :: String -> String
trimSpace [] = []
trimSpace (' ':'\n':xs) = trimSpace (' ':xs)
trimSpace (' ':'\t':xs) = trimSpace (' ':xs)
trimSpace (' ':' ':xs) = trimSpace (' ':xs)
trimSpace (' ':';':xs) = trimSpace (';':xs)
trimSpace (' ':'@':xs) = trimSpace ('@':xs)
trimSpace (' ':'(':xs) = trimSpace ('(':xs)
trimSpace (' ':')':xs) = trimSpace (')':xs)
trimSpace (' ':',':xs) = trimSpace (',':xs)
trimSpace ('\t':xs) = trimSpace (' ':xs)
trimSpace ('\n':xs) = trimSpace (' ':xs)
trimSpace (x:xs) = x:trimSpace xs
(=~) :: Verilog a => a -> T.Text -> Expectation
(=~) org exp' = (trimSpace' (toVerilog org)) `shouldBe` trimSpace' exp'
infix 1 =~
dff2 :: Circuit
dff2 = circuit "dff2" $ do
clk <- input "clk" Bit
rstn <- input "rstn" Bit
din <- fmap S $ input "din" Bit
_dout <- output "dout" Bit
reg' "dout" Bit [Posedge clk,Negedge rstn] $
If (Not (S rstn))
0
din
main :: IO ()
main = hspec $ do
describe "verilog" $ do
it "dff and simple register" $
dff2 =~
[sbt|module dff2 (clk, rstn, din, dout);
| input clk;
| input rstn;
| input din;
| output dout;
| reg dout;
| always @(posedge clk or negedge rstn) begin
| if (!rstn)
| dout <= 0;
| else
| dout <= din;
| end
|endmodule
|]
it "counter and simple register" $ do
counter <- circuitM "counter" $ do
clk <- input "clk" Bit
rstn <- input "rstn" Bit
_ <- output "dout" $ 7><0
reg "dout" (7><0) [Posedge clk,Negedge rstn] $ \dout ->
If (Not (S rstn)) 0 $
If (Eq dout 7)
0
(dout + 1)
counter =~
[sbt|module counter (clk, rstn, dout);
| input clk;
| input rstn;
| output [7:0] dout;
| reg [7:0] dout;
| always @(posedge clk or negedge rstn) begin
| if (!rstn)
| dout[7:0] <= 0;
| else if ((dout[7:0] == 7))
| dout[7:0] <= 0;
| else
| dout[7:0] <= (dout[7:0] + 1);
| end
|endmodule
|]
it "state machine(I think this is dirty.)" $ do
cir <- circuitM "StateMachine" $ do
clk <- input "clk" Bit
rstn <- input "rstn" Bit
let idx :: String -> Exp
idx state = (M.fromList $ zip ["init","run0","run1"] (map C [0..])) M.! state
reg "state" (7><0) [Posedge clk,Negedge rstn] $ \state ->
If (Not (S rstn)) (idx "init") $
If (Eq state (idx "init")) (idx "run0") $
If (Eq state (idx "run0")) (idx "run1") $ idx "init"
cir =~
[sbt|module StateMachine (clk, rstn);
| input clk;
| input rstn;
| reg [7:0] state;
| always @(posedge clk or negedge rstn) begin
| if (!rstn)
| state[7:0] <= 0;
| else if ((state[7:0] == 0))
| state[7:0] <= 1;
| else if ((state[7:0] == 1))
| state[7:0] <= 2;
| else
| state[7:0] <= 0;
| end
|endmodule
|]
it "instance" $ do
testTop <- circuitM "Top" $ do
clk <- input "clk" Bit
din <- input "din" Bit
rstn <- input "rstn" Bit
dout <- output "dout" Bit
i0 <- inst dff2 "dff0" [("clk",clk),
("din",din),
("rstn",rstn)]
i1 <- inst dff2 "dff1" [("clk",clk),
("din",i0.:"dout"),
("rstn",rstn)]
assign dout (S (i1.:"dout"))
testTop =~
[sbt|module Top (clk, din, rstn, dout);
| input clk;
| input din;
| input rstn;
| output dout;
| wire dff0_dout;
| wire dff1_dout;
| assign dout = dff1_dout
| dff2 dff0(.clk(clk),
| .din(din),
| .rstn(rstn),
| .dout(dff0_dout));
| dff2 dff1(.clk(clk),
| .din(dff0_dout),
| .rstn(rstn),
| .dout(dff1_dout));
|endmodule
|]
it "instance loop" $ do
testTop <- circuitM "Top" $ do
clk <- input "clk" Bit
rstn <- input "rstn" Bit
i0 <- inst dff2 "dff0" [("clk",clk),
("rstn",rstn)]
i1 <- inst dff2 "dff1" [("clk",clk),
("rstn",rstn)]
connect i0 "din" $ i1.:"dout"
connect i1 "din" $ i0.:"dout"
testTop =~
[sbt|module Top (clk, rstn);
| input clk;
| input rstn;
| wire dff0_dout;
| wire dff1_dout;
| dff2 dff0(.clk(clk),
| .rstn(rstn),
| .dout(dff0_dout),
| .din(dff1_dout));
| dff2 dff1(.clk(clk),
| .rstn(rstn),
| .dout(dff1_dout),
| .din(dff0_dout));
|endmodule
|]
it "assign" $ do
cir <- circuitM "mulAdd" $ do
din0 <- fmap S $ input "din0" Bit
din1 <- fmap S $ input "din1" Bit
din2 <- fmap S $ input "din2" Bit
dout <- output "dout" Bit
assign dout $ (din0 * din1) + din2
cir =~
[sbt|module mulAdd (din0, din1, din2, dout);
| input din0;
| input din1;
| input din2;
| output dout;
| assign dout = ((din0 * din1) + din2)
|endmodule
|]
it "range" $ do
cir <- circuitM "mulAdd" $ do
din0 <- fmap S $ input "din0" $ 7><0
din1 <- fmap S $ input "din1" $ 7><0
din2 <- fmap S $ input "din2" $ 7><0
dout <- output "dout" $ 7><0
assign dout $ din0 * din1 + din2
cir =~
[sbt|module mulAdd (din0, din1, din2, dout);
| input [7:0] din0;
| input [7:0] din1;
| input [7:0] din2;
| output [7:0] dout;
| assign dout[7:0] = ((din0[7:0] * din1[7:0]) + din2[7:0])
|endmodule
|]
describe "simulation: Exp" $ do
-- it "Add" $ do
-- val (initCircuit "hoge") (2 + 1) `shouldBe` 3
-- it "Mul" $
-- val (initCircuit "hoge") (2 * 2) `shouldBe` 4
it "count up" $ do
print "123"
counter <- circuitM "counter" $ do
clk <- input "clk" Bit
rstn <- input "rstn" Bit
_ <- output "dout" $ 7><0
reg "dout" (7><0) [Posedge clk,Negedge rstn] $ \dout ->
If (Not (S rstn)) 0 $
If (Eq dout 7)
0
(dout + 1)
simM counter $ do
readInput "rstn" `shouldReturn` 0
"rstn" <== 1
readInput "rstn" `shouldReturn` 1
readReg "dout" `shouldReturn` 0
updateReg
readReg "dout" `shouldReturn` 1
updateReg
readReg "dout" `shouldReturn` 2
updateReg
readReg "dout" `shouldReturn` 3
updateReg
readReg "dout" `shouldReturn` 4
print'
return ()