├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── clippy.toml ├── dev └── xczu3eg-sbva484.csv ├── examples ├── asm │ ├── add.asm │ ├── addreduce_placed.asm │ ├── fsm_3.asm │ ├── fsm_5.asm │ ├── fsm_7.asm │ ├── fsm_9.asm │ ├── mux128.asm │ ├── tadd.asm │ ├── tadd_128.asm │ ├── tadd_256.asm │ ├── tadd_512.asm │ ├── tadd_64.asm │ ├── tdot.asm │ ├── tdot_5_18.asm │ ├── tdot_5_3.asm │ ├── tdot_5_36.asm │ ├── tdot_5_3_opt.asm │ └── tdot_5_9.asm ├── behav │ └── add.v ├── ir │ ├── add.ir │ ├── addreduce.ir │ ├── aes_encrypt.ir │ ├── fsm_3.ir │ ├── fsm_5.ir │ ├── fsm_7.ir │ ├── fsm_9.ir │ ├── mux128.ir │ ├── rom_8x8.ir │ ├── srom_8x256.ir │ ├── tadd.ir │ ├── tadd_128.ir │ ├── tadd_256.ir │ ├── tadd_512.ir │ ├── tadd_64.ir │ ├── tdot.ir │ ├── tdot_5_18.ir │ ├── tdot_5_3.ir │ ├── tdot_5_36.ir │ └── tdot_5_9.ir ├── mmap │ ├── aes.json │ ├── brom_8x256.json │ └── lrom_8x8.json ├── pat │ ├── dsp.pat │ ├── lut.pat │ └── mem.pat ├── struct │ ├── add.v │ ├── addreduce_placed.v │ ├── brom_8x256.v │ ├── brom_8x256_mmap.v │ ├── fsm_3.v │ ├── fsm_5.v │ ├── fsm_7.v │ ├── fsm_9.v │ ├── lrom_8x8.v │ ├── lrom_8x8_mmap.v │ ├── mux128.v │ ├── tadd.v │ ├── tadd_128.v │ ├── tadd_256.v │ ├── tadd_512.v │ ├── tadd_64.v │ ├── tdot.v │ ├── tdot_5_18.v │ ├── tdot_5_3.v │ ├── tdot_5_36.v │ └── tdot_5_9.v ├── xim │ ├── dsp.xim │ ├── lut.xim │ └── mem.xim └── xir │ ├── add.xir │ ├── addreduce_placed.xir │ ├── brom_8x256.xir │ ├── fsm_3.xir │ ├── fsm_5.xir │ ├── fsm_7.xir │ ├── fsm_9.xir │ ├── lrom_8x8.xir │ ├── mux128.xir │ ├── tadd.xir │ ├── tadd_128.xir │ ├── tadd_256.xir │ ├── tadd_512.xir │ ├── tadd_64.xir │ ├── tdot.xir │ ├── tdot_5_18.xir │ ├── tdot_5_3.xir │ ├── tdot_5_36.xir │ └── tdot_5_9.xir ├── rustfmt.toml └── src ├── bin ├── ro.rs └── rt.rs ├── langs ├── asm │ ├── Cargo.toml │ ├── src │ │ ├── ast.rs │ │ ├── default.rs │ │ ├── display.rs │ │ ├── errors.rs │ │ ├── from.rs │ │ ├── from_str.rs │ │ ├── helpers.rs │ │ ├── infer.rs │ │ ├── lib.rs │ │ ├── parser.rs │ │ ├── pretty_print.rs │ │ └── syntax.pest │ └── tests │ │ └── parser.rs ├── ir │ ├── Cargo.toml │ ├── src │ │ ├── ast.rs │ │ ├── default.rs │ │ ├── display.rs │ │ ├── errors.rs │ │ ├── from.rs │ │ ├── from_str.rs │ │ ├── helpers.rs │ │ ├── infer.rs │ │ ├── lib.rs │ │ ├── parser.rs │ │ ├── pretty_print.rs │ │ ├── syntax.pest │ │ └── try_from.rs │ └── tests │ │ └── parser.rs ├── pat │ ├── Cargo.toml │ ├── src │ │ ├── ast.rs │ │ ├── display.rs │ │ ├── errors.rs │ │ ├── from.rs │ │ ├── helpers.rs │ │ ├── infer.rs │ │ ├── lib.rs │ │ ├── parser.rs │ │ ├── pretty_print.rs │ │ └── syntax.pest │ └── tests │ │ └── parser.rs ├── verilog │ ├── Cargo.toml │ └── src │ │ ├── ast.rs │ │ └── lib.rs ├── xim │ ├── Cargo.toml │ ├── src │ │ ├── ast.rs │ │ ├── default.rs │ │ ├── display.rs │ │ ├── errors.rs │ │ ├── helpers.rs │ │ ├── infer.rs │ │ ├── lib.rs │ │ ├── parser.rs │ │ ├── pretty_print.rs │ │ └── syntax.pest │ └── tests │ │ └── parser.rs └── xir │ ├── Cargo.toml │ ├── src │ ├── ast.rs │ ├── display.rs │ ├── errors.rs │ ├── from.rs │ ├── from_str.rs │ ├── helpers.rs │ ├── infer.rs │ ├── lib.rs │ ├── parser.rs │ ├── pretty_print.rs │ └── syntax.pest │ └── tests │ └── parser.rs └── tools ├── bler ├── Cargo.toml ├── build.rs ├── src │ ├── errors.rs │ └── lib.rs └── tests │ └── assemble.rs ├── bline ├── Cargo.toml ├── src │ ├── errors.rs │ └── lib.rs └── tests │ └── behav.rs ├── io ├── Cargo.toml └── src │ └── lib.rs ├── isel ├── Cargo.toml ├── build.rs ├── src │ ├── errors.rs │ ├── lib.rs │ └── tree │ │ ├── default.rs │ │ ├── display.rs │ │ ├── from.rs │ │ ├── helpers.rs │ │ ├── mod.rs │ │ └── try_from.rs └── tests │ └── select.rs ├── mmap ├── Cargo.toml ├── src │ └── lib.rs └── tests │ └── mmap.rs ├── optimizer ├── Cargo.toml ├── src │ ├── cascader.rs │ ├── driver.rs │ ├── errors.rs │ ├── lib.rs │ └── opt.rs └── tests │ └── cascade.rs ├── prettyprint ├── Cargo.toml └── src │ └── lib.rs ├── prim ├── Cargo.toml ├── src │ ├── lib.rs │ ├── prim │ │ ├── borrow.rs │ │ ├── eq.rs │ │ ├── from.rs │ │ ├── hash.rs │ │ ├── helpers.rs │ │ ├── mod.rs │ │ ├── partial_eq.rs │ │ └── to_prim.rs │ └── ultrascale │ │ ├── bram.rs │ │ ├── carry.rs │ │ ├── clock.rs │ │ ├── dsp.rs │ │ ├── gnd.rs │ │ ├── lram.rs │ │ ├── mod.rs │ │ ├── reset.rs │ │ ├── uram.rs │ │ └── vcc.rs └── tests │ └── ultrascale.rs ├── tile ├── Cargo.toml ├── src │ └── lib.rs └── tests │ └── tile.rs ├── translate ├── Cargo.toml └── src │ ├── driver.rs │ ├── errors.rs │ ├── lib.rs │ └── opt.rs └── xpand ├── Cargo.toml ├── src ├── bram.rs ├── carry.rs ├── cat.rs ├── decl.rs ├── display.rs ├── dsp.rs ├── errors.rs ├── expr.rs ├── ext.rs ├── fdre.rs ├── fdse.rs ├── gnd.rs ├── id.rs ├── instance.rs ├── lib.rs ├── loc.rs ├── lram.rs ├── lut.rs ├── param.rs ├── port.rs ├── to_verilog.rs └── vcc.rs └── tests ├── prim.rs └── xpand.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | release: 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest] 17 | runs-on: ${{ matrix.os }} 18 | steps: 19 | - name: Checkout the repository. 20 | uses: actions/checkout@v2 21 | 22 | - name: Install stable toolchain 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | profile: minimal 26 | toolchain: 1.50.0 27 | override: true 28 | components: rustfmt, clippy 29 | 30 | - name: Setup the Rust dependency cache. 31 | uses: Swatinem/rust-cache@v1 32 | 33 | - name: Format 34 | run: cargo fmt --all -- --check 35 | 36 | - name: Clippy 37 | run: cargo clippy --all-targets --all-features 38 | 39 | - name: Build 40 | run: cargo build --release 41 | 42 | - name: Test IR 43 | run: cargo test -p ir 44 | 45 | - name: Test Asm 46 | run: cargo test -p asm 47 | 48 | - name: Test Xir 49 | run: cargo test -p xir 50 | 51 | - name: Test Pat 52 | run: cargo test -p pat 53 | 54 | - name: Test Xim 55 | run: cargo test -p xim 56 | 57 | - name: Test Isel 58 | run: cargo test -p isel 59 | 60 | - name: Test Optimizer 61 | run: cargo test -p optimizer 62 | 63 | - name: Test Bler 64 | run: cargo test -p bler 65 | 66 | - name: Test Bline 67 | run: cargo test -p bline 68 | 69 | - name: Test Prim 70 | run: cargo test -p prim 71 | 72 | - name: Test Xpand 73 | run: cargo test -p xpand 74 | 75 | - name: Test Mmap 76 | run: cargo test -p mmap 77 | 78 | - name: Test Tile 79 | run: cargo test -p tile 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | debug/ 3 | Cargo.lock 4 | .DS_Store 5 | venv 6 | *.log 7 | *.pb 8 | __pycache__/ 9 | *.cpython.* 10 | .cargo/ 11 | .pytest_cache/ 12 | *.pdf 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reticle" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | ir = { path = "src/langs/ir"} 10 | asm = { path = "src/langs/asm" } 11 | pat = { path = "src/langs/pat"} 12 | xim = { path = "src/langs/xim"} 13 | xir = { path = "src/langs/xir"} 14 | isel = { path = "src/tools/isel" } 15 | translate = { path = "src/tools/translate" } 16 | optimizer = { path = "src/tools/optimizer" } 17 | 18 | [[bin]] 19 | name = "rt" 20 | path = "src/bin/rt.rs" 21 | 22 | [[bin]] 23 | name = "ro" 24 | path = "src/bin/ro.rs" 25 | 26 | [workspace] 27 | members = [ 28 | "src/langs/ir", 29 | "src/langs/pat", 30 | "src/langs/asm", 31 | "src/langs/xir", 32 | "src/langs/xim", 33 | "src/langs/verilog", 34 | "src/tools/io", 35 | "src/tools/prettyprint", 36 | "src/tools/isel", 37 | "src/tools/translate", 38 | "src/tools/optimizer", 39 | "src/tools/bler", 40 | "src/tools/bline", 41 | "src/tools/xpand", 42 | "src/tools/prim", 43 | "src/tools/mmap", 44 | "src/tools/tile", 45 | ] 46 | 47 | exclude = ["ci", "dev", "docker"] 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reticle (WIP, highly experimental) 2 | 3 | ## Setup, build, and install 4 | 5 | 1. Install [rustup](https://www.rust-lang.org/tools/install) 6 | ```bash 7 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 8 | ``` 9 | 2. Install `1.50.0` rust version 10 | ```bash 11 | rustup toolchain install 1.50.0 12 | rustup override set 1.50.0 13 | ``` 14 | 3. Run unit tests 15 | ```bash 16 | cargo test --all 17 | ``` 18 | 4. Build, binaries are located in `target/release` 19 | ```bash 20 | cargo build --release 21 | ``` 22 | 5. Optional, install locally (binaries are normally located in `~/.cargo/bin`) 23 | ```bash 24 | cargo install --bin rt --bin ro --path . 25 | ``` 26 | 27 | ## How to use reticle compiler 28 | 29 | 1. Compile IR program to assembly (asm) 30 | ```bash 31 | ./target/release/rt --from ir --to asm examples/ir/add.ir 32 | ``` 33 | 2. Compile IR program to machine IR (xir) 34 | ```bash 35 | ./target/release/rt --from ir --to xir examples/ir/add.ir 36 | ``` 37 | 3. Compile IR program to structural Verilog (struct) 38 | ```bash 39 | ./target/release/rt --from ir --to struct examples/ir/add.ir 40 | ``` 41 | 4. Compile IR program to behavioral Verilog (behav) 42 | ```bash 43 | ./target/release/rt --from ir --to behav examples/ir/add.ir 44 | ``` 45 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.31.0" 2 | -------------------------------------------------------------------------------- /examples/asm/add.asm: -------------------------------------------------------------------------------- 1 | def main(a: i8, b: i8, en: bool) -> (y: i8) { 2 | y:i8 = laddrega_i8(a, b, en) @lut(??, ??); 3 | } 4 | 5 | -------------------------------------------------------------------------------- /examples/asm/addreduce_placed.asm: -------------------------------------------------------------------------------- 1 | def main(a:i8, b:i8, c:i8, d:i8, e:i8, f:i8, g:i8, h:i8, en:bool) -> (y:i8) { 2 | y:i8 = laddrega_i8(t10, t11, en) @lut(0, 0); 3 | t10:i8 = laddrega_i8(t4, t5, en) @lut(0, 1); 4 | t11:i8 = laddrega_i8(t6, t7, en) @lut(0, 2); 5 | t4:i8 = laddrega_i8(a, b, en) @lut(0, 3); 6 | t5:i8 = laddrega_i8(c, d, en) @lut(0, 4); 7 | t6:i8 = laddrega_i8(e, f, en) @lut(0, 5); 8 | t7:i8 = laddrega_i8(g, h, en) @lut(0, 6); 9 | } 10 | -------------------------------------------------------------------------------- /examples/asm/fsm_3.asm: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool) -> (y:i4) { 2 | t13:i4 = lmuxrega_i4(t9, t0, t11, t3) @lut(??, ??); 3 | t3:bool = const[1]; 4 | t9:bool = land_bool(t6, i2) @lut(??, ??); 5 | t0:i4 = const[0]; 6 | t11:i4 = lmux_i4(t8, t2, t10) @lut(??, ??); 7 | t6:bool = leq_i4(t13, t2) @lut(??, ??); 8 | t8:bool = land_bool(t5, i1) @lut(??, ??); 9 | t2:i4 = const[2]; 10 | t10:i4 = lmux_i4(t7, t1, t13) @lut(??, ??); 11 | t5:bool = leq_i4(t13, t1) @lut(??, ??); 12 | t7:bool = land_bool(t4, i0) @lut(??, ??); 13 | t1:i4 = const[1]; 14 | t4:bool = leq_i4(t13, t0) @lut(??, ??); 15 | y:i4 = id(t13); 16 | } -------------------------------------------------------------------------------- /examples/asm/fsm_5.asm: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3:bool, i4:bool) -> (y:i4) { 2 | t21:i4 = lmuxrega_i4(t15, t0, t19, t5) @lut(??, ??); 3 | t5:bool = const[1]; 4 | t15:bool = land_bool(t10, i4) @lut(??, ??); 5 | t0:i4 = const[0]; 6 | t19:i4 = lmux_i4(t14, t4, t18) @lut(??, ??); 7 | t10:bool = leq_i4(t21, t4) @lut(??, ??); 8 | t14:bool = land_bool(t9, i3) @lut(??, ??); 9 | t4:i4 = const[4]; 10 | t18:i4 = lmux_i4(t13, t3, t17) @lut(??, ??); 11 | t9:bool = leq_i4(t21, t3) @lut(??, ??); 12 | t13:bool = land_bool(t8, i2) @lut(??, ??); 13 | t3:i4 = const[3]; 14 | t17:i4 = lmux_i4(t12, t2, t16) @lut(??, ??); 15 | t8:bool = leq_i4(t21, t2) @lut(??, ??); 16 | t12:bool = land_bool(t7, i1) @lut(??, ??); 17 | t2:i4 = const[2]; 18 | t16:i4 = lmux_i4(t11, t1, t21) @lut(??, ??); 19 | t7:bool = leq_i4(t21, t1) @lut(??, ??); 20 | t11:bool = land_bool(t6, i0) @lut(??, ??); 21 | t1:i4 = const[1]; 22 | t6:bool = leq_i4(t21, t0) @lut(??, ??); 23 | y:i4 = id(t21); 24 | } -------------------------------------------------------------------------------- /examples/asm/fsm_7.asm: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3:bool, i4:bool, i5:bool, i6:bool) -> (y:i4) { 2 | t29:i4 = lmuxrega_i4(t21, t0, t27, t7) @lut(??, ??); 3 | t7:bool = const[1]; 4 | t21:bool = land_bool(t14, i6) @lut(??, ??); 5 | t0:i4 = const[0]; 6 | t27:i4 = lmux_i4(t20, t6, t26) @lut(??, ??); 7 | t14:bool = leq_i4(t29, t6) @lut(??, ??); 8 | t20:bool = land_bool(t13, i5) @lut(??, ??); 9 | t6:i4 = const[6]; 10 | t26:i4 = lmux_i4(t19, t5, t25) @lut(??, ??); 11 | t13:bool = leq_i4(t29, t5) @lut(??, ??); 12 | t19:bool = land_bool(t12, i4) @lut(??, ??); 13 | t5:i4 = const[5]; 14 | t25:i4 = lmux_i4(t18, t4, t24) @lut(??, ??); 15 | t12:bool = leq_i4(t29, t4) @lut(??, ??); 16 | t18:bool = land_bool(t11, i3) @lut(??, ??); 17 | t4:i4 = const[4]; 18 | t24:i4 = lmux_i4(t17, t3, t23) @lut(??, ??); 19 | t11:bool = leq_i4(t29, t3) @lut(??, ??); 20 | t17:bool = land_bool(t10, i2) @lut(??, ??); 21 | t3:i4 = const[3]; 22 | t23:i4 = lmux_i4(t16, t2, t22) @lut(??, ??); 23 | t10:bool = leq_i4(t29, t2) @lut(??, ??); 24 | t16:bool = land_bool(t9, i1) @lut(??, ??); 25 | t2:i4 = const[2]; 26 | t22:i4 = lmux_i4(t15, t1, t29) @lut(??, ??); 27 | t9:bool = leq_i4(t29, t1) @lut(??, ??); 28 | t15:bool = land_bool(t8, i0) @lut(??, ??); 29 | t1:i4 = const[1]; 30 | t8:bool = leq_i4(t29, t0) @lut(??, ??); 31 | y:i4 = id(t29); 32 | } -------------------------------------------------------------------------------- /examples/asm/fsm_9.asm: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3:bool, i4:bool, i5:bool, i6:bool, i7:bool, i8:bool) -> (y:i4) { 2 | t37:i4 = lmuxrega_i4(t27, t0, t35, t9) @lut(??, ??); 3 | t9:bool = const[1]; 4 | t27:bool = land_bool(t18, i8) @lut(??, ??); 5 | t0:i4 = const[0]; 6 | t35:i4 = lmux_i4(t26, t8, t34) @lut(??, ??); 7 | t18:bool = leq_i4(t37, t8) @lut(??, ??); 8 | t26:bool = land_bool(t17, i7) @lut(??, ??); 9 | t8:i4 = const[8]; 10 | t34:i4 = lmux_i4(t25, t7, t33) @lut(??, ??); 11 | t17:bool = leq_i4(t37, t7) @lut(??, ??); 12 | t25:bool = land_bool(t16, i6) @lut(??, ??); 13 | t7:i4 = const[7]; 14 | t33:i4 = lmux_i4(t24, t6, t32) @lut(??, ??); 15 | t16:bool = leq_i4(t37, t6) @lut(??, ??); 16 | t24:bool = land_bool(t15, i5) @lut(??, ??); 17 | t6:i4 = const[6]; 18 | t32:i4 = lmux_i4(t23, t5, t31) @lut(??, ??); 19 | t15:bool = leq_i4(t37, t5) @lut(??, ??); 20 | t23:bool = land_bool(t14, i4) @lut(??, ??); 21 | t5:i4 = const[5]; 22 | t31:i4 = lmux_i4(t22, t4, t30) @lut(??, ??); 23 | t14:bool = leq_i4(t37, t4) @lut(??, ??); 24 | t22:bool = land_bool(t13, i3) @lut(??, ??); 25 | t4:i4 = const[4]; 26 | t30:i4 = lmux_i4(t21, t3, t29) @lut(??, ??); 27 | t13:bool = leq_i4(t37, t3) @lut(??, ??); 28 | t21:bool = land_bool(t12, i2) @lut(??, ??); 29 | t3:i4 = const[3]; 30 | t29:i4 = lmux_i4(t20, t2, t28) @lut(??, ??); 31 | t12:bool = leq_i4(t37, t2) @lut(??, ??); 32 | t20:bool = land_bool(t11, i1) @lut(??, ??); 33 | t2:i4 = const[2]; 34 | t28:i4 = lmux_i4(t19, t1, t37) @lut(??, ??); 35 | t11:bool = leq_i4(t37, t1) @lut(??, ??); 36 | t19:bool = land_bool(t10, i0) @lut(??, ??); 37 | t1:i4 = const[1]; 38 | t10:bool = leq_i4(t37, t0) @lut(??, ??); 39 | y:i4 = id(t37); 40 | } -------------------------------------------------------------------------------- /examples/asm/mux128.asm: -------------------------------------------------------------------------------- 1 | def main(c:bool, a:i128, b:i128) -> (y:i128) { 2 | t0:i8 = ext[0, 7](a); 3 | t1:i8 = ext[0, 7](b); 4 | t2:i8 = lmux_i8(c, t0, t1) @lut(??, ??); 5 | t3:i8 = ext[8, 15](a); 6 | t4:i8 = ext[8, 15](b); 7 | t5:i8 = lmux_i8(c, t3, t4) @lut(??, ??); 8 | t6:i8 = ext[16, 23](a); 9 | t7:i8 = ext[16, 23](b); 10 | t8:i8 = lmux_i8(c, t6, t7) @lut(??, ??); 11 | t9:i8 = ext[24, 31](a); 12 | t10:i8 = ext[24, 31](b); 13 | t11:i8 = lmux_i8(c, t9, t10) @lut(??, ??); 14 | t12:i8 = ext[32, 39](a); 15 | t13:i8 = ext[32, 39](b); 16 | t14:i8 = lmux_i8(c, t12, t13) @lut(??, ??); 17 | t15:i8 = ext[40, 47](a); 18 | t16:i8 = ext[40, 47](b); 19 | t17:i8 = lmux_i8(c, t15, t16) @lut(??, ??); 20 | t18:i8 = ext[48, 55](a); 21 | t19:i8 = ext[48, 55](b); 22 | t20:i8 = lmux_i8(c, t18, t19) @lut(??, ??); 23 | t21:i8 = ext[56, 63](a); 24 | t22:i8 = ext[56, 63](b); 25 | t23:i8 = lmux_i8(c, t21, t22) @lut(??, ??); 26 | t24:i8 = ext[64, 71](a); 27 | t25:i8 = ext[64, 71](b); 28 | t26:i8 = lmux_i8(c, t24, t25) @lut(??, ??); 29 | t27:i8 = ext[72, 79](a); 30 | t28:i8 = ext[72, 79](b); 31 | t29:i8 = lmux_i8(c, t27, t28) @lut(??, ??); 32 | t30:i8 = ext[80, 87](a); 33 | t31:i8 = ext[80, 87](b); 34 | t32:i8 = lmux_i8(c, t30, t31) @lut(??, ??); 35 | t33:i8 = ext[88, 95](a); 36 | t34:i8 = ext[88, 95](b); 37 | t35:i8 = lmux_i8(c, t33, t34) @lut(??, ??); 38 | t36:i8 = ext[96, 103](a); 39 | t37:i8 = ext[96, 103](b); 40 | t38:i8 = lmux_i8(c, t36, t37) @lut(??, ??); 41 | t39:i8 = ext[104, 111](a); 42 | t40:i8 = ext[104, 111](b); 43 | t41:i8 = lmux_i8(c, t39, t40) @lut(??, ??); 44 | t42:i8 = ext[112, 119](a); 45 | t43:i8 = ext[112, 119](b); 46 | t44:i8 = lmux_i8(c, t42, t43) @lut(??, ??); 47 | t45:i8 = ext[120, 127](a); 48 | t46:i8 = ext[120, 127](b); 49 | t47:i8 = lmux_i8(c, t45, t46) @lut(??, ??); 50 | y:i128 = cat(t2, t5, t8, t11, t14, t17, t20, t23, t26, t29, t32, t35, t38, t41, t44, t47); 51 | } -------------------------------------------------------------------------------- /examples/asm/tadd.asm: -------------------------------------------------------------------------------- 1 | def main(en:bool, a:i8<4>, b:i8<4>) -> (y:i8<4>) { 2 | y:i8<4> = daddrega_i8v4(a, b, en, en, en) @dsp(??, ??); 3 | } -------------------------------------------------------------------------------- /examples/asm/tadd_128.asm: -------------------------------------------------------------------------------- 1 | def main(en:bool, a0:i8<4>, b0:i8<4>, a1:i8<4>, b1:i8<4>, a2:i8<4>, b2:i8<4>, a3:i8<4>, b3:i8<4>, a4:i8<4>, b4:i8<4>, a5:i8<4>, b5:i8<4>, a6:i8<4>, b6:i8<4>, a7:i8<4>, b7:i8<4>, a8:i8<4>, b8:i8<4>, a9:i8<4>, b9:i8<4>, a10:i8<4>, b10:i8<4>, a11:i8<4>, b11:i8<4>, a12:i8<4>, b12:i8<4>, a13:i8<4>, b13:i8<4>, a14:i8<4>, b14:i8<4>, a15:i8<4>, b15:i8<4>, a16:i8<4>, b16:i8<4>, a17:i8<4>, b17:i8<4>, a18:i8<4>, b18:i8<4>, a19:i8<4>, b19:i8<4>, a20:i8<4>, b20:i8<4>, a21:i8<4>, b21:i8<4>, a22:i8<4>, b22:i8<4>, a23:i8<4>, b23:i8<4>, a24:i8<4>, b24:i8<4>, a25:i8<4>, b25:i8<4>, a26:i8<4>, b26:i8<4>, a27:i8<4>, b27:i8<4>, a28:i8<4>, b28:i8<4>, a29:i8<4>, b29:i8<4>, a30:i8<4>, b30:i8<4>, a31:i8<4>, b31:i8<4>) -> (y0:i8<4>, y1:i8<4>, y2:i8<4>, y3:i8<4>, y4:i8<4>, y5:i8<4>, y6:i8<4>, y7:i8<4>, y8:i8<4>, y9:i8<4>, y10:i8<4>, y11:i8<4>, y12:i8<4>, y13:i8<4>, y14:i8<4>, y15:i8<4>, y16:i8<4>, y17:i8<4>, y18:i8<4>, y19:i8<4>, y20:i8<4>, y21:i8<4>, y22:i8<4>, y23:i8<4>, y24:i8<4>, y25:i8<4>, y26:i8<4>, y27:i8<4>, y28:i8<4>, y29:i8<4>, y30:i8<4>, y31:i8<4>) { 2 | y0:i8<4> = daddrega_i8v4(a0, b0, en, en, en) @dsp(??, ??); 3 | y1:i8<4> = daddrega_i8v4(a1, b1, en, en, en) @dsp(??, ??); 4 | y2:i8<4> = daddrega_i8v4(a2, b2, en, en, en) @dsp(??, ??); 5 | y3:i8<4> = daddrega_i8v4(a3, b3, en, en, en) @dsp(??, ??); 6 | y4:i8<4> = daddrega_i8v4(a4, b4, en, en, en) @dsp(??, ??); 7 | y5:i8<4> = daddrega_i8v4(a5, b5, en, en, en) @dsp(??, ??); 8 | y6:i8<4> = daddrega_i8v4(a6, b6, en, en, en) @dsp(??, ??); 9 | y7:i8<4> = daddrega_i8v4(a7, b7, en, en, en) @dsp(??, ??); 10 | y8:i8<4> = daddrega_i8v4(a8, b8, en, en, en) @dsp(??, ??); 11 | y9:i8<4> = daddrega_i8v4(a9, b9, en, en, en) @dsp(??, ??); 12 | y10:i8<4> = daddrega_i8v4(a10, b10, en, en, en) @dsp(??, ??); 13 | y11:i8<4> = daddrega_i8v4(a11, b11, en, en, en) @dsp(??, ??); 14 | y12:i8<4> = daddrega_i8v4(a12, b12, en, en, en) @dsp(??, ??); 15 | y13:i8<4> = daddrega_i8v4(a13, b13, en, en, en) @dsp(??, ??); 16 | y14:i8<4> = daddrega_i8v4(a14, b14, en, en, en) @dsp(??, ??); 17 | y15:i8<4> = daddrega_i8v4(a15, b15, en, en, en) @dsp(??, ??); 18 | y16:i8<4> = daddrega_i8v4(a16, b16, en, en, en) @dsp(??, ??); 19 | y17:i8<4> = daddrega_i8v4(a17, b17, en, en, en) @dsp(??, ??); 20 | y18:i8<4> = daddrega_i8v4(a18, b18, en, en, en) @dsp(??, ??); 21 | y19:i8<4> = daddrega_i8v4(a19, b19, en, en, en) @dsp(??, ??); 22 | y20:i8<4> = daddrega_i8v4(a20, b20, en, en, en) @dsp(??, ??); 23 | y21:i8<4> = daddrega_i8v4(a21, b21, en, en, en) @dsp(??, ??); 24 | y22:i8<4> = daddrega_i8v4(a22, b22, en, en, en) @dsp(??, ??); 25 | y23:i8<4> = daddrega_i8v4(a23, b23, en, en, en) @dsp(??, ??); 26 | y24:i8<4> = daddrega_i8v4(a24, b24, en, en, en) @dsp(??, ??); 27 | y25:i8<4> = daddrega_i8v4(a25, b25, en, en, en) @dsp(??, ??); 28 | y26:i8<4> = daddrega_i8v4(a26, b26, en, en, en) @dsp(??, ??); 29 | y27:i8<4> = daddrega_i8v4(a27, b27, en, en, en) @dsp(??, ??); 30 | y28:i8<4> = daddrega_i8v4(a28, b28, en, en, en) @dsp(??, ??); 31 | y29:i8<4> = daddrega_i8v4(a29, b29, en, en, en) @dsp(??, ??); 32 | y30:i8<4> = daddrega_i8v4(a30, b30, en, en, en) @dsp(??, ??); 33 | y31:i8<4> = daddrega_i8v4(a31, b31, en, en, en) @dsp(??, ??); 34 | } -------------------------------------------------------------------------------- /examples/asm/tadd_64.asm: -------------------------------------------------------------------------------- 1 | def main(en:bool, a0:i8<4>, b0:i8<4>, a1:i8<4>, b1:i8<4>, a2:i8<4>, b2:i8<4>, a3:i8<4>, b3:i8<4>, a4:i8<4>, b4:i8<4>, a5:i8<4>, b5:i8<4>, a6:i8<4>, b6:i8<4>, a7:i8<4>, b7:i8<4>, a8:i8<4>, b8:i8<4>, a9:i8<4>, b9:i8<4>, a10:i8<4>, b10:i8<4>, a11:i8<4>, b11:i8<4>, a12:i8<4>, b12:i8<4>, a13:i8<4>, b13:i8<4>, a14:i8<4>, b14:i8<4>, a15:i8<4>, b15:i8<4>) -> (y0:i8<4>, y1:i8<4>, y2:i8<4>, y3:i8<4>, y4:i8<4>, y5:i8<4>, y6:i8<4>, y7:i8<4>, y8:i8<4>, y9:i8<4>, y10:i8<4>, y11:i8<4>, y12:i8<4>, y13:i8<4>, y14:i8<4>, y15:i8<4>) { 2 | y0:i8<4> = daddrega_i8v4(a0, b0, en, en, en) @dsp(??, ??); 3 | y1:i8<4> = daddrega_i8v4(a1, b1, en, en, en) @dsp(??, ??); 4 | y2:i8<4> = daddrega_i8v4(a2, b2, en, en, en) @dsp(??, ??); 5 | y3:i8<4> = daddrega_i8v4(a3, b3, en, en, en) @dsp(??, ??); 6 | y4:i8<4> = daddrega_i8v4(a4, b4, en, en, en) @dsp(??, ??); 7 | y5:i8<4> = daddrega_i8v4(a5, b5, en, en, en) @dsp(??, ??); 8 | y6:i8<4> = daddrega_i8v4(a6, b6, en, en, en) @dsp(??, ??); 9 | y7:i8<4> = daddrega_i8v4(a7, b7, en, en, en) @dsp(??, ??); 10 | y8:i8<4> = daddrega_i8v4(a8, b8, en, en, en) @dsp(??, ??); 11 | y9:i8<4> = daddrega_i8v4(a9, b9, en, en, en) @dsp(??, ??); 12 | y10:i8<4> = daddrega_i8v4(a10, b10, en, en, en) @dsp(??, ??); 13 | y11:i8<4> = daddrega_i8v4(a11, b11, en, en, en) @dsp(??, ??); 14 | y12:i8<4> = daddrega_i8v4(a12, b12, en, en, en) @dsp(??, ??); 15 | y13:i8<4> = daddrega_i8v4(a13, b13, en, en, en) @dsp(??, ??); 16 | y14:i8<4> = daddrega_i8v4(a14, b14, en, en, en) @dsp(??, ??); 17 | y15:i8<4> = daddrega_i8v4(a15, b15, en, en, en) @dsp(??, ??); 18 | } -------------------------------------------------------------------------------- /examples/asm/tdot.asm: -------------------------------------------------------------------------------- 1 | def main(a0:i8, a1:i8, a2:i8, b0:i8, b1:i8, b2:i8, c:i8, en:bool) -> (y:i8) { 2 | y:i8 = dmuladdrega_i8i8(a2, b2, t11, en, en, en, en) @dsp(??, ??); 3 | t11:i8 = dmuladdrega_i8i8(a1, b1, t5, en, en, en, en) @dsp(??, ??); 4 | t5:i8 = dmuladdrega_i8i8(a0, b0, c, en, en, en, en) @dsp(??, ??); 5 | } -------------------------------------------------------------------------------- /examples/asm/tdot_5_3.asm: -------------------------------------------------------------------------------- 1 | def main(a0:i8, c0:i8, e0:i8, g0:i8, i0:i8, a1:i8, c1:i8, e1:i8, g1:i8, i1:i8, a2:i8, c2:i8, e2:i8, g2:i8, i2:i8, b0:i8, d0:i8, f0:i8, h0:i8, j0:i8, b1:i8, d1:i8, f1:i8, h1:i8, j1:i8, b2:i8, d2:i8, f2:i8, h2:i8, j2:i8, m:i8, n:i8, o:i8, p:i8, q:i8, en:bool) -> (v:i8, w:i8, x:i8, y:i8, z:i8) { 2 | v:i8 = dmuladdrega_i8i8(a2, b2, t11, en, en, en, en) @dsp(??, ??); 3 | t11:i8 = dmuladdrega_i8i8(a1, b1, t5, en, en, en, en) @dsp(??, ??); 4 | t5:i8 = dmuladdrega_i8i8(a0, b0, m, en, en, en, en) @dsp(??, ??); 5 | w:i8 = dmuladdrega_i8i8(c2, d2, t29, en, en, en, en) @dsp(??, ??); 6 | t29:i8 = dmuladdrega_i8i8(c1, d1, t23, en, en, en, en) @dsp(??, ??); 7 | t23:i8 = dmuladdrega_i8i8(c0, d0, n, en, en, en, en) @dsp(??, ??); 8 | x:i8 = dmuladdrega_i8i8(e2, f2, t47, en, en, en, en) @dsp(??, ??); 9 | t47:i8 = dmuladdrega_i8i8(e1, f1, t41, en, en, en, en) @dsp(??, ??); 10 | t41:i8 = dmuladdrega_i8i8(e0, f0, o, en, en, en, en) @dsp(??, ??); 11 | y:i8 = dmuladdrega_i8i8(g2, h2, t65, en, en, en, en) @dsp(??, ??); 12 | t65:i8 = dmuladdrega_i8i8(g1, h1, t59, en, en, en, en) @dsp(??, ??); 13 | t59:i8 = dmuladdrega_i8i8(g0, h0, p, en, en, en, en) @dsp(??, ??); 14 | z:i8 = dmuladdrega_i8i8(i2, j2, t83, en, en, en, en) @dsp(??, ??); 15 | t83:i8 = dmuladdrega_i8i8(i1, j1, t77, en, en, en, en) @dsp(??, ??); 16 | t77:i8 = dmuladdrega_i8i8(i0, j0, q, en, en, en, en) @dsp(??, ??); 17 | } 18 | -------------------------------------------------------------------------------- /examples/asm/tdot_5_3_opt.asm: -------------------------------------------------------------------------------- 1 | def main(a0:i8, c0:i8, e0:i8, g0:i8, i0:i8, a1:i8, c1:i8, e1:i8, g1:i8, i1:i8, a2:i8, c2:i8, e2:i8, g2:i8, i2:i8, b0:i8, d0:i8, f0:i8, h0:i8, j0:i8, b1:i8, d1:i8, f1:i8, h1:i8, j1:i8, b2:i8, d2:i8, f2:i8, h2:i8, j2:i8, m:i8, n:i8, o:i8, p:i8, q:i8, en:bool) -> (v:i8, w:i8, x:i8, y:i8, z:i8) { 2 | v:i8 = dmuladdregaci_i8i8(a2, b2, t11, en, en, en, en) @dsp(x0, y0+2); 3 | t11:i8 = dmuladdregacio_i8i8(a1, b1, t5, en, en, en, en) @dsp(x0, y0+1); 4 | t5:i8 = dmuladdregaco_i8i8(a0, b0, m, en, en, en, en) @dsp(x0, y0); 5 | w:i8 = dmuladdregaci_i8i8(c2, d2, t29, en, en, en, en) @dsp(x1, y1+2); 6 | t29:i8 = dmuladdregacio_i8i8(c1, d1, t23, en, en, en, en) @dsp(x1, y1+1); 7 | t23:i8 = dmuladdregaco_i8i8(c0, d0, n, en, en, en, en) @dsp(x1, y1); 8 | x:i8 = dmuladdregaci_i8i8(e2, f2, t47, en, en, en, en) @dsp(x2, y2+2); 9 | t47:i8 = dmuladdregacio_i8i8(e1, f1, t41, en, en, en, en) @dsp(x2, y2+1); 10 | t41:i8 = dmuladdregaco_i8i8(e0, f0, o, en, en, en, en) @dsp(x2, y2); 11 | y:i8 = dmuladdregaci_i8i8(g2, h2, t65, en, en, en, en) @dsp(x3, y3+2); 12 | t65:i8 = dmuladdregacio_i8i8(g1, h1, t59, en, en, en, en) @dsp(x3, y3+1); 13 | t59:i8 = dmuladdregaco_i8i8(g0, h0, p, en, en, en, en) @dsp(x3, y3); 14 | z:i8 = dmuladdregaci_i8i8(i2, j2, t83, en, en, en, en) @dsp(x4, y4+2); 15 | t83:i8 = dmuladdregacio_i8i8(i1, j1, t77, en, en, en, en) @dsp(x4, y4+1); 16 | t77:i8 = dmuladdregaco_i8i8(i0, j0, q, en, en, en, en) @dsp(x4, y4); 17 | } 18 | -------------------------------------------------------------------------------- /examples/behav/add.v: -------------------------------------------------------------------------------- 1 | module main ( 2 | input wire clock, 3 | input wire reset, 4 | input wire [7:0] a, 5 | input wire [7:0] b, 6 | input wire en, 7 | output reg [7:0] y 8 | ); 9 | wire [7:0] t0; 10 | assign t0 = a + b; 11 | always @(posedge clock) begin 12 | if(reset) begin 13 | y <= 0; 14 | end else if(en) begin 15 | y <= t0; 16 | end 17 | end 18 | endmodule 19 | -------------------------------------------------------------------------------- /examples/ir/add.ir: -------------------------------------------------------------------------------- 1 | def main(a: i8, b: i8, en: bool) -> (y: i8) { 2 | t0:i8 = add(a, b); 3 | y:i8 = reg[0](t0, en); 4 | } 5 | -------------------------------------------------------------------------------- /examples/ir/addreduce.ir: -------------------------------------------------------------------------------- 1 | def main(a: i8, b: i8, c:i8, d:i8, e:i8, f:i8, g:i8, h:i8, en: bool) -> (y: i8) { 2 | t0:i8 = add(a, b); 3 | t1:i8 = add(c, d); 4 | t2:i8 = add(e, f); 5 | t3:i8 = add(g, h); 6 | t4:i8 = reg[0](t0, en); 7 | t5:i8 = reg[0](t1, en); 8 | t6:i8 = reg[0](t2, en); 9 | t7:i8 = reg[0](t3, en); 10 | t8:i8 = add(t4, t5); 11 | t9:i8 = add(t6, t7); 12 | t10:i8 = reg[0](t8, en); 13 | t11:i8 = reg[0](t9, en); 14 | t12:i8 = add(t10, t11); 15 | y:i8 = reg[0](t12, en); 16 | } 17 | -------------------------------------------------------------------------------- /examples/ir/fsm_3.ir: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool) -> (y:i4) { 2 | t0: i4 = const[0]; 3 | t1: i4 = const[1]; 4 | t2: i4 = const[2]; 5 | t3: bool = const[1]; 6 | t4: bool = eq(t13, t0); 7 | t5: bool = eq(t13, t1); 8 | t6: bool = eq(t13, t2); 9 | t7: bool = and(t4, i0); 10 | t8: bool = and(t5, i1); 11 | t9: bool = and(t6, i2); 12 | t10: i4 = mux(t7, t1, t13); 13 | t11: i4 = mux(t8, t2, t10); 14 | t12: i4 = mux(t9, t0, t11); 15 | t13: i4 = reg[0](t12, t3); 16 | y: i4 = id(t13); 17 | } 18 | -------------------------------------------------------------------------------- /examples/ir/fsm_5.ir: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3: bool, i4:bool) -> (y:i4) { 2 | t0: i4 = const[0]; 3 | t1: i4 = const[1]; 4 | t2: i4 = const[2]; 5 | t3: i4 = const[3]; 6 | t4: i4 = const[4]; 7 | t5: bool = const[1]; 8 | t6: bool = eq(t21, t0); 9 | t7: bool = eq(t21, t1); 10 | t8: bool = eq(t21, t2); 11 | t9: bool = eq(t21, t3); 12 | t10: bool = eq(t21, t4); 13 | t11: bool = and(t6, i0); 14 | t12: bool = and(t7, i1); 15 | t13: bool = and(t8, i2); 16 | t14: bool = and(t9, i3); 17 | t15: bool = and(t10, i4); 18 | t16: i4 = mux(t11, t1, t21); 19 | t17: i4 = mux(t12, t2, t16); 20 | t18: i4 = mux(t13, t3, t17); 21 | t19: i4 = mux(t14, t4, t18); 22 | t20: i4 = mux(t15, t0, t19); 23 | t21: i4 = reg[0](t20, t5); 24 | y: i4 = id(t21); 25 | } 26 | -------------------------------------------------------------------------------- /examples/ir/fsm_7.ir: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3: bool, i4:bool, i5:bool, i6:bool) -> (y:i4) { 2 | t0: i4 = const[0]; 3 | t1: i4 = const[1]; 4 | t2: i4 = const[2]; 5 | t3: i4 = const[3]; 6 | t4: i4 = const[4]; 7 | t5: i4 = const[5]; 8 | t6: i4 = const[6]; 9 | t7: bool = const[1]; 10 | t8: bool = eq(t29, t0); 11 | t9: bool = eq(t29, t1); 12 | t10: bool = eq(t29, t2); 13 | t11: bool = eq(t29, t3); 14 | t12: bool = eq(t29, t4); 15 | t13: bool = eq(t29, t5); 16 | t14: bool = eq(t29, t6); 17 | t15: bool = and(t8, i0); 18 | t16: bool = and(t9, i1); 19 | t17: bool = and(t10, i2); 20 | t18: bool = and(t11, i3); 21 | t19: bool = and(t12, i4); 22 | t20: bool = and(t13, i5); 23 | t21: bool = and(t14, i6); 24 | t22: i4 = mux(t15, t1, t29); 25 | t23: i4 = mux(t16, t2, t22); 26 | t24: i4 = mux(t17, t3, t23); 27 | t25: i4 = mux(t18, t4, t24); 28 | t26: i4 = mux(t19, t5, t25); 29 | t27: i4 = mux(t20, t6, t26); 30 | t28: i4 = mux(t21, t0, t27); 31 | t29: i4 = reg[0](t28, t7); 32 | y: i4 = id(t29); 33 | } 34 | -------------------------------------------------------------------------------- /examples/ir/fsm_9.ir: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool, i3:bool, i4:bool, i5:bool, i6:bool, i7:bool, i8:bool) -> (y:i4) { 2 | t0: i4 = const[0]; 3 | t1: i4 = const[1]; 4 | t2: i4 = const[2]; 5 | t3: i4 = const[3]; 6 | t4: i4 = const[4]; 7 | t5: i4 = const[5]; 8 | t6: i4 = const[6]; 9 | t7: i4 = const[7]; 10 | t8: i4 = const[8]; 11 | t9: bool = const[1]; 12 | t10: bool = eq(t37, t0); 13 | t11: bool = eq(t37, t1); 14 | t12: bool = eq(t37, t2); 15 | t13: bool = eq(t37, t3); 16 | t14: bool = eq(t37, t4); 17 | t15: bool = eq(t37, t5); 18 | t16: bool = eq(t37, t6); 19 | t17: bool = eq(t37, t7); 20 | t18: bool = eq(t37, t8); 21 | t19: bool = and(t10, i0); 22 | t20: bool = and(t11, i1); 23 | t21: bool = and(t12, i2); 24 | t22: bool = and(t13, i3); 25 | t23: bool = and(t14, i4); 26 | t24: bool = and(t15, i5); 27 | t25: bool = and(t16, i6); 28 | t26: bool = and(t17, i7); 29 | t27: bool = and(t18, i8); 30 | t28: i4 = mux(t19, t1, t37); 31 | t29: i4 = mux(t20, t2, t28); 32 | t30: i4 = mux(t21, t3, t29); 33 | t31: i4 = mux(t22, t4, t30); 34 | t32: i4 = mux(t23, t5, t31); 35 | t33: i4 = mux(t24, t6, t32); 36 | t34: i4 = mux(t25, t7, t33); 37 | t35: i4 = mux(t26, t8, t34); 38 | t36: i4 = mux(t27, t0, t35); 39 | t37: i4 = reg[0](t36, t9); 40 | y: i4 = id(t37); 41 | } 42 | -------------------------------------------------------------------------------- /examples/ir/mux128.ir: -------------------------------------------------------------------------------- 1 | def main(c:bool, a:i128, b:i128) -> (y:i128) { 2 | y:i128 = mux(c, a, b); 3 | } 4 | -------------------------------------------------------------------------------- /examples/ir/rom_8x8.ir: -------------------------------------------------------------------------------- 1 | def main(a:i3) -> (y:i8) { 2 | y:i8 = rom(a); 3 | } 4 | -------------------------------------------------------------------------------- /examples/ir/srom_8x256.ir: -------------------------------------------------------------------------------- 1 | def main(a:i8) -> (y:i8) { 2 | y:i8 = srom(a); 3 | } 4 | -------------------------------------------------------------------------------- /examples/ir/tadd.ir: -------------------------------------------------------------------------------- 1 | def main(en:bool, a:i8<4>, b:i8<4>)->(y:i8<4>) { 2 | t0:i8<4> = reg[0](a, en); 3 | t1:i8<4> = reg[0](b, en); 4 | t2:i8<4> = add(t0, t1); 5 | y:i8<4> = reg[0](t2, en); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ir/tadd_64.ir: -------------------------------------------------------------------------------- 1 | def main(en:bool, a0:i8<4>, b0:i8<4>, a1:i8<4>, b1:i8<4>, a2:i8<4>, b2:i8<4>, a3:i8<4>, b3:i8<4>, a4:i8<4>, b4:i8<4>, a5:i8<4>, b5:i8<4>, a6:i8<4>, b6:i8<4>, a7:i8<4>, b7:i8<4>, a8:i8<4>, b8:i8<4>, a9:i8<4>, b9:i8<4>, a10:i8<4>, b10:i8<4>, a11:i8<4>, b11:i8<4>, a12:i8<4>, b12:i8<4>, a13:i8<4>, b13:i8<4>, a14:i8<4>, b14:i8<4>, a15:i8<4>, b15:i8<4>)->(y0:i8<4>, y1:i8<4>, y2:i8<4>, y3:i8<4>, y4:i8<4>, y5:i8<4>, y6:i8<4>, y7:i8<4>, y8:i8<4>, y9:i8<4>, y10:i8<4>, y11:i8<4>, y12:i8<4>, y13:i8<4>, y14:i8<4>, y15:i8<4>) { 2 | t0:i8<4> = reg[0](a0, en); 3 | t1:i8<4> = reg[0](b0, en); 4 | t2:i8<4> = add(t0, t1); 5 | y0:i8<4> = reg[0](t2, en); 6 | t3:i8<4> = reg[0](a1, en); 7 | t4:i8<4> = reg[0](b1, en); 8 | t5:i8<4> = add(t3, t4); 9 | y1:i8<4> = reg[0](t5, en); 10 | t6:i8<4> = reg[0](a2, en); 11 | t7:i8<4> = reg[0](b2, en); 12 | t8:i8<4> = add(t6, t7); 13 | y2:i8<4> = reg[0](t8, en); 14 | t9:i8<4> = reg[0](a3, en); 15 | t10:i8<4> = reg[0](b3, en); 16 | t11:i8<4> = add(t9, t10); 17 | y3:i8<4> = reg[0](t11, en); 18 | t12:i8<4> = reg[0](a4, en); 19 | t13:i8<4> = reg[0](b4, en); 20 | t14:i8<4> = add(t12, t13); 21 | y4:i8<4> = reg[0](t14, en); 22 | t15:i8<4> = reg[0](a5, en); 23 | t16:i8<4> = reg[0](b5, en); 24 | t17:i8<4> = add(t15, t16); 25 | y5:i8<4> = reg[0](t17, en); 26 | t18:i8<4> = reg[0](a6, en); 27 | t19:i8<4> = reg[0](b6, en); 28 | t20:i8<4> = add(t18, t19); 29 | y6:i8<4> = reg[0](t20, en); 30 | t21:i8<4> = reg[0](a7, en); 31 | t22:i8<4> = reg[0](b7, en); 32 | t23:i8<4> = add(t21, t22); 33 | y7:i8<4> = reg[0](t23, en); 34 | t24:i8<4> = reg[0](a8, en); 35 | t25:i8<4> = reg[0](b8, en); 36 | t26:i8<4> = add(t24, t25); 37 | y8:i8<4> = reg[0](t26, en); 38 | t27:i8<4> = reg[0](a9, en); 39 | t28:i8<4> = reg[0](b9, en); 40 | t29:i8<4> = add(t27, t28); 41 | y9:i8<4> = reg[0](t29, en); 42 | t30:i8<4> = reg[0](a10, en); 43 | t31:i8<4> = reg[0](b10, en); 44 | t32:i8<4> = add(t30, t31); 45 | y10:i8<4> = reg[0](t32, en); 46 | t33:i8<4> = reg[0](a11, en); 47 | t34:i8<4> = reg[0](b11, en); 48 | t35:i8<4> = add(t33, t34); 49 | y11:i8<4> = reg[0](t35, en); 50 | t36:i8<4> = reg[0](a12, en); 51 | t37:i8<4> = reg[0](b12, en); 52 | t38:i8<4> = add(t36, t37); 53 | y12:i8<4> = reg[0](t38, en); 54 | t39:i8<4> = reg[0](a13, en); 55 | t40:i8<4> = reg[0](b13, en); 56 | t41:i8<4> = add(t39, t40); 57 | y13:i8<4> = reg[0](t41, en); 58 | t42:i8<4> = reg[0](a14, en); 59 | t43:i8<4> = reg[0](b14, en); 60 | t44:i8<4> = add(t42, t43); 61 | y14:i8<4> = reg[0](t44, en); 62 | t45:i8<4> = reg[0](a15, en); 63 | t46:i8<4> = reg[0](b15, en); 64 | t47:i8<4> = add(t45, t46); 65 | y15:i8<4> = reg[0](t47, en); 66 | } -------------------------------------------------------------------------------- /examples/ir/tdot.ir: -------------------------------------------------------------------------------- 1 | def main(a0:i8, a1:i8, a2:i8, b0:i8, b1:i8, b2:i8, c:i8, en:bool)->(y:i8) { 2 | t0:i8 = reg[0](a0, en); 3 | t1:i8 = reg[0](b0, en); 4 | t2:i8 = mul(t0, t1); 5 | t3:i8 = reg[0](t2, en); 6 | t4:i8 = add(t3, c); 7 | t5:i8 = reg[0](t4, en); 8 | t6:i8 = reg[0](a1, en); 9 | t7:i8 = reg[0](b1, en); 10 | t8:i8 = mul(t6, t7); 11 | t9:i8 = reg[0](t8, en); 12 | t10:i8 = add(t9, t5); 13 | t11:i8 = reg[0](t10, en); 14 | t12:i8 = reg[0](a2, en); 15 | t13:i8 = reg[0](b2, en); 16 | t14:i8 = mul(t12, t13); 17 | t15:i8 = reg[0](t14, en); 18 | t16:i8 = add(t15, t11); 19 | y:i8 = reg[0](t16, en); 20 | } 21 | -------------------------------------------------------------------------------- /examples/ir/tdot_5_3.ir: -------------------------------------------------------------------------------- 1 | def main(a0:i8, c0:i8, e0:i8, g0:i8, i0:i8, a1:i8, c1:i8, e1:i8, g1:i8, i1:i8, a2:i8, c2:i8, e2:i8, g2:i8, i2:i8, b0:i8, d0:i8, f0:i8, h0:i8, j0:i8, b1:i8, d1:i8, f1:i8, h1:i8, j1:i8, b2:i8, d2:i8, f2:i8, h2:i8, j2:i8, m:i8, n:i8, o:i8, p:i8, q:i8, en:bool)->(v:i8, w:i8, x:i8, y:i8, z:i8) { 2 | t0:i8 = reg[0](a0, en); 3 | t1:i8 = reg[0](b0, en); 4 | t2:i8 = mul(t0, t1); 5 | t3:i8 = reg[0](t2, en); 6 | t4:i8 = add(t3, m); 7 | t5:i8 = reg[0](t4, en); 8 | t6:i8 = reg[0](a1, en); 9 | t7:i8 = reg[0](b1, en); 10 | t8:i8 = mul(t6, t7); 11 | t9:i8 = reg[0](t8, en); 12 | t10:i8 = add(t9, t5); 13 | t11:i8 = reg[0](t10, en); 14 | t12:i8 = reg[0](a2, en); 15 | t13:i8 = reg[0](b2, en); 16 | t14:i8 = mul(t12, t13); 17 | t15:i8 = reg[0](t14, en); 18 | t16:i8 = add(t15, t11); 19 | v:i8 = reg[0](t16, en); 20 | t18:i8 = reg[0](c0, en); 21 | t19:i8 = reg[0](d0, en); 22 | t20:i8 = mul(t18, t19); 23 | t21:i8 = reg[0](t20, en); 24 | t22:i8 = add(t21, n); 25 | t23:i8 = reg[0](t22, en); 26 | t24:i8 = reg[0](c1, en); 27 | t25:i8 = reg[0](d1, en); 28 | t26:i8 = mul(t24, t25); 29 | t27:i8 = reg[0](t26, en); 30 | t28:i8 = add(t27, t23); 31 | t29:i8 = reg[0](t28, en); 32 | t30:i8 = reg[0](c2, en); 33 | t31:i8 = reg[0](d2, en); 34 | t32:i8 = mul(t30, t31); 35 | t33:i8 = reg[0](t32, en); 36 | t34:i8 = add(t33, t29); 37 | w:i8 = reg[0](t34, en); 38 | t36:i8 = reg[0](e0, en); 39 | t37:i8 = reg[0](f0, en); 40 | t38:i8 = mul(t36, t37); 41 | t39:i8 = reg[0](t38, en); 42 | t40:i8 = add(t39, o); 43 | t41:i8 = reg[0](t40, en); 44 | t42:i8 = reg[0](e1, en); 45 | t43:i8 = reg[0](f1, en); 46 | t44:i8 = mul(t42, t43); 47 | t45:i8 = reg[0](t44, en); 48 | t46:i8 = add(t45, t41); 49 | t47:i8 = reg[0](t46, en); 50 | t48:i8 = reg[0](e2, en); 51 | t49:i8 = reg[0](f2, en); 52 | t50:i8 = mul(t48, t49); 53 | t51:i8 = reg[0](t50, en); 54 | t52:i8 = add(t51, t47); 55 | x:i8 = reg[0](t52, en); 56 | t54:i8 = reg[0](g0, en); 57 | t55:i8 = reg[0](h0, en); 58 | t56:i8 = mul(t54, t55); 59 | t57:i8 = reg[0](t56, en); 60 | t58:i8 = add(t57, p); 61 | t59:i8 = reg[0](t58, en); 62 | t60:i8 = reg[0](g1, en); 63 | t61:i8 = reg[0](h1, en); 64 | t62:i8 = mul(t60, t61); 65 | t63:i8 = reg[0](t62, en); 66 | t64:i8 = add(t63, t59); 67 | t65:i8 = reg[0](t64, en); 68 | t66:i8 = reg[0](g2, en); 69 | t67:i8 = reg[0](h2, en); 70 | t68:i8 = mul(t66, t67); 71 | t69:i8 = reg[0](t68, en); 72 | t70:i8 = add(t69, t65); 73 | y:i8 = reg[0](t70, en); 74 | t72:i8 = reg[0](i0, en); 75 | t73:i8 = reg[0](j0, en); 76 | t74:i8 = mul(t72, t73); 77 | t75:i8 = reg[0](t74, en); 78 | t76:i8 = add(t75, q); 79 | t77:i8 = reg[0](t76, en); 80 | t78:i8 = reg[0](i1, en); 81 | t79:i8 = reg[0](j1, en); 82 | t80:i8 = mul(t78, t79); 83 | t81:i8 = reg[0](t80, en); 84 | t82:i8 = add(t81, t77); 85 | t83:i8 = reg[0](t82, en); 86 | t84:i8 = reg[0](i2, en); 87 | t85:i8 = reg[0](j2, en); 88 | t86:i8 = mul(t84, t85); 89 | t87:i8 = reg[0](t86, en); 90 | t88:i8 = add(t87, t83); 91 | z:i8 = reg[0](t88, en); 92 | } 93 | -------------------------------------------------------------------------------- /examples/mmap/brom_8x256.json: -------------------------------------------------------------------------------- 1 | { 2 | "y":{ 3 | "offset":0, 4 | "values":[ 5 | 170, 6 | 187, 7 | 204, 8 | 221, 9 | 238, 10 | 255, 11 | 17, 12 | 34 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/mmap/lrom_8x8.json: -------------------------------------------------------------------------------- 1 | { 2 | "y":{ 3 | "offset":0, 4 | "values":[ 5 | 170, 6 | 187, 7 | 204, 8 | 221, 9 | 238, 10 | 255, 11 | 17, 12 | 34 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/pat/dsp.pat: -------------------------------------------------------------------------------- 1 | pat dmul_i8(a:i8, b:i8) -> (y:i8) { 2 | y:i8 = mul(a, b) @dsp; 3 | } 4 | 5 | pat dmuladd_i8i8(a:i8, b:i8, c:i8) -> (y:i8) { 6 | t0:i8 = mul(a, b) @dsp; 7 | y:i8 = add(t0, c) @dsp; 8 | } 9 | 10 | pat daddrega_i8v4(a:i8<4>, b:i8<4>, ena:bool, enb:bool, enp:bool) -> (y:i8<4>) { 11 | t0:i8<4> = reg[0](a, ena) @dsp; 12 | t1:i8<4> = reg[0](b, enb) @dsp; 13 | t2:i8<4> = add(t0, t1) @dsp; 14 | y:i8<4> = reg[0](t2, enp) @dsp; 15 | } 16 | 17 | pat dmuladdrega_i8i8(a:i8, b:i8, c:i8, ena:bool, enb:bool, enm:bool, enp:bool) -> (y:i8) { 18 | t0:i8 = reg[0](a, ena) @dsp; 19 | t1:i8 = reg[0](b, enb) @dsp; 20 | t2:i8 = mul(t0, t1) @dsp; 21 | t3:i8 = reg[0](t2, enm) @dsp; 22 | t4:i8 = add(t3, c) @dsp; 23 | y:i8 = reg[0](t4, enp) @dsp; 24 | } 25 | -------------------------------------------------------------------------------- /examples/pat/lut.pat: -------------------------------------------------------------------------------- 1 | pat ladd_i8(a:i8, b:i8) -> (y:i8) { 2 | y:i8 = add(a, b) @lut; 3 | } 4 | 5 | pat ladd_i4(a:i4, b:i4) -> (y:i4) { 6 | y:i4 = add(a, b) @lut; 7 | } 8 | 9 | pat laddrega_i8(a:i8, b:i8, en:bool) -> (y:i8) { 10 | t0:i8 = add(a, b) @lut; 11 | y:i8 = reg[0](t0, en) @lut; 12 | } 13 | 14 | pat laddrega_i4(a:i4, b:i4, en:bool) -> (y:i4) { 15 | t0:i4 = add(a, b) @lut; 16 | y:i4 = reg[0](t0, en) @lut; 17 | } 18 | 19 | pat lrega_i8(a:i8, en:bool) -> (y:i8) { 20 | y:i8 = reg[0](a, en) @lut; 21 | } 22 | 23 | pat lrega_i4(a:i4, en:bool) -> (y:i4) { 24 | y:i4 = reg[0](a, en) @lut; 25 | } 26 | 27 | pat lrega_i128(a:i128, en:bool) -> (y:i128) { 28 | y:i128 = reg[0](a, en) @lut; 29 | } 30 | 31 | pat leq_i2(a:i2, b:i2) -> (y:bool) { 32 | y:bool = eq(a, b) @lut; 33 | } 34 | 35 | pat leq_i4(a:i4, b:i4) -> (y:bool) { 36 | y:bool = eq(a, b) @lut; 37 | } 38 | 39 | pat leq_bool(a:bool, b:bool) -> (y:bool) { 40 | y:bool = eq(a, b) @lut; 41 | } 42 | 43 | pat land_bool(a:bool, b:bool) -> (y:bool) { 44 | y:bool = and(a, b) @lut; 45 | } 46 | 47 | pat lmux_i2(sel:bool, a:i2, b:i2) -> (y:i2) { 48 | y:i2 = mux(sel, a, b) @lut; 49 | } 50 | 51 | pat lmux_i4(sel:bool, a:i4, b:i4) -> (y:i4) { 52 | y:i4 = mux(sel, a, b) @lut; 53 | } 54 | 55 | pat lmux_i8(sel:bool, a:i8, b:i8) -> (y:i8) { 56 | y:i8 = mux(sel, a, b) @lut; 57 | } 58 | 59 | pat lmux_i128(sel:bool, a:i128, b:i128) -> (y:i128) { 60 | y:i128 = mux(sel, a, b) @lut; 61 | } 62 | 63 | pat lmuxrega_i2(sel:bool, a:i2, b:i2, en:bool) -> (y:i2) { 64 | t0:i2 = mux(sel, a, b) @lut; 65 | y:i2 = reg[0](t0, en) @lut; 66 | } 67 | 68 | pat lmuxrega_i4(sel:bool, a:i4, b:i4, en:bool) -> (y:i4) { 69 | t0:i4 = mux(sel, a, b) @lut; 70 | y:i4 = reg[0](t0, en) @lut; 71 | } 72 | 73 | pat lmuxrega_i8(sel:bool, a:i8, b:i8, en:bool) -> (y:i8) { 74 | t0:i8 = mux(sel, a, b) @lut; 75 | y:i8 = reg[0](t0, en) @lut; 76 | } 77 | 78 | pat lmuxrega_i128(sel:bool, a:i128, b:i128, en:bool) -> (y:i128) { 79 | t0:i128 = mux(sel, a, b) @lut; 80 | y:i128 = reg[0](t0, en) @lut; 81 | } 82 | 83 | pat lnot_bool(a:bool) -> (y:bool) { 84 | y:bool = not(a) @lut; 85 | } 86 | 87 | pat lxor_i8(a:i8, b:i8) -> (y:i8) { 88 | y:i8 = xor(a, b) @lut; 89 | } 90 | 91 | pat lxor_i32(a:i32, b:i32) -> (y:i32) { 92 | y:i32 = xor(a, b) @lut; 93 | } 94 | 95 | pat lxor_i128(a:i128, b:i128) -> (y:i128) { 96 | y:i128 = xor(a, b) @lut; 97 | } 98 | -------------------------------------------------------------------------------- /examples/pat/mem.pat: -------------------------------------------------------------------------------- 1 | pat lrom_i8i3(a:i3) -> (y:i8) { 2 | y:i8 = rom(a) @lram; 3 | } 4 | 5 | pat brom_i8i8(a:i8) -> (y:i8) { 6 | y:i8 = srom(a) @bram; 7 | } 8 | -------------------------------------------------------------------------------- /examples/struct/lrom_8x8.v: -------------------------------------------------------------------------------- 1 | module main ( 2 | input wire clock, 3 | input wire reset, 4 | input wire [2:0] addr, 5 | output wire [7:0] y 6 | ); 7 | wire gnd; 8 | wire vcc; 9 | GND _gnd ( 10 | .G(gnd) 11 | ); 12 | VCC _vcc ( 13 | .P(vcc) 14 | ); 15 | (*LOC = "SLICE_X0Y0", BEL = "H6LUT"*) 16 | RAM64M8 # ( 17 | .INIT_A(64'h0000000000000000), 18 | .INIT_B(64'h0000000000000000), 19 | .INIT_C(64'h0000000000000000), 20 | .INIT_D(64'h0000000000000000), 21 | .INIT_E(64'h0000000000000000), 22 | .INIT_F(64'h0000000000000000), 23 | .INIT_G(64'h0000000000000000), 24 | .INIT_H(64'h0000000000000000), 25 | .IS_WCLK_INVERTED(1'b0) 26 | ) __y ( 27 | .ADDRA({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 28 | .ADDRB({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 29 | .ADDRC({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 30 | .ADDRD({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 31 | .ADDRE({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 32 | .ADDRF({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 33 | .ADDRG({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 34 | .ADDRH({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 35 | .DIA(gnd), 36 | .DIB(gnd), 37 | .DIC(gnd), 38 | .DID(gnd), 39 | .DIE(gnd), 40 | .DIF(gnd), 41 | .DIG(gnd), 42 | .DIH(gnd), 43 | .DOA(y[0]), 44 | .DOB(y[1]), 45 | .DOC(y[2]), 46 | .DOD(y[3]), 47 | .DOE(y[4]), 48 | .DOF(y[5]), 49 | .DOG(y[6]), 50 | .DOH(y[7]), 51 | .WCLK(clock), 52 | .WE(gnd) 53 | ); 54 | endmodule 55 | -------------------------------------------------------------------------------- /examples/struct/lrom_8x8_mmap.v: -------------------------------------------------------------------------------- 1 | module main ( 2 | input wire clock, 3 | input wire reset, 4 | input wire [2:0] addr, 5 | output wire [7:0] y 6 | ); 7 | wire gnd; 8 | wire vcc; 9 | GND _gnd ( 10 | .G(gnd) 11 | ); 12 | VCC _vcc ( 13 | .P(vcc) 14 | ); 15 | (*LOC = "SLICE_X0Y0", BEL = "H6LUT"*) 16 | RAM64M8 # ( 17 | .INIT_A(64'h0001010001000100), 18 | .INIT_B(64'h0100010100000101), 19 | .INIT_C(64'h0000010101010000), 20 | .INIT_D(64'h0000010101010101), 21 | .INIT_E(64'h0001010001000100), 22 | .INIT_F(64'h0100010100000101), 23 | .INIT_G(64'h0000010101010000), 24 | .INIT_H(64'h0000010101010101), 25 | .IS_WCLK_INVERTED(1'b0) 26 | ) __y ( 27 | .ADDRA({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 28 | .ADDRB({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 29 | .ADDRC({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 30 | .ADDRD({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 31 | .ADDRE({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 32 | .ADDRF({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 33 | .ADDRG({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 34 | .ADDRH({addr[2], addr[1], addr[0], gnd, gnd, gnd}), 35 | .DIA(gnd), 36 | .DIB(gnd), 37 | .DIC(gnd), 38 | .DID(gnd), 39 | .DIE(gnd), 40 | .DIF(gnd), 41 | .DIG(gnd), 42 | .DIH(gnd), 43 | .DOA(y[0]), 44 | .DOB(y[1]), 45 | .DOC(y[2]), 46 | .DOD(y[3]), 47 | .DOE(y[4]), 48 | .DOF(y[5]), 49 | .DOG(y[6]), 50 | .DOH(y[7]), 51 | .WCLK(clock), 52 | .WE(gnd) 53 | ); 54 | endmodule 55 | -------------------------------------------------------------------------------- /examples/xim/dsp.xim: -------------------------------------------------------------------------------- 1 | imp dmul_i8[1, 1](a:i8, b:i8) -> (y:i8) { 2 | y:i8 = mul(a, b) @alu(??, ??); 3 | } 4 | imp dmuladd_i8i8[1, 1](a:i8, b:i8, c:i8) -> (y:i8) { 5 | y:i8 = muladd(a, b, c) @alu(??, ??); 6 | } 7 | 8 | imp daddrega_i8v4[1, 1](a:i8<4>, b:i8<4>, ena:bool, enb:bool, enp:bool) -> (y:i8<4>) { 9 | y:i8<4> = vaddrega(a, b, ena, enb, enp) @alu(??, ??); 10 | } 11 | 12 | imp dmuladdrega_i8i8[1, 1](a:i8, b:i8, c:i8, ena:bool, enb:bool, enm:bool, enp:bool) -> (y:i8) { 13 | y:i8 = muladdrega(a, b, c, ena, enb, enm, enp) @alu(??, ??); 14 | } 15 | 16 | imp dmuladdregaci_i8i8[1, 1](a:i8, b:i8, c:i8, ena:bool, enb:bool, enm:bool, enp:bool) -> (y:i8) { 17 | y:i8 = muladdregaci(a, b, c, ena, enb, enm, enp) @alu(??, ??); 18 | } 19 | 20 | imp dmuladdregaco_i8i8[1, 1](a:i8, b:i8, c:i8, ena:bool, enb:bool, enm:bool, enp:bool) -> (y:i8) { 21 | y:i8 = muladdregaco(a, b, c, ena, enb, enm, enp) @alu(??, ??); 22 | } 23 | 24 | imp dmuladdregacio_i8i8[1, 1](a:i8, b:i8, c:i8, ena:bool, enb:bool, enm:bool, enp:bool) -> (y:i8) { 25 | y:i8 = muladdregacio(a, b, c, ena, enb, enm, enp) @alu(??, ??); 26 | } 27 | -------------------------------------------------------------------------------- /examples/xim/mem.xim: -------------------------------------------------------------------------------- 1 | imp lrom_i8i3[1, 3](a:i3) -> (y:i8) { 2 | y:i8 = lrom(a) @h6(??, ??); 3 | } 4 | 5 | imp brom_i8i8[1, 2](a:i8) -> (y:i8) { 6 | t0:i16 = brom(a) @l(??, ??); 7 | y:i8 = ext[0, 7](t0); 8 | } 9 | -------------------------------------------------------------------------------- /examples/xir/add.xir: -------------------------------------------------------------------------------- 1 | def main(a:i8, b:i8, en:bool) -> (y:i8) { 2 | t0:bool = ext[0](a); 3 | t1:bool = ext[1](a); 4 | t2:bool = ext[2](a); 5 | t3:bool = ext[3](a); 6 | t4:bool = ext[4](a); 7 | t5:bool = ext[5](a); 8 | t6:bool = ext[6](a); 9 | t7:bool = ext[7](a); 10 | t8:bool = ext[0](b); 11 | t9:bool = ext[1](b); 12 | t10:bool = ext[2](b); 13 | t11:bool = ext[3](b); 14 | t12:bool = ext[4](b); 15 | t13:bool = ext[5](b); 16 | t14:bool = ext[6](b); 17 | t15:bool = ext[7](b); 18 | t16:bool = lut2[6](t0, t8) @a6(??, ??); 19 | t17:bool = lut2[6](t1, t9) @b6(??, ??); 20 | t18:bool = lut2[6](t2, t10) @c6(??, ??); 21 | t19:bool = lut2[6](t3, t11) @d6(??, ??); 22 | t20:bool = lut2[6](t4, t12) @e6(??, ??); 23 | t21:bool = lut2[6](t5, t13) @f6(??, ??); 24 | t22:bool = lut2[6](t6, t14) @g6(??, ??); 25 | t23:bool = lut2[6](t7, t15) @h6(??, ??); 26 | t24:i8 = cat(t16,t17,t18,t19,t20,t21,t22,t23); 27 | t25:i8 = carryadd(a, t24) @c8(??, ??); 28 | t26:bool = ext[0](t25); 29 | t27:bool = ext[1](t25); 30 | t28:bool = ext[2](t25); 31 | t29:bool = ext[3](t25); 32 | t30:bool = ext[4](t25); 33 | t31:bool = ext[5](t25); 34 | t32:bool = ext[6](t25); 35 | t33:bool = ext[7](t25); 36 | t34:bool = fdre(t26, en) @a(??, ??); 37 | t35:bool = fdre(t27, en) @b(??, ??); 38 | t36:bool = fdre(t28, en) @c(??, ??); 39 | t37:bool = fdre(t29, en) @d(??, ??); 40 | t38:bool = fdre(t30, en) @e(??, ??); 41 | t39:bool = fdre(t31, en) @f(??, ??); 42 | t40:bool = fdre(t32, en) @g(??, ??); 43 | t41:bool = fdre(t33, en) @h(??, ??); 44 | y:i8 = cat(t34, t35, t36, t37, t38, t39, t40, t41); 45 | } 46 | -------------------------------------------------------------------------------- /examples/xir/brom_8x256.xir: -------------------------------------------------------------------------------- 1 | def main(addr:i8) -> (y:i8) { 2 | y:i8 = brom(addr) @u(0, 0); 3 | } 4 | -------------------------------------------------------------------------------- /examples/xir/fsm_3.xir: -------------------------------------------------------------------------------- 1 | def main(i0:bool, i1:bool, i2:bool) -> (y:i4) { 2 | t5:bool = ext[0](t1); 3 | t6:bool = ext[0](t2); 4 | t7:bool = ext[1](t1); 5 | t8:bool = ext[1](t2); 6 | t9:bool = ext[2](t1); 7 | t10:bool = ext[2](t2); 8 | t11:bool = ext[3](t1); 9 | t12:bool = ext[3](t2); 10 | t13:bool = lut3[172](t5, t6, t0) @a6(??, ??); 11 | t14:bool = lut3[172](t7, t8, t0) @b6(??, ??); 12 | t15:bool = lut3[172](t9, t10, t0) @c6(??, ??); 13 | t16:bool = lut3[172](t11, t12, t0) @d6(??, ??); 14 | t17:bool = fdre(t13, t3) @a(??, ??); 15 | t18:bool = fdre(t14, t3) @b(??, ??); 16 | t19:bool = fdre(t15, t3) @c(??, ??); 17 | t20:bool = fdre(t16, t3) @d(??, ??); 18 | t4:i4 = cat(t17, t18, t19, t20); 19 | t3:bool = vcc(); 20 | t0:bool = lut2[8](t21, i2) @a6(??, ??); 21 | t22:bool = gnd(); 22 | t23:bool = gnd(); 23 | t24:bool = gnd(); 24 | t25:bool = gnd(); 25 | t1:i4 = cat(t22, t23, t24, t25); 26 | t29:bool = ext[0](t27); 27 | t30:bool = ext[0](t28); 28 | t31:bool = ext[1](t27); 29 | t32:bool = ext[1](t28); 30 | t33:bool = ext[2](t27); 31 | t34:bool = ext[2](t28); 32 | t35:bool = ext[3](t27); 33 | t36:bool = ext[3](t28); 34 | t37:bool = lut3[172](t29, t30, t26) @a6(??, ??); 35 | t38:bool = lut3[172](t31, t32, t26) @b6(??, ??); 36 | t39:bool = lut3[172](t33, t34, t26) @c6(??, ??); 37 | t40:bool = lut3[172](t35, t36, t26) @d6(??, ??); 38 | t2:i4 = cat(t37, t38, t39, t40); 39 | t41:bool = ext[0](t4); 40 | t42:bool = ext[0](t27); 41 | t43:bool = ext[1](t4); 42 | t44:bool = ext[1](t27); 43 | t45:bool = ext[2](t4); 44 | t46:bool = ext[2](t27); 45 | t47:bool = ext[3](t4); 46 | t48:bool = ext[3](t27); 47 | t49:bool = lut6[-8067917257457496055](t41, t42, t46, t45, t44, t43) @a6(??, ??); 48 | t21:bool = lut3[144](t47, t48, t49) @b6(??, ??); 49 | t26:bool = lut2[8](t50, i1) @a6(??, ??); 50 | t51:bool = gnd(); 51 | t52:bool = vcc(); 52 | t53:bool = gnd(); 53 | t54:bool = gnd(); 54 | t27:i4 = cat(t51, t52, t53, t54); 55 | t57:bool = ext[0](t56); 56 | t58:bool = ext[0](t4); 57 | t59:bool = ext[1](t56); 58 | t60:bool = ext[1](t4); 59 | t61:bool = ext[2](t56); 60 | t62:bool = ext[2](t4); 61 | t63:bool = ext[3](t56); 62 | t64:bool = ext[3](t4); 63 | t65:bool = lut3[172](t57, t58, t55) @a6(??, ??); 64 | t66:bool = lut3[172](t59, t60, t55) @b6(??, ??); 65 | t67:bool = lut3[172](t61, t62, t55) @c6(??, ??); 66 | t68:bool = lut3[172](t63, t64, t55) @d6(??, ??); 67 | t28:i4 = cat(t65, t66, t67, t68); 68 | t69:bool = ext[0](t4); 69 | t70:bool = ext[0](t56); 70 | t71:bool = ext[1](t4); 71 | t72:bool = ext[1](t56); 72 | t73:bool = ext[2](t4); 73 | t74:bool = ext[2](t56); 74 | t75:bool = ext[3](t4); 75 | t76:bool = ext[3](t56); 76 | t77:bool = lut6[-8067917257457496055](t69, t70, t74, t73, t72, t71) @a6(??, ??); 77 | t50:bool = lut3[144](t75, t76, t77) @b6(??, ??); 78 | t55:bool = lut2[8](t78, i0) @a6(??, ??); 79 | t79:bool = vcc(); 80 | t80:bool = gnd(); 81 | t81:bool = gnd(); 82 | t82:bool = gnd(); 83 | t56:i4 = cat(t79, t80, t81, t82); 84 | t83:bool = ext[0](t4); 85 | t84:bool = ext[0](t1); 86 | t85:bool = ext[1](t4); 87 | t86:bool = ext[1](t1); 88 | t87:bool = ext[2](t4); 89 | t88:bool = ext[2](t1); 90 | t89:bool = ext[3](t4); 91 | t90:bool = ext[3](t1); 92 | t91:bool = lut6[-8067917257457496055](t83, t84, t88, t87, t86, t85) @a6(??, ??); 93 | t78:bool = lut3[144](t89, t90, t91) @b6(??, ??); 94 | y:i4 = id(t4); 95 | } 96 | -------------------------------------------------------------------------------- /examples/xir/lrom_8x8.xir: -------------------------------------------------------------------------------- 1 | def main(addr:i3) -> (y:i8) { 2 | y:i8 = lrom(addr) @h6(0, 0); 3 | } 4 | -------------------------------------------------------------------------------- /examples/xir/tadd.xir: -------------------------------------------------------------------------------- 1 | def main(en:bool, a:i8<4>, b:i8<4>) -> (y:i8<4>) { 2 | y:i8<4> = vaddrega(a, b, en, en, en) @alu(??, ??); 3 | } -------------------------------------------------------------------------------- /examples/xir/tadd_128.xir: -------------------------------------------------------------------------------- 1 | def main(en:bool, a0:i8<4>, b0:i8<4>, a1:i8<4>, b1:i8<4>, a2:i8<4>, b2:i8<4>, a3:i8<4>, b3:i8<4>, a4:i8<4>, b4:i8<4>, a5:i8<4>, b5:i8<4>, a6:i8<4>, b6:i8<4>, a7:i8<4>, b7:i8<4>, a8:i8<4>, b8:i8<4>, a9:i8<4>, b9:i8<4>, a10:i8<4>, b10:i8<4>, a11:i8<4>, b11:i8<4>, a12:i8<4>, b12:i8<4>, a13:i8<4>, b13:i8<4>, a14:i8<4>, b14:i8<4>, a15:i8<4>, b15:i8<4>, a16:i8<4>, b16:i8<4>, a17:i8<4>, b17:i8<4>, a18:i8<4>, b18:i8<4>, a19:i8<4>, b19:i8<4>, a20:i8<4>, b20:i8<4>, a21:i8<4>, b21:i8<4>, a22:i8<4>, b22:i8<4>, a23:i8<4>, b23:i8<4>, a24:i8<4>, b24:i8<4>, a25:i8<4>, b25:i8<4>, a26:i8<4>, b26:i8<4>, a27:i8<4>, b27:i8<4>, a28:i8<4>, b28:i8<4>, a29:i8<4>, b29:i8<4>, a30:i8<4>, b30:i8<4>, a31:i8<4>, b31:i8<4>) -> (y0:i8<4>, y1:i8<4>, y2:i8<4>, y3:i8<4>, y4:i8<4>, y5:i8<4>, y6:i8<4>, y7:i8<4>, y8:i8<4>, y9:i8<4>, y10:i8<4>, y11:i8<4>, y12:i8<4>, y13:i8<4>, y14:i8<4>, y15:i8<4>, y16:i8<4>, y17:i8<4>, y18:i8<4>, y19:i8<4>, y20:i8<4>, y21:i8<4>, y22:i8<4>, y23:i8<4>, y24:i8<4>, y25:i8<4>, y26:i8<4>, y27:i8<4>, y28:i8<4>, y29:i8<4>, y30:i8<4>, y31:i8<4>) { 2 | y0:i8<4> = vaddrega(a0, b0, en, en, en) @alu(??, ??); 3 | y1:i8<4> = vaddrega(a1, b1, en, en, en) @alu(??, ??); 4 | y2:i8<4> = vaddrega(a2, b2, en, en, en) @alu(??, ??); 5 | y3:i8<4> = vaddrega(a3, b3, en, en, en) @alu(??, ??); 6 | y4:i8<4> = vaddrega(a4, b4, en, en, en) @alu(??, ??); 7 | y5:i8<4> = vaddrega(a5, b5, en, en, en) @alu(??, ??); 8 | y6:i8<4> = vaddrega(a6, b6, en, en, en) @alu(??, ??); 9 | y7:i8<4> = vaddrega(a7, b7, en, en, en) @alu(??, ??); 10 | y8:i8<4> = vaddrega(a8, b8, en, en, en) @alu(??, ??); 11 | y9:i8<4> = vaddrega(a9, b9, en, en, en) @alu(??, ??); 12 | y10:i8<4> = vaddrega(a10, b10, en, en, en) @alu(??, ??); 13 | y11:i8<4> = vaddrega(a11, b11, en, en, en) @alu(??, ??); 14 | y12:i8<4> = vaddrega(a12, b12, en, en, en) @alu(??, ??); 15 | y13:i8<4> = vaddrega(a13, b13, en, en, en) @alu(??, ??); 16 | y14:i8<4> = vaddrega(a14, b14, en, en, en) @alu(??, ??); 17 | y15:i8<4> = vaddrega(a15, b15, en, en, en) @alu(??, ??); 18 | y16:i8<4> = vaddrega(a16, b16, en, en, en) @alu(??, ??); 19 | y17:i8<4> = vaddrega(a17, b17, en, en, en) @alu(??, ??); 20 | y18:i8<4> = vaddrega(a18, b18, en, en, en) @alu(??, ??); 21 | y19:i8<4> = vaddrega(a19, b19, en, en, en) @alu(??, ??); 22 | y20:i8<4> = vaddrega(a20, b20, en, en, en) @alu(??, ??); 23 | y21:i8<4> = vaddrega(a21, b21, en, en, en) @alu(??, ??); 24 | y22:i8<4> = vaddrega(a22, b22, en, en, en) @alu(??, ??); 25 | y23:i8<4> = vaddrega(a23, b23, en, en, en) @alu(??, ??); 26 | y24:i8<4> = vaddrega(a24, b24, en, en, en) @alu(??, ??); 27 | y25:i8<4> = vaddrega(a25, b25, en, en, en) @alu(??, ??); 28 | y26:i8<4> = vaddrega(a26, b26, en, en, en) @alu(??, ??); 29 | y27:i8<4> = vaddrega(a27, b27, en, en, en) @alu(??, ??); 30 | y28:i8<4> = vaddrega(a28, b28, en, en, en) @alu(??, ??); 31 | y29:i8<4> = vaddrega(a29, b29, en, en, en) @alu(??, ??); 32 | y30:i8<4> = vaddrega(a30, b30, en, en, en) @alu(??, ??); 33 | y31:i8<4> = vaddrega(a31, b31, en, en, en) @alu(??, ??); 34 | } -------------------------------------------------------------------------------- /examples/xir/tadd_64.xir: -------------------------------------------------------------------------------- 1 | def main(en:bool, a0:i8<4>, b0:i8<4>, a1:i8<4>, b1:i8<4>, a2:i8<4>, b2:i8<4>, a3:i8<4>, b3:i8<4>, a4:i8<4>, b4:i8<4>, a5:i8<4>, b5:i8<4>, a6:i8<4>, b6:i8<4>, a7:i8<4>, b7:i8<4>, a8:i8<4>, b8:i8<4>, a9:i8<4>, b9:i8<4>, a10:i8<4>, b10:i8<4>, a11:i8<4>, b11:i8<4>, a12:i8<4>, b12:i8<4>, a13:i8<4>, b13:i8<4>, a14:i8<4>, b14:i8<4>, a15:i8<4>, b15:i8<4>) -> (y0:i8<4>, y1:i8<4>, y2:i8<4>, y3:i8<4>, y4:i8<4>, y5:i8<4>, y6:i8<4>, y7:i8<4>, y8:i8<4>, y9:i8<4>, y10:i8<4>, y11:i8<4>, y12:i8<4>, y13:i8<4>, y14:i8<4>, y15:i8<4>) { 2 | y0:i8<4> = vaddrega(a0, b0, en, en, en) @alu(??, ??); 3 | y1:i8<4> = vaddrega(a1, b1, en, en, en) @alu(??, ??); 4 | y2:i8<4> = vaddrega(a2, b2, en, en, en) @alu(??, ??); 5 | y3:i8<4> = vaddrega(a3, b3, en, en, en) @alu(??, ??); 6 | y4:i8<4> = vaddrega(a4, b4, en, en, en) @alu(??, ??); 7 | y5:i8<4> = vaddrega(a5, b5, en, en, en) @alu(??, ??); 8 | y6:i8<4> = vaddrega(a6, b6, en, en, en) @alu(??, ??); 9 | y7:i8<4> = vaddrega(a7, b7, en, en, en) @alu(??, ??); 10 | y8:i8<4> = vaddrega(a8, b8, en, en, en) @alu(??, ??); 11 | y9:i8<4> = vaddrega(a9, b9, en, en, en) @alu(??, ??); 12 | y10:i8<4> = vaddrega(a10, b10, en, en, en) @alu(??, ??); 13 | y11:i8<4> = vaddrega(a11, b11, en, en, en) @alu(??, ??); 14 | y12:i8<4> = vaddrega(a12, b12, en, en, en) @alu(??, ??); 15 | y13:i8<4> = vaddrega(a13, b13, en, en, en) @alu(??, ??); 16 | y14:i8<4> = vaddrega(a14, b14, en, en, en) @alu(??, ??); 17 | y15:i8<4> = vaddrega(a15, b15, en, en, en) @alu(??, ??); 18 | } -------------------------------------------------------------------------------- /examples/xir/tdot.xir: -------------------------------------------------------------------------------- 1 | def main(a0:i8, a1:i8, a2:i8, b0:i8, b1:i8, b2:i8, c:i8, en:bool) -> (y:i8) { 2 | y:i8 = muladdrega(a2, b2, t0, en, en, en, en) @alu(??, ??); 3 | t0:i8 = muladdrega(a1, b1, t1, en, en, en, en) @alu(??, ??); 4 | t1:i8 = muladdrega(a0, b0, c, en, en, en, en) @alu(??, ??); 5 | } -------------------------------------------------------------------------------- /examples/xir/tdot_5_3.xir: -------------------------------------------------------------------------------- 1 | def main(a0:i8, c0:i8, e0:i8, g0:i8, i0:i8, a1:i8, c1:i8, e1:i8, g1:i8, i1:i8, a2:i8, c2:i8, e2:i8, g2:i8, i2:i8, b0:i8, d0:i8, f0:i8, h0:i8, j0:i8, b1:i8, d1:i8, f1:i8, h1:i8, j1:i8, b2:i8, d2:i8, f2:i8, h2:i8, j2:i8, m:i8, n:i8, o:i8, p:i8, q:i8, en:bool) -> (v:i8, w:i8, x:i8, y:i8, z:i8) { 2 | v:i8 = muladdrega(a2, b2, t0, en, en, en, en) @alu(??, ??); 3 | t0:i8 = muladdrega(a1, b1, t1, en, en, en, en) @alu(??, ??); 4 | t1:i8 = muladdrega(a0, b0, m, en, en, en, en) @alu(??, ??); 5 | w:i8 = muladdrega(c2, d2, t2, en, en, en, en) @alu(??, ??); 6 | t2:i8 = muladdrega(c1, d1, t3, en, en, en, en) @alu(??, ??); 7 | t3:i8 = muladdrega(c0, d0, n, en, en, en, en) @alu(??, ??); 8 | x:i8 = muladdrega(e2, f2, t4, en, en, en, en) @alu(??, ??); 9 | t4:i8 = muladdrega(e1, f1, t5, en, en, en, en) @alu(??, ??); 10 | t5:i8 = muladdrega(e0, f0, o, en, en, en, en) @alu(??, ??); 11 | y:i8 = muladdrega(g2, h2, t6, en, en, en, en) @alu(??, ??); 12 | t6:i8 = muladdrega(g1, h1, t7, en, en, en, en) @alu(??, ??); 13 | t7:i8 = muladdrega(g0, h0, p, en, en, en, en) @alu(??, ??); 14 | z:i8 = muladdrega(i2, j2, t8, en, en, en, en) @alu(??, ??); 15 | t8:i8 = muladdrega(i1, j1, t9, en, en, en, en) @alu(??, ??); 16 | t9:i8 = muladdrega(i0, j0, q, en, en, en, en) @alu(??, ??); 17 | } -------------------------------------------------------------------------------- /examples/xir/tdot_5_9.xir: -------------------------------------------------------------------------------- 1 | def main(a0:i8, c0:i8, e0:i8, g0:i8, i0:i8, a1:i8, c1:i8, e1:i8, g1:i8, i1:i8, a2:i8, c2:i8, e2:i8, g2:i8, i2:i8, a3:i8, c3:i8, e3:i8, g3:i8, i3:i8, a4:i8, c4:i8, e4:i8, g4:i8, i4:i8, a5:i8, c5:i8, e5:i8, g5:i8, i5:i8, a6:i8, c6:i8, e6:i8, g6:i8, i6:i8, a7:i8, c7:i8, e7:i8, g7:i8, i7:i8, a8:i8, c8:i8, e8:i8, g8:i8, i8:i8, b0:i8, d0:i8, f0:i8, h0:i8, j0:i8, b1:i8, d1:i8, f1:i8, h1:i8, j1:i8, b2:i8, d2:i8, f2:i8, h2:i8, j2:i8, b3:i8, d3:i8, f3:i8, h3:i8, j3:i8, b4:i8, d4:i8, f4:i8, h4:i8, j4:i8, b5:i8, d5:i8, f5:i8, h5:i8, j5:i8, b6:i8, d6:i8, f6:i8, h6:i8, j6:i8, b7:i8, d7:i8, f7:i8, h7:i8, j7:i8, b8:i8, d8:i8, f8:i8, h8:i8, j8:i8, m:i8, n:i8, o:i8, p:i8, q:i8, en:bool) -> (v:i8, w:i8, x:i8, y:i8, z:i8) { 2 | v:i8 = muladdrega(a8, b8, t0, en, en, en, en) @alu(??, ??); 3 | t0:i8 = muladdrega(a7, b7, t1, en, en, en, en) @alu(??, ??); 4 | t1:i8 = muladdrega(a6, b6, t2, en, en, en, en) @alu(??, ??); 5 | t2:i8 = muladdrega(a5, b5, t3, en, en, en, en) @alu(??, ??); 6 | t3:i8 = muladdrega(a4, b4, t4, en, en, en, en) @alu(??, ??); 7 | t4:i8 = muladdrega(a3, b3, t5, en, en, en, en) @alu(??, ??); 8 | t5:i8 = muladdrega(a2, b2, t6, en, en, en, en) @alu(??, ??); 9 | t6:i8 = muladdrega(a1, b1, t7, en, en, en, en) @alu(??, ??); 10 | t7:i8 = muladdrega(a0, b0, m, en, en, en, en) @alu(??, ??); 11 | w:i8 = muladdrega(c8, d8, t8, en, en, en, en) @alu(??, ??); 12 | t8:i8 = muladdrega(c7, d7, t9, en, en, en, en) @alu(??, ??); 13 | t9:i8 = muladdrega(c6, d6, t10, en, en, en, en) @alu(??, ??); 14 | t10:i8 = muladdrega(c5, d5, t11, en, en, en, en) @alu(??, ??); 15 | t11:i8 = muladdrega(c4, d4, t12, en, en, en, en) @alu(??, ??); 16 | t12:i8 = muladdrega(c3, d3, t13, en, en, en, en) @alu(??, ??); 17 | t13:i8 = muladdrega(c2, d2, t14, en, en, en, en) @alu(??, ??); 18 | t14:i8 = muladdrega(c1, d1, t15, en, en, en, en) @alu(??, ??); 19 | t15:i8 = muladdrega(c0, d0, n, en, en, en, en) @alu(??, ??); 20 | x:i8 = muladdrega(e8, f8, t16, en, en, en, en) @alu(??, ??); 21 | t16:i8 = muladdrega(e7, f7, t17, en, en, en, en) @alu(??, ??); 22 | t17:i8 = muladdrega(e6, f6, t18, en, en, en, en) @alu(??, ??); 23 | t18:i8 = muladdrega(e5, f5, t19, en, en, en, en) @alu(??, ??); 24 | t19:i8 = muladdrega(e4, f4, t20, en, en, en, en) @alu(??, ??); 25 | t20:i8 = muladdrega(e3, f3, t21, en, en, en, en) @alu(??, ??); 26 | t21:i8 = muladdrega(e2, f2, t22, en, en, en, en) @alu(??, ??); 27 | t22:i8 = muladdrega(e1, f1, t23, en, en, en, en) @alu(??, ??); 28 | t23:i8 = muladdrega(e0, f0, o, en, en, en, en) @alu(??, ??); 29 | y:i8 = muladdrega(g8, h8, t24, en, en, en, en) @alu(??, ??); 30 | t24:i8 = muladdrega(g7, h7, t25, en, en, en, en) @alu(??, ??); 31 | t25:i8 = muladdrega(g6, h6, t26, en, en, en, en) @alu(??, ??); 32 | t26:i8 = muladdrega(g5, h5, t27, en, en, en, en) @alu(??, ??); 33 | t27:i8 = muladdrega(g4, h4, t28, en, en, en, en) @alu(??, ??); 34 | t28:i8 = muladdrega(g3, h3, t29, en, en, en, en) @alu(??, ??); 35 | t29:i8 = muladdrega(g2, h2, t30, en, en, en, en) @alu(??, ??); 36 | t30:i8 = muladdrega(g1, h1, t31, en, en, en, en) @alu(??, ??); 37 | t31:i8 = muladdrega(g0, h0, p, en, en, en, en) @alu(??, ??); 38 | z:i8 = muladdrega(i8, j8, t32, en, en, en, en) @alu(??, ??); 39 | t32:i8 = muladdrega(i7, j7, t33, en, en, en, en) @alu(??, ??); 40 | t33:i8 = muladdrega(i6, j6, t34, en, en, en, en) @alu(??, ??); 41 | t34:i8 = muladdrega(i5, j5, t35, en, en, en, en) @alu(??, ??); 42 | t35:i8 = muladdrega(i4, j4, t36, en, en, en, en) @alu(??, ??); 43 | t36:i8 = muladdrega(i3, j3, t37, en, en, en, en) @alu(??, ??); 44 | t37:i8 = muladdrega(i2, j2, t38, en, en, en, en) @alu(??, ??); 45 | t38:i8 = muladdrega(i1, j1, t39, en, en, en, en) @alu(??, ??); 46 | t39:i8 = muladdrega(i0, j0, q, en, en, en, en) @alu(??, ??); 47 | } -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 100 2 | -------------------------------------------------------------------------------- /src/bin/ro.rs: -------------------------------------------------------------------------------- 1 | use optimizer::driver::Driver; 2 | use optimizer::errors::Error; 3 | 4 | fn main() -> Result<(), Error> { 5 | let driver = Driver::default(); 6 | driver.run()?; 7 | Ok(()) 8 | } 9 | -------------------------------------------------------------------------------- /src/bin/rt.rs: -------------------------------------------------------------------------------- 1 | use translate::driver::Driver; 2 | use translate::errors::Error; 3 | 4 | fn main() -> Result<(), Error> { 5 | let driver = Driver::default(); 6 | driver.run()?; 7 | Ok(()) 8 | } 9 | -------------------------------------------------------------------------------- /src/langs/asm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "asm" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | serde = { version = "1.0", features = ["derive", "rc"] } 10 | serde_json = "1.0" 11 | pest = "2.0" 12 | pest_derive = "2.0" 13 | pest_consume = "1.0.5" 14 | ir = { path = "../ir" } 15 | prettyprint = { path = "../../tools/prettyprint" } 16 | io = { path = "../../tools/io" } 17 | -------------------------------------------------------------------------------- /src/langs/asm/src/ast.rs: -------------------------------------------------------------------------------- 1 | use ir::ast as ir; 2 | use serde::{Deserialize, Serialize}; 3 | use std::rc::Rc; 4 | 5 | pub type Id = ir::Id; 6 | pub type Ty = ir::Ty; 7 | pub type Prim = ir::Prim; 8 | pub type ExprTerm = ir::ExprTerm; 9 | pub type ExprTup = ir::ExprTup; 10 | pub type Expr = ir::Expr; 11 | pub type OpWire = ir::OpWire; 12 | pub type InstrWire = ir::InstrWire; 13 | pub type Sig = ir::Sig; 14 | 15 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 16 | pub enum OpCoord { 17 | Add, 18 | } 19 | 20 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 21 | pub enum ExprCoord { 22 | Any, 23 | Var(Id), 24 | Val(u64), 25 | Bin(OpCoord, Rc, Rc), 26 | } 27 | 28 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 29 | pub struct Loc { 30 | pub prim: Prim, 31 | pub x: ExprCoord, 32 | pub y: ExprCoord, 33 | } 34 | 35 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 36 | pub enum OpAsm { 37 | Op(Id), 38 | } 39 | 40 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 41 | pub struct InstrAsm { 42 | pub op: OpAsm, 43 | pub dst: Expr, 44 | pub arg: Expr, 45 | pub loc: Loc, 46 | } 47 | 48 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 49 | pub enum Instr { 50 | Wire(InstrWire), 51 | Asm(InstrAsm), 52 | } 53 | 54 | #[derive(Serialize, Deserialize, PartialEq, Default, Clone, Debug, Eq, Hash)] 55 | pub struct Prog { 56 | pub sig: Sig, 57 | pub body: Vec, 58 | } 59 | -------------------------------------------------------------------------------- /src/langs/asm/src/default.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl Default for ExprCoord { 4 | fn default() -> Self { 5 | ExprCoord::Any 6 | } 7 | } 8 | 9 | impl Default for Loc { 10 | fn default() -> Self { 11 | Loc { 12 | prim: Prim::Any, 13 | x: ExprCoord::default(), 14 | y: ExprCoord::default(), 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/langs/asm/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use prettyprint::PrettyPrint; 3 | use std::fmt; 4 | 5 | macro_rules! display { 6 | ($ty:tt) => { 7 | impl fmt::Display for $ty { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 9 | write!(f, "{}", self.to_pretty()) 10 | } 11 | } 12 | }; 13 | } 14 | 15 | display!(OpCoord); 16 | display!(ExprCoord); 17 | display!(Loc); 18 | display!(OpAsm); 19 | display!(InstrAsm); 20 | display!(Instr); 21 | display!(Prog); 22 | -------------------------------------------------------------------------------- /src/langs/asm/src/errors.rs: -------------------------------------------------------------------------------- 1 | use crate::parser; 2 | use std::fmt; 3 | use std::num::ParseIntError; 4 | use std::num::TryFromIntError; 5 | 6 | #[derive(Debug)] 7 | pub enum Error { 8 | Parser(pest_consume::Error), 9 | Conversion(String), 10 | Type(String), 11 | TryFromInt(TryFromIntError), 12 | ParseInt(ParseIntError), 13 | } 14 | 15 | impl Error { 16 | pub fn new_conv_error(msg: &str) -> Self { 17 | Error::Conversion(msg.to_string()) 18 | } 19 | pub fn new_type_error(msg: &str) -> Self { 20 | Error::Conversion(msg.to_string()) 21 | } 22 | } 23 | 24 | impl From> for Error { 25 | fn from(e: pest_consume::Error) -> Self { 26 | Error::Parser(e) 27 | } 28 | } 29 | 30 | impl From for Error { 31 | fn from(e: TryFromIntError) -> Self { 32 | Error::TryFromInt(e) 33 | } 34 | } 35 | 36 | impl From for Error { 37 | fn from(e: ParseIntError) -> Self { 38 | Error::ParseInt(e) 39 | } 40 | } 41 | 42 | impl fmt::Display for Error { 43 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 44 | match self { 45 | Error::Parser(msg) => write!(f, "{}", msg), 46 | Error::ParseInt(msg) => write!(f, "{}", msg), 47 | Error::Conversion(msg) => write!(f, "{}", msg), 48 | Error::Type(msg) => write!(f, "{}", msg), 49 | Error::TryFromInt(msg) => write!(f, "{}", msg), 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/langs/asm/src/from.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl From for Instr { 4 | fn from(instr: InstrWire) -> Self { 5 | Instr::Wire(instr) 6 | } 7 | } 8 | 9 | impl From for Instr { 10 | fn from(instr: InstrAsm) -> Self { 11 | Instr::Asm(instr) 12 | } 13 | } 14 | 15 | impl From for OpAsm { 16 | fn from(op: Id) -> Self { 17 | OpAsm::Op(op) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/langs/asm/src/from_str.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use crate::errors::Error; 3 | use std::str::FromStr; 4 | 5 | impl FromStr for ExprCoord { 6 | type Err = Error; 7 | fn from_str(input: &str) -> Result { 8 | let num = input.parse::(); 9 | match num { 10 | Ok(n) => Ok(ExprCoord::Val(n)), 11 | Err(_) if input == "??" => Ok(ExprCoord::Any), 12 | _ => Ok(ExprCoord::Var(input.to_string())), 13 | } 14 | } 15 | } 16 | 17 | impl FromStr for OpAsm { 18 | type Err = Error; 19 | fn from_str(input: &str) -> Result { 20 | if OpWire::from_str(input).is_ok() { 21 | let err = format!( 22 | "Error: {} is a wire operation and cannot be an asm operation", 23 | input 24 | ); 25 | Err(Error::new_conv_error(&err)) 26 | } else { 27 | Ok(OpAsm::Op(input.to_string())) 28 | } 29 | } 30 | } 31 | 32 | impl FromStr for OpCoord { 33 | type Err = Error; 34 | fn from_str(input: &str) -> Result { 35 | let err = format!("Error: {} is not valid coordinate operation", input); 36 | match input { 37 | "+" => Ok(OpCoord::Add), 38 | _ => Err(Error::new_conv_error(&err)), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/langs/asm/src/helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl Loc { 4 | pub fn prim(&self) -> &Prim { 5 | &self.prim 6 | } 7 | pub fn x(&self) -> &ExprCoord { 8 | &self.x 9 | } 10 | pub fn y(&self) -> &ExprCoord { 11 | &self.y 12 | } 13 | pub fn is_lut(&self) -> bool { 14 | matches!(self.prim, Prim::Lut) 15 | } 16 | pub fn is_dsp(&self) -> bool { 17 | matches!(self.prim, Prim::Dsp) 18 | } 19 | pub fn is_unplaced(&self) -> bool { 20 | match (self.x(), self.y()) { 21 | (ExprCoord::Val(_), ExprCoord::Val(_)) => false, 22 | (_, _) => true, 23 | } 24 | } 25 | pub fn set_x(&mut self, x: ExprCoord) { 26 | self.x = x; 27 | } 28 | pub fn set_y(&mut self, y: ExprCoord) { 29 | self.y = y; 30 | } 31 | } 32 | 33 | impl OpAsm { 34 | pub fn name(&self) -> String { 35 | match self { 36 | OpAsm::Op(n) => n.to_string(), 37 | } 38 | } 39 | } 40 | 41 | impl InstrAsm { 42 | pub fn dst(&self) -> &Expr { 43 | &self.dst 44 | } 45 | pub fn op(&self) -> &OpAsm { 46 | &self.op 47 | } 48 | pub fn arg(&self) -> &Expr { 49 | &self.arg 50 | } 51 | pub fn loc(&self) -> &Loc { 52 | &self.loc 53 | } 54 | pub fn is_lut(&self) -> bool { 55 | self.loc.is_lut() 56 | } 57 | pub fn is_dsp(&self) -> bool { 58 | self.loc.is_dsp() 59 | } 60 | pub fn set_op(&mut self, op: OpAsm) { 61 | self.op = op; 62 | } 63 | pub fn set_loc(&mut self, loc: Loc) { 64 | self.loc = loc; 65 | } 66 | pub fn set_dst(&mut self, dst: Expr) { 67 | self.dst = dst; 68 | } 69 | pub fn set_arg(&mut self, arg: Expr) { 70 | self.arg = arg; 71 | } 72 | } 73 | 74 | impl Instr { 75 | pub fn dst(&self) -> &Expr { 76 | match self { 77 | Instr::Asm(instr) => instr.dst(), 78 | Instr::Wire(instr) => instr.dst(), 79 | } 80 | } 81 | pub fn arg(&self) -> &Expr { 82 | match self { 83 | Instr::Asm(instr) => instr.arg(), 84 | Instr::Wire(instr) => instr.arg(), 85 | } 86 | } 87 | pub fn set_dst(&mut self, dst: Expr) { 88 | match self { 89 | Instr::Asm(instr) => instr.set_dst(dst), 90 | Instr::Wire(instr) => instr.set_dst(dst), 91 | } 92 | } 93 | pub fn set_arg(&mut self, arg: Expr) { 94 | match self { 95 | Instr::Asm(instr) => instr.set_arg(arg), 96 | Instr::Wire(instr) => instr.set_arg(arg), 97 | } 98 | } 99 | } 100 | 101 | impl Prog { 102 | pub fn sig(&self) -> &Sig { 103 | &self.sig 104 | } 105 | pub fn body(&self) -> &Vec { 106 | &self.body 107 | } 108 | pub fn set_id(&mut self, id: &str) { 109 | self.sig.set_id(id); 110 | } 111 | pub fn set_sig(&mut self, sig: Sig) { 112 | self.sig = sig; 113 | } 114 | pub fn set_body(&mut self, instr: Vec) { 115 | self.body = instr; 116 | } 117 | pub fn body_mut(&mut self) -> &mut Vec { 118 | &mut self.body 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/langs/asm/src/infer.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use std::collections::HashMap; 3 | 4 | fn build_env(prog: &Prog) -> HashMap { 5 | let mut env: HashMap = HashMap::new(); 6 | let inp: Vec = prog.sig().input().clone().into(); 7 | // add prog inputs to environment 8 | for e in inp { 9 | if let Some(id) = e.id() { 10 | if let Some(ty) = e.ty() { 11 | env.insert(id, ty.clone()); 12 | } 13 | } 14 | } 15 | // add instr outputs to environment 16 | for instr in prog.body() { 17 | let dst: Vec = instr.dst().clone().into(); 18 | for e in dst { 19 | if let Some(id) = e.id() { 20 | if let Some(ty) = e.ty() { 21 | env.insert(id, ty.clone()); 22 | } 23 | } 24 | } 25 | } 26 | env 27 | } 28 | 29 | pub fn infer_type_try_from_prog(prog: &Prog) -> Prog { 30 | let env = build_env(prog); 31 | let mut prog = prog.clone(); 32 | // solve instr arg types with environment 33 | for instr in prog.body_mut() { 34 | let mut arg = ExprTup::default(); 35 | if let Some(tup) = instr.arg().tup() { 36 | for e in tup.term() { 37 | if let Some(id) = e.id() { 38 | if let Some(ty) = env.get(&id) { 39 | let term = ExprTerm::Var(id.to_string(), ty.clone()); 40 | arg.add_term(term); 41 | } 42 | } 43 | } 44 | } 45 | let e = Expr::from(arg); 46 | instr.set_arg(e); 47 | } 48 | prog 49 | } 50 | -------------------------------------------------------------------------------- /src/langs/asm/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod default; 3 | pub mod display; 4 | pub mod errors; 5 | pub mod from; 6 | pub mod from_str; 7 | pub mod helpers; 8 | pub mod infer; 9 | pub mod parser; 10 | pub mod pretty_print; 11 | -------------------------------------------------------------------------------- /src/langs/asm/src/pretty_print.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use ir::pretty_print::expr_names; 3 | use prettyprint::{block_with_braces, intersperse, PrettyHelper, PrettyPrint, RcDoc}; 4 | 5 | impl PrettyPrint for OpCoord { 6 | fn to_doc(&self) -> RcDoc<()> { 7 | match self { 8 | OpCoord::Add => RcDoc::text("+"), 9 | } 10 | } 11 | } 12 | 13 | impl PrettyPrint for ExprCoord { 14 | fn to_doc(&self) -> RcDoc<()> { 15 | match self { 16 | ExprCoord::Any => RcDoc::text("??"), 17 | ExprCoord::Val(n) => RcDoc::as_string(n), 18 | ExprCoord::Var(n) => RcDoc::as_string(n), 19 | ExprCoord::Bin(op, lhs, rhs) => lhs.to_doc().append(op.to_doc()).append(rhs.to_doc()), 20 | } 21 | } 22 | } 23 | 24 | impl PrettyPrint for Loc { 25 | fn to_doc(&self) -> RcDoc<()> { 26 | let coord = self 27 | .x() 28 | .to_doc() 29 | .append(RcDoc::text(",")) 30 | .append(RcDoc::space()) 31 | .append(self.y().to_doc()); 32 | self.prim().to_doc().append(coord.parens()) 33 | } 34 | } 35 | 36 | impl PrettyPrint for OpAsm { 37 | fn to_doc(&self) -> RcDoc<()> { 38 | match self { 39 | OpAsm::Op(n) => RcDoc::as_string(n), 40 | } 41 | } 42 | } 43 | 44 | impl PrettyPrint for InstrAsm { 45 | fn to_doc(&self) -> RcDoc<()> { 46 | self.dst() 47 | .to_doc() 48 | .append(RcDoc::space()) 49 | .append(RcDoc::text("=")) 50 | .append(RcDoc::space()) 51 | .append(self.op().to_doc()) 52 | .append(expr_names(self.arg())) 53 | .append(RcDoc::space()) 54 | .append(RcDoc::text("@")) 55 | .append(self.loc().to_doc()) 56 | } 57 | } 58 | 59 | impl PrettyPrint for Instr { 60 | fn to_doc(&self) -> RcDoc<()> { 61 | match self { 62 | Instr::Wire(instr) => instr.to_doc(), 63 | Instr::Asm(instr) => instr.to_doc(), 64 | } 65 | } 66 | } 67 | 68 | impl PrettyPrint for Prog { 69 | fn to_doc(&self) -> RcDoc<()> { 70 | let sig = self.sig().to_doc(); 71 | let body = intersperse( 72 | self.body() 73 | .iter() 74 | .map(|i| i.to_doc().append(RcDoc::text(";"))), 75 | RcDoc::hardline(), 76 | ); 77 | block_with_braces(sig, body) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/langs/asm/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\t" | NEWLINE } 2 | 3 | COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } 4 | 5 | sep = _{ "_" | "-"} 6 | 7 | id = @{ ASCII_ALPHA+ ~ (sep | ASCII_ALPHA | ASCII_DIGIT)* } 8 | 9 | val_bin = { ASCII_BIN_DIGIT+ } 10 | 11 | val_hex = { ASCII_HEX_DIGIT+ } 12 | 13 | val_dec = { ("+" | "-")? ~ ASCII_DIGIT+ } 14 | 15 | val = { "0b" ~ val_bin | "0x" ~ val_hex | val_dec } 16 | 17 | int = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ } 18 | 19 | bool = @{ ASCII_ALPHA_LOWER+ } 20 | 21 | vector = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ ~ "<" ~ ASCII_DIGIT+ ~ ">" } 22 | 23 | ty = ${ vector | int | bool } 24 | 25 | var = { id ~ ":" ~ ty | id } 26 | 27 | tup_var = { (var ~ ("," ~ var)*)? } 28 | 29 | tup_val = { (val ~ ("," ~ val)*)? } 30 | 31 | io = { var | "(" ~ tup_var ~ ")" } 32 | 33 | attr = _{ "[" ~ tup_val ~ "]" } 34 | 35 | prim = { id } 36 | 37 | coord = { "??" | id | ASCII_DIGIT+ } 38 | 39 | op_coord = { "+" } 40 | 41 | expr_coord = { coord ~ (op_coord ~ coord)? } 42 | 43 | xy = _{ "(" ~ expr_coord ~ "," ~ expr_coord ~ ")" } 44 | 45 | loc = { "@" ~ prim ~ xy? } 46 | 47 | op_wire = { "id" | "const" | "sll" | "srl" | "sra" | "ext" | "cat" } 48 | 49 | op_asm = { id } 50 | 51 | op = _{ op_wire | op_asm } 52 | 53 | instr = { io ~ "=" ~ op ~ attr? ~ io? ~ loc? ~ ";" } 54 | 55 | body = { instr+ } 56 | 57 | sig = { "def" ~ id ~ io? ~ "->" ~ io? } 58 | 59 | prog = { sig ~ "{" ~ body? ~ "}" } 60 | 61 | file = { SOI ~ prog ~ EOI } -------------------------------------------------------------------------------- /src/langs/asm/tests/parser.rs: -------------------------------------------------------------------------------- 1 | use asm::ast::Prog; 2 | use asm::parser::Parser; 3 | 4 | #[test] 5 | fn simple_prog() { 6 | let res = Parser::parse_from_str("def main () -> () {}").unwrap(); 7 | let mut exp = Prog::default(); 8 | exp.set_id("main"); 9 | assert_eq!(res, exp); 10 | } 11 | -------------------------------------------------------------------------------- /src/langs/ir/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ir" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | serde = { version = "1.0", features = ["derive", "rc"] } 10 | serde_json = "1.0" 11 | rand = "0.8.2" 12 | itertools = "0.9.0" 13 | regex = "1.3.9" 14 | lazy_static = "1.4.0" 15 | pest = "2.0" 16 | pest_derive = "2.0" 17 | pest_consume = "1.0.5" 18 | prettyprint = { path = "../../tools/prettyprint" } 19 | io = { path = "../../tools/io" } 20 | -------------------------------------------------------------------------------- /src/langs/ir/src/ast.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::{HashMap, HashSet}; 3 | use std::rc::Rc; 4 | 5 | pub type Id = String; 6 | pub type InstrMap = HashMap; 7 | pub type TermMap = HashMap; 8 | pub type ExprSet = HashSet; 9 | 10 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 11 | pub enum Ty { 12 | Any, 13 | Bool, 14 | UInt(u64), 15 | SInt(u64), 16 | Vector(Rc, u64), 17 | } 18 | 19 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 20 | pub enum ExprTerm { 21 | Any, 22 | Val(i64), 23 | Var(Id, Ty), 24 | } 25 | 26 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash, Default)] 27 | pub struct ExprTup { 28 | pub term: Vec, 29 | } 30 | 31 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 32 | pub enum Expr { 33 | Term(ExprTerm), 34 | Tup(ExprTup), 35 | } 36 | 37 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 38 | pub enum Prim { 39 | Any, 40 | Lut, 41 | Dsp, 42 | Lram, 43 | Bram, 44 | Uram, 45 | } 46 | 47 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 48 | pub enum OpWire { 49 | Id, 50 | Con, 51 | Sll, 52 | Srl, 53 | Sra, 54 | Ext, 55 | Cat, 56 | } 57 | 58 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 59 | pub enum OpPrim { 60 | Reg, 61 | Ram, 62 | Rom, 63 | Sram, 64 | Srom, 65 | Add, 66 | Sub, 67 | Mul, 68 | Not, 69 | And, 70 | Or, 71 | Xor, 72 | Mux, 73 | Eql, 74 | Neql, 75 | Gt, 76 | Lt, 77 | Ge, 78 | Le, 79 | } 80 | 81 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 82 | pub struct OpCall { 83 | pub op: Id, 84 | } 85 | 86 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 87 | pub struct InstrWire { 88 | pub op: OpWire, 89 | pub dst: Expr, 90 | pub attr: Expr, 91 | pub arg: Expr, 92 | } 93 | 94 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 95 | pub struct InstrPrim { 96 | pub op: OpPrim, 97 | pub dst: Expr, 98 | pub attr: Expr, 99 | pub arg: Expr, 100 | pub prim: Prim, 101 | } 102 | 103 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 104 | pub struct InstrCall { 105 | pub op: OpCall, 106 | pub dst: Expr, 107 | pub arg: Expr, 108 | } 109 | 110 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 111 | pub enum Instr { 112 | Wire(InstrWire), 113 | Prim(InstrPrim), 114 | Call(InstrCall), 115 | } 116 | 117 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 118 | pub struct Sig { 119 | pub id: Id, 120 | pub input: Expr, 121 | pub output: Expr, 122 | } 123 | 124 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash, Default)] 125 | pub struct Def { 126 | pub sig: Sig, 127 | pub body: Vec, 128 | } 129 | 130 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Default)] 131 | pub struct Prog { 132 | pub def: HashMap, 133 | } 134 | -------------------------------------------------------------------------------- /src/langs/ir/src/default.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl Default for Sig { 4 | fn default() -> Self { 5 | Sig { 6 | id: String::new(), 7 | input: Expr::Tup(ExprTup::default()), 8 | output: Expr::Tup(ExprTup::default()), 9 | } 10 | } 11 | } 12 | 13 | impl Default for Expr { 14 | fn default() -> Self { 15 | Expr::Tup(ExprTup::default()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/langs/ir/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use prettyprint::PrettyPrint; 3 | use std::fmt; 4 | 5 | macro_rules! display { 6 | ($ty:tt) => { 7 | impl fmt::Display for $ty { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 9 | write!(f, "{}", self.to_pretty()) 10 | } 11 | } 12 | }; 13 | } 14 | 15 | display!(Ty); 16 | display!(Prim); 17 | display!(ExprTerm); 18 | display!(ExprTup); 19 | display!(Expr); 20 | display!(OpWire); 21 | display!(OpPrim); 22 | display!(OpCall); 23 | display!(InstrCall); 24 | display!(InstrPrim); 25 | display!(InstrWire); 26 | display!(Instr); 27 | display!(Sig); 28 | display!(Def); 29 | display!(Prog); 30 | -------------------------------------------------------------------------------- /src/langs/ir/src/errors.rs: -------------------------------------------------------------------------------- 1 | use crate::parser; 2 | use std::fmt; 3 | use std::num::ParseIntError; 4 | use std::num::TryFromIntError; 5 | 6 | #[derive(Debug)] 7 | pub enum Error { 8 | Parser(pest_consume::Error), 9 | Conversion(String), 10 | Type(String), 11 | TryFromInt(TryFromIntError), 12 | ParseInt(ParseIntError), 13 | } 14 | 15 | impl Error { 16 | pub fn new_conv_error(msg: &str) -> Self { 17 | Error::Conversion(msg.to_string()) 18 | } 19 | pub fn new_type_error(msg: &str) -> Self { 20 | Error::Conversion(msg.to_string()) 21 | } 22 | } 23 | 24 | impl From> for Error { 25 | fn from(e: pest_consume::Error) -> Self { 26 | Error::Parser(e) 27 | } 28 | } 29 | 30 | impl From for Error { 31 | fn from(e: TryFromIntError) -> Self { 32 | Error::TryFromInt(e) 33 | } 34 | } 35 | 36 | impl From for Error { 37 | fn from(e: ParseIntError) -> Self { 38 | Error::ParseInt(e) 39 | } 40 | } 41 | 42 | impl fmt::Display for Error { 43 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 44 | match self { 45 | Error::Parser(msg) => write!(f, "{}", msg), 46 | Error::ParseInt(msg) => write!(f, "{}", msg), 47 | Error::Conversion(msg) => write!(f, "{}", msg), 48 | Error::Type(msg) => write!(f, "{}", msg), 49 | Error::TryFromInt(msg) => write!(f, "{}", msg), 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/langs/ir/src/from.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl From> for ExprTup { 4 | fn from(term: Vec) -> Self { 5 | ExprTup { term } 6 | } 7 | } 8 | 9 | impl From for Expr { 10 | fn from(tup: ExprTup) -> Self { 11 | Expr::Tup(tup) 12 | } 13 | } 14 | 15 | impl From for Expr { 16 | fn from(term: ExprTerm) -> Self { 17 | Expr::Term(term) 18 | } 19 | } 20 | 21 | impl From for Instr { 22 | fn from(instr: InstrCall) -> Self { 23 | Instr::Call(instr) 24 | } 25 | } 26 | 27 | impl From for Instr { 28 | fn from(instr: InstrWire) -> Self { 29 | Instr::Wire(instr) 30 | } 31 | } 32 | 33 | impl From for Instr { 34 | fn from(instr: InstrPrim) -> Self { 35 | Instr::Prim(instr) 36 | } 37 | } 38 | 39 | impl From for Vec { 40 | fn from(expr: Expr) -> Self { 41 | match expr { 42 | Expr::Tup(t) => t.term().clone(), 43 | Expr::Term(t) => vec![t], 44 | } 45 | } 46 | } 47 | 48 | impl From for TermMap { 49 | fn from(expr: Expr) -> Self { 50 | let mut map = TermMap::new(); 51 | match expr { 52 | Expr::Tup(t) => { 53 | for t in t.term() { 54 | if let Some(id) = t.id() { 55 | map.insert(id, t.clone()); 56 | } 57 | } 58 | } 59 | Expr::Term(t) => { 60 | if let Some(id) = t.id() { 61 | map.insert(id, t); 62 | } 63 | } 64 | } 65 | map 66 | } 67 | } 68 | 69 | impl From for ExprSet { 70 | fn from(expr: Expr) -> Self { 71 | let mut set = ExprSet::new(); 72 | match expr { 73 | Expr::Tup(tup) => { 74 | for t in tup.term() { 75 | set.insert(Expr::from(t.clone())); 76 | } 77 | } 78 | Expr::Term(t) => { 79 | set.insert(Expr::from(t)); 80 | } 81 | } 82 | set 83 | } 84 | } 85 | 86 | impl From for InstrMap { 87 | fn from(input: Def) -> Self { 88 | let mut imap = InstrMap::new(); 89 | for instr in input.body() { 90 | if let Some(term) = instr.dst().term() { 91 | if let Some(id) = term.id() { 92 | imap.insert(id, instr.clone()); 93 | } 94 | } 95 | } 96 | imap 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/langs/ir/src/infer.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use std::collections::HashMap; 3 | 4 | fn build_env(def: &Def) -> HashMap { 5 | let mut env: HashMap = HashMap::new(); 6 | let inp: Vec = def.sig().input().clone().into(); 7 | // add def inputs to environment 8 | for e in inp { 9 | if let Some(id) = e.id() { 10 | if let Some(ty) = e.ty() { 11 | env.insert(id, ty.clone()); 12 | } 13 | } 14 | } 15 | // add instr outputs to environment 16 | for instr in def.body() { 17 | let dst: Vec = instr.dst().clone().into(); 18 | for e in dst { 19 | if let Some(id) = e.id() { 20 | if let Some(ty) = e.ty() { 21 | env.insert(id, ty.clone()); 22 | } 23 | } 24 | } 25 | } 26 | env 27 | } 28 | 29 | fn infer_type_try_from_def(def: &Def) -> Def { 30 | let env = build_env(&def); 31 | let mut def = def.clone(); 32 | // solve instr arg types with environment 33 | for instr in def.body_mut() { 34 | let mut arg = ExprTup::default(); 35 | if let Some(tup) = instr.arg().tup() { 36 | for e in tup.term() { 37 | if let Some(id) = e.id() { 38 | if let Some(ty) = env.get(&id) { 39 | let term = ExprTerm::Var(id.to_string(), ty.clone()); 40 | arg.add_term(term); 41 | } 42 | } 43 | } 44 | } 45 | let e = Expr::from(arg); 46 | instr.set_arg(e); 47 | } 48 | def 49 | } 50 | 51 | pub fn type_try_from_prog(prog: &Prog) -> Prog { 52 | let mut res = Prog::default(); 53 | for (name, def) in prog.def() { 54 | res.insert(name, infer_type_try_from_def(def)); 55 | } 56 | res 57 | } 58 | -------------------------------------------------------------------------------- /src/langs/ir/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod default; 3 | pub mod display; 4 | pub mod errors; 5 | pub mod from; 6 | pub mod from_str; 7 | pub mod helpers; 8 | pub mod infer; 9 | pub mod parser; 10 | pub mod pretty_print; 11 | pub mod try_from; 12 | -------------------------------------------------------------------------------- /src/langs/ir/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\t" | NEWLINE } 2 | 3 | COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } 4 | 5 | sep = _{ "_" | "-"} 6 | 7 | id = @{ ASCII_ALPHA+ ~ (sep | ASCII_ALPHA | ASCII_DIGIT)* } 8 | 9 | val_bin = { ASCII_BIN_DIGIT+ } 10 | 11 | val_hex = { ASCII_HEX_DIGIT+ } 12 | 13 | val_dec = { ("+" | "-")? ~ ASCII_DIGIT+ } 14 | 15 | val = { "0b" ~ val_bin | "0x" ~ val_hex | val_dec } 16 | 17 | int = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ } 18 | 19 | bool = @{ ASCII_ALPHA_LOWER+ } 20 | 21 | vector = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ ~ "<" ~ ASCII_DIGIT+ ~ ">" } 22 | 23 | ty = ${ vector | int | bool } 24 | 25 | var = { id ~ ":" ~ ty | id } 26 | 27 | tup_var = { (var ~ ("," ~ var)*)? } 28 | 29 | tup_val = { (val ~ ("," ~ val)*)? } 30 | 31 | io = { var | "(" ~ tup_var ~ ")" } 32 | 33 | attr = _{ "[" ~ tup_val ~ "]" } 34 | 35 | prim = { "??" | id } 36 | 37 | hint = _{ "@" ~ prim } 38 | 39 | op_prim = { "reg" | 40 | "sram" | 41 | "srom" | 42 | "ram" | 43 | "rom" | 44 | "add" | 45 | "sub" | 46 | "mul" | 47 | "not" | 48 | "and" | 49 | "or" | 50 | "xor" | 51 | "mux" | 52 | "eq" | 53 | "neq" | 54 | "gt" | 55 | "lt" | 56 | "ge" | 57 | "le" } 58 | 59 | op_wire = { "id" | 60 | "const" | 61 | "sll" | 62 | "srl" | 63 | "sra" | 64 | "ext" | 65 | "cat" } 66 | 67 | op_call = { id } 68 | 69 | op = _{ op_prim | op_wire | op_call } 70 | 71 | instr = { io ~ "=" ~ op ~ attr? ~ io? ~ hint? ~ ";" } 72 | 73 | body = { instr+ } 74 | 75 | sig = { "def" ~ id ~ io? ~ "->" ~ io? } 76 | 77 | def = { sig ~ "{" ~ body? ~ "}" } 78 | 79 | prog = { def+ } 80 | 81 | file = { SOI ~ prog ~ EOI } 82 | -------------------------------------------------------------------------------- /src/langs/ir/src/try_from.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use crate::errors::Error; 3 | use std::convert::TryFrom; 4 | use std::convert::TryInto; 5 | 6 | impl TryFrom for i64 { 7 | type Error = Error; 8 | fn try_from(term: ExprTerm) -> Result { 9 | match term { 10 | ExprTerm::Val(n) => Ok(n), 11 | _ => Err(Error::new_conv_error("not a term value")), 12 | } 13 | } 14 | } 15 | 16 | impl TryFrom for i32 { 17 | type Error = Error; 18 | fn try_from(term: ExprTerm) -> Result { 19 | match term { 20 | ExprTerm::Val(n) => Ok(i32::try_from(n)?), 21 | _ => Err(Error::new_conv_error("not a term value")), 22 | } 23 | } 24 | } 25 | 26 | impl TryFrom for Id { 27 | type Error = Error; 28 | fn try_from(term: ExprTerm) -> Result { 29 | match term { 30 | ExprTerm::Var(n, _) => Ok(n), 31 | ExprTerm::Any => Ok(String::new()), 32 | _ => Err(Error::new_conv_error("not a term variable")), 33 | } 34 | } 35 | } 36 | 37 | impl TryFrom for Vec { 38 | type Error = Error; 39 | fn try_from(tup: ExprTup) -> Result { 40 | let mut val: Vec = Vec::new(); 41 | for term in tup.term() { 42 | val.push(i64::try_from(term.clone())?) 43 | } 44 | Ok(val) 45 | } 46 | } 47 | 48 | impl TryFrom for Vec { 49 | type Error = Error; 50 | fn try_from(tup: ExprTup) -> Result { 51 | let mut val: Vec = Vec::new(); 52 | for term in tup.term() { 53 | val.push(i32::try_from(term.clone())?) 54 | } 55 | Ok(val) 56 | } 57 | } 58 | 59 | impl TryFrom for Vec { 60 | type Error = Error; 61 | fn try_from(tup: ExprTup) -> Result { 62 | let mut id: Vec = Vec::new(); 63 | for term in tup.term() { 64 | id.push(Id::try_from(term.clone())?) 65 | } 66 | Ok(id) 67 | } 68 | } 69 | 70 | impl TryFrom for Vec { 71 | type Error = Error; 72 | fn try_from(expr: Expr) -> Result { 73 | match expr { 74 | Expr::Term(term) => Ok(vec![i64::try_from(term)?]), 75 | Expr::Tup(tup) => Ok(tup.try_into()?), 76 | } 77 | } 78 | } 79 | 80 | impl TryFrom for Vec { 81 | type Error = Error; 82 | fn try_from(expr: Expr) -> Result { 83 | match expr { 84 | Expr::Term(term) => Ok(vec![i32::try_from(term)?]), 85 | Expr::Tup(tup) => Ok(tup.try_into()?), 86 | } 87 | } 88 | } 89 | 90 | impl TryFrom for Vec { 91 | type Error = Error; 92 | fn try_from(expr: Expr) -> Result { 93 | match expr { 94 | Expr::Term(term) => Ok(vec![Id::try_from(term)?]), 95 | Expr::Tup(tup) => Ok(tup.try_into()?), 96 | } 97 | } 98 | } 99 | 100 | impl TryFrom for InstrWire { 101 | type Error = Error; 102 | fn try_from(instr: Instr) -> Result { 103 | match instr { 104 | Instr::Wire(instr) => Ok(instr), 105 | _ => Err(Error::new_conv_error("not a wire instruction")), 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/langs/ir/tests/parser.rs: -------------------------------------------------------------------------------- 1 | use ir::ast::{Def, Prog}; 2 | use ir::parser::Parser; 3 | 4 | #[test] 5 | fn simple_prog() { 6 | let res = Parser::parse_from_str("def main () -> () {}").unwrap(); 7 | let mut def = Def::default(); 8 | def.set_id("main"); 9 | let mut exp = Prog::default(); 10 | exp.insert(&def.id(), def); 11 | assert_eq!(res, exp); 12 | } 13 | -------------------------------------------------------------------------------- /src/langs/pat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pat" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | bincode = "1.3.1" 10 | serde = { version = "1.0", features = ["derive", "rc"] } 11 | serde_json = "1.0" 12 | itertools = "0.9.0" 13 | pest = "2.0" 14 | pest_derive = "2.0" 15 | pest_consume = "1.0.5" 16 | prettyprint = { path = "../../tools/prettyprint" } 17 | io = { path = "../../tools/io" } 18 | ir = { path = "../ir" } 19 | -------------------------------------------------------------------------------- /src/langs/pat/src/ast.rs: -------------------------------------------------------------------------------- 1 | use ir::ast as ir; 2 | use serde::{Deserialize, Serialize}; 3 | use std::collections::HashMap; 4 | 5 | pub type Id = ir::Id; 6 | pub type Ty = ir::Ty; 7 | pub type Prim = ir::Prim; 8 | pub type ExprTerm = ir::ExprTerm; 9 | pub type ExprTup = ir::ExprTup; 10 | pub type Expr = ir::Expr; 11 | pub type OpWire = ir::OpWire; 12 | pub type OpPrim = ir::OpPrim; 13 | pub type InstrWire = ir::InstrWire; 14 | pub type InstrPrim = ir::InstrPrim; 15 | pub type Sig = ir::Sig; 16 | 17 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 18 | pub enum Instr { 19 | Wire(InstrWire), 20 | Prim(InstrPrim), 21 | } 22 | 23 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash, Default)] 24 | pub struct Pat { 25 | pub sig: Sig, 26 | pub body: Vec, 27 | } 28 | 29 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Default)] 30 | pub struct Target { 31 | pub pat: HashMap, 32 | } 33 | -------------------------------------------------------------------------------- /src/langs/pat/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use prettyprint::PrettyPrint; 3 | use std::fmt; 4 | 5 | macro_rules! display { 6 | ($ty:tt) => { 7 | impl fmt::Display for $ty { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 9 | write!(f, "{}", self.to_pretty()) 10 | } 11 | } 12 | }; 13 | } 14 | 15 | display!(Instr); 16 | display!(Pat); 17 | display!(Target); 18 | -------------------------------------------------------------------------------- /src/langs/pat/src/errors.rs: -------------------------------------------------------------------------------- 1 | use crate::parser; 2 | use std::fmt; 3 | use std::num::ParseIntError; 4 | use std::num::TryFromIntError; 5 | 6 | #[derive(Debug)] 7 | pub enum Error { 8 | Parse(pest_consume::Error), 9 | Type(String), 10 | TryFromInt(TryFromIntError), 11 | ParseInt(ParseIntError), 12 | } 13 | 14 | impl From> for Error { 15 | fn from(e: pest_consume::Error) -> Self { 16 | Error::Parse(e) 17 | } 18 | } 19 | 20 | impl From for Error { 21 | fn from(e: TryFromIntError) -> Self { 22 | Error::TryFromInt(e) 23 | } 24 | } 25 | 26 | impl From for Error { 27 | fn from(e: ParseIntError) -> Self { 28 | Error::ParseInt(e) 29 | } 30 | } 31 | 32 | impl fmt::Display for Error { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | match self { 35 | Error::Parse(msg) => write!(f, "{}", msg), 36 | Error::ParseInt(msg) => write!(f, "{}", msg), 37 | Error::Type(msg) => write!(f, "{}", msg), 38 | Error::TryFromInt(msg) => write!(f, "{}", msg), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/langs/pat/src/from.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use ir::ast as ir; 3 | 4 | impl From for Instr { 5 | fn from(instr: InstrWire) -> Self { 6 | Instr::Wire(instr) 7 | } 8 | } 9 | 10 | impl From for Instr { 11 | fn from(instr: InstrPrim) -> Self { 12 | Instr::Prim(instr) 13 | } 14 | } 15 | 16 | impl From for ir::Instr { 17 | fn from(instr: Instr) -> Self { 18 | match instr { 19 | Instr::Wire(instr) => ir::Instr::from(instr), 20 | Instr::Prim(instr) => ir::Instr::from(instr), 21 | } 22 | } 23 | } 24 | 25 | impl From for ir::InstrMap { 26 | fn from(input: Pat) -> ir::InstrMap { 27 | let mut map = ir::InstrMap::new(); 28 | for instr in input.body() { 29 | if let Some(term) = instr.dst().term() { 30 | if let Some(id) = term.id() { 31 | let value = ir::Instr::from(instr.clone()); 32 | map.insert(id, value); 33 | } 34 | } 35 | } 36 | map 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/langs/pat/src/helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use bincode::{deserialize_from, serialize_into}; 3 | use std::collections::HashMap; 4 | use std::fs::File; 5 | use std::io::{BufReader, BufWriter}; 6 | use std::path::Path; 7 | 8 | impl Instr { 9 | pub fn is_reg(&self) -> bool { 10 | match self { 11 | Instr::Prim(instr) => instr.is_reg(), 12 | _ => false, 13 | } 14 | } 15 | pub fn is_prim(&self) -> bool { 16 | matches!(self, Instr::Prim(_)) 17 | } 18 | pub fn is_wire(&self) -> bool { 19 | matches!(self, Instr::Wire(_)) 20 | } 21 | pub fn dst(&self) -> &Expr { 22 | match self { 23 | Instr::Prim(instr) => instr.dst(), 24 | Instr::Wire(instr) => instr.dst(), 25 | } 26 | } 27 | pub fn arg(&self) -> &Expr { 28 | match self { 29 | Instr::Prim(instr) => instr.arg(), 30 | Instr::Wire(instr) => instr.arg(), 31 | } 32 | } 33 | pub fn set_dst(&mut self, dst: Expr) { 34 | match self { 35 | Instr::Prim(instr) => instr.set_dst(dst), 36 | Instr::Wire(instr) => instr.set_dst(dst), 37 | } 38 | } 39 | pub fn set_arg(&mut self, arg: Expr) { 40 | match self { 41 | Instr::Prim(instr) => instr.set_arg(arg), 42 | Instr::Wire(instr) => instr.set_arg(arg), 43 | } 44 | } 45 | } 46 | 47 | impl Pat { 48 | pub fn id(&self) -> String { 49 | self.sig.id() 50 | } 51 | pub fn sig(&self) -> &Sig { 52 | &self.sig 53 | } 54 | pub fn input(&self) -> &Expr { 55 | self.sig.input() 56 | } 57 | pub fn output(&self) -> &Expr { 58 | self.sig.output() 59 | } 60 | pub fn body(&self) -> &Vec { 61 | &self.body 62 | } 63 | pub fn set_sig(&mut self, sig: Sig) { 64 | self.sig = sig; 65 | } 66 | pub fn set_body(&mut self, body: Vec) { 67 | self.body = body; 68 | } 69 | pub fn body_mut(&mut self) -> &mut Vec { 70 | &mut self.body 71 | } 72 | } 73 | 74 | impl Target { 75 | pub fn deserialize_from_file>(path: P) -> Target { 76 | let file = File::open(path).expect("Error: cannot open the bin file"); 77 | let mut buf = BufReader::new(file); 78 | deserialize_from(&mut buf).expect("Error: cannot deserialize") 79 | } 80 | pub fn pat(&self) -> &HashMap { 81 | &self.pat 82 | } 83 | pub fn get(&self, name: &str) -> Option<&Pat> { 84 | self.pat.get(name) 85 | } 86 | pub fn serialize_to_file>(&self, path: P) { 87 | let file = File::create(path).expect("Error: cannot create the bin file"); 88 | let mut buf = BufWriter::new(file); 89 | serialize_into(&mut buf, &self).expect("Error: cannot serialize"); 90 | } 91 | pub fn get_mut(&mut self, name: &str) -> Option<&mut Pat> { 92 | self.pat.get_mut(name) 93 | } 94 | pub fn insert(&mut self, name: &str, pat: Pat) -> Option { 95 | self.pat.insert(name.to_string(), pat) 96 | } 97 | pub fn extend(&mut self, target: Target) { 98 | self.pat.extend(target.pat().clone()); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/langs/pat/src/infer.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use std::collections::HashMap; 3 | 4 | fn build_env(pat: &Pat) -> HashMap { 5 | let mut env: HashMap = HashMap::new(); 6 | let inp: Vec = pat.sig().input().clone().into(); 7 | // add pat inputs to environment 8 | for e in inp { 9 | if let Some(id) = e.id() { 10 | if let Some(ty) = e.ty() { 11 | env.insert(id, ty.clone()); 12 | } 13 | } 14 | } 15 | // add instr outputs to environment 16 | for instr in pat.body() { 17 | let dst: Vec = instr.dst().clone().into(); 18 | for e in dst { 19 | if let Some(id) = e.id() { 20 | if let Some(ty) = e.ty() { 21 | env.insert(id, ty.clone()); 22 | } 23 | } 24 | } 25 | } 26 | env 27 | } 28 | 29 | fn infer_type_try_from_pat(pat: &Pat) -> Pat { 30 | let env = build_env(pat); 31 | let mut pat = pat.clone(); 32 | // solve instr arg types with environment 33 | for instr in pat.body_mut() { 34 | let mut arg = ExprTup::default(); 35 | if let Some(tup) = instr.arg().tup() { 36 | for e in tup.term() { 37 | if let Some(id) = e.id() { 38 | if let Some(ty) = env.get(&id) { 39 | let term = ExprTerm::Var(id.to_string(), ty.clone()); 40 | arg.add_term(term); 41 | } 42 | } 43 | } 44 | } 45 | let e = Expr::from(arg); 46 | instr.set_arg(e); 47 | } 48 | pat 49 | } 50 | 51 | pub fn infer_type_try_from_target(target: &Target) -> Target { 52 | let mut res = Target::default(); 53 | for (name, pat) in target.pat() { 54 | res.insert(name, infer_type_try_from_pat(pat)); 55 | } 56 | res 57 | } 58 | -------------------------------------------------------------------------------- /src/langs/pat/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod display; 3 | pub mod errors; 4 | pub mod from; 5 | pub mod helpers; 6 | pub mod infer; 7 | pub mod parser; 8 | pub mod pretty_print; 9 | -------------------------------------------------------------------------------- /src/langs/pat/src/pretty_print.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use itertools::Itertools; 3 | use prettyprint::{block_with_braces, intersperse, PrettyPrint, RcDoc}; 4 | 5 | impl PrettyPrint for Instr { 6 | fn to_doc(&self) -> RcDoc<()> { 7 | match self { 8 | Instr::Wire(instr) => instr.to_doc(), 9 | Instr::Prim(instr) => instr.to_doc(), 10 | } 11 | } 12 | } 13 | 14 | impl PrettyPrint for Pat { 15 | fn to_doc(&self) -> RcDoc<()> { 16 | let sig = self.sig().to_doc(); 17 | let body = intersperse( 18 | self.body() 19 | .iter() 20 | .map(|i| i.to_doc().append(RcDoc::text(";"))), 21 | RcDoc::hardline(), 22 | ); 23 | block_with_braces(sig, body) 24 | } 25 | } 26 | 27 | impl PrettyPrint for Target { 28 | fn to_doc(&self) -> RcDoc<()> { 29 | intersperse( 30 | self.pat() 31 | .iter() 32 | .sorted_by_key(|(id, _)| (*id).clone()) 33 | .map(|(_, pat)| pat.to_doc()), 34 | RcDoc::hardline(), 35 | ) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/langs/pat/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\t" | NEWLINE } 2 | 3 | COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } 4 | 5 | sep = _{ "_" | "-"} 6 | 7 | id = @{ ASCII_ALPHA+ ~ (sep | ASCII_ALPHA | ASCII_DIGIT)* } 8 | 9 | val_bin = { ASCII_BIN_DIGIT+ } 10 | 11 | val_hex = { ASCII_HEX_DIGIT+ } 12 | 13 | val_dec = { ("+" | "-")? ~ ASCII_DIGIT+ } 14 | 15 | val = { "0b" ~ val_bin | "0x" ~ val_hex | val_dec } 16 | 17 | int = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ } 18 | 19 | bool = @{ ASCII_ALPHA_LOWER+ } 20 | 21 | vector = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ ~ "<" ~ ASCII_DIGIT+ ~ ">" } 22 | 23 | ty = ${ vector | int | bool } 24 | 25 | var = { id ~ ":" ~ ty | id } 26 | 27 | tup_var = { (var ~ ("," ~ var)*)? } 28 | 29 | tup_val = { (val ~ ("," ~ val)*)? } 30 | 31 | io = { var | "(" ~ tup_var ~ ")" } 32 | 33 | attr = _{ "[" ~ tup_val ~ "]" } 34 | 35 | prim = { "??" | id } 36 | 37 | hint = _{ "@" ~ prim } 38 | 39 | op_prim = { "reg" | 40 | "sram" | 41 | "srom" | 42 | "ram" | 43 | "rom" | 44 | "add" | 45 | "sub" | 46 | "mul" | 47 | "not" | 48 | "and" | 49 | "or" | 50 | "xor" | 51 | "mux" | 52 | "eq" | 53 | "neq" | 54 | "gt" | 55 | "lt" | 56 | "ge" | 57 | "le" } 58 | 59 | op_wire = { "id" | 60 | "const" | 61 | "sll" | 62 | "srl" | 63 | "sra" | 64 | "ext" | 65 | "cat" } 66 | 67 | op_call = { id } 68 | 69 | op = _{ op_prim | op_wire | op_call } 70 | 71 | instr = { io ~ "=" ~ op ~ attr? ~ io? ~ hint? ~ ";" } 72 | 73 | body = { instr+ } 74 | 75 | sig = { "pat" ~ id ~ io? ~ "->" ~ io? } 76 | 77 | pat = { sig ~ "{" ~ body? ~ "}" } 78 | 79 | target = { pat+ } 80 | 81 | file = { SOI ~ target ~ EOI } 82 | -------------------------------------------------------------------------------- /src/langs/pat/tests/parser.rs: -------------------------------------------------------------------------------- 1 | use pat::ast::{Pat, Sig, Target}; 2 | use pat::parser::Parser; 3 | 4 | #[test] 5 | fn simple_target() { 6 | let res = Parser::parse_from_str("pat add_i8_0 () -> () {}").unwrap(); 7 | let mut sig = Sig::default(); 8 | sig.set_id("add_i8_0"); 9 | let mut pat = Pat::default(); 10 | pat.set_sig(sig); 11 | let mut exp = Target::default(); 12 | exp.insert(&pat.id(), pat); 13 | assert_eq!(res, exp); 14 | } 15 | -------------------------------------------------------------------------------- /src/langs/verilog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "verilog" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | vast = { git = "https://github.com/vegaluisjose/vast.git", rev = "9238cf93e66701787370f848995004ac884ae2a7" } 10 | -------------------------------------------------------------------------------- /src/langs/verilog/src/ast.rs: -------------------------------------------------------------------------------- 1 | use vast::v05::ast as vl; 2 | 3 | pub use vl::*; 4 | -------------------------------------------------------------------------------- /src/langs/verilog/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | -------------------------------------------------------------------------------- /src/langs/xim/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xim" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | bincode = "1.3.1" 10 | serde = { version = "1.0", features = ["derive", "rc"] } 11 | serde_json = "1.0" 12 | itertools = "0.9.0" 13 | pest = "2.0" 14 | pest_derive = "2.0" 15 | pest_consume = "1.0.5" 16 | prettyprint = { path = "../../tools/prettyprint" } 17 | io = { path = "../../tools/io" } 18 | xir = { path = "../xir" } 19 | -------------------------------------------------------------------------------- /src/langs/xim/src/ast.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::HashMap; 3 | use xir::ast as xir; 4 | 5 | pub type Id = xir::Id; 6 | pub type Ty = xir::Ty; 7 | pub type Prim = xir::Prim; 8 | pub type OpCoord = xir::OpCoord; 9 | pub type OpBasc = xir::OpBasc; 10 | pub type OpMach = xir::OpMach; 11 | pub type ExprTerm = xir::ExprTerm; 12 | pub type ExprTup = xir::ExprTup; 13 | pub type Expr = xir::Expr; 14 | pub type ExprCoord = xir::ExprCoord; 15 | pub type BelLut = xir::BelLut; 16 | pub type BelReg = xir::BelReg; 17 | pub type BelCarry = xir::BelCarry; 18 | pub type BelDsp = xir::BelDsp; 19 | pub type BelLum = xir::BelLum; 20 | pub type BelBlock = xir::BelBlock; 21 | pub type Bel = xir::Bel; 22 | pub type Loc = xir::Loc; 23 | pub type InstrMach = xir::InstrMach; 24 | pub type InstrBasc = xir::InstrBasc; 25 | pub type Instr = xir::Instr; 26 | 27 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 28 | pub struct Sig { 29 | pub id: Id, 30 | pub input: Expr, 31 | pub output: Expr, 32 | pub area: u64, 33 | pub perf: u64, 34 | } 35 | 36 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash, Default)] 37 | pub struct Imp { 38 | pub sig: Sig, 39 | pub body: Vec, 40 | } 41 | 42 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Default)] 43 | pub struct Target { 44 | pub imp: HashMap, 45 | } 46 | -------------------------------------------------------------------------------- /src/langs/xim/src/default.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl Default for Sig { 4 | fn default() -> Self { 5 | Sig { 6 | id: String::new(), 7 | input: Expr::Tup(ExprTup::default()), 8 | output: Expr::Tup(ExprTup::default()), 9 | area: 0, 10 | perf: 0, 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/langs/xim/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use prettyprint::PrettyPrint; 3 | use std::fmt; 4 | 5 | macro_rules! display { 6 | ($ty:tt) => { 7 | impl fmt::Display for $ty { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 9 | write!(f, "{}", self.to_pretty()) 10 | } 11 | } 12 | }; 13 | } 14 | 15 | display!(Sig); 16 | display!(Imp); 17 | display!(Target); 18 | -------------------------------------------------------------------------------- /src/langs/xim/src/errors.rs: -------------------------------------------------------------------------------- 1 | use crate::parser; 2 | use std::fmt; 3 | use std::num::ParseIntError; 4 | use std::num::TryFromIntError; 5 | 6 | #[derive(Debug)] 7 | pub enum Error { 8 | Parse(pest_consume::Error), 9 | Type(String), 10 | TryFromInt(TryFromIntError), 11 | ParseInt(ParseIntError), 12 | } 13 | 14 | impl From> for Error { 15 | fn from(e: pest_consume::Error) -> Self { 16 | Error::Parse(e) 17 | } 18 | } 19 | 20 | impl From for Error { 21 | fn from(e: TryFromIntError) -> Self { 22 | Error::TryFromInt(e) 23 | } 24 | } 25 | 26 | impl From for Error { 27 | fn from(e: ParseIntError) -> Self { 28 | Error::ParseInt(e) 29 | } 30 | } 31 | 32 | impl fmt::Display for Error { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | match self { 35 | Error::Parse(msg) => write!(f, "{}", msg), 36 | Error::ParseInt(msg) => write!(f, "{}", msg), 37 | Error::Type(msg) => write!(f, "{}", msg), 38 | Error::TryFromInt(msg) => write!(f, "{}", msg), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/langs/xim/src/helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use bincode::{deserialize_from, serialize_into}; 3 | use std::collections::HashMap; 4 | use std::fs::File; 5 | use std::io::{BufReader, BufWriter}; 6 | use std::path::Path; 7 | 8 | impl Sig { 9 | pub fn id(&self) -> String { 10 | self.id.to_string() 11 | } 12 | pub fn input(&self) -> &Expr { 13 | &self.input 14 | } 15 | pub fn output(&self) -> &Expr { 16 | &self.output 17 | } 18 | pub fn area(&self) -> u64 { 19 | self.area 20 | } 21 | pub fn perf(&self) -> u64 { 22 | self.perf 23 | } 24 | pub fn set_id(&mut self, id: &str) { 25 | self.id = id.to_string(); 26 | } 27 | pub fn set_area(&mut self, area: u64) { 28 | self.area = area; 29 | } 30 | pub fn set_perf(&mut self, perf: u64) { 31 | self.perf = perf; 32 | } 33 | } 34 | 35 | impl Imp { 36 | pub fn id(&self) -> String { 37 | self.sig.id() 38 | } 39 | pub fn sig(&self) -> &Sig { 40 | &self.sig 41 | } 42 | pub fn area(&self) -> u64 { 43 | self.sig.area 44 | } 45 | pub fn perf(&self) -> u64 { 46 | self.sig.perf 47 | } 48 | pub fn input(&self) -> &Expr { 49 | self.sig.input() 50 | } 51 | pub fn output(&self) -> &Expr { 52 | self.sig.output() 53 | } 54 | pub fn body(&self) -> &Vec { 55 | &self.body 56 | } 57 | pub fn set_sig(&mut self, sig: Sig) { 58 | self.sig = sig; 59 | } 60 | pub fn set_body(&mut self, body: Vec) { 61 | self.body = body; 62 | } 63 | pub fn body_mut(&mut self) -> &mut Vec { 64 | &mut self.body 65 | } 66 | } 67 | 68 | impl Target { 69 | pub fn deserialize_from_file>(path: P) -> Target { 70 | let file = File::open(path).expect("Error: cannot open the bin file"); 71 | let mut buf = BufReader::new(file); 72 | deserialize_from(&mut buf).expect("Error: cannot deserialize") 73 | } 74 | pub fn imp(&self) -> &HashMap { 75 | &self.imp 76 | } 77 | pub fn get(&self, name: &str) -> Option<&Imp> { 78 | self.imp.get(name) 79 | } 80 | pub fn serialize_to_file>(&self, path: P) { 81 | let file = File::create(path).expect("Error: cannot create the bin file"); 82 | let mut buf = BufWriter::new(file); 83 | serialize_into(&mut buf, &self).expect("Error: cannot serialize"); 84 | } 85 | pub fn get_mut(&mut self, name: &str) -> Option<&mut Imp> { 86 | self.imp.get_mut(name) 87 | } 88 | pub fn insert(&mut self, name: &str, imp: Imp) -> Option { 89 | self.imp.insert(name.to_string(), imp) 90 | } 91 | pub fn extend(&mut self, target: Target) { 92 | self.imp.extend(target.imp().clone()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/langs/xim/src/infer.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use std::collections::HashMap; 3 | 4 | fn build_env(imp: &Imp) -> HashMap { 5 | let mut env: HashMap = HashMap::new(); 6 | let inp: Vec = imp.sig().input().clone().into(); 7 | // add imp inputs to environment 8 | for e in inp { 9 | if let Some(id) = e.id() { 10 | if let Some(ty) = e.ty() { 11 | env.insert(id, ty.clone()); 12 | } 13 | } 14 | } 15 | // add instr outputs to environment 16 | for instr in imp.body() { 17 | let dst: Vec = instr.dst().clone().into(); 18 | for e in dst { 19 | if let Some(id) = e.id() { 20 | if let Some(ty) = e.ty() { 21 | env.insert(id, ty.clone()); 22 | } 23 | } 24 | } 25 | } 26 | env 27 | } 28 | 29 | fn infer_type_try_from_imp(imp: &Imp) -> Imp { 30 | let env = build_env(imp); 31 | let mut imp = imp.clone(); 32 | // solve instr arg types with environment 33 | for instr in imp.body_mut() { 34 | let mut arg = ExprTup::default(); 35 | if let Some(tup) = instr.arg().tup() { 36 | for e in tup.term() { 37 | if let Some(id) = e.id() { 38 | if let Some(ty) = env.get(&id) { 39 | let term = ExprTerm::Var(id.to_string(), ty.clone()); 40 | arg.add_term(term); 41 | } 42 | } 43 | } 44 | } 45 | let e = Expr::from(arg); 46 | instr.set_arg(e); 47 | } 48 | imp 49 | } 50 | 51 | pub fn infer_type_try_from_target(target: &Target) -> Target { 52 | let mut res = Target::default(); 53 | for (name, imp) in target.imp() { 54 | res.insert(name, infer_type_try_from_imp(imp)); 55 | } 56 | res 57 | } 58 | -------------------------------------------------------------------------------- /src/langs/xim/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod default; 3 | pub mod display; 4 | pub mod errors; 5 | pub mod helpers; 6 | pub mod infer; 7 | pub mod parser; 8 | pub mod pretty_print; 9 | -------------------------------------------------------------------------------- /src/langs/xim/src/pretty_print.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use itertools::Itertools; 3 | use prettyprint::{block_with_braces, intersperse, PrettyHelper, PrettyPrint, RcDoc}; 4 | 5 | impl PrettyPrint for Sig { 6 | fn to_doc(&self) -> RcDoc<()> { 7 | let attr_val = vec![RcDoc::as_string(self.area()), RcDoc::as_string(self.perf())]; 8 | let attr = intersperse( 9 | attr_val.iter().cloned(), 10 | RcDoc::text(",").append(RcDoc::space()), 11 | ) 12 | .brackets(); 13 | RcDoc::text("imp") 14 | .append(RcDoc::space()) 15 | .append(RcDoc::as_string(self.id())) 16 | .append(attr) 17 | .append(self.input().to_doc()) 18 | .append(RcDoc::space()) 19 | .append(RcDoc::text("->")) 20 | .append(RcDoc::space()) 21 | .append(self.output().to_doc()) 22 | } 23 | } 24 | 25 | impl PrettyPrint for Imp { 26 | fn to_doc(&self) -> RcDoc<()> { 27 | let sig = self.sig().to_doc(); 28 | let body = intersperse( 29 | self.body() 30 | .iter() 31 | .map(|i| i.to_doc().append(RcDoc::text(";"))), 32 | RcDoc::hardline(), 33 | ); 34 | block_with_braces(sig, body) 35 | } 36 | } 37 | 38 | impl PrettyPrint for Target { 39 | fn to_doc(&self) -> RcDoc<()> { 40 | intersperse( 41 | self.imp() 42 | .iter() 43 | .sorted_by_key(|(id, _)| (*id).clone()) 44 | .map(|(_, imp)| imp.to_doc()), 45 | RcDoc::hardline(), 46 | ) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/langs/xim/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\t" | NEWLINE } 2 | 3 | COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } 4 | 5 | sep = _{ "_" | "-"} 6 | 7 | id = @{ ASCII_ALPHA+ ~ (sep | ASCII_ALPHA | ASCII_DIGIT)* } 8 | 9 | val_bin = { ASCII_BIN_DIGIT+ } 10 | 11 | val_hex = { ASCII_HEX_DIGIT+ } 12 | 13 | val_dec = { ("+" | "-")? ~ ASCII_DIGIT+ } 14 | 15 | cost = { ASCII_DIGIT+ } 16 | 17 | val = { "0b" ~ val_bin | "0x" ~ val_hex | val_dec } 18 | 19 | int = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ } 20 | 21 | bool = @{ ASCII_ALPHA_LOWER+ } 22 | 23 | vector = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ ~ "<" ~ ASCII_DIGIT+ ~ ">" } 24 | 25 | ty = ${ vector | int | bool } 26 | 27 | var = { id ~ ":" ~ ty | id } 28 | 29 | tup_var = { (var ~ ("," ~ var)*)? } 30 | 31 | tup_val = { (val ~ ("," ~ val)*)? } 32 | 33 | io = { var | "(" ~ tup_var ~ ")" } 34 | 35 | attr = _{ "[" ~ tup_val ~ "]" } 36 | 37 | bel_block = { "u" | "l" } 38 | 39 | bel_dsp = { "alu" } 40 | 41 | bel_reg = { 42 | "a" | 43 | "b" | 44 | "c" | 45 | "d" | 46 | "e" | 47 | "f" | 48 | "g" | 49 | "h" | 50 | "a2" | 51 | "b2" | 52 | "c2" | 53 | "d2" | 54 | "e2" | 55 | "f2" | 56 | "g2" | 57 | "h2"} 58 | 59 | bel_lut = { 60 | "a5" | 61 | "b5" | 62 | "c5" | 63 | "d5" | 64 | "e5" | 65 | "f5" | 66 | "g5" | 67 | "h5" | 68 | "a6" | 69 | "b6" | 70 | "c6" | 71 | "d6" | 72 | "e6" | 73 | "f6" | 74 | "g6" | 75 | "h6"} 76 | 77 | bel_carry = { "c8" | "c4" } 78 | 79 | bel_lum = { "h6" } 80 | 81 | coord = { "??" | id | ASCII_DIGIT+ } 82 | 83 | op_coord = { "+" } 84 | 85 | expr_coord = { coord ~ (op_coord ~ coord)? } 86 | 87 | xy = _{ "(" ~ expr_coord ~ "," ~ expr_coord ~ ")" } 88 | 89 | loc_block = { "@" ~ bel_block ~ xy } 90 | 91 | loc_dsp = { "@" ~ bel_dsp ~ xy } 92 | 93 | loc_reg = { "@" ~ bel_reg ~ xy } 94 | 95 | loc_carry = { "@" ~ bel_carry ~ xy } 96 | 97 | loc_lut = { "@" ~ bel_lut ~ xy } 98 | 99 | loc_lum = { "@" ~ bel_lum ~ xy } 100 | 101 | op_basc = { "id" | "gnd" | "vcc" | "ext" | "cat" } 102 | 103 | op_lut = { 104 | "lut1" | 105 | "lut2" | 106 | "lut3" | 107 | "lut4" | 108 | "lut5" | 109 | "lut6" } 110 | 111 | op_lum = { "lram" | "lrom"} 112 | 113 | op_carry = { "carryadd" | "carrysub" } 114 | 115 | op_reg = { "fdre" | "fdse" } 116 | 117 | op_block = { "bram" | "brom" } 118 | 119 | op_dsp = { 120 | "vaddrega" | 121 | "vadd" | 122 | "vsub" | 123 | "vmul" | 124 | "muladdregacio" | 125 | "muladdregaco" | 126 | "muladdregaci" | 127 | "muladdrega" | 128 | "muladd" | 129 | "mul" } 130 | 131 | instr_reg = { io ~ "=" ~ op_reg ~ attr? ~ io? ~ loc_reg? ~ ";" } 132 | 133 | instr_block = { io ~ "=" ~ op_block ~ attr? ~ io? ~ loc_block? ~ ";" } 134 | 135 | instr_dsp = { io ~ "=" ~ op_dsp ~ attr? ~ io? ~ loc_dsp? ~ ";" } 136 | 137 | instr_carry = { io ~ "=" ~ op_carry ~ attr? ~ io? ~ loc_carry? ~ ";" } 138 | 139 | instr_lut = { io ~ "=" ~ op_lut ~ attr? ~ io? ~ loc_lut? ~ ";" } 140 | 141 | instr_lum = { io ~ "=" ~ op_lum ~ attr? ~ io? ~ loc_lum? ~ ";" } 142 | 143 | instr_basc = { io ~ "=" ~ op_basc ~ attr? ~ io? ~ ";" } 144 | 145 | instr = { 146 | instr_basc | 147 | instr_reg | 148 | instr_carry | 149 | instr_dsp | 150 | instr_lut | 151 | instr_lum | 152 | instr_block } 153 | 154 | body = { instr+ } 155 | 156 | area = _{ cost } 157 | 158 | perf = _{ cost } 159 | 160 | sig = { "imp" ~ id ~ "[" ~ area ~ "," ~ perf ~ "]" ~ io? ~ "->" ~ io? } 161 | 162 | imp = { sig ~ "{" ~ body? ~ "}" } 163 | 164 | target = { imp+ } 165 | 166 | file = { SOI ~ target ~ EOI } 167 | -------------------------------------------------------------------------------- /src/langs/xim/tests/parser.rs: -------------------------------------------------------------------------------- 1 | use xim::ast::{Imp, Sig, Target}; 2 | use xim::parser::Parser; 3 | 4 | #[test] 5 | fn simple_target() { 6 | let res = Parser::parse_from_str("imp add_i8_0[1, 1]() -> () {}").unwrap(); 7 | let mut sig = Sig::default(); 8 | sig.set_id("add_i8_0"); 9 | sig.set_area(1); 10 | sig.set_perf(1); 11 | let mut imp = Imp::default(); 12 | imp.set_sig(sig); 13 | let mut exp = Target::default(); 14 | exp.insert(&imp.id(), imp); 15 | assert_eq!(res, exp); 16 | } 17 | -------------------------------------------------------------------------------- /src/langs/xir/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xir" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | bincode = "1.3.1" 10 | serde = { version = "1.0", features = ["derive", "rc"] } 11 | serde_json = "1.0" 12 | pest = "2.0" 13 | pest_derive = "2.0" 14 | pest_consume = "1.0.5" 15 | prettyprint = { path = "../../tools/prettyprint" } 16 | io = { path = "../../tools/io" } 17 | ir = { path = "../ir" } 18 | asm = { path = "../asm" } 19 | mmap = { path = "../../tools/mmap" } 20 | -------------------------------------------------------------------------------- /src/langs/xir/src/ast.rs: -------------------------------------------------------------------------------- 1 | use asm::ast as asm; 2 | use ir::ast as ir; 3 | use serde::{Deserialize, Serialize}; 4 | 5 | pub type Id = ir::Id; 6 | pub type Ty = ir::Ty; 7 | pub type Prim = ir::Prim; 8 | pub type OpCoord = asm::OpCoord; 9 | pub type ExprTerm = ir::ExprTerm; 10 | pub type ExprTup = ir::ExprTup; 11 | pub type Expr = ir::Expr; 12 | pub type ExprCoord = asm::ExprCoord; 13 | pub type Sig = ir::Sig; 14 | pub type Mem = mmap::Mem; 15 | // pub type Mmap = mmap::Mmap; 16 | 17 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 18 | pub enum OpBasc { 19 | Id, 20 | Gnd, 21 | Vcc, 22 | Ext, 23 | Cat, 24 | } 25 | 26 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 27 | pub enum OpMach { 28 | Lut1, 29 | Lut2, 30 | Lut3, 31 | Lut4, 32 | Lut5, 33 | Lut6, 34 | Fdre, 35 | Fdse, 36 | CarryAdd, 37 | CarrySub, 38 | VecAddRegA, 39 | VecAdd, 40 | VecSub, 41 | VecMul, 42 | Mul, 43 | MulAdd, 44 | MulAddRegA, 45 | MulAddRegACi, 46 | MulAddRegACo, 47 | MulAddRegACio, 48 | Lram, 49 | Bram, 50 | Lrom, 51 | Brom, 52 | } 53 | 54 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 55 | pub enum BelLut { 56 | A5, 57 | B5, 58 | C5, 59 | D5, 60 | E5, 61 | F5, 62 | G5, 63 | H5, 64 | A6, 65 | B6, 66 | C6, 67 | D6, 68 | E6, 69 | F6, 70 | G6, 71 | H6, 72 | } 73 | 74 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 75 | pub enum BelReg { 76 | A, 77 | B, 78 | C, 79 | D, 80 | E, 81 | F, 82 | G, 83 | H, 84 | A2, 85 | B2, 86 | C2, 87 | D2, 88 | E2, 89 | F2, 90 | G2, 91 | H2, 92 | } 93 | 94 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 95 | pub enum BelCarry { 96 | Carry8, 97 | Carry4, 98 | } 99 | 100 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 101 | pub enum BelDsp { 102 | Alu, 103 | } 104 | 105 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 106 | pub enum BelBlock { 107 | L, 108 | U, 109 | } 110 | 111 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 112 | pub enum BelLum { 113 | H6, 114 | } 115 | 116 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 117 | pub enum Bel { 118 | Lut(BelLut), 119 | Reg(BelReg), 120 | Carry(BelCarry), 121 | Dsp(BelDsp), 122 | Block(BelBlock), 123 | Lum(BelLum), 124 | } 125 | 126 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 127 | pub struct Loc { 128 | pub bel: Bel, 129 | pub x: ExprCoord, 130 | pub y: ExprCoord, 131 | } 132 | 133 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 134 | pub struct InstrBasc { 135 | pub op: OpBasc, 136 | pub attr: Expr, 137 | pub dst: Expr, 138 | pub arg: Expr, 139 | } 140 | 141 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 142 | pub struct InstrMach { 143 | pub op: OpMach, 144 | pub attr: Expr, 145 | pub dst: Expr, 146 | pub arg: Expr, 147 | pub loc: Option, 148 | pub mem: Option, 149 | } 150 | 151 | #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Eq, Hash)] 152 | pub enum Instr { 153 | Basc(InstrBasc), 154 | Mach(InstrMach), 155 | } 156 | 157 | #[derive(Serialize, Deserialize, PartialEq, Default, Clone, Debug, Eq)] 158 | pub struct Prog { 159 | pub sig: Sig, 160 | pub body: Vec, 161 | } 162 | -------------------------------------------------------------------------------- /src/langs/xir/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use prettyprint::PrettyPrint; 3 | use std::fmt; 4 | 5 | macro_rules! display { 6 | ($ty:tt) => { 7 | impl fmt::Display for $ty { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 9 | write!(f, "{}", self.to_pretty()) 10 | } 11 | } 12 | }; 13 | } 14 | 15 | display!(OpBasc); 16 | display!(OpMach); 17 | display!(BelLut); 18 | display!(BelReg); 19 | display!(BelCarry); 20 | display!(BelDsp); 21 | display!(Bel); 22 | display!(Loc); 23 | display!(InstrBasc); 24 | display!(InstrMach); 25 | display!(Instr); 26 | display!(Prog); 27 | -------------------------------------------------------------------------------- /src/langs/xir/src/errors.rs: -------------------------------------------------------------------------------- 1 | use crate::parser; 2 | use pest_consume::Error as PestError; 3 | use std::fmt; 4 | use std::num::ParseIntError; 5 | use std::num::TryFromIntError; 6 | 7 | #[derive(Debug)] 8 | pub enum Error { 9 | Parser(PestError), 10 | Conversion(String), 11 | Type(String), 12 | TryFromInt(TryFromIntError), 13 | ParseInt(ParseIntError), 14 | } 15 | 16 | impl Error { 17 | pub fn new_conv_error(msg: &str) -> Self { 18 | Error::Conversion(msg.to_string()) 19 | } 20 | pub fn new_type_error(msg: &str) -> Self { 21 | Error::Conversion(msg.to_string()) 22 | } 23 | } 24 | 25 | impl From> for Error { 26 | fn from(e: PestError) -> Self { 27 | Error::Parser(e) 28 | } 29 | } 30 | 31 | impl From for Error { 32 | fn from(e: TryFromIntError) -> Self { 33 | Error::TryFromInt(e) 34 | } 35 | } 36 | 37 | impl From for Error { 38 | fn from(e: ParseIntError) -> Self { 39 | Error::ParseInt(e) 40 | } 41 | } 42 | 43 | impl fmt::Display for Error { 44 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 45 | match self { 46 | Error::Parser(msg) => write!(f, "{}", msg), 47 | Error::ParseInt(msg) => write!(f, "{}", msg), 48 | Error::Conversion(msg) => write!(f, "{}", msg), 49 | Error::Type(msg) => write!(f, "{}", msg), 50 | Error::TryFromInt(msg) => write!(f, "{}", msg), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/langs/xir/src/from.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | 3 | impl From for Bel { 4 | fn from(bel: BelLut) -> Self { 5 | Bel::Lut(bel) 6 | } 7 | } 8 | 9 | impl From for Bel { 10 | fn from(bel: BelReg) -> Self { 11 | Bel::Reg(bel) 12 | } 13 | } 14 | 15 | impl From for Bel { 16 | fn from(bel: BelCarry) -> Self { 17 | Bel::Carry(bel) 18 | } 19 | } 20 | 21 | impl From for Bel { 22 | fn from(bel: BelDsp) -> Self { 23 | Bel::Dsp(bel) 24 | } 25 | } 26 | 27 | impl From for Bel { 28 | fn from(bel: BelBlock) -> Self { 29 | Bel::Block(bel) 30 | } 31 | } 32 | 33 | impl From for Bel { 34 | fn from(bel: BelLum) -> Self { 35 | Bel::Lum(bel) 36 | } 37 | } 38 | 39 | impl From for Instr { 40 | fn from(instr: InstrBasc) -> Self { 41 | Instr::Basc(instr) 42 | } 43 | } 44 | 45 | impl From for Instr { 46 | fn from(instr: InstrMach) -> Self { 47 | Instr::Mach(instr) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/langs/xir/src/infer.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::*; 2 | use std::collections::HashMap; 3 | 4 | fn build_env(prog: &Prog) -> HashMap { 5 | let mut env: HashMap = HashMap::new(); 6 | let inp: Vec = prog.sig().input().clone().into(); 7 | // add prog inputs to environment 8 | for e in inp { 9 | if let Some(id) = e.id() { 10 | if let Some(ty) = e.ty() { 11 | env.insert(id, ty.clone()); 12 | } 13 | } 14 | } 15 | // add instr outputs to environment 16 | for instr in prog.body() { 17 | let dst: Vec = instr.dst().clone().into(); 18 | for e in dst { 19 | if let Some(id) = e.id() { 20 | if let Some(ty) = e.ty() { 21 | env.insert(id, ty.clone()); 22 | } 23 | } 24 | } 25 | } 26 | env 27 | } 28 | 29 | pub fn infer_type_try_from_prog(prog: &Prog) -> Prog { 30 | let env = build_env(prog); 31 | let mut prog = prog.clone(); 32 | // solve instr arg types with environment 33 | for instr in prog.body_mut() { 34 | let mut arg = ExprTup::default(); 35 | if let Some(tup) = instr.arg().tup() { 36 | for e in tup.term() { 37 | if let Some(id) = e.id() { 38 | if let Some(ty) = env.get(&id) { 39 | let term = ExprTerm::Var(id.to_string(), ty.clone()); 40 | arg.add_term(term); 41 | } 42 | } 43 | } 44 | } 45 | let e = Expr::from(arg); 46 | instr.set_arg(e); 47 | } 48 | prog 49 | } 50 | -------------------------------------------------------------------------------- /src/langs/xir/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod display; 3 | pub mod errors; 4 | pub mod from; 5 | pub mod from_str; 6 | pub mod helpers; 7 | pub mod infer; 8 | pub mod parser; 9 | pub mod pretty_print; 10 | -------------------------------------------------------------------------------- /src/langs/xir/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\t" | NEWLINE } 2 | 3 | COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } 4 | 5 | sep = _{ "_" | "-"} 6 | 7 | id = @{ ASCII_ALPHA+ ~ (sep | ASCII_ALPHA | ASCII_DIGIT)* } 8 | 9 | val_bin = { ASCII_BIN_DIGIT+ } 10 | 11 | val_hex = { ASCII_HEX_DIGIT+ } 12 | 13 | val_dec = { ("+" | "-")? ~ ASCII_DIGIT+ } 14 | 15 | val = { "0b" ~ val_bin | "0x" ~ val_hex | val_dec } 16 | 17 | int = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ } 18 | 19 | bool = @{ ASCII_ALPHA_LOWER+ } 20 | 21 | vector = @{ ASCII_ALPHA_LOWER ~ ASCII_DIGIT+ ~ "<" ~ ASCII_DIGIT+ ~ ">" } 22 | 23 | ty = ${ vector | int | bool } 24 | 25 | var = { id ~ ":" ~ ty | id } 26 | 27 | tup_var = { (var ~ ("," ~ var)*)? } 28 | 29 | tup_val = { (val ~ ("," ~ val)*)? } 30 | 31 | io = { var | "(" ~ tup_var ~ ")" } 32 | 33 | attr = _{ "[" ~ tup_val ~ "]" } 34 | 35 | bel_block = { "u" | "l" } 36 | 37 | bel_dsp = { "alu" } 38 | 39 | bel_reg = { 40 | "a" | 41 | "b" | 42 | "c" | 43 | "d" | 44 | "e" | 45 | "f" | 46 | "g" | 47 | "h" | 48 | "a2" | 49 | "b2" | 50 | "c2" | 51 | "d2" | 52 | "e2" | 53 | "f2" | 54 | "g2" | 55 | "h2"} 56 | 57 | bel_lut = { 58 | "a5" | 59 | "b5" | 60 | "c5" | 61 | "d5" | 62 | "e5" | 63 | "f5" | 64 | "g5" | 65 | "h5" | 66 | "a6" | 67 | "b6" | 68 | "c6" | 69 | "d6" | 70 | "e6" | 71 | "f6" | 72 | "g6" | 73 | "h6"} 74 | 75 | bel_carry = { "c8" | "c4" } 76 | 77 | bel_lum = { "h6" } 78 | 79 | coord = { "??" | id | ASCII_DIGIT+ } 80 | 81 | op_coord = { "+" } 82 | 83 | expr_coord = { coord ~ (op_coord ~ coord)? } 84 | 85 | xy = _{ "(" ~ expr_coord ~ "," ~ expr_coord ~ ")" } 86 | 87 | loc_block = { "@" ~ bel_block ~ xy } 88 | 89 | loc_dsp = { "@" ~ bel_dsp ~ xy } 90 | 91 | loc_reg = { "@" ~ bel_reg ~ xy } 92 | 93 | loc_carry = { "@" ~ bel_carry ~ xy } 94 | 95 | loc_lut = { "@" ~ bel_lut ~ xy } 96 | 97 | loc_lum = { "@" ~ bel_lum ~ xy } 98 | 99 | op_basc = { "id" | "gnd" | "vcc" | "ext" | "cat" } 100 | 101 | op_lut = { 102 | "lut1" | 103 | "lut2" | 104 | "lut3" | 105 | "lut4" | 106 | "lut5" | 107 | "lut6" } 108 | 109 | op_lum = { "lram" | "lrom"} 110 | 111 | op_carry = { "carryadd" | "carrysub" } 112 | 113 | op_reg = { "fdre" | "fdse" } 114 | 115 | op_block = { "bram" | "brom" } 116 | 117 | op_dsp = { 118 | "vaddrega" | 119 | "vadd" | 120 | "vsub" | 121 | "vmul" | 122 | "muladdregacio" | 123 | "muladdregaco" | 124 | "muladdregaci" | 125 | "muladdrega" | 126 | "muladd" | 127 | "mul" } 128 | 129 | instr_reg = { io ~ "=" ~ op_reg ~ attr? ~ io? ~ loc_reg? ~ ";" } 130 | 131 | instr_block = { io ~ "=" ~ op_block ~ attr? ~ io? ~ loc_block? ~ ";" } 132 | 133 | instr_dsp = { io ~ "=" ~ op_dsp ~ attr? ~ io? ~ loc_dsp? ~ ";" } 134 | 135 | instr_carry = { io ~ "=" ~ op_carry ~ attr? ~ io? ~ loc_carry? ~ ";" } 136 | 137 | instr_lut = { io ~ "=" ~ op_lut ~ attr? ~ io? ~ loc_lut? ~ ";" } 138 | 139 | instr_lum = { io ~ "=" ~ op_lum ~ attr? ~ io? ~ loc_lum? ~ ";" } 140 | 141 | instr_basc = { io ~ "=" ~ op_basc ~ attr? ~ io? ~ ";" } 142 | 143 | instr = { 144 | instr_basc | 145 | instr_reg | 146 | instr_carry | 147 | instr_dsp | 148 | instr_lut | 149 | instr_lum | 150 | instr_block } 151 | 152 | body = { instr+ } 153 | 154 | sig = { "def" ~ id ~ io? ~ "->" ~ io? } 155 | 156 | prog = { sig ~ "{" ~ body? ~ "}" } 157 | 158 | file = { SOI ~ prog ~ EOI } 159 | -------------------------------------------------------------------------------- /src/langs/xir/tests/parser.rs: -------------------------------------------------------------------------------- 1 | use xir::ast::Prog; 2 | use xir::parser::Parser; 3 | 4 | #[test] 5 | fn simple_prog() { 6 | let res = Parser::parse_from_str("def main () -> () {}").unwrap(); 7 | let mut exp = Prog::default(); 8 | exp.set_id("main"); 9 | assert_eq!(res, exp); 10 | } 11 | -------------------------------------------------------------------------------- /src/tools/bler/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bler" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [build-dependencies] 9 | xim = { path = "../../langs/xim" } 10 | 11 | [dependencies] 12 | ir = { path = "../../langs/ir" } 13 | asm = { path = "../../langs/asm" } 14 | xim = { path = "../../langs/xim" } 15 | xir = { path = "../../langs/xir" } 16 | mmap = { path = "../mmap" } 17 | -------------------------------------------------------------------------------- /src/tools/bler/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::Path; 3 | 4 | fn build_implementation(prim: &str) { 5 | use xim::parser::Parser; 6 | let out_dir = env::var("OUT_DIR").unwrap(); 7 | let imp_path = format!("../../../examples/xim/{}.xim", prim); 8 | let bin_name = format!("{}_xim.bin", prim); 9 | let imp = Parser::parse_from_file(imp_path).unwrap(); 10 | let bin_path = Path::new(&out_dir).join(bin_name); 11 | imp.serialize_to_file(bin_path); 12 | } 13 | 14 | fn build(prim: &str) { 15 | println!("cargo:rerun-if-changed=../../../examples/xim/{}.xim", prim); 16 | build_implementation(prim); 17 | } 18 | 19 | fn main() { 20 | let prim = ["lut", "dsp", "mem"]; 21 | for p in &prim { 22 | build(p); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/tools/bler/src/errors.rs: -------------------------------------------------------------------------------- 1 | use asm::errors::Error as AsmError; 2 | use ir::errors::Error as IrError; 3 | use std::fmt; 4 | use xir::errors::Error as XirError; 5 | 6 | #[derive(Debug)] 7 | pub enum Error { 8 | Ir(IrError), 9 | Asm(AsmError), 10 | Xir(XirError), 11 | Bler(String), 12 | } 13 | 14 | impl Error { 15 | pub fn new_bler_error(msg: &str) -> Self { 16 | Error::Bler(msg.to_string()) 17 | } 18 | } 19 | 20 | impl From for Error { 21 | fn from(e: AsmError) -> Self { 22 | Error::Asm(e) 23 | } 24 | } 25 | 26 | impl From for Error { 27 | fn from(e: XirError) -> Self { 28 | Error::Xir(e) 29 | } 30 | } 31 | 32 | impl From for Error { 33 | fn from(e: IrError) -> Self { 34 | Error::Ir(e) 35 | } 36 | } 37 | 38 | impl fmt::Display for Error { 39 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 40 | match self { 41 | Error::Ir(msg) => write!(f, "{}", msg), 42 | Error::Asm(msg) => write!(f, "{}", msg), 43 | Error::Xir(msg) => write!(f, "{}", msg), 44 | Error::Bler(msg) => write!(f, "{}", msg), 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/tools/bler/tests/assemble.rs: -------------------------------------------------------------------------------- 1 | use asm::parser::Parser as AsmParser; 2 | use bler::errors::Error; 3 | use bler::try_from_asm_prog; 4 | use std::path::Path; 5 | use xir::parser::Parser as XirParser; 6 | 7 | fn test(name: &str) -> Result<(), Error> { 8 | let mut input = Path::new("../../../examples/asm").join(name); 9 | let mut output = Path::new("../../../examples/xir").join(name); 10 | input.set_extension("asm"); 11 | output.set_extension("xir"); 12 | let parsed = AsmParser::parse_from_file(input)?; 13 | let exp = XirParser::parse_from_file(output)?; 14 | let (res, _) = try_from_asm_prog(&parsed, None)?; 15 | assert_eq!(res, exp); 16 | Ok(()) 17 | } 18 | 19 | #[test] 20 | fn add() -> Result<(), Error> { 21 | test("add") 22 | } 23 | 24 | #[test] 25 | fn addreduce_placed() -> Result<(), Error> { 26 | test("addreduce_placed") 27 | } 28 | 29 | #[test] 30 | fn fsm_3() -> Result<(), Error> { 31 | test("fsm_3") 32 | } 33 | 34 | #[test] 35 | fn fsm_5() -> Result<(), Error> { 36 | test("fsm_5") 37 | } 38 | 39 | #[test] 40 | fn fsm_7() -> Result<(), Error> { 41 | test("fsm_7") 42 | } 43 | 44 | #[test] 45 | fn fsm_9() -> Result<(), Error> { 46 | test("fsm_9") 47 | } 48 | 49 | #[test] 50 | fn tadd() -> Result<(), Error> { 51 | test("tadd") 52 | } 53 | 54 | #[test] 55 | fn tadd_64() -> Result<(), Error> { 56 | test("tadd_64") 57 | } 58 | 59 | #[test] 60 | fn tadd_128() -> Result<(), Error> { 61 | test("tadd_128") 62 | } 63 | 64 | #[test] 65 | fn tadd_256() -> Result<(), Error> { 66 | test("tadd_256") 67 | } 68 | 69 | #[test] 70 | fn tadd_512() -> Result<(), Error> { 71 | test("tadd_512") 72 | } 73 | 74 | #[test] 75 | fn tdot() -> Result<(), Error> { 76 | test("tdot") 77 | } 78 | 79 | #[test] 80 | fn tdot_5_3() -> Result<(), Error> { 81 | test("tdot_5_3") 82 | } 83 | 84 | #[test] 85 | fn tdot_5_9() -> Result<(), Error> { 86 | test("tdot_5_9") 87 | } 88 | 89 | #[test] 90 | fn tdot_5_18() -> Result<(), Error> { 91 | test("tdot_5_18") 92 | } 93 | 94 | #[test] 95 | fn tdot_5_36() -> Result<(), Error> { 96 | test("tdot_5_36") 97 | } 98 | 99 | #[test] 100 | fn mux128() -> Result<(), Error> { 101 | test("mux128") 102 | } 103 | -------------------------------------------------------------------------------- /src/tools/bline/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bline" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | itertools = "0.9.0" 10 | io = { path = "../io" } 11 | ir = { path = "../../langs/ir" } 12 | verilog = { path = "../../langs/verilog" } 13 | -------------------------------------------------------------------------------- /src/tools/bline/src/errors.rs: -------------------------------------------------------------------------------- 1 | use ir::errors::Error as IrError; 2 | use std::fmt; 3 | use std::num::TryFromIntError; 4 | 5 | #[derive(Debug)] 6 | pub enum Error { 7 | Ir(IrError), 8 | Bline(String), 9 | TryFromInt(TryFromIntError), 10 | } 11 | 12 | impl Error { 13 | pub fn new_bline_error(msg: &str) -> Self { 14 | Error::Bline(msg.to_string()) 15 | } 16 | } 17 | 18 | impl From for Error { 19 | fn from(e: IrError) -> Self { 20 | Error::Ir(e) 21 | } 22 | } 23 | 24 | impl From for Error { 25 | fn from(e: TryFromIntError) -> Self { 26 | Error::TryFromInt(e) 27 | } 28 | } 29 | 30 | impl fmt::Display for Error { 31 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 32 | match self { 33 | Error::Ir(msg) => write!(f, "{}", msg), 34 | Error::Bline(msg) => write!(f, "{}", msg), 35 | Error::TryFromInt(msg) => write!(f, "{}", msg), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/tools/bline/tests/behav.rs: -------------------------------------------------------------------------------- 1 | use bline::try_from_ir_prog; 2 | use io::read_to_string; 3 | use ir::parser::Parser as IrParser; 4 | 5 | #[test] 6 | fn add() { 7 | let prog = IrParser::parse_from_file("../../../examples/ir/add.ir").unwrap(); 8 | let exp = read_to_string("../../../examples/behav/add.v"); 9 | let res = try_from_ir_prog(&prog).unwrap().to_string(); 10 | assert_eq!(res, exp); 11 | } 12 | -------------------------------------------------------------------------------- /src/tools/io/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "io" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /src/tools/io/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::{self, File}; 3 | use std::io::prelude::*; 4 | use std::path::{Path, PathBuf}; 5 | 6 | pub fn create_abs_path>(path: P) -> PathBuf { 7 | let mut p = PathBuf::new(); 8 | p.push(env!("CARGO_MANIFEST_DIR")); 9 | p.push(path); 10 | p 11 | } 12 | 13 | pub fn create_tmp_path>(path: P) -> PathBuf { 14 | let mut p = env::temp_dir(); 15 | p.push(path); 16 | p 17 | } 18 | 19 | pub fn read_to_string>(path: P) -> String { 20 | let mut file = File::open(path).expect("Error: openning the file"); 21 | let mut contents = String::new(); 22 | file.read_to_string(&mut contents) 23 | .expect("Error: reading the file"); 24 | contents 25 | } 26 | 27 | pub fn write_to_file>(path: P, contents: &str) { 28 | let mut file = File::create(path).expect("Error: cannot create a file"); 29 | file.write_all(contents.as_bytes()) 30 | .expect("Error: writing the file"); 31 | } 32 | 33 | pub fn write_to_tmp_file>(path: P, contents: &str) -> PathBuf { 34 | let temp_path = create_tmp_path(path); 35 | write_to_file(&temp_path, contents); 36 | temp_path 37 | } 38 | 39 | pub fn read_from_tmp_file>(path: P) -> String { 40 | let temp_path = create_tmp_path(path); 41 | read_to_string(&temp_path) 42 | } 43 | 44 | pub fn remove_tmp_file>(path: P) { 45 | let temp_path = create_tmp_path(path); 46 | fs::remove_file(&temp_path).expect("Error: cannot remove temp file"); 47 | } 48 | -------------------------------------------------------------------------------- /src/tools/isel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "isel" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [build-dependencies] 9 | pat = { path = "../../langs/pat" } 10 | xim = { path = "../../langs/xim" } 11 | 12 | [dependencies] 13 | ir = { path = "../../langs/ir" } 14 | asm = { path = "../../langs/asm" } 15 | pat = { path = "../../langs/pat" } 16 | xim = { path = "../../langs/xim" } 17 | tile = { path = "../tile" } 18 | -------------------------------------------------------------------------------- /src/tools/isel/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::Path; 3 | 4 | fn build_pattern(prim: &str) { 5 | use pat::parser::Parser; 6 | let out_dir = env::var("OUT_DIR").unwrap(); 7 | let pat_path = format!("../../../examples/pat/{}.pat", prim); 8 | let bin_name = format!("{}_pat.bin", prim); 9 | let pat = Parser::parse_from_file(pat_path).unwrap(); 10 | let bin_path = Path::new(&out_dir).join(bin_name); 11 | pat.serialize_to_file(bin_path); 12 | } 13 | 14 | fn build_implementation(prim: &str) { 15 | use xim::parser::Parser; 16 | let out_dir = env::var("OUT_DIR").unwrap(); 17 | let imp_path = format!("../../../examples/xim/{}.xim", prim); 18 | let bin_name = format!("{}_xim.bin", prim); 19 | let imp = Parser::parse_from_file(imp_path).unwrap(); 20 | let bin_path = Path::new(&out_dir).join(bin_name); 21 | imp.serialize_to_file(bin_path); 22 | } 23 | 24 | fn build(prim: &str) { 25 | println!("cargo:rerun-if-changed=../../../examples/pat/{}.pat", prim); 26 | println!("cargo:rerun-if-changed=../../../examples/xim/{}.xim", prim); 27 | build_pattern(prim); 28 | build_implementation(prim); 29 | } 30 | 31 | fn main() { 32 | let prim = ["lut", "dsp", "mem"]; 33 | for p in &prim { 34 | build(p); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/tools/isel/src/errors.rs: -------------------------------------------------------------------------------- 1 | use asm::errors::Error as AsmError; 2 | use ir::errors::Error as IrError; 3 | use std::fmt; 4 | 5 | #[derive(Debug)] 6 | pub enum Error { 7 | Ir(IrError), 8 | Asm(AsmError), 9 | ISel(String), 10 | } 11 | 12 | impl Error { 13 | pub fn new_isel_error(msg: &str) -> Self { 14 | Error::ISel(msg.to_string()) 15 | } 16 | } 17 | 18 | impl From for Error { 19 | fn from(e: IrError) -> Self { 20 | Error::Ir(e) 21 | } 22 | } 23 | 24 | impl From for Error { 25 | fn from(e: AsmError) -> Self { 26 | Error::Asm(e) 27 | } 28 | } 29 | 30 | impl fmt::Display for Error { 31 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 32 | match self { 33 | Error::Ir(msg) => write!(f, "{}", msg), 34 | Error::Asm(msg) => write!(f, "{}", msg), 35 | Error::ISel(msg) => write!(f, "{}", msg), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/tools/isel/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod errors; 2 | pub mod tree; 3 | 4 | use crate::errors::Error; 5 | use crate::tree::helpers::{ 6 | tree_codegen, tree_commit, tree_select, treelist_try_from_prog, treemap_try_from_target_pair, 7 | }; 8 | use crate::tree::TreeMap; 9 | use asm::ast as asm; 10 | use ir::ast as ir; 11 | use pat::ast as pat; 12 | use std::collections::{HashMap, HashSet}; 13 | use std::path::Path; 14 | use xim::ast as xim; 15 | 16 | pub fn deserialize_pat_from_file(prim: &str) -> pat::Target { 17 | let filename = format!("{}_pat.bin", prim); 18 | let path = Path::new(env!("OUT_DIR")).join(filename); 19 | pat::Target::deserialize_from_file(path) 20 | } 21 | 22 | pub fn deserialize_imp_from_file(prim: &str) -> xim::Target { 23 | let filename = format!("{}_xim.bin", prim); 24 | let path = Path::new(env!("OUT_DIR")).join(filename); 25 | xim::Target::deserialize_from_file(path) 26 | } 27 | 28 | pub fn instrmap_from_prog(prog: &ir::Prog) -> Result { 29 | if let Some(main) = prog.get("main") { 30 | Ok(ir::InstrMap::from(main.clone())) 31 | } else { 32 | Err(Error::new_isel_error("main is not vailable")) 33 | } 34 | } 35 | 36 | // TODO: impl try_from after refactoring done 37 | pub fn try_from_ir_prog(prog: &ir::Prog) -> Result { 38 | if let Some(main) = prog.get("main") { 39 | let lpat = deserialize_pat_from_file("lut"); 40 | let dpat = deserialize_pat_from_file("dsp"); 41 | let mpat = deserialize_pat_from_file("mem"); 42 | let limp = deserialize_imp_from_file("lut"); 43 | let dimp = deserialize_imp_from_file("dsp"); 44 | let mimp = deserialize_imp_from_file("mem"); 45 | let lmap = treemap_try_from_target_pair(&lpat, &limp)?; 46 | let dmap = treemap_try_from_target_pair(&dpat, &dimp)?; 47 | let mmap = treemap_try_from_target_pair(&mpat, &mimp)?; 48 | let imap = instrmap_from_prog(prog)?; 49 | let blks = treelist_try_from_prog(prog)?; 50 | let blks = tree_select(&blks, &dmap)?; 51 | let blks = tree_select(&blks, &lmap)?; 52 | let blks = tree_select(&blks, &mmap)?; 53 | let blks = tree_commit(&blks)?; 54 | let mut body: Vec = Vec::new(); 55 | let mut iset: HashSet = HashSet::new(); 56 | let tree_map: TreeMap = lmap.into_iter().chain(dmap).chain(mmap).collect(); 57 | let pat_map: HashMap = lpat 58 | .pat() 59 | .clone() 60 | .into_iter() 61 | .chain(dpat.pat().clone()) 62 | .chain(mpat.pat().clone()) 63 | .collect(); 64 | for blk in blks { 65 | body.extend(tree_codegen(&mut iset, &imap, &blk, &tree_map, &pat_map)?); 66 | } 67 | let mut res = asm::Prog::default(); 68 | res.set_sig(main.sig().clone()); 69 | res.set_body(body); 70 | // tile operations that can be arranged in multiple slices 71 | Ok(tile::tile_from_prog(&res)) 72 | } else { 73 | Err(Error::new_isel_error("main is not present")) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/tools/isel/src/tree/default.rs: -------------------------------------------------------------------------------- 1 | use crate::tree::*; 2 | use std::collections::HashMap; 3 | 4 | impl Default for Tree { 5 | fn default() -> Self { 6 | Tree { 7 | index: 0, 8 | node: HashMap::new(), 9 | edge: HashMap::new(), 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tools/isel/src/tree/display.rs: -------------------------------------------------------------------------------- 1 | use crate::tree::*; 2 | use std::fmt; 3 | 4 | impl fmt::Display for NodeOp { 5 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 6 | match self { 7 | NodeOp::Wire(wire) => write!(f, "{}", wire), 8 | NodeOp::Prim(comp) => write!(f, "{}", comp), 9 | NodeOp::Inp => write!(f, "inp"), 10 | } 11 | } 12 | } 13 | 14 | impl fmt::Display for Node { 15 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 16 | write!( 17 | f, 18 | "{}-{}-{}-{}", 19 | self.ty(), 20 | self.op(), 21 | self.attr(), 22 | self.prim() 23 | ) 24 | } 25 | } 26 | 27 | impl fmt::Display for Tree { 28 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 29 | let mut digraph = String::from("digraph {\n"); 30 | // declare nodes 31 | for i in 0..self.index { 32 | if let Some(node) = self.node.get(&i) { 33 | let label = format!("{} [ label = \"{}\" ]\n", i, node); 34 | digraph.push_str(&label); 35 | } 36 | } 37 | // declare edges 38 | for i in 0..self.index { 39 | if let Some(edges) = self.edge.get(&i) { 40 | for e in edges { 41 | let edge = format!("{} -> {} [ ]\n", i, e); 42 | digraph.push_str(&edge); 43 | } 44 | } 45 | } 46 | digraph.push('}'); 47 | write!(f, "{}", digraph) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/tools/isel/src/tree/from.rs: -------------------------------------------------------------------------------- 1 | use crate::tree::*; 2 | 3 | impl From for NodeOp { 4 | fn from(input: OpWire) -> Self { 5 | NodeOp::Wire(input) 6 | } 7 | } 8 | 9 | impl From for NodeOp { 10 | fn from(input: OpPrim) -> Self { 11 | NodeOp::Prim(input) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/tools/isel/src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod default; 2 | pub mod display; 3 | pub mod from; 4 | pub mod helpers; 5 | pub mod try_from; 6 | 7 | use ir::ast as ir; 8 | use std::collections::HashMap; 9 | 10 | pub type Id = ir::Id; 11 | pub type Ty = ir::Ty; 12 | pub type Prim = ir::Prim; 13 | pub type ExprTerm = ir::ExprTerm; 14 | pub type Expr = ir::Expr; 15 | pub type OpWire = ir::OpWire; 16 | pub type OpPrim = ir::OpPrim; 17 | pub type Def = ir::Def; 18 | pub type InstrWire = ir::InstrWire; 19 | pub type InstrPrim = ir::InstrPrim; 20 | pub type Instr = ir::Instr; 21 | pub type InstrMap = ir::InstrMap; 22 | pub type TermMap = ir::TermMap; 23 | pub type Prog = ir::Prog; 24 | pub type TreeMap = HashMap; 25 | 26 | #[derive(Clone, Debug, Eq, PartialEq)] 27 | pub enum NodeOp { 28 | Wire(OpWire), 29 | Prim(OpPrim), 30 | Inp, 31 | } 32 | 33 | #[derive(Clone, Debug, Eq, PartialEq)] 34 | pub struct Node { 35 | pub index: u64, 36 | pub id: Id, 37 | pub ty: Ty, 38 | pub op: NodeOp, 39 | pub attr: Expr, 40 | pub prim: Prim, 41 | pub cost: u64, 42 | pub staged: bool, 43 | pub committed: bool, 44 | pub pat: Option, 45 | pub pat_prim: Prim, 46 | } 47 | 48 | #[derive(Clone, Debug, Eq, PartialEq)] 49 | pub struct Tree { 50 | pub index: u64, 51 | pub node: HashMap, 52 | pub edge: HashMap>, 53 | } 54 | -------------------------------------------------------------------------------- /src/tools/isel/src/tree/try_from.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::tree::*; 3 | use std::convert::TryFrom; 4 | 5 | impl TryFrom for Node { 6 | type Error = Error; 7 | fn try_from(input: InstrWire) -> Result { 8 | let id = input.dst().get_id(0)?; 9 | let ty = input.dst().get_ty(0)?; 10 | let op = NodeOp::from(input.op().clone()); 11 | let attr = input.attr().clone(); 12 | Ok(Node { 13 | index: 0, 14 | id, 15 | ty: ty.clone(), 16 | op, 17 | attr, 18 | prim: Prim::Any, 19 | cost: 0, 20 | staged: false, 21 | committed: false, 22 | pat: None, 23 | pat_prim: Prim::Any, 24 | }) 25 | } 26 | } 27 | 28 | impl TryFrom for Node { 29 | type Error = Error; 30 | fn try_from(input: InstrPrim) -> Result { 31 | let id = input.dst().get_id(0)?; 32 | let ty = input.dst().get_ty(0)?; 33 | let op = NodeOp::from(input.op().clone()); 34 | let attr = input.attr().clone(); 35 | let prim = input.prim().clone(); 36 | Ok(Node { 37 | index: 0, 38 | id, 39 | ty: ty.clone(), 40 | op, 41 | attr, 42 | prim, 43 | cost: u64::MAX, 44 | staged: false, 45 | committed: false, 46 | pat: None, 47 | pat_prim: Prim::Any, 48 | }) 49 | } 50 | } 51 | 52 | impl TryFrom for Node { 53 | type Error = Error; 54 | fn try_from(input: Instr) -> Result { 55 | match input { 56 | Instr::Wire(instr) => Ok(Node::try_from(instr)?), 57 | Instr::Prim(instr) => Ok(Node::try_from(instr)?), 58 | _ => Err(Error::new_isel_error( 59 | "call node conversion is not supported", 60 | )), 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/tools/isel/tests/select.rs: -------------------------------------------------------------------------------- 1 | use asm::parser::Parser as AsmParser; 2 | use ir::parser::Parser as IrParser; 3 | use isel::errors::Error; 4 | use isel::try_from_ir_prog; 5 | use std::path::Path; 6 | 7 | fn test(name: &str) -> Result<(), Error> { 8 | let mut input = Path::new("../../../examples/ir").join(name); 9 | let mut output = Path::new("../../../examples/asm").join(name); 10 | input.set_extension("ir"); 11 | output.set_extension("asm"); 12 | let parsed = IrParser::parse_from_file(input)?; 13 | let exp = AsmParser::parse_from_file(output)?; 14 | let res = try_from_ir_prog(&parsed)?; 15 | assert_eq!(res, exp); 16 | Ok(()) 17 | } 18 | 19 | #[test] 20 | fn add() -> Result<(), Error> { 21 | test("add") 22 | } 23 | 24 | #[test] 25 | fn fsm_3() -> Result<(), Error> { 26 | test("fsm_3") 27 | } 28 | 29 | #[test] 30 | fn fsm_5() -> Result<(), Error> { 31 | test("fsm_5") 32 | } 33 | 34 | #[test] 35 | fn fsm_7() -> Result<(), Error> { 36 | test("fsm_7") 37 | } 38 | 39 | #[test] 40 | fn fsm_9() -> Result<(), Error> { 41 | test("fsm_9") 42 | } 43 | 44 | #[test] 45 | fn tadd() -> Result<(), Error> { 46 | test("tadd") 47 | } 48 | 49 | #[test] 50 | fn tadd_64() -> Result<(), Error> { 51 | test("tadd_64") 52 | } 53 | 54 | #[test] 55 | fn tadd_128() -> Result<(), Error> { 56 | test("tadd_128") 57 | } 58 | 59 | #[test] 60 | fn tadd_256() -> Result<(), Error> { 61 | test("tadd_256") 62 | } 63 | 64 | #[test] 65 | fn tadd_512() -> Result<(), Error> { 66 | test("tadd_512") 67 | } 68 | 69 | #[test] 70 | fn tdot() -> Result<(), Error> { 71 | test("tdot") 72 | } 73 | 74 | #[test] 75 | fn tdot_5_3() -> Result<(), Error> { 76 | test("tdot_5_3") 77 | } 78 | 79 | #[test] 80 | fn tdot_5_9() -> Result<(), Error> { 81 | test("tdot_5_9") 82 | } 83 | 84 | #[test] 85 | fn tdot_5_18() -> Result<(), Error> { 86 | test("tdot_5_18") 87 | } 88 | 89 | #[test] 90 | fn tdot_5_36() -> Result<(), Error> { 91 | test("tdot_5_36") 92 | } 93 | 94 | #[test] 95 | fn mux128() -> Result<(), Error> { 96 | test("mux128") 97 | } 98 | -------------------------------------------------------------------------------- /src/tools/mmap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mmap" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | serde = { version = "1.0", features = ["derive", "rc"] } 10 | serde_json = "1.0" 11 | io = { path = "../io" } 12 | derive_more = { version = "0.99.0", features = ["deref", "deref_mut"] } 13 | -------------------------------------------------------------------------------- /src/tools/mmap/src/lib.rs: -------------------------------------------------------------------------------- 1 | use derive_more::{Deref, DerefMut}; 2 | use io::read_to_string; 3 | use serde::{Deserialize, Serialize}; 4 | use std::collections::HashMap; 5 | use std::path::Path; 6 | 7 | #[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] 8 | pub struct Mem { 9 | offset: u32, 10 | values: Vec, 11 | } 12 | 13 | #[derive(Clone, Debug, Default, PartialEq, Eq, Deref, DerefMut, Serialize, Deserialize)] 14 | pub struct Mmap(HashMap); 15 | 16 | impl Mem { 17 | #[must_use] 18 | pub fn new(offset: u32) -> Self { 19 | Mem { 20 | offset, 21 | values: Vec::new(), 22 | } 23 | } 24 | #[must_use] 25 | pub fn offset(&self) -> u32 { 26 | self.offset 27 | } 28 | #[must_use] 29 | pub fn values(&self) -> &Vec { 30 | &self.values 31 | } 32 | pub fn add_value(&mut self, value: u8) { 33 | self.values.push(value); 34 | } 35 | } 36 | 37 | impl Mmap { 38 | #[must_use] 39 | pub fn new() -> Self { 40 | Mmap::default() 41 | } 42 | #[must_use] 43 | pub fn from_file>(path: P) -> Mmap { 44 | let content = read_to_string(path); 45 | serde_json::from_str(&content).unwrap() 46 | } 47 | } 48 | 49 | pub fn mmap_from_file>(path: P) -> Mmap { 50 | let content = read_to_string(path); 51 | serde_json::from_str(&content).unwrap() 52 | } 53 | -------------------------------------------------------------------------------- /src/tools/mmap/tests/mmap.rs: -------------------------------------------------------------------------------- 1 | use mmap::{Mem, Mmap}; 2 | use serde_json::{json, Result}; 3 | 4 | #[test] 5 | fn test_one_empty_memory() -> Result<()> { 6 | let mut res = Mmap::new(); 7 | res.insert("m0".into(), Mem::default()); 8 | let mem = json!({"m0":{"offset": 0, "values": []}}); 9 | let exp: Mmap = serde_json::from_value(mem)?; 10 | assert_eq!(res, exp); 11 | Ok(()) 12 | } 13 | 14 | #[test] 15 | fn test_one_memory() -> Result<()> { 16 | let mut res = Mmap::new(); 17 | let mut m_0 = Mem::default(); 18 | m_0.add_value(1); 19 | m_0.add_value(9); 20 | m_0.add_value(10); 21 | res.insert("m0".into(), m_0); 22 | let mem = json!({"m0":{"offset": 0, "values": [1, 9, 10]}}); 23 | let exp: Mmap = serde_json::from_value(mem)?; 24 | assert_eq!(res, exp); 25 | Ok(()) 26 | } 27 | 28 | #[test] 29 | fn test_two_memory() -> Result<()> { 30 | let mut res = Mmap::new(); 31 | let mut m_0 = Mem::default(); 32 | let mut m_1 = Mem::default(); 33 | m_0.add_value(1); 34 | m_0.add_value(9); 35 | m_0.add_value(10); 36 | m_1.add_value(3); 37 | res.insert("m0".into(), m_0); 38 | res.insert("m1".into(), m_1); 39 | let mem = json!({"m0":{"offset": 0, "values": [1, 9, 10]}, "m1":{"offset": 0, "values": [3]}}); 40 | let exp: Mmap = serde_json::from_value(mem)?; 41 | assert_eq!(res, exp); 42 | Ok(()) 43 | } 44 | -------------------------------------------------------------------------------- /src/tools/optimizer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "optimizer" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | itertools = "0.9.0" 10 | structopt = { version = "0.3", default-features = false } 11 | asm = { path = "../../langs/asm" } 12 | ir = { path = "../../langs/ir" } 13 | io = { path = "../io" } 14 | -------------------------------------------------------------------------------- /src/tools/optimizer/src/driver.rs: -------------------------------------------------------------------------------- 1 | use crate::cascader::cascader; 2 | use crate::errors::Error; 3 | use crate::opt::{Opt, Optimization}; 4 | use asm::parser::Parser as AsmParser; 5 | use io::write_to_file; 6 | use std::path::PathBuf; 7 | use structopt::StructOpt; 8 | 9 | #[derive(Clone, Debug)] 10 | pub struct Driver { 11 | pub opts: Opt, 12 | } 13 | 14 | impl Default for Driver { 15 | fn default() -> Self { 16 | Driver { 17 | opts: Opt::from_args(), 18 | } 19 | } 20 | } 21 | 22 | fn write_output(path: Option<&PathBuf>, contents: &str) { 23 | if let Some(output) = path { 24 | write_to_file(output, contents); 25 | } else { 26 | println!("{}", contents); 27 | } 28 | } 29 | 30 | impl Driver { 31 | pub fn new(opts: Opt) -> Driver { 32 | Driver { opts } 33 | } 34 | pub fn opts(&self) -> &Opt { 35 | &self.opts 36 | } 37 | pub fn run(&self) -> Result<(), Error> { 38 | let input = self.opts().input(); 39 | let output = self.opts().output(); 40 | match self.opts().optimization() { 41 | Optimization::Cascade => { 42 | let prog = AsmParser::parse_from_file(input)?; 43 | let opt = cascader(&prog)?; 44 | write_output(output, &opt.to_string()); 45 | Ok(()) 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/tools/optimizer/src/errors.rs: -------------------------------------------------------------------------------- 1 | use asm::errors::Error as AsmError; 2 | use ir::errors::Error as IrError; 3 | use std::fmt; 4 | 5 | #[derive(Debug)] 6 | pub enum Error { 7 | Ir(IrError), 8 | Asm(AsmError), 9 | Driver(String), 10 | Opt(String), 11 | } 12 | 13 | impl Error { 14 | pub fn new_opt_error(msg: &str) -> Self { 15 | Error::Opt(msg.to_string()) 16 | } 17 | pub fn new_driver_error(msg: &str) -> Self { 18 | Error::Driver(msg.to_string()) 19 | } 20 | } 21 | 22 | impl From for Error { 23 | fn from(e: AsmError) -> Self { 24 | Error::Asm(e) 25 | } 26 | } 27 | 28 | impl From for Error { 29 | fn from(e: IrError) -> Self { 30 | Error::Ir(e) 31 | } 32 | } 33 | 34 | impl fmt::Display for Error { 35 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 36 | match self { 37 | Error::Ir(msg) => write!(f, "{}", msg), 38 | Error::Asm(msg) => write!(f, "{}", msg), 39 | Error::Driver(msg) => write!(f, "{}", msg), 40 | Error::Opt(msg) => write!(f, "{}", msg), 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/tools/optimizer/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cascader; 2 | pub mod driver; 3 | pub mod errors; 4 | pub mod opt; 5 | -------------------------------------------------------------------------------- /src/tools/optimizer/src/opt.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use std::fmt; 3 | use std::path::{Path, PathBuf}; 4 | use std::str::FromStr; 5 | use structopt::StructOpt; 6 | 7 | #[derive(Clone, Debug, StructOpt)] 8 | #[structopt( 9 | name = env!("CARGO_PKG_NAME"), 10 | version = env!("CARGO_PKG_VERSION"), 11 | author = env!("CARGO_PKG_AUTHORS") 12 | )] 13 | pub struct Opt { 14 | // Input file 15 | #[structopt(parse(from_os_str))] 16 | pub input: PathBuf, 17 | 18 | // Output file 19 | #[structopt(short = "o", long = "output", parse(from_os_str))] 20 | pub output: Option, 21 | 22 | // Language 23 | #[structopt(long = "lang", default_value = "asm")] 24 | pub lang: Lang, 25 | 26 | // Optimization 27 | #[structopt(long = "opt", default_value = "cascade")] 28 | pub optimization: Optimization, 29 | } 30 | 31 | impl Opt { 32 | pub fn input(&self) -> &Path { 33 | &self.input 34 | } 35 | pub fn output(&self) -> Option<&PathBuf> { 36 | self.output.as_ref() 37 | } 38 | pub fn lang(&self) -> &Lang { 39 | &self.lang 40 | } 41 | pub fn optimization(&self) -> &Optimization { 42 | &self.optimization 43 | } 44 | } 45 | 46 | #[derive(Clone, Debug)] 47 | pub enum Lang { 48 | Asm, 49 | } 50 | 51 | #[derive(Clone, Debug)] 52 | pub enum Optimization { 53 | Cascade, 54 | } 55 | 56 | impl fmt::Display for Lang { 57 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 58 | let lang = match self { 59 | Lang::Asm => "asm", 60 | }; 61 | write!(f, "{}", lang) 62 | } 63 | } 64 | 65 | impl FromStr for Lang { 66 | type Err = Error; 67 | fn from_str(input: &str) -> Result { 68 | match input { 69 | "asm" => Ok(Lang::Asm), 70 | _ => Err(Error::new_opt_error("Unsupported language")), 71 | } 72 | } 73 | } 74 | 75 | impl fmt::Display for Optimization { 76 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 77 | let opt = match self { 78 | Optimization::Cascade => "cascade", 79 | }; 80 | write!(f, "{}", opt) 81 | } 82 | } 83 | 84 | impl FromStr for Optimization { 85 | type Err = Error; 86 | fn from_str(input: &str) -> Result { 87 | match input { 88 | "cascade" => Ok(Optimization::Cascade), 89 | _ => Err(Error::new_opt_error("Unsupported language")), 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/tools/optimizer/tests/cascade.rs: -------------------------------------------------------------------------------- 1 | use asm::parser::Parser as AsmParser; 2 | use optimizer::cascader::cascader; 3 | 4 | #[test] 5 | fn tdot() { 6 | let prog = AsmParser::parse_from_file("../../../examples/asm/tdot_5_3.asm").unwrap(); 7 | let exp = AsmParser::parse_from_file("../../../examples/asm/tdot_5_3_opt.asm").unwrap(); 8 | let res = cascader(&prog).unwrap(); 9 | assert_eq!(res, exp); 10 | } 11 | -------------------------------------------------------------------------------- /src/tools/prettyprint/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "prettyprint" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | pretty = "0.10.0" 10 | -------------------------------------------------------------------------------- /src/tools/prettyprint/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use pretty::RcDoc; 2 | 3 | pub const PRETTY_WIDTH: usize = 100; 4 | pub const PRETTY_INDENT: isize = 4; 5 | 6 | pub trait PrettyPrint { 7 | fn to_doc(&self) -> RcDoc<()>; 8 | 9 | fn to_pretty_with_width(&self, width: usize) -> String { 10 | let mut w = Vec::new(); 11 | self.to_doc().render(width, &mut w).unwrap(); 12 | String::from_utf8(w).unwrap() 13 | } 14 | 15 | fn to_pretty(&self) -> String { 16 | self.to_pretty_with_width(PRETTY_WIDTH) 17 | } 18 | } 19 | 20 | pub trait PrettyHelper<'a>: Sized { 21 | fn surround(self, pre: &'a str, post: &'a str) -> Self; 22 | fn parens(self) -> Self { 23 | self.surround("(", ")") 24 | } 25 | fn brackets(self) -> Self { 26 | self.surround("[", "]") 27 | } 28 | fn braces(self) -> Self { 29 | self.surround("{", "}") 30 | } 31 | fn comps(self) -> Self { 32 | self.surround("<", ">") 33 | } 34 | fn quotes(self) -> Self { 35 | self.surround("\"", "\"") 36 | } 37 | } 38 | 39 | impl<'a, A> PrettyHelper<'a> for RcDoc<'a, A> { 40 | fn surround(self, l: &'a str, r: &'a str) -> Self { 41 | RcDoc::text(l).append(self).append(RcDoc::text(r)) 42 | } 43 | } 44 | 45 | pub fn intersperse<'a>(iter: impl Iterator>, separator: RcDoc<'a>) -> RcDoc<'a> { 46 | RcDoc::intersperse(iter, separator) 47 | } 48 | 49 | #[must_use] 50 | pub fn block(body: RcDoc<()>) -> RcDoc<()> { 51 | RcDoc::nil() 52 | .append(RcDoc::hardline()) 53 | .append(body) 54 | .nest(PRETTY_INDENT) 55 | .append(RcDoc::hardline()) 56 | } 57 | 58 | #[must_use] 59 | pub fn block_with_braces<'a>(name: RcDoc<'a>, body: RcDoc<'a>) -> RcDoc<'a> { 60 | name.append(RcDoc::space()).append(block(body).braces()) 61 | } 62 | 63 | #[must_use] 64 | pub fn block_with_parens<'a>(name: RcDoc<'a>, body: RcDoc<'a>) -> RcDoc<'a> { 65 | name.append(RcDoc::space()).append(block(body).parens()) 66 | } 67 | -------------------------------------------------------------------------------- /src/tools/prim/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "prim" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | anyhow = "1.0" 10 | thiserror = "1.0" 11 | derive_more = { version = "0.99.0", features = ["from", "deref", "deref_mut", "display"] } 12 | itertools = "0.10.0" 13 | -------------------------------------------------------------------------------- /src/tools/prim/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod prim; 2 | pub mod ultrascale; 3 | 4 | pub use crate::prim::{Error, Param, ParamSet, Port, PortSet, Prim, ToPrim}; 5 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/borrow.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{Param, Port}; 2 | use std::borrow::Borrow; 3 | 4 | impl Borrow for Port { 5 | fn borrow(&self) -> &String { 6 | &self.name 7 | } 8 | } 9 | 10 | impl Borrow for Port { 11 | fn borrow(&self) -> &str { 12 | &self.name.as_str() 13 | } 14 | } 15 | 16 | impl Borrow for Param { 17 | fn borrow(&self) -> &String { 18 | &self.name 19 | } 20 | } 21 | 22 | impl Borrow for Param { 23 | fn borrow(&self) -> &str { 24 | &self.name.as_str() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/eq.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::ParamSet; 2 | use std::hash::Hash; 3 | 4 | impl Eq for ParamSet where T: Eq + Hash {} 5 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/from.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{Param, Port, PortSet}; 2 | 3 | impl From<&(&str, u32)> for Port { 4 | fn from(input: &(&str, u32)) -> Self { 5 | Port { 6 | name: input.0.into(), 7 | width: input.1, 8 | } 9 | } 10 | } 11 | 12 | impl From<(&str, u32)> for Port { 13 | fn from(input: (&str, u32)) -> Self { 14 | Port { 15 | name: input.0.into(), 16 | width: input.1, 17 | } 18 | } 19 | } 20 | 21 | impl From<&[(&str, u32)]> for PortSet { 22 | fn from(input: &[(&str, u32)]) -> Self { 23 | let mut set = PortSet::new(); 24 | for t in input { 25 | set.insert(t.into()); 26 | } 27 | set 28 | } 29 | } 30 | 31 | impl From<&(&str, T)> for Param { 32 | fn from(input: &(&str, T)) -> Self { 33 | Param { 34 | name: input.0.into(), 35 | value: input.1.clone(), 36 | } 37 | } 38 | } 39 | 40 | impl From<(&str, T)> for Param { 41 | fn from(input: (&str, T)) -> Self { 42 | Param { 43 | name: input.0.into(), 44 | value: input.1, 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/hash.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{Param, Port}; 2 | use std::hash::{Hash, Hasher}; 3 | 4 | impl Hash for Param { 5 | fn hash(&self, state: &mut H) { 6 | self.name.hash(state); 7 | } 8 | } 9 | 10 | impl Hash for Port { 11 | fn hash(&self, state: &mut H) { 12 | self.name.hash(state); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{Error, Param, ParamSet, Port, PortSet, Prim}; 2 | use anyhow::Result; 3 | use std::collections::HashSet; 4 | use std::fmt; 5 | 6 | impl Port { 7 | #[must_use] 8 | pub fn new(name: &str, width: u32) -> Self { 9 | Port { 10 | name: name.into(), 11 | width, 12 | } 13 | } 14 | #[must_use] 15 | pub fn name(&self) -> String { 16 | self.name.to_string() 17 | } 18 | #[must_use] 19 | pub fn width(&self) -> u32 { 20 | self.width 21 | } 22 | pub fn set_name(&mut self, name: &str) { 23 | self.name = name.into(); 24 | } 25 | pub fn set_width(&mut self, width: u32) { 26 | self.width = width; 27 | } 28 | } 29 | 30 | impl Param { 31 | #[must_use] 32 | pub fn new(name: &str, value: T) -> Self { 33 | Param { 34 | name: name.into(), 35 | value, 36 | } 37 | } 38 | #[must_use] 39 | pub fn name(&self) -> String { 40 | self.name.to_string() 41 | } 42 | #[must_use] 43 | pub fn value(&self) -> &T { 44 | &self.value 45 | } 46 | pub fn set_name(&mut self, name: &str) { 47 | self.name = name.into(); 48 | } 49 | pub fn set_value(&mut self, value: T) { 50 | self.value = value; 51 | } 52 | } 53 | 54 | impl ParamSet { 55 | #[must_use] 56 | pub fn new() -> Self { 57 | ParamSet(HashSet::new()) 58 | } 59 | } 60 | 61 | impl PortSet { 62 | #[must_use] 63 | pub fn new() -> Self { 64 | PortSet(HashSet::new()) 65 | } 66 | } 67 | 68 | impl Prim { 69 | #[must_use] 70 | pub fn name(&self) -> String { 71 | self.name.to_string() 72 | } 73 | #[must_use] 74 | pub fn param(&self) -> &ParamSet { 75 | &self.param 76 | } 77 | #[must_use] 78 | pub fn input(&self) -> &PortSet { 79 | &self.input 80 | } 81 | #[must_use] 82 | pub fn output(&self) -> &PortSet { 83 | &self.output 84 | } 85 | /// # Errors 86 | /// 87 | /// Will return `Err` if value U is invalid or missing 88 | #[allow(clippy::option_if_let_else)] 89 | pub fn set_param(&mut self, name: &str, value: U) -> Result<()> 90 | where 91 | U: Into, 92 | { 93 | if let Some(old) = self.param.get(name) { 94 | let value: T = value.into(); 95 | if old.value() == &value { 96 | let param = Param { 97 | name: old.name(), 98 | value, 99 | }; 100 | self.param.replace(param); 101 | Ok(()) 102 | } else { 103 | Err(Error::InvalidParamValue(value.to_string()).into()) 104 | } 105 | } else { 106 | Err(Error::MissingParam(name.into()).into()) 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod borrow; 2 | pub mod eq; 3 | pub mod from; 4 | pub mod hash; 5 | pub mod helpers; 6 | pub mod partial_eq; 7 | mod to_prim; 8 | 9 | pub use crate::prim::to_prim::ToPrim; 10 | 11 | use derive_more::{Deref, DerefMut}; 12 | use std::collections::HashSet; 13 | use thiserror::Error; 14 | 15 | #[derive(Clone, Debug, Default, Eq)] 16 | pub struct Port { 17 | pub name: String, 18 | pub width: u32, 19 | } 20 | 21 | #[derive(Clone, Debug, Default, Eq)] 22 | pub struct Param { 23 | pub name: String, 24 | pub value: T, 25 | } 26 | 27 | #[derive(Clone, Debug, Default, Deref, DerefMut)] 28 | pub struct ParamSet(HashSet>); 29 | 30 | #[derive(Clone, Debug, Default, PartialEq, Deref, DerefMut)] 31 | pub struct PortSet(HashSet); 32 | 33 | // T ~> Param value type, every primitive is free to define T 34 | #[derive(Clone, Debug)] 35 | pub struct Prim { 36 | pub name: String, 37 | pub param: ParamSet, 38 | pub input: PortSet, 39 | pub output: PortSet, 40 | } 41 | 42 | #[derive(Error, Debug)] 43 | pub enum Error { 44 | #[error("Invalid parameter value: {0}")] 45 | InvalidParamValue(String), 46 | #[error("Missing parameter: {0}")] 47 | MissingParam(String), 48 | } 49 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/partial_eq.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{Param, ParamSet, Port}; 2 | use std::hash::Hash; 3 | 4 | impl PartialEq for Port { 5 | fn eq(&self, other: &Port) -> bool { 6 | self.name == other.name 7 | } 8 | } 9 | 10 | impl PartialEq for Param { 11 | fn eq(&self, other: &Param) -> bool { 12 | self.name == other.name 13 | } 14 | } 15 | 16 | impl PartialEq for ParamSet 17 | where 18 | T: Eq + Hash, 19 | { 20 | fn eq(&self, other: &ParamSet) -> bool { 21 | self.0 == other.0 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/tools/prim/src/prim/to_prim.rs: -------------------------------------------------------------------------------- 1 | use crate::prim::{ParamSet, PortSet, Prim}; 2 | 3 | pub trait ToPrim { 4 | fn to_name(&self) -> String; 5 | fn to_param(&self) -> ParamSet { 6 | ParamSet::new() 7 | } 8 | fn to_input(&self) -> PortSet { 9 | PortSet::new() 10 | } 11 | fn to_output(&self) -> PortSet { 12 | PortSet::new() 13 | } 14 | fn to_prim(&self) -> Prim { 15 | Prim { 16 | name: self.to_name(), 17 | param: self.to_param(), 18 | input: self.to_input(), 19 | output: self.to_output(), 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/carry.rs: -------------------------------------------------------------------------------- 1 | use crate::{Param, ParamSet, Port, PortSet, Prim, ToPrim}; 2 | use derive_more::{Deref, DerefMut, Display, From}; 3 | 4 | #[derive(Clone, Debug, PartialEq, Eq, Display)] 5 | pub enum Ty { 6 | #[display(fmt = "DUAL_CY4")] 7 | Dual, 8 | #[display(fmt = "SINGLE_CY8")] 9 | Single, 10 | } 11 | 12 | #[derive(Clone, Debug, From, Eq, Display)] 13 | pub enum ParamValue { 14 | Ty(Ty), 15 | } 16 | 17 | #[derive(Clone, Debug, Deref, DerefMut)] 18 | pub struct Carry(Prim); 19 | 20 | #[derive(Clone, Debug, Default)] 21 | struct CarryPrim; 22 | 23 | impl PartialEq for ParamValue { 24 | fn eq(&self, _: &Self) -> bool { 25 | true 26 | } 27 | } 28 | 29 | impl ToPrim for CarryPrim { 30 | fn to_name(&self) -> String { 31 | String::from("CARRY8") 32 | } 33 | fn to_param(&self) -> ParamSet { 34 | let mut param = ParamSet::new(); 35 | let ty = Param { 36 | name: "CARRY_TYPE".to_string(), 37 | value: Ty::Single.into(), 38 | }; 39 | param.insert(ty); 40 | param 41 | } 42 | fn to_input(&self) -> PortSet { 43 | let mut port = PortSet::new(); 44 | port.insert(Port::new("DI", 8)); 45 | port.insert(Port::new("S", 8)); 46 | port.insert(Port::new("CI", 1)); 47 | port.insert(Port::new("CI_TOP", 1)); 48 | port 49 | } 50 | fn to_output(&self) -> PortSet { 51 | let mut port = PortSet::new(); 52 | port.insert(Port::new("O", 8)); 53 | port.insert(Port::new("CO", 8)); 54 | port 55 | } 56 | } 57 | 58 | impl Default for Carry { 59 | fn default() -> Carry { 60 | let carry = CarryPrim; 61 | Carry(carry.to_prim()) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/clock.rs: -------------------------------------------------------------------------------- 1 | pub const CLOCK: &str = "clock"; 2 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/dsp.rs: -------------------------------------------------------------------------------- 1 | use crate::{ParamSet, PortSet, ToPrim}; 2 | 3 | #[derive(Clone, Debug, Default, PartialEq)] 4 | pub struct ParamValue; 5 | 6 | #[derive(Clone, Debug, Default)] 7 | pub struct Dsp; 8 | 9 | impl ToPrim for Dsp { 10 | fn to_name(&self) -> String { 11 | String::from("DSP48E2") 12 | } 13 | fn to_param(&self) -> ParamSet { 14 | ParamSet::new() 15 | } 16 | fn to_input(&self) -> PortSet { 17 | PortSet::new() 18 | } 19 | fn to_output(&self) -> PortSet { 20 | PortSet::new() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/gnd.rs: -------------------------------------------------------------------------------- 1 | use crate::{Port, PortSet, Prim, ToPrim}; 2 | use derive_more::{Deref, DerefMut, Display}; 3 | 4 | pub const GND: &str = "gnd"; 5 | 6 | #[derive(Clone, Debug, Default, PartialEq, Eq, Display)] 7 | pub struct ParamValue; 8 | 9 | #[derive(Clone, Debug, Deref, DerefMut)] 10 | pub struct Gnd(Prim); 11 | 12 | #[derive(Clone, Debug, Default)] 13 | struct GndPrim; 14 | 15 | impl ToPrim for GndPrim { 16 | fn to_name(&self) -> String { 17 | String::from("GND") 18 | } 19 | fn to_output(&self) -> PortSet { 20 | let mut port = PortSet::new(); 21 | port.insert(Port::new("G", 1)); 22 | port 23 | } 24 | } 25 | 26 | impl Default for Gnd { 27 | fn default() -> Gnd { 28 | Gnd(GndPrim::default().to_prim()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/lram.rs: -------------------------------------------------------------------------------- 1 | use crate::{Param, ParamSet, Port, PortSet, Prim, ToPrim}; 2 | use derive_more::{Deref, DerefMut, From}; 3 | use std::fmt; 4 | 5 | #[derive(Clone, Debug, From, Eq)] 6 | pub enum ParamValue { 7 | Bool(bool), 8 | Bytes(u32, Vec), 9 | } 10 | 11 | #[derive(Clone, Debug, Deref, DerefMut)] 12 | pub struct Lram(Prim); 13 | 14 | #[derive(Clone, Debug, Default)] 15 | struct LramPrim; 16 | 17 | impl PartialEq for ParamValue { 18 | fn eq(&self, other: &Self) -> bool { 19 | match (self, other) { 20 | (ParamValue::Bool(_), ParamValue::Bool(_)) 21 | | (ParamValue::Bytes(_, _), ParamValue::Bytes(_, _)) 22 | | (_, _) => false, 23 | } 24 | } 25 | } 26 | 27 | impl fmt::Display for ParamValue { 28 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 29 | match self { 30 | ParamValue::Bytes(w, v) => write!(f, "width:{} values:{:?}", w, v), 31 | _ => write!(f, "{}", self), 32 | } 33 | } 34 | } 35 | 36 | const LUT: [&str; 8] = ["A", "B", "C", "D", "E", "F", "G", "H"]; 37 | 38 | impl ToPrim for LramPrim { 39 | fn to_name(&self) -> String { 40 | String::from("RAM64M8") 41 | } 42 | fn to_param(&self) -> ParamSet { 43 | let mut param = ParamSet::new(); 44 | for l in &LUT { 45 | let name = format!("INIT_{}", l); 46 | param.insert(Param { 47 | name, 48 | value: (64, vec![0; 8]).into(), 49 | }); 50 | } 51 | param.insert(Param { 52 | name: "IS_WCLK_INVERTED".into(), 53 | value: false.into(), 54 | }); 55 | param 56 | } 57 | fn to_input(&self) -> PortSet { 58 | let mut port = PortSet::new(); 59 | for l in &LUT { 60 | let din = format!("DI{}", l); 61 | let addr = format!("ADDR{}", l); 62 | port.insert(Port::new(&din, 1)); 63 | port.insert(Port::new(&addr, 6)); 64 | } 65 | port.insert(Port::new("WE", 1)); 66 | port.insert(Port::new("WCLK", 1)); 67 | port 68 | } 69 | fn to_output(&self) -> PortSet { 70 | let mut port = PortSet::new(); 71 | for l in &LUT { 72 | let dout = format!("DO{}", l); 73 | port.insert(Port::new(&dout, 1)); 74 | } 75 | port 76 | } 77 | } 78 | 79 | impl Default for Lram { 80 | fn default() -> Self { 81 | let ram = LramPrim; 82 | Lram(ram.to_prim()) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bram; 2 | pub mod carry; 3 | pub mod clock; 4 | pub mod dsp; 5 | pub mod gnd; 6 | pub mod lram; 7 | pub mod reset; 8 | pub mod uram; 9 | pub mod vcc; 10 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/reset.rs: -------------------------------------------------------------------------------- 1 | pub const RESET: &str = "reset"; 2 | -------------------------------------------------------------------------------- /src/tools/prim/src/ultrascale/vcc.rs: -------------------------------------------------------------------------------- 1 | use crate::{Port, PortSet, Prim, ToPrim}; 2 | use derive_more::{Deref, DerefMut, Display}; 3 | 4 | pub const VCC: &str = "vcc"; 5 | 6 | #[derive(Clone, Debug, Default, PartialEq, Eq, Display)] 7 | pub struct ParamValue; 8 | 9 | #[derive(Clone, Debug, Deref, DerefMut)] 10 | pub struct Vcc(Prim); 11 | 12 | #[derive(Clone, Debug, Default)] 13 | struct VccPrim; 14 | 15 | impl ToPrim for VccPrim { 16 | fn to_name(&self) -> String { 17 | String::from("VCC") 18 | } 19 | fn to_output(&self) -> PortSet { 20 | let mut port = PortSet::new(); 21 | port.insert(Port::new("P", 1)); 22 | port 23 | } 24 | } 25 | 26 | impl Default for Vcc { 27 | fn default() -> Vcc { 28 | Vcc(VccPrim::default().to_prim()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/tools/tile/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tile" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | io = { path = "../io" } 10 | asm = { path = "../../langs/asm" } 11 | regex = "1.3.9" 12 | lazy_static = "1.4.0" 13 | pretty_assertions = "0.7.2" 14 | -------------------------------------------------------------------------------- /src/tools/translate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "translate" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | structopt = { version = "0.3", default-features = false } 10 | ir = { path = "../../langs/ir" } 11 | asm = { path = "../../langs/asm" } 12 | xir = { path = "../../langs/xir" } 13 | isel = { path = "../isel" } 14 | bler = { path = "../bler" } 15 | bline = { path = "../bline" } 16 | xpand = { path = "../xpand" } 17 | io = { path = "../io" } 18 | mmap = { path = "../mmap" } 19 | -------------------------------------------------------------------------------- /src/tools/translate/src/errors.rs: -------------------------------------------------------------------------------- 1 | use asm::errors::Error as AsmError; 2 | use bler::errors::Error as BlerError; 3 | use bline::errors::Error as BlineError; 4 | use ir::errors::Error as IrError; 5 | use isel::errors::Error as ISelError; 6 | use std::fmt; 7 | use xir::errors::Error as XirError; 8 | use xpand::errors::Error as XpandError; 9 | 10 | #[derive(Debug)] 11 | pub enum Error { 12 | Opt(String), 13 | Driver(String), 14 | Ir(IrError), 15 | Asm(AsmError), 16 | Xir(XirError), 17 | ISel(ISelError), 18 | Bler(BlerError), 19 | Bline(BlineError), 20 | Xpand(XpandError), 21 | } 22 | 23 | impl Error { 24 | pub fn new_opt_error(msg: &str) -> Self { 25 | Error::Opt(msg.to_string()) 26 | } 27 | pub fn new_driver_error(msg: &str) -> Self { 28 | Error::Driver(msg.to_string()) 29 | } 30 | } 31 | 32 | impl From for Error { 33 | fn from(e: IrError) -> Self { 34 | Error::Ir(e) 35 | } 36 | } 37 | 38 | impl From for Error { 39 | fn from(e: AsmError) -> Self { 40 | Error::Asm(e) 41 | } 42 | } 43 | 44 | impl From for Error { 45 | fn from(e: XirError) -> Self { 46 | Error::Xir(e) 47 | } 48 | } 49 | 50 | impl From for Error { 51 | fn from(e: ISelError) -> Self { 52 | Error::ISel(e) 53 | } 54 | } 55 | 56 | impl From for Error { 57 | fn from(e: BlerError) -> Self { 58 | Error::Bler(e) 59 | } 60 | } 61 | 62 | impl From for Error { 63 | fn from(e: BlineError) -> Self { 64 | Error::Bline(e) 65 | } 66 | } 67 | 68 | impl From for Error { 69 | fn from(e: XpandError) -> Self { 70 | Error::Xpand(e) 71 | } 72 | } 73 | 74 | impl fmt::Display for Error { 75 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 76 | match self { 77 | Error::Ir(msg) => write!(f, "{}", msg), 78 | Error::Asm(msg) => write!(f, "{}", msg), 79 | Error::Xir(msg) => write!(f, "{}", msg), 80 | Error::ISel(msg) => write!(f, "{}", msg), 81 | Error::Bler(msg) => write!(f, "{}", msg), 82 | Error::Bline(msg) => write!(f, "{}", msg), 83 | Error::Opt(msg) => write!(f, "{}", msg), 84 | Error::Driver(msg) => write!(f, "{}", msg), 85 | Error::Xpand(msg) => write!(f, "{}", msg), 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/tools/translate/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod driver; 2 | pub mod errors; 3 | pub mod opt; 4 | -------------------------------------------------------------------------------- /src/tools/translate/src/opt.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use std::fmt; 3 | use std::path::{Path, PathBuf}; 4 | use std::str::FromStr; 5 | use structopt::StructOpt; 6 | 7 | #[derive(Clone, Debug, StructOpt)] 8 | #[structopt( 9 | name = env!("CARGO_PKG_NAME"), 10 | version = env!("CARGO_PKG_VERSION"), 11 | author = env!("CARGO_PKG_AUTHORS") 12 | )] 13 | pub struct Opt { 14 | // Input file 15 | #[structopt(parse(from_os_str))] 16 | pub input: PathBuf, 17 | 18 | // Mmap file 19 | #[structopt(long = "mmap", parse(from_os_str))] 20 | pub mmap: Option, 21 | 22 | // Output file 23 | #[structopt(short = "o", long = "output", parse(from_os_str))] 24 | pub output: Option, 25 | 26 | // From language 27 | #[structopt(long = "from", default_value = "ir")] 28 | pub from: Lang, 29 | 30 | // To language 31 | #[structopt(long = "to", default_value = "asm")] 32 | pub to: Lang, 33 | } 34 | 35 | impl Opt { 36 | pub fn input(&self) -> &Path { 37 | &self.input 38 | } 39 | pub fn mmap(&self) -> Option<&PathBuf> { 40 | self.mmap.as_ref() 41 | } 42 | pub fn output(&self) -> Option<&PathBuf> { 43 | self.output.as_ref() 44 | } 45 | pub fn from(&self) -> &Lang { 46 | &self.from 47 | } 48 | pub fn to(&self) -> &Lang { 49 | &self.to 50 | } 51 | } 52 | 53 | #[derive(Clone, Debug)] 54 | pub enum Lang { 55 | Ir, 56 | Asm, 57 | Xir, 58 | Behav, 59 | Struct, 60 | } 61 | 62 | impl fmt::Display for Lang { 63 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 64 | let backend = match self { 65 | Lang::Ir => "ir", 66 | Lang::Asm => "asm", 67 | Lang::Xir => "xir", 68 | Lang::Behav => "behav", 69 | Lang::Struct => "struct", 70 | }; 71 | write!(f, "{}", backend) 72 | } 73 | } 74 | 75 | impl FromStr for Lang { 76 | type Err = Error; 77 | fn from_str(input: &str) -> Result { 78 | match input { 79 | "ir" => Ok(Lang::Ir), 80 | "asm" => Ok(Lang::Asm), 81 | "xir" => Ok(Lang::Xir), 82 | "behav" => Ok(Lang::Behav), 83 | "struct" => Ok(Lang::Struct), 84 | _ => Err(Error::new_opt_error("Unsupported language")), 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/tools/xpand/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xpand" 3 | version = "0.1.0" 4 | authors = ["The Reticle developers"] 5 | license = "Apache-2.0" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | itertools = "0.9.0" 10 | ir = { path = "../../langs/ir" } 11 | xir = { path = "../../langs/xir" } 12 | verilog = { path = "../../langs/verilog" } 13 | io = { path = "../io" } 14 | mmap = { path = "../mmap" } 15 | bline = { path = "../bline" } 16 | prim = { path = "../prim" } 17 | derive_more = { version = "0.99.0", features = ["from", "deref", "deref_mut"] } 18 | pretty_assertions = "0.7.2" 19 | -------------------------------------------------------------------------------- /src/tools/xpand/src/carry.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::loc::Loc; 3 | use crate::to_verilog::{ToVerilogExpr, ToVerilogInstance, VerilogExprMap}; 4 | use crate::{inst_name_try_from_instr, vec_expr_try_from_expr}; 5 | use prim::ultrascale::carry::{Carry, ParamValue, Ty}; 6 | use prim::{ParamSet, PortSet}; 7 | use verilog::ast as vl; 8 | use xir::ast as xir; 9 | 10 | impl ToVerilogExpr for Ty { 11 | fn to_expr(&self) -> vl::Expr { 12 | vl::Expr::new_str(&self.to_string()) 13 | } 14 | } 15 | 16 | impl ToVerilogExpr for ParamValue { 17 | fn to_expr(&self) -> vl::Expr { 18 | match self { 19 | ParamValue::Ty(c) => c.to_expr(), 20 | } 21 | } 22 | } 23 | 24 | impl ToVerilogInstance for Carry { 25 | fn to_name(&self) -> String { 26 | String::new() 27 | } 28 | fn to_prim(&self) -> String { 29 | self.name() 30 | } 31 | fn to_param_set(&self) -> &ParamSet { 32 | self.param() 33 | } 34 | fn to_input_set(&self) -> &PortSet { 35 | self.input() 36 | } 37 | fn to_output_set(&self) -> &PortSet { 38 | self.output() 39 | } 40 | } 41 | 42 | #[derive(Clone, Debug)] 43 | struct CarryAdd { 44 | pub prim: Carry, 45 | pub instr: xir::InstrMach, 46 | } 47 | 48 | impl CarryAdd { 49 | pub fn new(instr: xir::InstrMach) -> Self { 50 | CarryAdd { 51 | prim: Carry::default(), 52 | instr, 53 | } 54 | } 55 | } 56 | 57 | impl ToVerilogInstance for CarryAdd { 58 | fn to_name(&self) -> String { 59 | inst_name_try_from_instr(&self.instr).unwrap() 60 | } 61 | fn to_prim(&self) -> String { 62 | self.prim.name() 63 | } 64 | fn to_param_set(&self) -> &ParamSet { 65 | self.prim.param() 66 | } 67 | fn to_input_set(&self) -> &PortSet { 68 | self.prim.input() 69 | } 70 | fn to_output_set(&self) -> &PortSet { 71 | self.prim.output() 72 | } 73 | fn to_loc(&self) -> Option<&Loc> { 74 | self.instr.loc() 75 | } 76 | fn to_input_map(&self) -> VerilogExprMap { 77 | let mut map = VerilogExprMap::new(); 78 | let arg: Vec = vec_expr_try_from_expr(self.instr.arg()).unwrap(); 79 | for p in self.prim.input().iter() { 80 | let name = p.name(); 81 | if name.as_str() == "CI" || name.as_str() == "CI_TOP" { 82 | map.insert(name, vl::Expr::new_ulit_bin(1, "0")); 83 | } else if name.as_str() == "DI" { 84 | map.insert(name, arg[0].clone()); 85 | } else { 86 | map.insert(name, arg[1].clone()); 87 | } 88 | } 89 | map 90 | } 91 | fn to_output_map(&self) -> VerilogExprMap { 92 | let mut map = VerilogExprMap::new(); 93 | let dst: Vec = vec_expr_try_from_expr(self.instr.dst()).unwrap(); 94 | for p in self.prim.output().iter() { 95 | let name = p.name(); 96 | if name.as_str() == "O" { 97 | map.insert(name, dst[0].clone()); 98 | } else { 99 | map.insert(name, vl::Expr::new_ref("")); 100 | } 101 | } 102 | map 103 | } 104 | } 105 | 106 | pub fn carryadd_from_mach(instr: &xir::InstrMach) -> Result, Error> { 107 | let carry = CarryAdd::new(instr.clone()); 108 | Ok(carry.to_block()) 109 | } 110 | -------------------------------------------------------------------------------- /src/tools/xpand/src/cat.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::vec_expr_try_from_expr; 3 | use verilog::ast as vl; 4 | use xir::ast as xir; 5 | 6 | // TODO: add vector type support 7 | pub fn from_basc(instr: &xir::InstrBasc) -> Result, Error> { 8 | let term = instr.dst().get_term(0)?; 9 | if term.is_vector() { 10 | Err(Error::new_xpand_error("vector ext not supported yet")) 11 | } else { 12 | let arg: Vec = vec_expr_try_from_expr(instr.arg())?; 13 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 14 | let mut cat = vl::ExprConcat::default(); 15 | for a in arg { 16 | cat.add_expr(a.clone()); 17 | } 18 | let assign = vl::Parallel::Assign(dst[0].clone(), vl::Expr::from(cat)); 19 | let stmt = vl::Stmt::from(assign); 20 | Ok(vec![stmt]) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tools/xpand/src/decl.rs: -------------------------------------------------------------------------------- 1 | use verilog::ast as vl; 2 | 3 | // TODO: this will be eventually be replaced with 4 | // traits in to_verilog.rs file. Therefore, we can 5 | // bypass clippy checks here. 6 | #[allow(clippy::module_name_repetitions)] 7 | pub trait ToDecl { 8 | fn to_decl(&self) -> vl::Decl; 9 | } 10 | -------------------------------------------------------------------------------- /src/tools/xpand/src/display.rs: -------------------------------------------------------------------------------- 1 | use crate::dsp::Dsp; 2 | use crate::fdre::Fdre; 3 | use crate::fdse::Fdse; 4 | use crate::instance::ToInstance; 5 | use crate::lut::{Lut1, Lut2, Lut3, Lut4, Lut5, Lut6}; 6 | use crate::vcc::Vcc; 7 | use std::fmt; 8 | 9 | macro_rules! display { 10 | ($ty:tt) => { 11 | impl fmt::Display for $ty { 12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 | write!(f, "{}", self.to_instance()) 14 | } 15 | } 16 | }; 17 | } 18 | 19 | display!(Fdre); 20 | display!(Fdse); 21 | display!(Lut1); 22 | display!(Lut2); 23 | display!(Lut3); 24 | display!(Lut4); 25 | display!(Lut5); 26 | display!(Lut6); 27 | display!(Vcc); 28 | display!(Dsp); 29 | -------------------------------------------------------------------------------- /src/tools/xpand/src/errors.rs: -------------------------------------------------------------------------------- 1 | use bline::errors::Error as BlineError; 2 | use ir::errors::Error as IrError; 3 | use std::fmt; 4 | use std::num::TryFromIntError; 5 | use xir::errors::Error as XirError; 6 | 7 | #[derive(Debug)] 8 | pub enum Error { 9 | Ir(IrError), 10 | Xir(XirError), 11 | Bline(BlineError), 12 | Xpand(String), 13 | TryFromInt(TryFromIntError), 14 | } 15 | 16 | impl Error { 17 | pub fn new_xpand_error(msg: &str) -> Self { 18 | Error::Xpand(msg.to_string()) 19 | } 20 | } 21 | 22 | impl From for Error { 23 | fn from(e: IrError) -> Self { 24 | Error::Ir(e) 25 | } 26 | } 27 | 28 | impl From for Error { 29 | fn from(e: XirError) -> Self { 30 | Error::Xir(e) 31 | } 32 | } 33 | 34 | impl From for Error { 35 | fn from(e: BlineError) -> Self { 36 | Error::Bline(e) 37 | } 38 | } 39 | 40 | impl From for Error { 41 | fn from(e: TryFromIntError) -> Self { 42 | Error::TryFromInt(e) 43 | } 44 | } 45 | 46 | impl fmt::Display for Error { 47 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 48 | match self { 49 | Error::Ir(msg) => write!(f, "{}", msg), 50 | Error::Xir(msg) => write!(f, "{}", msg), 51 | Error::Xpand(msg) => write!(f, "{}", msg), 52 | Error::Bline(msg) => write!(f, "{}", msg), 53 | Error::TryFromInt(msg) => write!(f, "{}", msg), 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/tools/xpand/src/expr.rs: -------------------------------------------------------------------------------- 1 | use verilog::ast as vl; 2 | 3 | // TODO: this will be eventually be replaced with 4 | // traits in to_verilog.rs file. Therefore, we can 5 | // bypass clippy checks here. 6 | #[allow(clippy::module_name_repetitions)] 7 | pub trait ToExpr { 8 | fn to_expr(&self) -> vl::Expr; 9 | } 10 | -------------------------------------------------------------------------------- /src/tools/xpand/src/ext.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::vec_expr_try_from_expr; 3 | use std::convert::TryFrom; 4 | use verilog::ast as vl; 5 | use xir::ast as xir; 6 | 7 | // TODO: add vector type support 8 | pub fn from_basc(instr: &xir::InstrBasc) -> Result, Error> { 9 | match instr.attr().tup() { 10 | Some(tup) if tup.term().len() == 1 => { 11 | let index = instr.attr().get_val(0)?; 12 | let index = i32::try_from(index)?; 13 | let arg: Vec = vec_expr_try_from_expr(instr.arg())?; 14 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 15 | let assign = 16 | vl::Parallel::Assign(dst[0].clone(), vl::Expr::new_index_bit(&arg[0].id(), index)); 17 | let stmt = vl::Stmt::from(assign); 18 | Ok(vec![stmt]) 19 | } 20 | Some(tup) if tup.term().len() == 2 => { 21 | let low = instr.attr().get_val(0)?; 22 | let low = i32::try_from(low)?; 23 | let low = vl::Expr::new_int(low); 24 | let high = instr.attr().get_val(1)?; 25 | let high = i32::try_from(high)?; 26 | let high = vl::Expr::new_int(high); 27 | let arg: Vec = vec_expr_try_from_expr(instr.arg())?; 28 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 29 | let assign = 30 | vl::Parallel::Assign(dst[0].clone(), vl::Expr::new_slice(&arg[0].id(), high, low)); 31 | let stmt = vl::Stmt::from(assign); 32 | Ok(vec![stmt]) 33 | } 34 | _ => Err(Error::new_xpand_error("ext attr must be a tuple")), 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/tools/xpand/src/gnd.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::to_verilog::{ToVerilogDecl, ToVerilogExpr, ToVerilogInstance, VerilogExprMap}; 3 | use crate::vec_expr_try_from_expr; 4 | use prim::ultrascale::gnd::{Gnd, ParamValue, GND}; 5 | use prim::{ParamSet, PortSet}; 6 | use verilog::ast as vl; 7 | use xir::ast as xir; 8 | 9 | impl ToVerilogDecl for Gnd { 10 | fn to_decl(&self) -> vl::Decl { 11 | vl::Decl::new_wire(GND, 1) 12 | } 13 | } 14 | 15 | impl ToVerilogExpr for ParamValue { 16 | fn to_expr(&self) -> vl::Expr { 17 | vl::Expr::new_ref("") 18 | } 19 | } 20 | 21 | impl ToVerilogInstance for Gnd { 22 | fn to_name(&self) -> String { 23 | format!("_{}", GND) 24 | } 25 | fn to_prim(&self) -> String { 26 | self.name() 27 | } 28 | fn to_param_set(&self) -> &ParamSet { 29 | self.param() 30 | } 31 | fn to_input_set(&self) -> &PortSet { 32 | self.input() 33 | } 34 | fn to_output_set(&self) -> &PortSet { 35 | self.output() 36 | } 37 | fn to_output_map(&self) -> VerilogExprMap { 38 | let mut map = VerilogExprMap::new(); 39 | for o in self.to_output_set().iter() { 40 | if o.name().as_str() == "G" { 41 | map.insert(o.name(), vl::Expr::new_ref(GND)); 42 | } else { 43 | map.insert(o.name(), vl::Expr::new_ref("")); 44 | } 45 | } 46 | map 47 | } 48 | } 49 | 50 | pub fn from_basc(instr: &xir::InstrBasc) -> Result, Error> { 51 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 52 | let assign = vl::Parallel::Assign(dst[0].clone(), vl::Expr::new_ref(GND)); 53 | Ok(vec![vl::Stmt::from(assign)]) 54 | } 55 | -------------------------------------------------------------------------------- /src/tools/xpand/src/id.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::vec_expr_try_from_expr; 3 | use verilog::ast as vl; 4 | use xir::ast as xir; 5 | 6 | pub fn from_basc(instr: &xir::InstrBasc) -> Result, Error> { 7 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 8 | let arg: Vec = vec_expr_try_from_expr(instr.arg())?; 9 | let assign = vl::Parallel::Assign(dst[0].clone(), arg[0].clone()); 10 | Ok(vec![vl::Stmt::from(assign)]) 11 | } 12 | -------------------------------------------------------------------------------- /src/tools/xpand/src/instance.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use crate::param::Param; 3 | use verilog::ast as vl; 4 | 5 | // TODO: this will be eventually be replaced with 6 | // traits in to_verilog.rs file. Therefore, we can 7 | // bypass clippy checks here. 8 | #[allow(clippy::module_name_repetitions)] 9 | pub trait ToInstance { 10 | fn param(&self) -> &Param; 11 | fn to_instance(&self) -> vl::Instance; 12 | fn to_stmt(&self) -> vl::Stmt; 13 | fn set_name(&mut self, name: &str); 14 | fn set_input(&mut self, port: &str, expr: vl::Expr) -> Result<(), Error>; 15 | fn set_output(&mut self, port: &str, expr: vl::Expr) -> Result<(), Error>; 16 | } 17 | -------------------------------------------------------------------------------- /src/tools/xpand/src/param.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error; 2 | use derive_more::{Deref, DerefMut, From}; 3 | use std::collections::HashMap; 4 | 5 | pub type ParamMap = HashMap; 6 | 7 | #[derive(Clone, Debug, Default, From, Deref, DerefMut)] 8 | pub struct Param(ParamMap); 9 | 10 | impl Param { 11 | pub fn new() -> Param { 12 | Param::from(ParamMap::::new()) 13 | } 14 | pub fn param(&self) -> &ParamMap { 15 | &self 16 | } 17 | pub fn set_param(&mut self, name: &str, value: U) -> Result<(), Error> 18 | where 19 | U: Into, 20 | { 21 | if let Some(cur) = self.get_mut(name) { 22 | let val: T = value.into(); 23 | if *cur != val { 24 | Err(Error::new_xpand_error("invalid param type")) 25 | } else { 26 | *cur = val; 27 | Ok(()) 28 | } 29 | } else { 30 | Err(Error::new_xpand_error("param does not exists")) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/tools/xpand/src/port.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use verilog::ast as vl; 3 | 4 | pub type ConnectionMap = HashMap; 5 | pub type WidthMap = HashMap; 6 | 7 | #[derive(Clone, Debug, Default)] 8 | pub struct Port { 9 | pub width: WidthMap, 10 | pub connection: ConnectionMap, 11 | } 12 | 13 | pub trait DefaultPort { 14 | // implement default inputs 15 | fn default_input_port() -> Port; 16 | // implement default outputs 17 | fn default_output_port() -> Port; 18 | } 19 | 20 | impl Port { 21 | pub fn get_width(&self, port: &str) -> Option<&u32> { 22 | self.width.get(port) 23 | } 24 | pub fn width(&self) -> &WidthMap { 25 | &self.width 26 | } 27 | pub fn connection(&self) -> &ConnectionMap { 28 | &self.connection 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/tools/xpand/src/to_verilog.rs: -------------------------------------------------------------------------------- 1 | use crate::create_literal; 2 | use crate::loc::{attr_from_loc, Loc}; 3 | use prim::{ParamSet, PortSet}; 4 | use std::collections::HashMap; 5 | use verilog::ast as vl; 6 | 7 | pub type VerilogExprMap = HashMap; 8 | 9 | /// TODO: ToVerilogExpr trait should replace ToExpr trait 10 | pub trait ToVerilogExpr { 11 | /// emit Verilog expr 12 | fn to_expr(&self) -> vl::Expr { 13 | vl::Expr::new_ref("") 14 | } 15 | } 16 | 17 | /// TODO: ToVerilogDecl trait should replace ToDecl trait 18 | pub trait ToVerilogDecl { 19 | /// emit Verilog expr 20 | fn to_decl(&self) -> vl::Decl; 21 | } 22 | 23 | /// TODO: ToVerilogInstance trait should replace Instance trait 24 | /// 25 | /// ToVerilogInstance trait contains methods required to 26 | /// produce block of Verilog code, including at most one 27 | /// instance and multiple statements. 28 | pub trait ToVerilogInstance { 29 | /// name of the instance 30 | fn to_name(&self) -> String; 31 | /// name of the primitive 32 | fn to_prim(&self) -> String; 33 | /// primitive parameter set 34 | fn to_param_set(&self) -> &ParamSet; 35 | /// primitive input set 36 | fn to_input_set(&self) -> &PortSet; 37 | /// primitive output set 38 | fn to_output_set(&self) -> &PortSet; 39 | /// primitive location. Optional, because some primitives 40 | /// do not require location e.g., VCC or GND 41 | fn to_loc(&self) -> Option<&Loc> { 42 | None 43 | } 44 | /// parameter map 45 | fn to_param_map(&self) -> VerilogExprMap { 46 | let mut map = VerilogExprMap::new(); 47 | for p in self.to_param_set().iter() { 48 | map.insert(p.name(), p.value().to_expr()); 49 | } 50 | map 51 | } 52 | /// input map 53 | fn to_input_map(&self) -> VerilogExprMap { 54 | let mut map = VerilogExprMap::new(); 55 | for i in self.to_input_set().iter() { 56 | map.insert(i.name(), create_literal(i.width() as u64, 0)); 57 | } 58 | map 59 | } 60 | /// output map 61 | fn to_output_map(&self) -> VerilogExprMap { 62 | let mut map = VerilogExprMap::new(); 63 | for o in self.to_output_set().iter() { 64 | map.insert(o.name(), vl::Expr::new_ref("")); 65 | } 66 | map 67 | } 68 | /// emit Verilog instance 69 | fn to_instance(&self) -> vl::Instance { 70 | let mut inst = vl::Instance::new(&self.to_name(), &self.to_prim()); 71 | let param = self.to_param_map(); 72 | for (p, v) in param { 73 | inst.add_param(&p, v); 74 | } 75 | let input = self.to_input_map(); 76 | for (i, v) in input { 77 | inst.connect(&i, v); 78 | } 79 | let output = self.to_output_map(); 80 | for (o, v) in output { 81 | inst.connect(&o, v); 82 | } 83 | if let Some(loc) = self.to_loc() { 84 | if loc.is_placed() { 85 | let attr = attr_from_loc(&loc); 86 | inst.set_attr(attr); 87 | } 88 | } 89 | inst 90 | } 91 | /// emit Verilog stmt 92 | fn to_stmt(&self) -> vl::Stmt { 93 | vl::Stmt::from(self.to_instance()) 94 | } 95 | /// emit Verilog block 96 | fn to_block(&self) -> Vec { 97 | vec![self.to_stmt()] 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/tools/xpand/src/vcc.rs: -------------------------------------------------------------------------------- 1 | use crate::decl::ToDecl; 2 | use crate::errors::Error; 3 | use crate::instance::ToInstance; 4 | use crate::param::Param; 5 | use crate::port::{ConnectionMap, DefaultPort, Port, WidthMap}; 6 | use crate::vec_expr_try_from_expr; 7 | use verilog::ast as vl; 8 | use xir::ast as xir; 9 | 10 | pub const VCC: &str = "vcc"; 11 | 12 | #[derive(Clone, Debug, PartialEq)] 13 | pub struct ParamValue; 14 | 15 | #[derive(Clone, Debug)] 16 | pub struct Vcc { 17 | pub name: String, 18 | pub prim: String, 19 | pub param: Param, 20 | pub output: Port, 21 | } 22 | 23 | impl DefaultPort for Vcc { 24 | fn default_input_port() -> Port { 25 | Port::default() 26 | } 27 | fn default_output_port() -> Port { 28 | let mut width = WidthMap::new(); 29 | width.insert("P".to_string(), 1); 30 | let mut connection = ConnectionMap::new(); 31 | for k in width.keys() { 32 | connection.insert(k.clone(), vl::Expr::new_ref(VCC)); 33 | } 34 | Port { width, connection } 35 | } 36 | } 37 | 38 | impl Default for Param { 39 | fn default() -> Self { 40 | Param::::new() 41 | } 42 | } 43 | 44 | impl Default for Vcc { 45 | fn default() -> Self { 46 | let name = format!("_{}", VCC); 47 | Vcc { 48 | name, 49 | prim: "VCC".to_string(), 50 | param: Param::::default(), 51 | output: Vcc::default_output_port(), 52 | } 53 | } 54 | } 55 | 56 | impl ToDecl for Vcc { 57 | fn to_decl(&self) -> vl::Decl { 58 | vl::Decl::new_wire(VCC, 1) 59 | } 60 | } 61 | 62 | impl ToInstance for Vcc { 63 | fn param(&self) -> &Param { 64 | &self.param 65 | } 66 | fn to_instance(&self) -> vl::Instance { 67 | let mut inst = vl::Instance::new(&self.name, &self.prim); 68 | for (k, v) in self.output.connection.iter() { 69 | inst.connect(&k, v.clone()); 70 | } 71 | inst 72 | } 73 | fn to_stmt(&self) -> vl::Stmt { 74 | vl::Stmt::from(self.to_instance()) 75 | } 76 | fn set_name(&mut self, name: &str) { 77 | self.name = name.to_string(); 78 | } 79 | fn set_input(&mut self, _: &str, _: vl::Expr) -> Result<(), Error> { 80 | Err(Error::new_xpand_error("VCC does not support inputs")) 81 | } 82 | fn set_output(&mut self, port: &str, expr: vl::Expr) -> Result<(), Error> { 83 | if let Some(p) = self.output.connection.get_mut(port) { 84 | *p = expr; 85 | Ok(()) 86 | } else { 87 | let err = format!("output {} do not exist", port); 88 | Err(Error::new_xpand_error(&err)) 89 | } 90 | } 91 | } 92 | 93 | pub fn from_basc(instr: &xir::InstrBasc) -> Result, Error> { 94 | let dst: Vec = vec_expr_try_from_expr(instr.dst())?; 95 | let assign = vl::Parallel::Assign(dst[0].clone(), vl::Expr::new_ref(VCC)); 96 | Ok(vec![vl::Stmt::from(assign)]) 97 | } 98 | -------------------------------------------------------------------------------- /src/tools/xpand/tests/xpand.rs: -------------------------------------------------------------------------------- 1 | use io::read_to_string; 2 | use pretty_assertions::assert_eq; 3 | use std::path::Path; 4 | use xir::parser::Parser; 5 | use xpand::errors::Error; 6 | use xpand::try_from_xir_prog; 7 | 8 | fn test(name: &str) -> Result<(), Error> { 9 | let mut input = Path::new("../../../examples/xir").join(name); 10 | let mut output = Path::new("../../../examples/struct").join(name); 11 | input.set_extension("xir"); 12 | output.set_extension("v"); 13 | let parsed = Parser::parse_from_file(input)?; 14 | let exp = read_to_string(output); 15 | let res = try_from_xir_prog(&parsed, None)?; 16 | assert_eq!(res.to_string(), exp); 17 | Ok(()) 18 | } 19 | 20 | fn test_with_mmap(name: &str) -> Result<(), Error> { 21 | let filename = format!("{}_mmap", name); 22 | let mut input = Path::new("../../../examples/xir").join(name); 23 | let mut output = Path::new("../../../examples/struct").join(&filename); 24 | let mut mem = Path::new("../../../examples/mmap").join(name); 25 | input.set_extension("xir"); 26 | output.set_extension("v"); 27 | mem.set_extension("json"); 28 | let parsed = Parser::parse_from_file(input)?; 29 | let mmap = mmap::Mmap::from_file(mem); 30 | let exp = read_to_string(output); 31 | let res = try_from_xir_prog(&parsed, Some(&mmap))?; 32 | assert_eq!(res.to_string(), exp); 33 | Ok(()) 34 | } 35 | 36 | #[test] 37 | fn add() -> Result<(), Error> { 38 | test("add") 39 | } 40 | 41 | #[test] 42 | fn addreduce_placed() -> Result<(), Error> { 43 | test("addreduce_placed") 44 | } 45 | 46 | #[test] 47 | fn fsm_3() -> Result<(), Error> { 48 | test("fsm_3") 49 | } 50 | 51 | #[test] 52 | fn fsm_5() -> Result<(), Error> { 53 | test("fsm_5") 54 | } 55 | 56 | #[test] 57 | fn fsm_7() -> Result<(), Error> { 58 | test("fsm_7") 59 | } 60 | 61 | #[test] 62 | fn fsm_9() -> Result<(), Error> { 63 | test("fsm_9") 64 | } 65 | 66 | #[test] 67 | fn tadd() -> Result<(), Error> { 68 | test("tadd") 69 | } 70 | 71 | #[test] 72 | fn tadd_64() -> Result<(), Error> { 73 | test("tadd_64") 74 | } 75 | 76 | #[test] 77 | fn tadd_128() -> Result<(), Error> { 78 | test("tadd_128") 79 | } 80 | 81 | #[test] 82 | fn tadd_256() -> Result<(), Error> { 83 | test("tadd_256") 84 | } 85 | 86 | #[test] 87 | fn tadd_512() -> Result<(), Error> { 88 | test("tadd_512") 89 | } 90 | 91 | #[test] 92 | fn tdot() -> Result<(), Error> { 93 | test("tdot") 94 | } 95 | 96 | #[test] 97 | fn tdot_5_3() -> Result<(), Error> { 98 | test("tdot_5_3") 99 | } 100 | 101 | #[test] 102 | fn tdot_5_9() -> Result<(), Error> { 103 | test("tdot_5_9") 104 | } 105 | 106 | #[test] 107 | fn tdot_5_18() -> Result<(), Error> { 108 | test("tdot_5_18") 109 | } 110 | 111 | #[test] 112 | fn tdot_5_36() -> Result<(), Error> { 113 | test("tdot_5_36") 114 | } 115 | 116 | #[test] 117 | fn lrom_8x8() -> Result<(), Error> { 118 | test("lrom_8x8") 119 | } 120 | 121 | #[test] 122 | fn brom_8x256() -> Result<(), Error> { 123 | test("brom_8x256") 124 | } 125 | 126 | #[test] 127 | fn mux128() -> Result<(), Error> { 128 | test("mux128") 129 | } 130 | 131 | #[test] 132 | fn lrom_8x8_mmap() -> Result<(), Error> { 133 | test_with_mmap("lrom_8x8") 134 | } 135 | 136 | #[test] 137 | fn brom_8x256_mmap() -> Result<(), Error> { 138 | test_with_mmap("brom_8x256") 139 | } 140 | --------------------------------------------------------------------------------