aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver/CoqupDriver.ml4
-rw-r--r--src/translation/Veriloggen.v228
-rw-r--r--src/verilog/PrintVerilog.ml50
-rw-r--r--src/verilog/Verilog.v15
4 files changed, 183 insertions, 114 deletions
diff --git a/driver/CoqupDriver.ml b/driver/CoqupDriver.ml
index 92553c9..0a4f84f 100644
--- a/driver/CoqupDriver.ml
+++ b/driver/CoqupDriver.ml
@@ -85,7 +85,7 @@ let compile_i_file sourcename preproname =
""
end else if !option_S then begin
compile_c_file sourcename preproname
- (output_filename ~final:true sourcename ".c" ".s");
+ (output_filename ~final:true sourcename ".c" ".v");
""
end else begin
let asmname =
@@ -294,7 +294,7 @@ let cmdline_actions =
(* Processing options *)
[ Exact "-c", Set option_c;
Exact "-E", Set option_E;
- Exact "-S", Set option_S;
+ Exact "--hls", Set option_S;
Exact "-o", String(fun s -> option_o := Some s);
Prefix "-o", Self (fun s -> let s = String.sub s 2 ((String.length s) - 2) in
option_o := Some s);]
diff --git a/src/translation/Veriloggen.v b/src/translation/Veriloggen.v
index c2614ec..8ecb2ac 100644
--- a/src/translation/Veriloggen.v
+++ b/src/translation/Veriloggen.v
@@ -36,9 +36,7 @@ Record state: Type := mkstate {
st_freshstate : node;
st_stm : PositiveMap.t stmnt;
st_statetrans : PositiveMap.t statetrans;
- st_decl : list (reg * nat);
- st_fin : option reg;
- st_ret : option reg;
+ st_decl : PositiveMap.t nat;
}.
(** Map from initial register allocations to new allocations. *)
@@ -49,9 +47,7 @@ Definition init_state : state :=
1%positive
(PositiveMap.empty stmnt)
(PositiveMap.empty statetrans)
- nil
- None
- None.
+ (PositiveMap.empty nat).
Inductive res (A: Type) (s: state): Type :=
| Error : Errors.errmsg -> res A s
@@ -118,67 +114,94 @@ Fixpoint traverselist {A B: Type} (f: A -> mon B) (l: list A) {struct l}: mon (l
Definition nonblock (dst : reg) (e : expr) := Vnonblock (Vvar dst) e.
Definition block (dst : reg) (e : expr) := Vblock (Vvar dst) e.
-Definition bop (op : binop) (r1 r2 : reg) : option expr :=
- Some (Vbinop op (Vvar r1) (Vvar r2)).
+Definition bop (op : binop) (r1 r2 : reg) : expr :=
+ Vbinop op (Vvar r1) (Vvar r2).
-Definition boplit (op : binop) (r : reg) (l : Integers.int) : option expr :=
- Some (Vbinop op (Vvar r) (Vlit (intToValue l))).
+Definition boplit (op : binop) (r : reg) (l : Integers.int) : expr :=
+ Vbinop op (Vvar r) (Vlit (intToValue l)).
-Definition translate_comparison (c : Integers.comparison) (args : list reg) : option expr :=
+Definition boplitz (op: binop) (r: reg) (l: Z) : expr :=
+ Vbinop op (Vvar r) (Vlit (ZToValue 32%nat l)).
+
+Definition translate_comparison (c : Integers.comparison) (args : list reg) : mon expr :=
+ match c, args with
+ | Integers.Ceq, r1::r2::nil => ret (bop Veq r1 r2)
+ | Integers.Cne, r1::r2::nil => ret (bop Vne r1 r2)
+ | Integers.Clt, r1::r2::nil => ret (bop Vlt r1 r2)
+ | Integers.Cgt, r1::r2::nil => ret (bop Vgt r1 r2)
+ | Integers.Cle, r1::r2::nil => ret (bop Vle r1 r2)
+ | Integers.Cge, r1::r2::nil => ret (bop Vge r1 r2)
+ | _, _ => error (Errors.msg "Veriloggen: comparison instruction not implemented: other")
+ end.
+
+Definition translate_comparison_imm (c : Integers.comparison) (args : list reg) (i: Integers.int)
+ : mon expr :=
match c, args with
- | Integers.Ceq, r1::r2::nil => bop Veq r1 r2
- | Integers.Cne, r1::r2::nil => bop Vne r1 r2
- | Integers.Clt, r1::r2::nil => bop Vlt r1 r2
- | Integers.Cgt, r1::r2::nil => bop Vgt r1 r2
- | Integers.Cle, r1::r2::nil => bop Vle r1 r2
- | Integers.Cge, r1::r2::nil => bop Vge r1 r2
- | _, _ => None
+ | Integers.Ceq, r1::nil => ret (boplit Veq r1 i)
+ | Integers.Cne, r1::nil => ret (boplit Vne r1 i)
+ | Integers.Clt, r1::nil => ret (boplit Vlt r1 i)
+ | Integers.Cgt, r1::nil => ret (boplit Vgt r1 i)
+ | Integers.Cle, r1::nil => ret (boplit Vle r1 i)
+ | Integers.Cge, r1::nil => ret (boplit Vge r1 i)
+ | _, _ => error (Errors.msg "Veriloggen: comparison_imm instruction not implemented: other")
end.
-Definition translate_condition (c : Op.condition) (args : list reg) : option expr :=
+Definition translate_condition (c : Op.condition) (args : list reg) : mon expr :=
match c, args with
| Op.Ccomp c, _ => translate_comparison c args
- | Op.Ccompu c, _ => None
- | Op.Ccompimm c i, _ => None
- | Op.Ccompuimm c i, _ => None
- | Op.Cmaskzero n, _ => None
- | Op.Cmasknotzero n, _ => None
- | _, _ => None
+ | Op.Ccompu c, _ => translate_comparison c args
+ | Op.Ccompimm c i, _ => translate_comparison_imm c args i
+ | Op.Ccompuimm c i, _ => translate_comparison_imm c args i
+ | Op.Cmaskzero n, _ => error (Errors.msg "Veriloggen: condition instruction not implemented: Cmaskzero")
+ | Op.Cmasknotzero n, _ => error (Errors.msg "Veriloggen: condition instruction not implemented: Cmasknotzero")
+ | _, _ => error (Errors.msg "Veriloggen: condition instruction not implemented: other")
+ end.
+
+Definition translate_eff_addressing (a: Op.addressing) (args: list reg) : mon expr :=
+ match a, args with
+ | Op.Aindexed off, r1::nil => ret (boplitz Vadd r1 off)
+ | Op.Aindexed2 off, r1::r2::nil => ret (Vbinop Vadd (Vvar r1) (boplitz Vadd r2 off))
+ | Op.Ascaled scale offset, r1::nil =>
+ ret (Vbinop Vadd (boplitz Vadd r1 scale) (Vlit (ZToValue 32%nat offset)))
+ | Op.Aindexed2scaled scale offset, r1::r2::nil =>
+ ret (Vbinop Vadd (boplitz Vadd r1 offset) (boplitz Vmul r2 scale))
+ | _, _ => error (Errors.msg "Veriloggen: eff_addressing instruction not implemented: other")
end.
(** Translate an instruction to a statement. *)
-Definition translate_instr (op : Op.operation) (args : list reg) : option expr :=
+Definition translate_instr (op : Op.operation) (args : list reg) : mon expr :=
match op, args with
- | Op.Omove, r::nil => Some (Vvar r)
- | Op.Ointconst n, _ => Some (Vlit (intToValue n))
- | Op.Oneg, r::nil => Some (Vunop Vneg (Vvar r))
- | Op.Osub, r1::r2::nil => bop Vsub r1 r2
- | Op.Omul, r1::r2::nil => bop Vmul r1 r2
- | Op.Omulimm n, r::nil => boplit Vmul r n
- | Op.Omulhs, _ => None
- | Op.Omulhu, _ => None
- | Op.Odiv, r1::r2::nil => bop Vdiv r1 r2
- | Op.Odivu, r1::r2::nil => bop Vdivu r1 r2
- | Op.Omod, r1::r2::nil => bop Vmod r1 r2
- | Op.Omodu, r1::r2::nil => bop Vmodu r1 r2
- | Op.Oand, r1::r2::nil => bop Vand r1 r2
- | Op.Oandimm n, r::nil => boplit Vand r n
- | Op.Oor, r1::r2::nil => bop Vor r1 r2
- | Op.Oorimm n, r::nil => boplit Vor r n
- | Op.Oxor, r1::r2::nil => bop Vxor r1 r2
- | Op.Oxorimm n, r::nil => boplit Vxor r n
- | Op.Onot, r::nil => Some (Vunop Vnot (Vvar r))
- | Op.Oshl, r1::r2::nil => bop Vshl r1 r2
- | Op.Oshlimm n, r::nil => boplit Vshl r n
- | Op.Oshr, r1::r2::nil => bop Vshr r1 r2
- | Op.Oshrimm n, r::nil => boplit Vshr r n
- | Op.Oshrximm n, r::nil => None
- | Op.Oshru, r1::r2::nil => None
- | Op.Oshruimm n, r::nil => None
- | Op.Ororimm n, r::nil => None
- | Op.Oshldimm n, r::nil => None
+ | Op.Omove, r::nil => ret (Vvar r)
+ | Op.Ointconst n, _ => ret (Vlit (intToValue n))
+ | Op.Oneg, r::nil => ret (Vunop Vneg (Vvar r))
+ | Op.Osub, r1::r2::nil => ret (bop Vsub r1 r2)
+ | Op.Omul, r1::r2::nil => ret (bop Vmul r1 r2)
+ | Op.Omulimm n, r::nil => ret (boplit Vmul r n)
+ | Op.Omulhs, _ => error (Errors.msg "Veriloggen: Instruction not implemented: Omulhs")
+ | Op.Omulhu, _ => error (Errors.msg "Veriloggen: Instruction not implemented: Omulhu")
+ | Op.Odiv, r1::r2::nil => ret (bop Vdiv r1 r2)
+ | Op.Odivu, r1::r2::nil => ret (bop Vdivu r1 r2)
+ | Op.Omod, r1::r2::nil => ret (bop Vmod r1 r2)
+ | Op.Omodu, r1::r2::nil => ret (bop Vmodu r1 r2)
+ | Op.Oand, r1::r2::nil => ret (bop Vand r1 r2)
+ | Op.Oandimm n, r::nil => ret (boplit Vand r n)
+ | Op.Oor, r1::r2::nil => ret (bop Vor r1 r2)
+ | Op.Oorimm n, r::nil => ret (boplit Vor r n)
+ | Op.Oxor, r1::r2::nil => ret (bop Vxor r1 r2)
+ | Op.Oxorimm n, r::nil => ret (boplit Vxor r n)
+ | Op.Onot, r::nil => ret (Vunop Vnot (Vvar r))
+ | Op.Oshl, r1::r2::nil => ret (bop Vshl r1 r2)
+ | Op.Oshlimm n, r::nil => ret (boplit Vshl r n)
+ | Op.Oshr, r1::r2::nil => ret (bop Vshr r1 r2)
+ | Op.Oshrimm n, r::nil => ret (boplit Vshr r n)
+ | Op.Oshrximm n, r::nil => error (Errors.msg "Veriloggen: Instruction not implemented: Oshrximm")
+ | Op.Oshru, r1::r2::nil => error (Errors.msg "Veriloggen: Instruction not implemented: Oshru")
+ | Op.Oshruimm n, r::nil => error (Errors.msg "Veriloggen: Instruction not implemented: Oshruimm")
+ | Op.Ororimm n, r::nil => error (Errors.msg "Veriloggen: Instruction not implemented: Ororimm")
+ | Op.Oshldimm n, r::nil => error (Errors.msg "Veriloggen: Instruction not implemented: Oshldimm")
| Op.Ocmp c, _ => translate_condition c args
- | _, _ => None
+ | Op.Olea a, _ => translate_eff_addressing a args
+ | _, _ => error (Errors.msg "Veriloggen: Instruction not implemented: other")
end.
Definition add_instr (n : node) (n' : node) (st : stmnt) : mon node :=
@@ -187,65 +210,54 @@ Definition add_instr (n : node) (n' : node) (st : stmnt) : mon node :=
(Pos.max (Pos.succ n) s.(st_freshstate))
(PositiveMap.add n st s.(st_stm))
(PositiveMap.add n (StateGoto n') s.(st_statetrans))
- s.(st_decl)
- s.(st_fin)
- s.(st_ret)).
+ s.(st_decl)).
Definition add_reg (r: reg) (s: state) : state :=
mkstate (Pos.max (Pos.succ r) s.(st_freshreg))
s.(st_freshstate)
s.(st_stm)
s.(st_statetrans)
- ((r, 32%nat) :: s.(st_decl))
- s.(st_fin)
- s.(st_ret).
+ (PositiveMap.add r 32%nat s.(st_decl)).
Definition add_instr_reg (r: reg) (n: node) (n': node) (st: stmnt) : mon node :=
do _ <- map_state (add_reg r);
add_instr n n' st.
-Definition decl_fresh_reg (sz : nat) : mon reg :=
+Definition decl_fresh_reg (sz : nat) : mon (reg * nat) :=
fun s =>
let r := s.(st_freshreg) in
- OK r (mkstate
+ OK (r, sz) (mkstate
(Pos.succ r)
s.(st_freshstate)
s.(st_stm)
s.(st_statetrans)
- ((r, sz) :: s.(st_decl))
- s.(st_fin)
- s.(st_ret)).
-
-Definition add_fin_ret (f r: reg) : mon unit :=
- fun s => OK tt (mkstate
- s.(st_freshreg)
- s.(st_freshstate)
- s.(st_stm)
- s.(st_statetrans)
- s.(st_decl)
- (Some f) (Some r)).
-
-Definition transf_instr (ni: node * instruction) : mon node :=
+ (PositiveMap.add r sz s.(st_decl))).
+
+Definition transf_instr (fin rtrn: reg) (ni: node * instruction) : mon node :=
match ni with
(n, i) =>
match i with
| Inop n' => add_instr n n' Vskip
| Iop op args dst n' =>
- match translate_instr op args with
- | Some instr => add_instr_reg dst n n' (block dst instr)
- | _ => error (Errors.msg "Instruction is not implemented.")
- end
+ do instr <- translate_instr op args;
+ add_instr_reg dst n n' (block dst instr)
| Iload _ _ _ _ _ => error (Errors.msg "Loads are not implemented.")
| Istore _ _ _ _ _ => error (Errors.msg "Stores are not implemented.")
| Icall _ _ _ _ _ => error (Errors.msg "Calls are not implemented.")
| Itailcall _ _ _ => error (Errors.msg "Tailcalls are not implemented.")
| Ibuiltin _ _ _ _ => error (Errors.msg "Builtin functions not implemented.")
- | Icond cond args n1 n2 => error (Errors.msg "Condition not implemented.")
- | Ijumptable _ _ => error (Errors.msg "Jumptable not implemented.")
+ | Icond cond args n1 n2 =>
+ do e <- translate_condition cond args;
+ do st <- get;
+ do _ <- set (mkstate
+ st.(st_freshreg)
+ st.(st_freshstate)
+ st.(st_stm)
+ (PositiveMap.add n (StateCond e n1 n2) st.(st_statetrans))
+ st.(st_decl));
+ ret n
+ | Ijumptable _ _ => error (Errors.msg "Jumptable not implemented")
| Ireturn r =>
- do fin <- decl_fresh_reg 1%nat;
- do rtrn <- decl_fresh_reg 32%nat;
- do _ <- add_fin_ret fin rtrn;
match r with
| Some r' =>
add_instr n n (Vseq (block fin (Vlit (ZToValue 1%nat 1%Z)) :: block rtrn (Vvar r') :: nil))
@@ -272,7 +284,7 @@ Definition make_statetrans (r : reg) (s : PositiveMap.t statetrans) : stmnt :=
Fixpoint allocate_regs (e : list (reg * nat)) {struct e} : list module_item :=
match e with
- | (r, n)::es => Vdecl r n (Vlit (ZToValue n 0%Z)) :: allocate_regs es
+ | (r, n)::es => Vdecl r n :: allocate_regs es
| nil => nil
end.
@@ -282,24 +294,33 @@ Definition make_module_items (entry: node) (clk st rst: reg) (s: state) : list m
(nonblock st (posToExpr entry))
(make_statetrans st s.(st_statetrans))))
:: (Valways Valledge (make_stm st s.(st_stm)))
- :: (allocate_regs s.(st_decl)).
+ :: (allocate_regs (PositiveMap.elements s.(st_decl))).
(** To start out with, the assumption is made that there is only one
function/module in the original code. *)
+Definition decl_io (sz: nat): mon (reg * nat) :=
+ fun s => let r := s.(st_freshreg) in
+ OK (r, sz) (mkstate
+ (Pos.succ r)
+ s.(st_freshstate)
+ s.(st_stm)
+ s.(st_statetrans)
+ s.(st_decl)).
+
+Definition set_int_size (r: reg) : reg * nat := (r, 32%nat).
+
Definition transf_module (f: function) : mon module :=
- do _ <- traverselist transf_instr (Maps.PTree.elements f.(fn_code));
- do start <- decl_fresh_reg 1%nat;
- do rst <- decl_fresh_reg 1%nat;
- do clk <- decl_fresh_reg 1%nat;
+ do fin <- decl_io 1%nat;
+ do rtrn <- decl_io 32%nat;
+ do _ <- traverselist (transf_instr (fst fin) (fst rtrn)) (Maps.PTree.elements f.(fn_code));
+ do start <- decl_io 1%nat;
+ do rst <- decl_io 1%nat;
+ do clk <- decl_io 1%nat;
do st <- decl_fresh_reg 32%nat;
do current_state <- get;
- let mi := make_module_items f.(fn_entrypoint) clk st rst current_state in
- match current_state.(st_fin), current_state.(st_ret) with
- | Some fin, Some rtrn =>
- ret (mkmodule start rst clk fin rtrn f.(fn_params) mi)
- | _, _ => error (Errors.msg "Veriloggen: finish and return signals not generated")
- end.
+ let mi := make_module_items f.(fn_entrypoint) (fst clk) (fst st) (fst rst) current_state in
+ ret (mkmodule start rst clk fin rtrn (map set_int_size f.(fn_params)) mi).
Fixpoint main_function (main : ident) (flist : list (ident * AST.globdef fundef unit))
{struct flist} : option function :=
@@ -312,8 +333,15 @@ Fixpoint main_function (main : ident) (flist : list (ident * AST.globdef fundef
| nil => None
end.
+Definition max_state (f: function) : state :=
+ mkstate (Pos.succ (max_reg_function f))
+ (Pos.succ (max_pc_function f))
+ init_state.(st_stm)
+ init_state.(st_statetrans)
+ init_state.(st_decl).
+
Definition transf_program (d : program) : Errors.res module :=
match main_function d.(AST.prog_main) d.(AST.prog_defs) with
- | Some f => run_mon init_state (transf_module f)
- | _ => Errors.Error (Errors.msg "Veriloggen: could not find main module")
+ | Some f => run_mon (max_state f) (transf_module f)
+ | _ => Errors.Error (Errors.msg "Veriloggen: could not find main function")
end.
diff --git a/src/verilog/PrintVerilog.ml b/src/verilog/PrintVerilog.ml
index 5199872..292fcf2 100644
--- a/src/verilog/PrintVerilog.ml
+++ b/src/verilog/PrintVerilog.ml
@@ -92,9 +92,13 @@ let pprint_edge_top i = function
| Valledge -> "@*"
| Voredge (e1, e2) -> concat ["@("; pprint_edge e1; " or "; pprint_edge e2; ")"]
+let declare i t =
+ function (r, sz) ->
+ concat [ indent i; t; " ["; sprintf "%d" (Nat.to_int sz - 1); ":0] ";
+ register r; ";\n" ]
+
let pprint_module_item i = function
- | Vdecl (r, n, e) ->
- concat [indent i; "reg ["; sprintf "%d" (Nat.to_int n - 1); ":0] "; register r; " = "; pprint_expr e; ";\n"]
+ | Vdecl (r, sz) -> declare i "reg" (r, sz)
| Valways (e, s) ->
concat [indent i; "always "; pprint_edge_top i e; "\n"; pprint_stmnt (i+1) s]
@@ -105,12 +109,48 @@ let rec intersperse c = function
let make_io i io r = concat [indent i; io; " "; register r; ";\n"]
+let compose f g x = g x |> f
+
+let init_inputs i r = declare i "input" r
+
+let init_outputs i r = declare i "output reg" r
+
+let testbench = "module testbench;
+ reg start, reset, clk;
+ wire finish;
+ wire [31:0] return_val;
+
+ main m(start, reset, clk, finish, return_val);
+
+ initial begin
+ clk = 0;
+ start = 0;
+ reset = 0;
+ @(posedge clk) reset = 1;
+ @(posedge clk) reset = 0;
+ end
+
+ always #5 clk = ~clk;
+
+ always @(posedge clk) begin
+ if (finish == 1) begin
+ $display(\"finished: %d\", return_val);
+ $finish;
+ end
+ end
+endmodule
+"
+
let pprint_module i n m =
let inputs = m.mod_start :: m.mod_reset :: m.mod_clk :: m.mod_args in
let outputs = [m.mod_finish; m.mod_return] in
- concat [ indent i; "module "; n; "("; concat (intersperse ", " (List.map register (inputs @ outputs))); ");\n";
- fold_map (make_io (i+1) "input") inputs; fold_map (make_io (i+1) "output") outputs;
- fold_map (pprint_module_item (i+1)) m.mod_body; indent i; "endmodule\n"
+ concat [ indent i; "module "; n;
+ "("; concat (intersperse ", " (List.map (compose register fst) (inputs @ outputs))); ");\n";
+ fold_map (init_inputs (i+1)) inputs;
+ fold_map (init_outputs (i+1)) outputs;
+ fold_map (pprint_module_item (i+1)) m.mod_body;
+ indent i; "endmodule\n\n";
+ testbench
]
let print_program pp v = pstr pp (pprint_module 0 "main" v)
diff --git a/src/verilog/Verilog.v b/src/verilog/Verilog.v
index 212dbc0..b9200b7 100644
--- a/src/verilog/Verilog.v
+++ b/src/verilog/Verilog.v
@@ -32,6 +32,7 @@ From compcert Require Integers.
Import ListNotations.
Definition reg : Type := positive.
+Definition szreg : Type := reg * nat.
Record value : Type := mkvalue {
vsize : nat;
@@ -108,7 +109,7 @@ Inductive edge : Type :=
| Voredge : edge -> edge -> edge.
Inductive module_item : Type :=
-| Vdecl : reg -> nat -> expr -> module_item
+| Vdecl : reg -> nat -> module_item
| Valways : edge -> stmnt -> module_item.
(** [mod_start] If set, starts the computations in the module. *)
@@ -119,12 +120,12 @@ Inductive module_item : Type :=
(** [mod_return] The return value that was computed. *)
(** [mod_body] The body of the module, including the state machine. *)
Record module : Type := mkmodule {
- mod_start : reg;
- mod_reset : reg;
- mod_clk : reg;
- mod_finish : reg;
- mod_return : reg;
- mod_args : list reg;
+ mod_start : szreg;
+ mod_reset : szreg;
+ mod_clk : szreg;
+ mod_finish : szreg;
+ mod_return : szreg;
+ mod_args : list szreg;
mod_body : list module_item;
}.