import FIFO::*; import GetPut::*; import ClientServer::*; typedef enum { ADD, SUB, MUL, DIV } Operation deriving(Bits, Eq); typedef union tagged { void Clear; struct { Operation op; value val; } Operate; } Command#(type value) deriving(Bits, Eq); typedef Server#(Command#(value), value) Calculator#(type value); instance Arith#(Bool); function Bool \+ (Bool a, Bool b) = a || b; function Bool \- (Bool a, Bool b) = !(a || b); function Bool \* (Bool a, Bool b) = a && b; function Bool \/ (Bool a, Bool b) = !(a && b); endinstance instance Literal#(Bool); function Bool fromInteger(Integer i) = (i != 0); endinstance module mkCalculator (Calculator#(value)) provisos(Arith#(value), Literal#(value), Bits#(value, value_sz)); Reg#(value) acc <- mkReg(0); FIFO#(value) outfifo <- mkFIFO(); interface Put request; method Action put(Command#(value) cmd); value upd = ?; case (cmd) matches tagged Clear: upd = 0; tagged Operate { op: .op, val: .val }: begin case (op) ADD: upd = acc + val; SUB: upd = acc - val; MUL: upd = acc * val; DIV: upd = acc / val; endcase end endcase acc <= upd; outfifo.enq(upd); endmethod endinterface interface Get response = toGet(outfifo); endmodule module mkDriver (Empty); Reg#(Int#(32)) state <- mkReg(0); Calculator#(8) calc <- mkCalculator(); rule s0 (state == 0); calc.request.put(tagged Operate { op: ADD, val: True }); state <= state + 1; endrule rule s1 (state == 1); calc.request.put(tagged Operate { op: SUB, val: False }); state <= state + 1; endrule rule s2 (state == 2); calc.request.put(tagged Clear); state <= state + 1; endrule rule s3 (state == 3); calc.request.put(tagged Operate { op: ADD, val: True }); state <= state + 1; endrule rule printout (True); let x <- calc.response.get(); $display(x); if (state == 4) begin $finish(); end endrule endmodule