diff options
| author | Brian Campbell | 2017-08-17 10:30:34 +0100 |
|---|---|---|
| committer | Brian Campbell | 2017-08-17 10:30:34 +0100 |
| commit | f88cb793118d28d061fdee4d5bd8317f541136b8 (patch) | |
| tree | e71c1bf514a01288f56b9d59f8bcdc6ec749f39e /risc-v | |
| parent | f5ce4223dbd99349fd1cdbeb99a2839a799589c5 (diff) | |
| parent | c6d639e0f03053b905a9cb0ab6929f4efe6153f4 (diff) | |
Merge remote-tracking branch 'origin' into mono-experiments
# Conflicts:
# src/type_internal.ml
Diffstat (limited to 'risc-v')
23 files changed, 1098 insertions, 29 deletions
diff --git a/risc-v/Makefile b/risc-v/Makefile new file mode 100644 index 00000000..856a48eb --- /dev/null +++ b/risc-v/Makefile @@ -0,0 +1,13 @@ + +SAIL:=../src/sail.native +SOURCES:=riscv.sail ../etc/regfp.sail riscv_regfp.sail +all: lem_ast shallow + +lem_ast: $(SOURCES) $(SAIL) + $(SAIL) -lem_ast $(SOURCES) + +shallow: $(SOURCES) $(SAIL) + $(SAIL) -lem_lib Riscv_extras_embed -lem $(SOURCES) + +clean: + rm -f riscv.lem riscv_embed*.lem diff --git a/risc-v/hgen/ast.hgen b/risc-v/hgen/ast.hgen new file mode 100644 index 00000000..8983b5ae --- /dev/null +++ b/risc-v/hgen/ast.hgen @@ -0,0 +1,13 @@ +| `RISCVUTYPE of bit20 * reg * riscvUop +| `RISCVJAL of bit20 * reg +| `RISCVJALR of bit12 * reg * reg +| `RISCVBType of bit12 * reg * reg * riscvBop +| `RISCVIType of bit12 * reg * reg * riscvIop +| `RISCVShiftIop of bit6 * reg * reg * riscvSop +| `RISCVRType of reg * reg * reg * riscvRop +| `RISCVLoad of bit12 * reg * reg * bool * wordWidth +| `RISCVStore of bit12 * reg * reg * wordWidth +| `RISCVADDIW of bit12 * reg * reg +| `RISCVSHIFTW of bit5 * reg * reg * riscvSop +| `RISCVRTYPEW of reg * reg * reg * riscvRopw +| `RISCVFENCE of bit4 * bit4 diff --git a/risc-v/hgen/fold.hgen b/risc-v/hgen/fold.hgen new file mode 100644 index 00000000..03318805 --- /dev/null +++ b/risc-v/hgen/fold.hgen @@ -0,0 +1,13 @@ +| `RISCVThreadStart -> (y_reg, y_sreg) +| `RISCVUTYPE (_, r0, _) -> fold_reg r0 (y_reg, y_sreg) +| `RISCVJAL (_, r0) -> fold_reg r0 (y_reg, y_sreg) +| `RISCVJALR (_, r0, r1) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVBType (_, r0, r1, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVIType (_, r0, r1, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVShiftIop (_, r0, r1, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVRType (r0, r1, r2, _) -> fold_reg r0 (fold_reg r1 (fold_reg r2 (y_reg, y_sreg))) +| `RISCVLoad (_, r0, r1, _, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVStore (_, r0, r1, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVADDIW (_, r0, r1) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVSHIFTW (_, r0, r1, _) -> fold_reg r0 (fold_reg r1 (y_reg, y_sreg)) +| `RISCVRTYPEW (r0, r1, r2, _) -> fold_reg r0 (fold_reg r1 (fold_reg r2 (y_reg, y_sreg))) diff --git a/risc-v/hgen/herdtools_ast_to_shallow_ast.hgen b/risc-v/hgen/herdtools_ast_to_shallow_ast.hgen new file mode 100644 index 00000000..50026612 --- /dev/null +++ b/risc-v/hgen/herdtools_ast_to_shallow_ast.hgen @@ -0,0 +1,60 @@ +| `RISCVStopFetching -> EBREAK +| `RISCVUTYPE(imm, rd, op) -> UTYPE( + translate_imm20 "imm" imm, + translate_reg "rd" rd, + translate_uop op) +| `RISCVJAL(imm, rd) -> JAL0( + translate_imm21 "imm" imm, + translate_reg "rd" rd) +| `RISCVJALR(imm, rs, rd) -> JALR0( + translate_imm12 "imm" imm, + translate_reg "rs" rd, + translate_reg "rd" rd) +| `RISCVBType(imm, rs2, rs1, op) -> BTYPE( + translate_imm13 "imm" imm, + translate_reg "rs2" rs2, + translate_reg "rs1" rs1, + translate_bop op) +| `RISCVIType(imm, rs1, rd, op) -> ITYPE( + translate_imm12 "imm" imm, + translate_reg "rs1" rs1, + translate_reg "rd" rd, + translate_iop op) +| `RISCVShiftIop(imm, rs, rd, op) -> SHIFTIOP( + translate_imm6 "imm" imm, + translate_reg "rs" rs, + translate_reg "rd" rd, + translate_sop op) +| `RISCVRType (rs2, rs1, rd, op) -> RTYPE ( + translate_reg "rs2" rs2, + translate_reg "rs1" rs1, + translate_reg "rd" rd, + translate_rop op) +| `RISCVLoad(imm, rs, rd, unsigned, width) -> LOAD( + translate_imm12 "imm" imm, + translate_reg "rs" rs, + translate_reg "rd" rd, + translate_bool "unsigned" unsigned, + translate_wordWidth width) +| `RISCVStore(imm, rs, rd, width) -> STORE ( + translate_imm12 "imm" imm, + translate_reg "rs" rs, + translate_reg "rd" rd, + translate_wordWidth width) +| `RISCVADDIW(imm, rs, rd) -> ADDIW( + translate_imm12 "imm" imm, + translate_reg "rs" rs, + translate_reg "rd" rd) +| `RISCVSHIFTW(imm, rs, rd, op) -> SHIFTW( + translate_imm5 "imm" imm, + translate_reg "rs" rs, + translate_reg "rd" rd, + translate_sop op) +| `RISCVRTYPEW(rs2, rs1, rd, op) -> RTYPEW( + translate_reg "rs2" rs2, + translate_reg "rs1" rs1, + translate_reg "rd" rd, + translate_ropw op) +| `RISCVFENCE(pred, succ) -> FENCE( + translate_imm4 "pred" pred, + translate_imm4 "succ" succ) diff --git a/risc-v/hgen/herdtools_types_to_shallow_types.hgen b/risc-v/hgen/herdtools_types_to_shallow_types.hgen new file mode 100644 index 00000000..4d8bd87a --- /dev/null +++ b/risc-v/hgen/herdtools_types_to_shallow_types.hgen @@ -0,0 +1,79 @@ +let is_inc = false + +let translate_reg name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 5,Nat_big_num.of_int (reg_to_int value)) + +let translate_uop op = match op with + | RISCVLUI -> LUI0 + | RISCVAUIPC -> AUIPC + +let translate_bop op = match op with + | RISCVBEQ -> BEQ0 + | RISCVBNE -> BNE + | RISCVBLT -> BLT + | RISCVBGE -> BGE + | RISCVBLTU -> BLTU + | RISCVBGEU -> BGEU + +let translate_iop op = match op with + | RISCVADDI -> ADDI0 + | RISCVSLTI -> SLTI0 + | RISCVSLTIU -> SLTIU0 + | RISCVXORI -> XORI0 + | RISCVORI -> ORI0 + | RISCVANDI -> ANDI0 + +let translate_sop op = match op with + | RISCVSLLI -> SLLI + | RISCVSRLI -> SRLI + | RISCVSRAI -> SRAI + +let translate_rop op = match op with + | RISCVADD -> ADD0 + | RISCVSUB -> SUB0 + | RISCVSLL -> SLL0 + | RISCVSLT -> SLT0 + | RISCVSLTU -> SLTU0 + | RISCVXOR -> XOR0 + | RISCVSRL -> SRL0 + | RISCVSRA -> SRA0 + | RISCVOR -> OR0 + | RISCVAND -> AND0 + +let translate_ropw op = match op with + | RISCVADDW -> ADDW + | RISCVSUBW -> SUBW + | RISCVSLLW -> SLLW + | RISCVSRLW -> SRLW + | RISCVSRAW -> SRAW + +let translate_wordWidth op = match op with + | RISCVBYTE -> BYTE + | RISCVHALF -> HALF + | RISCVWORD -> WORD + | RISCVDOUBLE -> DOUBLE + +let translate_bool name = function + | true -> Sail_values.B1 + | false -> Sail_values.B0 + +let translate_imm21 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 21,Nat_big_num.of_int value) + +let translate_imm20 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 20,Nat_big_num.of_int value) + +let translate_imm13 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 13,Nat_big_num.of_int value) + +let translate_imm12 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 12,Nat_big_num.of_int value) + +let translate_imm6 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 6,Nat_big_num.of_int value) + +let translate_imm5 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 5,Nat_big_num.of_int value) + +let translate_imm4 name value = + Sail_values.to_vec0 is_inc (Nat_big_num.of_int 4,Nat_big_num.of_int value) diff --git a/risc-v/hgen/lexer.hgen b/risc-v/hgen/lexer.hgen new file mode 100644 index 00000000..5f2c8326 --- /dev/null +++ b/risc-v/hgen/lexer.hgen @@ -0,0 +1,64 @@ +"lui" , UTYPE { op=RISCVLUI }; +"auipc" , UTYPE { op=RISCVAUIPC }; + +"jal", JAL (); +"jalr", JALR (); + +"beq", BTYPE {op=RISCVBEQ}; +"bne", BTYPE {op=RISCVBNE}; +"blt", BTYPE {op=RISCVBLT}; +"bge", BTYPE {op=RISCVBGE}; +"bltu", BTYPE {op=RISCVBLTU}; +"bgeu", BTYPE {op=RISCVBGEU}; + +"addi", ITYPE {op=RISCVADDI}; +"stli", ITYPE {op=RISCVSLTI}; +"sltiu", ITYPE {op=RISCVSLTIU}; +"xori", ITYPE {op=RISCVXORI}; +"ori", ITYPE {op=RISCVORI}; +"andi", ITYPE {op=RISCVANDI}; + +"slli", SHIFTIOP{op=RISCVSLLI}; +"srli", SHIFTIOP{op=RISCVSRLI}; +"srai", SHIFTIOP{op=RISCVSRAI}; + +"add", RTYPE{op=RISCVADD}; +"sub", RTYPE{op=RISCVSUB}; +"sll", RTYPE{op=RISCVSLL}; +"slt", RTYPE{op=RISCVSLT}; +"sltu", RTYPE{op=RISCVSLT}; +"xor", RTYPE{op=RISCVXOR}; +"srl", RTYPE{op=RISCVSRL}; +"sra", RTYPE{op=RISCVSRA}; +"or", RTYPE{op=RISCVOR}; +"and", RTYPE{op=RISCVAND}; + +"lb", LOAD{unsigned=false; width=RISCVBYTE}; +"lbu", LOAD{unsigned=true; width=RISCVBYTE}; +"lh", LOAD{unsigned=false; width=RISCVHALF}; +"lhu", LOAD{unsigned=true; width=RISCVHALF}; +"lw", LOAD{unsigned=false; width=RISCVWORD}; +"lwu", LOAD{unsigned=true; width=RISCVWORD}; +"ld", LOAD{unsigned=false; width=RISCVDOUBLE}; + +"sb", STORE{width=RISCVBYTE}; +"sh", STORE{width=RISCVHALF}; +"sw", STORE{width=RISCVWORD}; +"sd", STORE{width=RISCVDOUBLE}; + +"addiw", ADDIW (); + +"slliw", SHIFTW{op=RISCVSLLI}; +"srliw", SHIFTW{op=RISCVSRLI}; +"sraiw", SHIFTW{op=RISCVSRAI}; + +"addw", RTYPEW{op=RISCVADDW}; +"subw", RTYPEW{op=RISCVSUBW}; +"sslw", RTYPEW{op=RISCVSLLW}; +"srlw", RTYPEW{op=RISCVSRLW}; +"sraw", RTYPEW{op=RISCVSRAW}; + +"fence", FENCE (); +"r", FENCEOPTION Fence_R; +"w", FENCEOPTION Fence_W; +"rw", FENCEOPTION Fence_RW; diff --git a/risc-v/hgen/map.hgen b/risc-v/hgen/map.hgen new file mode 100644 index 00000000..ff14c428 --- /dev/null +++ b/risc-v/hgen/map.hgen @@ -0,0 +1,12 @@ +| `RISCVUTYPE (x, r0, y) -> `RISCVUTYPE (x, map_reg r0, y) +| `RISCVJAL (x, r0) -> `RISCVJAL (x, map_reg r0) +| `RISCVJALR (x, r0, r1) -> `RISCVJALR (x, map_reg r0, map_reg r1) +| `RISCVBType (x, r0, r1, y) -> `RISCVBType (x, map_reg r0, map_reg r1, y) +| `RISCVIType (x, r0, r1, y) -> `RISCVIType (x, map_reg r0, map_reg r1, y) +| `RISCVShiftIop (x, r0, r1, y) -> `RISCVShiftIop (x, map_reg r0, map_reg r1, y) +| `RISCVRType (r0, r1, r2, y) -> `RISCVRType (r0, map_reg r1, map_reg r2, y) +| `RISCVLoad (x, r0, r1, y, z) -> `RISCVLoad (x, map_reg r0, map_reg r1, y, z) +| `RISCVStore (x, r0, r1, y) -> `RISCVStore (x, map_reg r0, map_reg r1, y) +| `RISCVADDIW (x, r0, r1) -> `RISCVADDIW (x, map_reg r0, map_reg r1) +| `RISCVSHIFTW (x, r0, r1, y) -> `RISCVSHIFTW (x, map_reg r0, map_reg r1, y) +| `RISCVRTYPEW (r0, r1, r2, x) -> `RISCVRTYPEW (r0, map_reg r1, map_reg r2, x) diff --git a/risc-v/hgen/parser.hgen b/risc-v/hgen/parser.hgen new file mode 100644 index 00000000..37fd8d8d --- /dev/null +++ b/risc-v/hgen/parser.hgen @@ -0,0 +1,36 @@ +| UTYPE reg COMMA NUM + { `RISCVUTYPE($4, $2, $1.op) } +| JAL reg COMMA NUM + { `RISCVJAL($4, $2) } +| JALR reg COMMA reg COMMA NUM + { `RISCVJALR($6, $4, $2) } +| BTYPE reg COMMA reg COMMA NUM + { `RISCVBType($6, $4, $2, $1.op) } +| ITYPE reg COMMA reg COMMA NUM + { `RISCVIType($6, $4, $2, $1.op) } +| SHIFTIOP reg COMMA reg COMMA NUM + { `RISCVShiftIop($6, $4, $2, $1.op) } +| RTYPE reg COMMA reg COMMA reg + { `RISCVRType ($6, $4, $2, $1.op) } +| LOAD reg COMMA NUM LPAR reg RPAR + { `RISCVLoad($4, $6, $2, $1.unsigned, $1.width) } +| STORE reg COMMA NUM LPAR reg RPAR + { `RISCVStore($4, $2, $6, $1.width) } +| ADDIW reg COMMA reg COMMA NUM + { `RISCVADDIW ($6, $4, $2) } +| SHIFTW reg COMMA reg COMMA NUM + { `RISCVSHIFTW ($6, $4, $2, $1.op) } +| RTYPEW reg COMMA reg COMMA reg + { `RISCVRTYPEW ($6, $4, $2, $1.op) } +| FENCE FENCEOPTION COMMA FENCEOPTION + { match ($2, $4) with + | (Fence_RW, Fence_RW) -> `RISCVFENCE (0b0011, 0b0011) + | (Fence_R, Fence_RW) -> `RISCVFENCE (0b0010, 0b0011) + | (Fence_RW, Fence_W) -> `RISCVFENCE (0b0011, 0b0001) + | (Fence_RW, Fence_R) -> failwith "'fence rw,r' is not supported" + | (Fence_R, Fence_R) -> failwith "'fence r,r' is not supported" + | (Fence_R, Fence_W) -> failwith "'fence r,w' is not supported" + | (Fence_W, Fence_RW) -> failwith "'fence w,rw' is not supported" + | (Fence_W, Fence_R) -> failwith "'fence w,r' is not supported" + | (Fence_W, Fence_W) -> failwith "'fence w,w' is not supported" + } diff --git a/risc-v/hgen/pretty.hgen b/risc-v/hgen/pretty.hgen new file mode 100644 index 00000000..1da3ef11 --- /dev/null +++ b/risc-v/hgen/pretty.hgen @@ -0,0 +1,15 @@ +| `RISCVThreadStart -> "start" +| `RISCVStopFetching -> "stop" +| `RISCVUTYPE(imm, rd, op) -> sprintf "%s %s, %d" (pp_riscv_uop op) (pp_reg rd) imm +| `RISCVJAL(imm, rd) -> sprintf "jal %s, %d" (pp_reg rd) imm +| `RISCVJALR(imm, rs, rd) -> sprintf "jalr %s, %s, %d" (pp_reg rd) (pp_reg rs) imm +| `RISCVBType(imm, rs2, rs1, op) -> sprintf "%s %s, %s, %d" (pp_riscv_bop op) (pp_reg rs1) (pp_reg rs2) imm +| `RISCVIType(imm, rs2, rs1, op) -> sprintf "%s %s, %s, %d" (pp_riscv_iop op) (pp_reg rs1) (pp_reg rs2) imm +| `RISCVShiftIop(imm, rs, rd, op) -> sprintf "%s %s, %s, %d" (pp_riscv_sop op) (pp_reg rd) (pp_reg rs) imm +| `RISCVRType (rs2, rs1, rd, op) -> sprintf "%s %s, %s, %s" (pp_riscv_rop op) (pp_reg rd) (pp_reg rs1) (pp_reg rs2) +| `RISCVLoad(imm, rs, rd, unsigned, width) -> sprintf "%s %s, %d(%s)" (pp_riscv_load_op (unsigned, width)) (pp_reg rd) imm (pp_reg rs) +| `RISCVStore(imm, rs2, rs1, width) -> sprintf "%s %s, %d(%s)" (pp_riscv_store_op width) (pp_reg rs2) imm (pp_reg rs1) +| `RISCVADDIW(imm, rs, rd) -> sprintf "addiw %s, %s, %d" (pp_reg rd) (pp_reg rs) imm +| `RISCVSHIFTW(imm, rs, rd, op) -> sprintf "%s %s, %s, %d" (pp_riscv_sop op) (pp_reg rd) (pp_reg rs) imm +| `RISCVRTYPEW(rs2, rs1, rd, op) -> sprintf "%s %s, %s, %s" (pp_riscv_ropw op) (pp_reg rd) (pp_reg rs1) (pp_reg rs2) +| `RISCVFENCE(pred, succ) -> sprintf "fence %s, %s" (pp_riscv_fence_option pred) (pp_riscv_fence_option succ) diff --git a/risc-v/hgen/sail_trans_out.hgen b/risc-v/hgen/sail_trans_out.hgen new file mode 100644 index 00000000..dca5bea1 --- /dev/null +++ b/risc-v/hgen/sail_trans_out.hgen @@ -0,0 +1,14 @@ +| ("EBREAK", []) -> `RISCVStopFetching +| ("UTYPE", [imm; rd; op]) -> `RISCVUTYPE(translate_out_simm20 imm, translate_out_ireg rd, translate_out_uop op) +| ("JAL", [imm; rd]) -> `RISCVJAL(translate_out_simm21 imm, translate_out_ireg rd) +| ("JALR", [imm; rs; rd]) -> `RISCVJALR(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd) +| ("BTYPE", [imm; rs2; rs1; op]) -> `RISCVBType(translate_out_simm13 imm, translate_out_ireg rs2, translate_out_ireg rs1, translate_out_bop op) +| ("ITYPE", [imm; rs1; rd; op]) -> `RISCVIType(translate_out_simm12 imm, translate_out_ireg rs1, translate_out_ireg rd, translate_out_iop op) +| ("SHIFTIOP", [imm; rs; rd; op]) -> `RISCVShiftIop(translate_out_imm6 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_sop op) +| ("RTYPE", [rs2; rs1; rd; op]) -> `RISCVRType (translate_out_ireg rs2, translate_out_ireg rs1, translate_out_ireg rd, translate_out_rop op) +| ("LOAD", [imm; rs; rd; unsigned; width]) -> `RISCVLoad(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_bool unsigned, translate_out_wordWidth width) +| ("STORE", [imm; rs; rd; width]) -> `RISCVStore(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_wordWidth width) +| ("ADDIW", [imm; rs; rd]) -> `RISCVADDIW(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd) +| ("SHIFTW", [imm; rs; rd; op]) -> `RISCVSHIFTW(translate_out_imm5 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_sop op) +| ("RTYPEW", [rs2; rs1; rd; op]) -> `RISCVRTYPEW(translate_out_ireg rs2, translate_out_ireg rs1, translate_out_ireg rd, translate_out_ropw op) +| ("FENCE", [pred; succ]) -> `RISCVFENCE(translate_out_imm4 pred, translate_out_imm4 succ) diff --git a/risc-v/hgen/shallow_ast_to_herdtools_ast.hgen b/risc-v/hgen/shallow_ast_to_herdtools_ast.hgen new file mode 100644 index 00000000..6158ebd7 --- /dev/null +++ b/risc-v/hgen/shallow_ast_to_herdtools_ast.hgen @@ -0,0 +1,14 @@ +| EBREAK -> `RISCVStopFetching +| UTYPE( imm, rd, op) -> `RISCVUTYPE(translate_out_simm20 imm, translate_out_ireg rd, translate_out_uop op) +| JAL0( imm, rd) -> `RISCVJAL(translate_out_simm21 imm, translate_out_ireg rd) +| JALR0( imm, rs, rd) -> `RISCVJALR(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd) +| BTYPE( imm, rs2, rs1, op) -> `RISCVBType(translate_out_simm13 imm, translate_out_ireg rs2, translate_out_ireg rs1, translate_out_bop op) +| ITYPE( imm, rs1, rd, op) -> `RISCVIType(translate_out_simm12 imm, translate_out_ireg rs1, translate_out_ireg rd, translate_out_iop op) +| SHIFTIOP( imm, rs, rd, op) -> `RISCVShiftIop(translate_out_imm6 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_sop op) +| RTYPE( rs2, rs1, rd, op) -> `RISCVRType (translate_out_ireg rs2, translate_out_ireg rs1, translate_out_ireg rd, translate_out_rop op) +| LOAD( imm, rs, rd, unsigned, width) -> `RISCVLoad(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_bool unsigned, translate_out_wordWidth width) +| STORE( imm, rs, rd, width) -> `RISCVStore(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_wordWidth width) +| ADDIW( imm, rs, rd) -> `RISCVADDIW(translate_out_simm12 imm, translate_out_ireg rs, translate_out_ireg rd) +| SHIFTW( imm, rs, rd, op) -> `RISCVSHIFTW(translate_out_imm5 imm, translate_out_ireg rs, translate_out_ireg rd, translate_out_sop op) +| RTYPEW( rs2, rs1, rd, op) -> `RISCVRTYPEW(translate_out_ireg rs2, translate_out_ireg rs1, translate_out_ireg rd, translate_out_ropw op) +| FENCE( pred, succ) -> `RISCVFENCE(translate_out_imm4 pred, translate_out_imm4 succ) diff --git a/risc-v/hgen/shallow_types_to_herdtools_types.hgen b/risc-v/hgen/shallow_types_to_herdtools_types.hgen new file mode 100644 index 00000000..a891d7d0 --- /dev/null +++ b/risc-v/hgen/shallow_types_to_herdtools_types.hgen @@ -0,0 +1,73 @@ +let translate_out_big_bit = Sail_values.unsigned + +let translate_out_int inst = (Nat_big_num.to_int (translate_out_big_bit inst)) +let translate_out_signed_int inst bits = + let i = (Nat_big_num.to_int (translate_out_big_bit inst)) in + if (i >= (1 lsl (bits - 1))) then + (i - (1 lsl bits)) else + i + +let translate_out_ireg ireg = IReg (int_to_ireg (translate_out_int ireg)) + +let translate_out_uop op = match op with + | LUI0 -> RISCVLUI + | AUIPC -> RISCVAUIPC + +let translate_out_bop op = match op with + | BEQ0 -> RISCVBEQ + | BNE -> RISCVBNE + | BLT -> RISCVBLT + | BGE -> RISCVBGE + | BLTU -> RISCVBLTU + | BGEU -> RISCVBGEU + +let translate_out_iop op = match op with + | ADDI0 -> RISCVADDI + | SLTI0 -> RISCVSLTI + | SLTIU0 -> RISCVSLTIU + | XORI0 -> RISCVXORI + | ORI0 -> RISCVORI + | ANDI0 -> RISCVANDI + +let translate_out_sop op = match op with + | SLLI -> RISCVSLLI + | SRLI -> RISCVSRLI + | SRAI -> RISCVSRAI + +let translate_out_rop op = match op with + | ADD0 -> RISCVADD + | SUB0 -> RISCVSUB + | SLL0 -> RISCVSLL + | SLT0 -> RISCVSLT + | SLTU0 -> RISCVSLTU + | XOR0 -> RISCVXOR + | SRL0 -> RISCVSRL + | SRA0 -> RISCVSRA + | OR0 -> RISCVOR + | AND0 -> RISCVAND + +let translate_out_ropw op = match op with + | ADDW -> RISCVADDW + | SUBW -> RISCVSUBW + | SLLW -> RISCVSLLW + | SRLW -> RISCVSRLW + | SRAW -> RISCVSRAW + +let translate_out_wordWidth op = match op with + | BYTE -> RISCVBYTE + | HALF -> RISCVHALF + | WORD -> RISCVWORD + | DOUBLE -> RISCVDOUBLE + +let translate_out_bool = function + | Sail_values.B1 -> true + | Sail_values.B0 -> false + | _ -> failwith "translate_out_bool Undef" + +let translate_out_simm21 imm = translate_out_signed_int imm 21 +let translate_out_simm20 imm = translate_out_signed_int imm 20 +let translate_out_simm13 imm = translate_out_signed_int imm 13 +let translate_out_simm12 imm = translate_out_signed_int imm 12 +let translate_out_imm6 imm = translate_out_int imm +let translate_out_imm5 imm = translate_out_int imm +let translate_out_imm4 imm = translate_out_int imm diff --git a/risc-v/hgen/token_types.hgen b/risc-v/hgen/token_types.hgen new file mode 100644 index 00000000..2980b985 --- /dev/null +++ b/risc-v/hgen/token_types.hgen @@ -0,0 +1,15 @@ +type token_UTYPE = {op : riscvUop } +type token_JAL = unit +type token_JALR = unit +type token_BType = {op : riscvBop } +type token_IType = {op : riscvIop } +type token_ShiftIop = {op : riscvSop } +type token_RTYPE = {op : riscvRop } +type token_Load = {unsigned: bool; width : wordWidth } +type token_Store = {width : wordWidth } +type token_ADDIW = unit +type token_SHIFTW = {op : riscvSop } +type token_RTYPEW = {op : riscvRopw } +type token_FENCE = unit + +type token_FENCEOPTION = Fence_R | Fence_W | Fence_RW diff --git a/risc-v/hgen/tokens.hgen b/risc-v/hgen/tokens.hgen new file mode 100644 index 00000000..f952cf77 --- /dev/null +++ b/risc-v/hgen/tokens.hgen @@ -0,0 +1,14 @@ +%token <RISCVHGenBase.token_UTYPE> UTYPE +%token <RISCVHGenBase.token_JAL> JAL +%token <RISCVHGenBase.token_JALR> JALR +%token <RISCVHGenBase.token_BType> BTYPE +%token <RISCVHGenBase.token_IType> ITYPE +%token <RISCVHGenBase.token_ShiftIop> SHIFTIOP +%token <RISCVHGenBase.token_RTYPE> RTYPE +%token <RISCVHGenBase.token_Load> LOAD +%token <RISCVHGenBase.token_Store> STORE +%token <RISCVHGenBase.token_ADDIW> ADDIW +%token <RISCVHGenBase.token_SHIFTW> SHIFTW +%token <RISCVHGenBase.token_RTYPEW> RTYPEW +%token <RISCVHGenBase.token_FENCE> FENCE +%token <RISCVHGenBase.token_FENCEOPTION> FENCEOPTION diff --git a/risc-v/hgen/trans_sail.hgen b/risc-v/hgen/trans_sail.hgen new file mode 100644 index 00000000..df22d9dc --- /dev/null +++ b/risc-v/hgen/trans_sail.hgen @@ -0,0 +1,112 @@ +| `RISCVStopFetching -> ("EBREAK", [], []) +| `RISCVUTYPE(imm, rd, op) -> + ("UTYPE", + [ + translate_imm20 "imm" imm; + translate_reg "rd" rd; + translate_uop "op" op; + ], + []) +| `RISCVJAL(imm, rd) -> + ("JAL", + [ + translate_imm21 "imm" imm; + translate_reg "rd" rd; + ], + []) +| `RISCVJALR(imm, rs, rd) -> + ("JALR", + [ + translate_imm12 "imm" imm; + translate_reg "rs" rd; + translate_reg "rd" rd; + ], + []) +| `RISCVBType(imm, rs2, rs1, op) -> + ("BTYPE", + [ + translate_imm13 "imm" imm; + translate_reg "rs2" rs2; + translate_reg "rs1" rs1; + translate_bop "op" op; + ], + []) +| `RISCVIType(imm, rs1, rd, op) -> + ("ITYPE", + [ + translate_imm12 "imm" imm; + translate_reg "rs1" rs1; + translate_reg "rd" rd; + translate_iop "op" op; + ], + []) +| `RISCVShiftIop(imm, rs, rd, op) -> + ("SHIFTIOP", + [ + translate_imm6 "imm" imm; + translate_reg "rs" rs; + translate_reg "rd" rd; + translate_sop "op" op; + ], + []) +| `RISCVRType (rs2, rs1, rd, op) -> + ("RTYPE", + [ + translate_reg "rs2" rs2; + translate_reg "rs1" rs1; + translate_reg "rd" rd; + translate_rop "op" op; + ], + []) +| `RISCVLoad(imm, rs, rd, unsigned, width) -> + ("LOAD", + [ + translate_imm12 "imm" imm; + translate_reg "rs" rs; + translate_reg "rd" rd; + translate_bool "unsigned" unsigned; + translate_width "width" width; + ], + []) +| `RISCVStore(imm, rs2, rs1, width) -> + ("STORE", + [ + translate_imm12 "imm" imm; + translate_reg "rs2" rs2; + translate_reg "rs1" rs1; + translate_width "width" width; + ], + []) +| `RISCVADDIW(imm, rs, rd) -> + ("ADDIW", + [ + translate_imm12 "imm" imm; + translate_reg "rs" rs; + translate_reg "rd" rd; + ], + []) +| `RISCVSHIFTW(imm, rs, rd, op) -> + ("SHIFTW", + [ + translate_imm5 "imm" imm; + translate_reg "rs" rs; + translate_reg "rd" rd; + translate_sop "op" op; + ], + []) +| `RISCVRTYPEW(rs2, rs1, rd, op) -> + ("RTYPEW", + [ + translate_reg "rs2" rs2; + translate_reg "rs1" rs1; + translate_reg "rd" rd; + translate_ropw "op" op; + ], + []) +| `RISCVFENCE(pred, succ) -> + ("FENCE", + [ + translate_imm4 "pred" pred; + translate_imm4 "succ" succ; + ], + []) diff --git a/risc-v/hgen/types.hgen b/risc-v/hgen/types.hgen new file mode 100644 index 00000000..87fc9b95 --- /dev/null +++ b/risc-v/hgen/types.hgen @@ -0,0 +1,123 @@ +type bit20 = int +type bit12 = int +type bit6 = int +type bit5 = int +type bit4 = int + +type riscvUop = (* upper immediate ops *) +| RISCVLUI +| RISCVAUIPC + +let pp_riscv_uop = function +| RISCVLUI -> "lui" +| RISCVAUIPC -> "auipc" + + +type riscvBop = (* branch ops *) +| RISCVBEQ +| RISCVBNE +| RISCVBLT +| RISCVBGE +| RISCVBLTU +| RISCVBGEU + +let pp_riscv_bop = function +| RISCVBEQ -> "beq" +| RISCVBNE -> "bne" +| RISCVBLT -> "blt" +| RISCVBGE -> "bge" +| RISCVBLTU -> "bltu" +| RISCVBGEU -> "bgeu" + +type riscvIop = (* immediate ops *) +| RISCVADDI +| RISCVSLTI +| RISCVSLTIU +| RISCVXORI +| RISCVORI +| RISCVANDI + +let pp_riscv_iop = function +| RISCVADDI -> "addi" +| RISCVSLTI -> "slti" +| RISCVSLTIU -> "sltiu" +| RISCVXORI -> "xori" +| RISCVORI -> "ori" +| RISCVANDI -> "andi" + +type riscvSop = (* shift ops *) +| RISCVSLLI +| RISCVSRLI +| RISCVSRAI + +let pp_riscv_sop = function +| RISCVSLLI -> "slli" +| RISCVSRLI -> "srli" +| RISCVSRAI -> "srai" + +type riscvRop = (* reg-reg ops *) +| RISCVADD +| RISCVSUB +| RISCVSLL +| RISCVSLT +| RISCVSLTU +| RISCVXOR +| RISCVSRL +| RISCVSRA +| RISCVOR +| RISCVAND + +let pp_riscv_rop = function +| RISCVADD -> "add" +| RISCVSUB -> "sub" +| RISCVSLL -> "sll" +| RISCVSLT -> "slt" +| RISCVSLTU -> "sltu" +| RISCVXOR -> "xor" +| RISCVSRL -> "srl" +| RISCVSRA -> "sra" +| RISCVOR -> "or" +| RISCVAND -> "and" + +type riscvRopw = (* reg-reg 32-bit ops *) +| RISCVADDW +| RISCVSUBW +| RISCVSLLW +| RISCVSRLW +| RISCVSRAW + +let pp_riscv_ropw = function +| RISCVADDW -> "addw" +| RISCVSUBW -> "subw" +| RISCVSLLW -> "sllw" +| RISCVSRLW -> "srlw" +| RISCVSRAW -> "sraw" + +type wordWidth = + | RISCVBYTE + | RISCVHALF + | RISCVWORD + | RISCVDOUBLE + +let pp_riscv_load_op (unsigned, width) = match (unsigned, width) with + | (false, RISCVBYTE) -> "lb" + | (true, RISCVBYTE) -> "lbu" + | (false, RISCVHALF) -> "lh" + | (true, RISCVHALF) -> "lhu" + | (false, RISCVWORD) -> "lw" + | (true, RISCVWORD) -> "lwu" + | (_, RISCVDOUBLE) -> "ld" + | _ -> failwith "unexpected load op" + +let pp_riscv_store_op width = match width with +| RISCVBYTE -> "sb" +| RISCVHALF -> "sh" +| RISCVWORD -> "sw" +| RISCVDOUBLE -> "sd" +| _ -> failwith "unexpected store op" + +let pp_riscv_fence_option = function + | 0b0011 -> "rw" + | 0b0010 -> "r" + | 0b0001 -> "w" + | _ -> failwith "unexpected fence option" diff --git a/risc-v/hgen/types_sail_trans_out.hgen b/risc-v/hgen/types_sail_trans_out.hgen new file mode 100644 index 00000000..e22110d0 --- /dev/null +++ b/risc-v/hgen/types_sail_trans_out.hgen @@ -0,0 +1,86 @@ +let translate_out_big_bit = function + | (name, Bvector _, bits) -> IInt.integer_of_bit_list bits + | _ -> assert false + +let translate_out_int inst = (Nat_big_num.to_int (translate_out_big_bit inst)) +let translate_out_signed_int inst bits = + let i = (Nat_big_num.to_int (translate_out_big_bit inst)) in + if (i >= (1 lsl (bits - 1))) then + (i - (1 lsl bits)) else + i + +let translate_out_ireg ireg = IReg (int_to_ireg (translate_out_int ireg)) + +let translate_out_simm21 imm = translate_out_signed_int imm 21 +let translate_out_simm20 imm = translate_out_signed_int imm 20 +let translate_out_simm13 imm = translate_out_signed_int imm 13 +let translate_out_simm12 imm = translate_out_signed_int imm 12 +let translate_out_imm6 imm = translate_out_int imm +let translate_out_imm5 imm = translate_out_int imm +let translate_out_imm4 imm = translate_out_int imm + +let translate_out_bool = function + | (name, Bit, [Bitc_one]) -> true + | (name, Bit, [Bitc_zero]) -> false + | _ -> assert false + +let translate_out_enum (name,_,bits) = + Nat_big_num.to_int (IInt.integer_of_bit_list bits) + +let translate_out_wordWidth w = + match translate_out_enum w with + | 0 -> RISCVBYTE + | 1 -> RISCVHALF + | 2 -> RISCVWORD + | 3 -> RISCVDOUBLE + | _ -> failwith "Unknown wordWidth in sail translate out" + +let translate_out_uop op = match translate_out_enum op with + | 0 -> RISCVLUI + | 1 -> RISCVAUIPC + | _ -> failwith "Unknown uop in sail translate out" + +let translate_out_bop op = match translate_out_enum op with +| 0 -> RISCVBEQ +| 1 -> RISCVBNE +| 2 -> RISCVBLT +| 3 -> RISCVBGE +| 4 -> RISCVBLTU +| 5 -> RISCVBGEU +| _ -> failwith "Unknown bop in sail translate out" + +let translate_out_iop op = match translate_out_enum op with +| 0 -> RISCVADDI +| 1 -> RISCVSLTI +| 2 -> RISCVSLTIU +| 3 -> RISCVXORI +| 4 -> RISCVORI +| 5 -> RISCVANDI +| _ -> failwith "Unknown iop in sail translate out" + +let translate_out_sop op = match translate_out_enum op with +| 0 -> RISCVSLLI +| 1 -> RISCVSRLI +| 2 -> RISCVSRAI +| _ -> failwith "Unknown sop in sail translate out" + +let translate_out_rop op = match translate_out_enum op with +| 0 -> RISCVADD +| 1 -> RISCVSUB +| 2 -> RISCVSLL +| 3 -> RISCVSLT +| 4 -> RISCVSLTU +| 5 -> RISCVXOR +| 6 -> RISCVSRL +| 7 -> RISCVSRA +| 8 -> RISCVOR +| 9 -> RISCVAND +| _ -> failwith "Unknown rop in sail translate out" + +let translate_out_ropw op = match translate_out_enum op with +| 0 -> RISCVADDW +| 1 -> RISCVSUBW +| 2 -> RISCVSLLW +| 3 -> RISCVSRLW +| 4 -> RISCVSRAW +| _ -> failwith "Unknown ropw in sail translate out" diff --git a/risc-v/hgen/types_trans_sail.hgen b/risc-v/hgen/types_trans_sail.hgen new file mode 100644 index 00000000..1bf174fa --- /dev/null +++ b/risc-v/hgen/types_trans_sail.hgen @@ -0,0 +1,39 @@ +let translate_enum enum_values name value = + let rec bit_count n = + if n = 0 then 0 + else 1 + (bit_count (n lsr 1)) in + let rec find_index element = function + | h::tail -> if h = element then 0 else 1 + (find_index element tail) + | _ -> failwith "translate_enum could not find value" + in + let size = bit_count (List.length enum_values) in + let index = find_index value enum_values in + (name, Range0 (Some size), IInt.bit_list_of_integer size (Nat_big_num.of_int index)) + +let translate_uop = translate_enum [RISCVLUI; RISCVAUIPC] +let translate_bop = translate_enum [RISCVBEQ; RISCVBNE; RISCVBLT; RISCVBGE; RISCVBLTU; RISCVBGEU] (* branch ops *) +let translate_iop = translate_enum [RISCVADDI; RISCVSLTI; RISCVSLTIU; RISCVXORI; RISCVORI; RISCVANDI] (* immediate ops *) +let translate_sop = translate_enum [RISCVSLLI; RISCVSRLI; RISCVSRAI] (* shift ops *) +let translate_rop = translate_enum [RISCVADD; RISCVSUB; RISCVSLL; RISCVSLT; RISCVSLTU; RISCVXOR; RISCVSRL; RISCVSRA; RISCVOR; RISCVAND] (* reg-reg ops *) +let translate_ropw = translate_enum [RISCVADDW; RISCVSUBW; RISCVSLLW; RISCVSRLW; RISCVSRAW] (* reg-reg 32-bit ops *) +let translate_width = translate_enum [RISCVBYTE; RISCVHALF; RISCVWORD; RISCVDOUBLE] +let translate_reg name value = + (name, Bvector (Some 5), bit_list_of_integer 5 (Nat_big_num.of_int (reg_to_int value))) +let translate_imm21 name value = + (name, Bvector (Some 21), bit_list_of_integer 21 (Nat_big_num.of_int value)) +let translate_imm20 name value = + (name, Bvector (Some 20), bit_list_of_integer 20 (Nat_big_num.of_int value)) +let translate_imm16 name value = + (name, Bvector (Some 16), bit_list_of_integer 16 (Nat_big_num.of_int value)) +let translate_imm13 name value = + (name, Bvector (Some 13), bit_list_of_integer 13 (Nat_big_num.of_int value)) +let translate_imm12 name value = + (name, Bvector (Some 12), bit_list_of_integer 12 (Nat_big_num.of_int value)) +let translate_imm6 name value = + (name, Bvector (Some 6), bit_list_of_integer 6 (Nat_big_num.of_int value)) +let translate_imm5 name value = + (name, Bvector (Some 5), bit_list_of_integer 5 (Nat_big_num.of_int value)) +let translate_imm4 name value = + (name, Bvector (Some 4), bit_list_of_integer 4 (Nat_big_num.of_int value)) +let translate_bool name value = + (name, Bit, [if value then Bitc_one else Bitc_zero]) diff --git a/risc-v/risc-v.sail b/risc-v/riscv.sail index edf95c62..4a80adb0 100644 --- a/risc-v/risc-v.sail +++ b/risc-v/riscv.sail @@ -52,9 +52,17 @@ function unit wGPR((regno) r, (regval) v) = if (r != 0) then GPRs[r] := v +function forall 'a. 'a effect { escape } not_implemented((string) message) = +{ + exit message; +} + val extern forall Nat 'n. ( bit[64] , [|'n|] ) -> (bit[8 * 'n]) effect { rmem } MEMr val extern forall Nat 'n. ( bit[64] , [|'n|]) -> unit effect { eamem } MEMea val extern forall Nat 'n. ( bit[64] , [|'n|] , bit[8*'n]) -> unit effect { wmv } MEMval +val extern unit -> unit effect { barr } MEM_fence_rw_rw +val extern unit -> unit effect { barr } MEM_fence_r_rw +val extern unit -> unit effect { barr } MEM_fence_rw_w (* Ideally these would be sail builtin *) function (bit[64]) shift_right_arith64 ((bit[64]) v, (bit[6]) shift) = @@ -72,6 +80,8 @@ typedef sop = enumerate {SLLI; SRLI; SRAI} (* shift ops *) typedef rop = enumerate {ADD; SUB; SLL; SLT; SLTU; XOR; SRL; SRA; OR; AND} (* reg-reg ops *) typedef ropw = enumerate {ADDW; SUBW; SLLW; SRLW; SRAW} (* reg-reg 32-bit ops *) +typedef word_width = enumerate {BYTE; HALF; WORD; DOUBLE} + scattered function unit execute scattered typedef ast = const union @@ -92,10 +102,10 @@ function clause execute (UTYPE(imm, rd, op)) = } in wGPR(rd, ret) -union ast member ((bit[20]), regno) JAL -function clause decode ((bit[20]) imm : (regno) rd : 0b1101111) = Some (JAL(imm, rd)) +union ast member ((bit[21]), regno) JAL +function clause decode ((bit[20]) imm : (regno) rd : 0b1101111) = Some (JAL(imm[19] : imm[7..0] : imm[8] : imm[18..13] : imm[12..9] : 0b0, rd)) function clause execute (JAL(imm, rd)) = - let (bit[64]) offset = EXTS(imm[19] : imm[7..0] : imm[8] : imm[18..13] : imm[12..9] : 0b0) in { + let (bit[64]) offset = EXTS(imm) in { nextPC := PC + offset; wGPR(rd, PC + 4); } @@ -109,13 +119,13 @@ function clause execute (JALR(imm, rs1, rd)) = wGPR(rd, PC + 4); } -union ast member ((bit[12]), regno, regno, bop) BTYPE -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b000 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BEQ)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b001 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BNE)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b100 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BLT)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b101 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BGE)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b110 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BLTU)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b111 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1], rs2, rs1, BGEU)) +union ast member ((bit[13]), regno, regno, bop) BTYPE +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b000 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BEQ)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b001 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BNE)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b100 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BLT)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b101 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BGE)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b110 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BLTU)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b111 : (bit[5]) imm5 : 0b1100011) = Some(BTYPE(imm7[6] : imm5[0] : imm7[5..0] : imm5[4..1] : 0b0, rs2, rs1, BGEU)) function clause execute (BTYPE(imm, rs2, rs1, op)) = let rs1_val = rGPR(rs1) in @@ -126,10 +136,10 @@ function clause execute (BTYPE(imm, rs2, rs1, op)) = case BLT -> rs1_val <_s rs2_val case BGE -> rs1_val >=_s rs2_val case BLTU -> rs1_val <_u rs2_val - case BGEU -> rs1_val >= rs2_val (* XXX is this signed or unsigned? *) + case BGEU -> unsigned(rs1_val) >= unsigned(rs2_val) (* XXX sail missing >=_u *) } in if (taken) then - nextPC := PC + EXTS(imm : 0b0) + nextPC := PC + EXTS(imm) union ast member ((bit[12]), regno, regno, iop) ITYPE function clause decode ((bit[12]) imm : (regno) rs1 : 0b000 : (regno) rd : 0b0010011) = Some(ITYPE(imm, rs1, rd, ADDI)) @@ -192,31 +202,52 @@ function clause execute (RTYPE(rs2, rs1, rd, op)) = } in wGPR(rd, result) -union ast member ((bit[12]), regno, regno, bool, [|8|]) LOAD -function clause decode ((bit[12]) imm : (regno) rs1 : 0b000 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, 1)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b001 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, 2)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b010 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, 4)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b011 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, 8)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b100 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, 1)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b101 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, 2)) -function clause decode ((bit[12]) imm : (regno) rs1 : 0b110 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, 4)) +union ast member ((bit[12]), regno, regno, bool, word_width) LOAD +function clause decode ((bit[12]) imm : (regno) rs1 : 0b000 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, BYTE)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b001 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, HALF)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b010 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, WORD)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b011 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, false, DOUBLE)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b100 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, BYTE)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b101 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, HALF)) +function clause decode ((bit[12]) imm : (regno) rs1 : 0b110 : (regno) rd : 0b0000011) = Some(LOAD(imm, rs1, rd, true, WORD)) function clause execute(LOAD(imm, rs1, rd, unsigned, width)) = let (bit[64]) addr = rGPR(rs1) + EXTS(imm) in let (bit[64]) result = if unsigned then - EXTZ(MEMr(addr, width)) + switch (width) { + case BYTE -> EXTZ(MEMr(addr, 1)) + case HALF -> EXTZ(MEMr(addr, 2)) + case WORD -> EXTZ(MEMr(addr, 4)) + case DOUBLE -> MEMr(addr, 8) + } else - EXTS(MEMr(addr, width)) in + switch (width) { + case BYTE -> EXTS(MEMr(addr, 1)) + case HALF -> EXTS(MEMr(addr, 2)) + case WORD -> EXTS(MEMr(addr, 4)) + case DOUBLE -> MEMr(addr, 8) + } in wGPR(rd, result) -union ast member ((bit[12]), regno, regno, [|8|]) STORE -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b000 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, 1)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b001 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, 2)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b010 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, 4)) -function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b011 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, 8)) +union ast member ((bit[12]), regno, regno, word_width) STORE +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b000 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, BYTE)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b001 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, HALF)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b010 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, WORD)) +function clause decode ((bit[7]) imm7 : (regno) rs2 : (regno) rs1 : 0b011 : (bit[5]) imm5 : 0b0100011) = Some(STORE(imm7 : imm5, rs2, rs1, DOUBLE)) function clause execute (STORE(imm, rs2, rs1, width)) = let (bit[64]) addr = rGPR(rs1) + EXTS(imm) in { - MEMea(addr, width); - MEMval(addr, width, rGPR(rs2)); + switch (width) { + case BYTE -> MEMea(addr, 1) + case HALF -> MEMea(addr, 2) + case WORD -> MEMea(addr, 4) + case DOUBLE -> MEMea(addr, 8) + }; + let rs2_val = rGPR(rs2) in + switch (width) { + case BYTE -> MEMval(addr, 1, rs2_val[7..0]) + case HALF -> MEMval(addr, 2, rs2_val[15..0]) + case WORD -> MEMval(addr, 4, rs2_val[31..0]) + case DOUBLE -> MEMval(addr, 8, rs2_val) + } } union ast member ((bit[12]), regno, regno) ADDIW @@ -258,6 +289,32 @@ function clause execute (RTYPEW(rs2, rs1, rd, op)) = } in wGPR(rd, EXTS(result)) +union ast member (bit[4], bit[4]) FENCE +function clause decode (0b0000 : (bit[4]) pred : (bit[4]) succ : 0b00000 : 0b000 : 0b00000 : 0b0001111) = Some(FENCE (pred, succ)) +function clause execute (FENCE(pred, succ)) = { + switch(pred, succ) { + case (0b0011, 0b0011) -> MEM_fence_rw_rw() + case (0b0010, 0b0011) -> MEM_fence_r_rw() + case (0b0011, 0b0001) -> MEM_fence_rw_w() + case _ -> not_implemented("unsupported fence") + } +} + +union ast member unit FENCEI +function clause decode (0b0000 : 0b0000 : 0b0000 : 0b00000 : 0b001 : 0b00000 : 0b0001111) = Some(FENCEI) +function clause execute FENCEI = () (* XXX TODO *) + +union ast member unit ECALL +function clause decode (0b000000000000 : 0b00000 : 0b000 : 0b00000 : 0b1110011) = Some(ECALL ()) +function clause execute ECALL = () + +union ast member unit EBREAK +function clause decode (0b000000000001 : 0b00000 : 0b000 : 0b00000 : 0b1110011) = Some(EBREAK ()) +function clause execute EBREAK = { exit () } + + +function clause decode _ = None + end ast end decode end execute diff --git a/risc-v/riscv_extras.lem b/risc-v/riscv_extras.lem new file mode 100644 index 00000000..aa5d8fb8 --- /dev/null +++ b/risc-v/riscv_extras.lem @@ -0,0 +1,60 @@ +open import Pervasives +open import Interp_ast +open import Interp_interface +open import Sail_impl_base +open import Interp_inter_imp +import Set_extra + +let memory_parameter_transformer mode v = + match v with + | Interp_ast.V_tuple [location;length] -> + let (v,loc_regs) = extern_with_track mode extern_vector_value location in + + match length with + | Interp_ast.V_lit (L_aux (L_num len) _) -> + (v,(natFromInteger len),loc_regs) + | Interp_ast.V_track (Interp_ast.V_lit (L_aux (L_num len) _)) size_regs -> + match loc_regs with + | Nothing -> (v,(natFromInteger len),Just (List.map (fun r -> extern_reg r Nothing) (Set_extra.toList size_regs))) + | Just loc_regs -> (v,(natFromInteger len),Just (loc_regs++(List.map (fun r -> extern_reg r Nothing) (Set_extra.toList size_regs)))) + end + | _ -> Assert_extra.failwith "expected 'V_lit (L_aux (L_num _) _)' or 'V_track (V_lit (L_aux (L_num len) _)) _'" + end + | _ -> Assert_extra.failwith ("memory_parameter_transformer: expected 'V_tuple [_;_]' given " ^ (Interp.string_of_value v)) + end + +let memory_parameter_transformer_option_address _mode v = + match v with + | Interp_ast.V_tuple [location;_] -> + Just (extern_vector_value location) + | _ -> Assert_extra.failwith ("memory_parameter_transformer_option_address: expected 'V_tuple [_;_]' given " ^ (Interp.string_of_value v)) + end + + +let read_memory_functions : memory_reads = + [ ("MEMr", (MR Read_plain memory_parameter_transformer)); + ("MEMr_reserve", (MR Read_reserve memory_parameter_transformer)); + ] + +let memory_writes : memory_writes = + [] + +let memory_eas : memory_write_eas = + [ ("MEMea", (MEA Write_plain memory_parameter_transformer)); + ("MEMea_conditional", (MEA Write_conditional memory_parameter_transformer)); + ] + +let memory_vals : memory_write_vals = + [ ("MEMval", (MV memory_parameter_transformer_option_address Nothing)); + ("MEMval_conditional", (MV memory_parameter_transformer_option_address + (Just + (fun (IState interp context) b -> + let bit = Interp_ast.V_lit (L_aux (if b then L_one else L_zero) Interp_ast.Unknown) in + (IState (Interp.add_answer_to_stack interp bit) context))))); + ] + +let barrier_functions = + [ ("MEM_fence_rw_rw", Barrier_RISCV_rw_rw); + ("MEM_fence_r_rw", Barrier_RISCV_r_rw); + ("MEM_fence_rw_w", Barrier_RISCV_rw_w); + ] diff --git a/risc-v/riscv_extras_embed.lem b/risc-v/riscv_extras_embed.lem new file mode 100644 index 00000000..1146d1cd --- /dev/null +++ b/risc-v/riscv_extras_embed.lem @@ -0,0 +1,36 @@ +open import Pervasives +open import Pervasives_extra +open import Sail_impl_base +open import Sail_values +open import Prompt + +val MEMr : (vector bitU * integer) -> M (vector bitU) +val MEMr_reserve : (vector bitU * integer) -> M (vector bitU) + +let MEMr (addr,size) = read_mem false Read_plain addr size +let MEMr_reserve (addr,size) = read_mem false Read_reserve addr size + +val MEMea : (vector bitU * integer) -> M unit +val MEMea_conditional : (vector bitU * integer) -> M unit + +let MEMea (addr,size) = write_mem_ea Write_plain addr size +let MEMea_conditional (addr,size) = write_mem_ea Write_conditional addr size + +val MEMval : (vector bitU * integer * vector bitU) -> M unit +val MEMval_conditional : (vector bitU * integer * vector bitU) -> M bitU + +let MEMval (_,_,v) = write_mem_val v >>= fun _ -> return () +let MEMval_conditional (_,_,v) = write_mem_val v >>= fun b -> return (if b then B1 else B0) + +val MEM_fence_rw_rw : unit -> M unit +val MEM_fence_r_rw : unit -> M unit +val MEM_fence_rw_w : unit -> M unit + +let MEM_fence_rw_rw () = barrier Barrier_RISCV_rw_rw +let MEM_fence_r_rw () = barrier Barrier_RISCV_r_rw +let MEM_fence_rw_w () = barrier Barrier_RISCV_rw_w + +let duplicate (bit,len) = + let bits = repeat [bit] len in + let start = len - 1 in + Vector bits start false diff --git a/risc-v/riscv_extras_embed_sequential.lem b/risc-v/riscv_extras_embed_sequential.lem new file mode 100644 index 00000000..f6709ff7 --- /dev/null +++ b/risc-v/riscv_extras_embed_sequential.lem @@ -0,0 +1,37 @@ +open import Pervasives +open import Pervasives_extra +open import Sail_impl_base +open import Sail_values +open import State + +val MEMr : (vector bitU * integer) -> M (vector bitU) +val MEMr_reserve : (vector bitU * integer) -> M (vector bitU) + +let MEMr (addr,size) = read_mem false Read_plain addr size +let MEMr_reserve (addr,size) = read_mem false Read_reserve addr size + +val MEMea : (vector bitU * integer) -> M unit +val MEMea_conditional : (vector bitU * integer) -> M unit + +let MEMea (addr,size) = write_mem_ea Write_plain addr size +let MEMea_conditional (addr,size) = write_mem_ea Write_conditional addr size + + +val MEMval : (vector bitU * integer * vector bitU) -> M unit +val MEMval_conditional : (vector bitU * integer * vector bitU) -> M bitU + +let MEMval (_,_,v) = write_mem_val v >>= fun _ -> return () +let MEMval_conditional (_,_,v) = write_mem_val v >>= fun b -> return (if b then B1 else B0) + +val MEM_fence_rw_rw : unit -> M unit +val MEM_fence_r_rw : unit -> M unit +val MEM_fence_rw_w : unit -> M unit + +let MEM_fence_rw_rw () = barrier Barrier_RISCV_rw_rw +let MEM_fence_r_rw () = barrier Barrier_RISCV_r_rw +let MEM_fence_rw_w () = barrier Barrier_RISCV_rw_w + +let duplicate (bit,len) = + let bits = repeat [bit] len in + let start = len - 1 in + Vector bits start false diff --git a/risc-v/riscv_regfp.sail b/risc-v/riscv_regfp.sail new file mode 100644 index 00000000..0c7a67d8 --- /dev/null +++ b/risc-v/riscv_regfp.sail @@ -0,0 +1,84 @@ +let (vector <0, 32, inc, string >) GPRstr = + [ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", + "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", + "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31" + ] + +let CIA_fp = RFull("CIA") +let NIA_fp = RFull("NIA") + +function (regfps,regfps,regfps,niafps,diafp,instruction_kind) initial_analysis (instr) = { + iR := [|| ||]; + oR := [|| ||]; + aR := [|| ||]; + ik := IK_simple; + Nias := [|| NIAFP_successor ||]; + Dia := DIAFP_none; + + switch instr { + case (EBREAK) -> () + case (UTYPE ( imm, rd, op)) -> { + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (JAL ( imm, rd)) -> { + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + let (bit[64]) offset = EXTS(imm) in + Nias := [|| NIAFP_concrete_address (PC + offset) ||] + } + case (JALR ( imm, rs, rd)) -> { + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + let (bit[64]) offset = EXTS(imm) in + Nias := [|| NIAFP_register (RFull(GPRstr[rs])) ||]; (* XXX this should br rs + offset... *) + } + case (BTYPE ( imm, rs2, rs1, op)) -> { + if (rs2 == 0) then () else iR := RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR := RFull(GPRstr[rs1]) :: iR; + ik := IK_cond_branch; + let (bit[64]) offset = EXTS(imm) in + Nias := NIAFP_concrete_address(PC + offset) :: Nias; + } + case (ITYPE ( imm, rs, rd, op)) -> { + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (SHIFTIOP ( imm, rs, rd, op)) -> { + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (RTYPE ( rs2, rs1, rd, op)) -> { + if (rs2 == 0) then () else iR := RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR := RFull(GPRstr[rs1]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (LOAD ( imm, rs, rd, unsign, width)) -> { (* XXX "unsigned" causes name conflict in lem shallow embedding... *) + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + aR := iR; + ik := IK_mem_read (Read_plain); + } + case (STORE( imm, rs2, rs1, width)) -> { + if (rs2 == 0) then () else iR := RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR := RFull(GPRstr[rs1]) :: iR; + if (rs1 == 0) then () else aR := RFull(GPRstr[rs1]) :: aR; + ik := IK_mem_write (Write_plain); + } + case (ADDIW ( imm, rs, rd)) -> { + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (SHIFTW ( imm, rs, rd, op)) -> { + if (rs == 0) then () else iR := RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (RTYPEW ( rs2, rs1, rd, op))-> { + if (rs2 == 0) then () else iR := RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR := RFull(GPRstr[rs1]) :: iR; + if (rd == 0) then () else oR := RFull(GPRstr[rd]) :: oR; + } + case (FENCE(pred, succ)) -> { + ik := IK_barrier (Barrier_MIPS_SYNC); + } + }; + (iR,oR,aR,Nias,Dia,ik) +} |
