├── .mill-version ├── .mill-jvm-opts ├── project ├── build.properties └── plugins.sbt ├── .github └── workflows │ ├── test.yml │ └── template-cleanup.yml ├── LICENSE ├── src ├── main │ └── scala │ │ └── gcd │ │ ├── GCD.scala │ │ └── DecoupledGCD.scala └── test │ └── scala │ └── gcd │ └── GCDSpec.scala ├── README.md ├── .gitignore └── mill /.mill-version: -------------------------------------------------------------------------------- 1 | 0.12.5 -------------------------------------------------------------------------------- /.mill-jvm-opts: -------------------------------------------------------------------------------- 1 | -Dchisel.project.root=${PWD} 2 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 1.9.7 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn 2 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | tags: ['*'] 6 | branches: ['main'] 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | jobs: 11 | ci: 12 | name: ci 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | - name: Cleanup 18 | run: sed -i "s/%NAME%/test/g" build.mill 19 | - name: Cache Scala 20 | uses: coursier/cache-action@v6 21 | - name: Setup Scala 22 | uses: coursier/setup-action@v1 23 | with: 24 | jvm: adopt:11 25 | apps: sbt 26 | - name: Setup Dependencies 27 | run: | 28 | sudo apt-get install verilator 29 | verilator --version 30 | - name: SBT Test 31 | run: sbt test 32 | - name: mill Test 33 | run: ./mill _.test 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /src/main/scala/gcd/GCD.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import chisel3._ 6 | // _root_ disambiguates from package chisel3.util.circt if user imports chisel3.util._ 7 | import _root_.circt.stage.ChiselStage 8 | 9 | /** 10 | * Compute GCD using subtraction method. 11 | * Subtracts the smaller from the larger until register y is zero. 12 | * value in register x is then the GCD 13 | */ 14 | class GCD extends Module { 15 | val io = IO(new Bundle { 16 | val value1 = Input(UInt(16.W)) 17 | val value2 = Input(UInt(16.W)) 18 | val loadingValues = Input(Bool()) 19 | val outputGCD = Output(UInt(16.W)) 20 | val outputValid = Output(Bool()) 21 | }) 22 | 23 | val x = Reg(UInt()) 24 | val y = Reg(UInt()) 25 | 26 | when(x > y) { x := x - y } 27 | .otherwise { y := y - x } 28 | 29 | when(io.loadingValues) { 30 | x := io.value1 31 | y := io.value2 32 | } 33 | 34 | io.outputGCD := x 35 | io.outputValid := y === 0.U 36 | } 37 | 38 | /** 39 | * Generate Verilog sources and save it in file GCD.v 40 | */ 41 | object GCD extends App { 42 | ChiselStage.emitSystemVerilogFile( 43 | new GCD, 44 | firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info", "-default-layer-specialization=enable") 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/gcd/DecoupledGCD.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import chisel3._ 6 | import chisel3.util.Decoupled 7 | 8 | class GcdInputBundle(val w: Int) extends Bundle { 9 | val value1 = UInt(w.W) 10 | val value2 = UInt(w.W) 11 | } 12 | 13 | class GcdOutputBundle(val w: Int) extends Bundle { 14 | val value1 = UInt(w.W) 15 | val value2 = UInt(w.W) 16 | val gcd = UInt(w.W) 17 | } 18 | 19 | /** 20 | * Compute Gcd using subtraction method. 21 | * Subtracts the smaller from the larger until register y is zero. 22 | * value input register x is then the Gcd. 23 | * Unless first input is zero then the Gcd is y. 24 | * Can handle stalls on the producer or consumer side 25 | */ 26 | class DecoupledGcd(width: Int) extends Module { 27 | val input = IO(Flipped(Decoupled(new GcdInputBundle(width)))) 28 | val output = IO(Decoupled(new GcdOutputBundle(width))) 29 | 30 | val xInitial = Reg(UInt()) 31 | val yInitial = Reg(UInt()) 32 | val x = Reg(UInt()) 33 | val y = Reg(UInt()) 34 | val busy = RegInit(false.B) 35 | val resultValid = RegInit(false.B) 36 | 37 | input.ready := ! busy 38 | output.valid := resultValid 39 | output.bits := DontCare 40 | 41 | when(busy) { 42 | when(x > y) { 43 | x := x - y 44 | }.otherwise { 45 | y := y - x 46 | } 47 | when(x === 0.U || y === 0.U) { 48 | when(x === 0.U) { 49 | output.bits.gcd := y 50 | }.otherwise { 51 | output.bits.gcd := x 52 | } 53 | 54 | output.bits.value1 := xInitial 55 | output.bits.value2 := yInitial 56 | resultValid := true.B 57 | 58 | when(output.ready && resultValid) { 59 | busy := false.B 60 | resultValid := false.B 61 | } 62 | } 63 | }.otherwise { 64 | when(input.valid) { 65 | val bundle = input.deq() 66 | x := bundle.value1 67 | y := bundle.value2 68 | xInitial := bundle.value1 69 | yInitial := bundle.value2 70 | busy := true.B 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/scala/gcd/GCDSpec.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import chisel3._ 6 | import chisel3.experimental.BundleLiterals._ 7 | import chisel3.simulator.scalatest.ChiselSim 8 | import org.scalatest.freespec.AnyFreeSpec 9 | import org.scalatest.matchers.must.Matchers 10 | 11 | /** 12 | * This is a trivial example of how to run this Specification 13 | * From within sbt use: 14 | * {{{ 15 | * testOnly gcd.GCDSpec 16 | * }}} 17 | * From a terminal shell use: 18 | * {{{ 19 | * sbt 'testOnly gcd.GCDSpec' 20 | * }}} 21 | * Testing from mill: 22 | * {{{ 23 | * mill %NAME%.test.testOnly gcd.GCDSpec 24 | * }}} 25 | */ 26 | class GCDSpec extends AnyFreeSpec with Matchers with ChiselSim { 27 | 28 | "Gcd should calculate proper greatest common denominator" in { 29 | simulate(new DecoupledGcd(16)) { dut => 30 | val testValues = for { x <- 0 to 10; y <- 0 to 10} yield (x, y) 31 | val inputSeq = testValues.map { case (x, y) => (new GcdInputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U) } 32 | val resultSeq = testValues.map { case (x, y) => 33 | (new GcdOutputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U, _.gcd -> BigInt(x).gcd(BigInt(y)).U) 34 | } 35 | 36 | dut.reset.poke(true.B) 37 | dut.clock.step() 38 | dut.reset.poke(false.B) 39 | dut.clock.step() 40 | 41 | var sent, received, cycles: Int = 0 42 | while (sent != 100 && received != 100) { 43 | assert(cycles <= 1000, "timeout reached") 44 | 45 | if (sent < 100) { 46 | dut.input.valid.poke(true.B) 47 | dut.input.bits.value1.poke(testValues(sent)._1.U) 48 | dut.input.bits.value2.poke(testValues(sent)._2.U) 49 | if (dut.input.ready.peek().litToBoolean) { 50 | sent += 1 51 | } 52 | } 53 | 54 | if (received < 100) { 55 | dut.output.ready.poke(true.B) 56 | if (dut.output.valid.peekValue().asBigInt == 1) { 57 | dut.output.bits.gcd.expect(BigInt(testValues(received)._1).gcd(testValues(received)._2)) 58 | received += 1 59 | } 60 | } 61 | 62 | // Step the simulation forward. 63 | dut.clock.step() 64 | cycles += 1 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /.github/workflows/template-cleanup.yml: -------------------------------------------------------------------------------- 1 | # Workflow to cleanup projects created from this template 2 | # Adapted from workflow of the same name in https://github.com/JetBrains/intellij-platform-plugin-template 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | name: Template Cleanup 6 | on: 7 | push: 8 | branches: [main] 9 | 10 | jobs: 11 | # Triggered on first push to repos created from the template 12 | template-cleanup: 13 | name: Template Cleanup 14 | permissions: 15 | contents: write 16 | runs-on: ubuntu-latest 17 | if: github.event.repository.name != 'chisel-template' 18 | steps: 19 | 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | with: 23 | # These are needed to make ad-m/github-push-action work 24 | # https://github.com/ad-m/github-push-action/tree/d91a481090679876dfc4178fef17f286781251df#example-workflow-file 25 | persist-credentials: false 26 | fetch-depth: 0 27 | 28 | - name: Cleanup 29 | run: | 30 | export LC_CTYPE=C 31 | export LANG=C 32 | 33 | # Prepare variables 34 | NAME="${GITHUB_REPOSITORY##*/}" 35 | ORG="$GITHUB_REPOSITORY_OWNER" 36 | SAFE_ORG=$(echo $ORG | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') 37 | GROUP="com.github.$SAFE_ORG" 38 | 39 | # Prepare wrapped name 40 | WRAPPED_NAME="\`${NAME}\`" 41 | 42 | # Replace placeholders 43 | sed -i "s/%NAME%/$NAME/g" build.sbt README.md src/test/scala/gcd/* 44 | sed -i "s/%NAME%/$WRAPPED_NAME/g" build.mill 45 | sed -i "s/%REPOSITORY%/${GITHUB_REPOSITORY/\//\\/}/g" README.md 46 | sed -i "s/%ORGANIZATION%/$GROUP/g" build.sbt 47 | 48 | # Remove lines marked with #REMOVE-ON-CLEANUP# 49 | sed -i '/#REMOVE-ON-CLEANUP#/d' README.md 50 | 51 | rm -rf \ 52 | .github/workflows/template-cleanup.yml \ 53 | LICENSE 54 | 55 | - name: Commit 56 | run: | 57 | git config --local user.email "action@github.com" 58 | git config --local user.name "GitHub Action" 59 | git add . 60 | git commit -m "Template cleanup" 61 | 62 | - name: Push changes 63 | uses: ad-m/github-push-action@v0.8.0 64 | with: 65 | branch: main 66 | github_token: ${{ secrets.GITHUB_TOKEN }} 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Chisel Project Template 2 | ======================= 3 | 4 | You've done the [Chisel Bootcamp](https://github.com/freechipsproject/chisel-bootcamp), and now you 5 | are ready to start your own Chisel project. The following procedure should get you started 6 | with a clean running [Chisel3](https://www.chisel-lang.org/) project. 7 | 8 | ## Make your own Chisel3 project 9 | 10 | ### Dependencies 11 | 12 | #### JDK 11 or newer 13 | 14 | We recommend using Java 11 or later LTS releases. While Chisel itself works with Java 8, our preferred build tool Mill requires Java 11. You can install the JDK as your operating system recommends, or use the prebuilt binaries from [Adoptium](https://adoptium.net/) (formerly AdoptOpenJDK). 15 | 16 | #### SBT or mill 17 | 18 | SBT is the most common build tool in the Scala community. You can download it [here](https://www.scala-sbt.org/download.html). 19 | Mill is another Scala/Java build tool preferred by Chisel's developers. 20 | This repository includes a bootstrap script `./mill` so that no installation is necessary. 21 | You can read more about Mill on its website: https://mill-build.org. 22 | 23 | #### Verilator 24 | 25 | The test with `svsim` needs Verilator installed. 26 | See Verilator installation instructions [here](https://verilator.org/guide/latest/install.html). 27 | 28 | ### How to get started 29 | 30 | #### Create a repository from the template 31 | 32 | This repository is a Github template. You can create your own repository from it by clicking the green `Use this template` in the top right. 33 | Please leave `Include all branches` **unchecked**; checking it will pollute the history of your new repository. 34 | For more information, see ["Creating a repository from a template"](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template). 35 | 36 | #### Wait for the template cleanup workflow to complete 37 | 38 | After using the template to create your own blank project, please wait a minute or two for the `Template cleanup` workflow to run which will removes some template-specific stuff from the repository (like the LICENSE). 39 | Refresh the repository page in your browser until you see a 2nd commit by `actions-user` titled `Template cleanup`. 40 | 41 | 42 | #### Clone your repository 43 | 44 | Once you have created a repository from this template and the `Template cleanup` workflow has completed, you can click the green button to get a link for cloning your repository. 45 | Note that it is easiest to push to a repository if you set up SSH with Github, please see the [related documentation](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh). SSH is required for pushing to a Github repository when using two-factor authentication. 46 | 47 | ```sh 48 | git clone git@github.com:%REPOSITORY%.git 49 | cd %NAME% 50 | ``` 51 | (The variables wrapped in `%` will be filled in by the template cleanup) 52 | 53 | #### Set project organization and name in build.sbt 54 | 55 | The cleanup workflow will have attempted to provide sensible defaults for `ThisBuild / organization` and `name` in the `build.sbt`. 56 | Feel free to use your text editor of choice to change them as you see fit. 57 | 58 | #### Clean up the README.md file 59 | 60 | Again, use you editor of choice to make the README specific to your project. 61 | 62 | #### Add a LICENSE file 63 | 64 | It is important to have a LICENSE for open source (or closed source) code. 65 | This template repository has the Unlicense in order to allow users to add any license they want to derivative code. 66 | The Unlicense is stripped when creating a repository from this template so that users do not accidentally unlicense their own work. 67 | 68 | For more information about a license, check out the [Github Docs](https://docs.github.com/en/free-pro-team@latest/github/building-a-strong-community/adding-a-license-to-a-repository). 69 | 70 | #### Commit your changes 71 | ```sh 72 | git commit -m 'Starting %NAME%' 73 | git push origin main 74 | ``` 75 | 76 | ### Did it work? 77 | 78 | You should now have a working Chisel3 project. 79 | 80 | You can run the included test with: 81 | ```sh 82 | sbt test 83 | ``` 84 | 85 | Alternatively, if you use Mill: 86 | ```sh 87 | ./mill %NAME%.test 88 | ``` 89 | 90 | You should see a whole bunch of output that ends with something like the following lines 91 | ``` 92 | [info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 93 | [info] All tests passed. 94 | [success] Total time: 5 s, completed Dec 16, 2020 12:18:44 PM 95 | ``` 96 | If you see the above then... 97 | 98 | ### It worked! 99 | 100 | You are ready to go. We have a few recommended practices and things to do. 101 | 102 | * Use packages and following conventions for [structure](https://www.scala-sbt.org/1.x/docs/Directories.html) and [naming](http://docs.scala-lang.org/style/naming-conventions.html) 103 | * Package names should be clearly reflected in the testing hierarchy 104 | * Build tests for all your work 105 | * Read more about testing in SBT in the [SBT docs](https://www.scala-sbt.org/1.x/docs/Testing.html) 106 | * This template includes a [test dependency](https://www.scala-sbt.org/1.x/docs/Library-Dependencies.html#Per-configuration+dependencies) on [ScalaTest](https://www.scalatest.org/). This, coupled with `svsim` (included with Chisel) and `verilator`, are a starting point for testing Chisel generators. 107 | * You can remove this dependency in the build.sbt file if you want to 108 | * Change the name of your project in the build.sbt file 109 | * Change your README.md 110 | 111 | ## Problems? Questions? 112 | 113 | Check out the [Chisel Users Community](https://www.chisel-lang.org/community.html) page for links to get in contact! 114 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Project Specific stuff 2 | test_run_dir/* 3 | ### XilinxISE template 4 | # intermediate build files 5 | *.bgn 6 | *.bit 7 | *.bld 8 | *.cmd_log 9 | *.drc 10 | *.ll 11 | *.lso 12 | *.msd 13 | *.msk 14 | *.ncd 15 | *.ngc 16 | *.ngd 17 | *.ngr 18 | *.pad 19 | *.par 20 | *.pcf 21 | *.prj 22 | *.ptwx 23 | *.rbb 24 | *.rbd 25 | *.stx 26 | *.syr 27 | *.twr 28 | *.twx 29 | *.unroutes 30 | *.ut 31 | *.xpi 32 | *.xst 33 | *_bitgen.xwbt 34 | *_envsettings.html 35 | *_map.map 36 | *_map.mrp 37 | *_map.ngm 38 | *_map.xrpt 39 | *_ngdbuild.xrpt 40 | *_pad.csv 41 | *_pad.txt 42 | *_par.xrpt 43 | *_summary.html 44 | *_summary.xml 45 | *_usage.xml 46 | *_xst.xrpt 47 | 48 | # project-wide generated files 49 | *.gise 50 | par_usage_statistics.html 51 | usage_statistics_webtalk.html 52 | webtalk.log 53 | webtalk_pn.xml 54 | 55 | # generated folders 56 | iseconfig/ 57 | xlnx_auto_0_xdb/ 58 | xst/ 59 | _ngo/ 60 | _xmsgs/ 61 | ### Eclipse template 62 | *.pydevproject 63 | .metadata 64 | .gradle 65 | bin/ 66 | tmp/ 67 | *.tmp 68 | *.bak 69 | *.swp 70 | *~.nib 71 | local.properties 72 | .settings/ 73 | .loadpath 74 | 75 | # Eclipse Core 76 | .project 77 | 78 | # External tool builders 79 | .externalToolBuilders/ 80 | 81 | # Locally stored "Eclipse launch configurations" 82 | *.launch 83 | 84 | # CDT-specific 85 | .cproject 86 | 87 | # JDT-specific (Eclipse Java Development Tools) 88 | .classpath 89 | 90 | # Java annotation processor (APT) 91 | .factorypath 92 | 93 | # PDT-specific 94 | .buildpath 95 | 96 | # sbteclipse plugin 97 | .target 98 | 99 | # TeXlipse plugin 100 | .texlipse 101 | ### C template 102 | # Object files 103 | *.o 104 | *.ko 105 | *.obj 106 | *.elf 107 | 108 | # Precompiled Headers 109 | *.gch 110 | *.pch 111 | 112 | # Libraries 113 | *.lib 114 | *.a 115 | *.la 116 | *.lo 117 | 118 | # Shared objects (inc. Windows DLLs) 119 | *.dll 120 | *.so 121 | *.so.* 122 | *.dylib 123 | 124 | # Executables 125 | *.exe 126 | *.out 127 | *.app 128 | *.i*86 129 | *.x86_64 130 | *.hex 131 | 132 | # Debug files 133 | *.dSYM/ 134 | ### SBT template 135 | # Simple Build Tool 136 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control 137 | 138 | target/ 139 | lib_managed/ 140 | src_managed/ 141 | project/boot/ 142 | .history 143 | .cache 144 | ### Emacs template 145 | # -*- mode: gitignore; -*- 146 | *~ 147 | \#*\# 148 | /.emacs.desktop 149 | /.emacs.desktop.lock 150 | *.elc 151 | auto-save-list 152 | tramp 153 | .\#* 154 | 155 | # Org-mode 156 | .org-id-locations 157 | *_archive 158 | 159 | # flymake-mode 160 | *_flymake.* 161 | 162 | # eshell files 163 | /eshell/history 164 | /eshell/lastdir 165 | 166 | # elpa packages 167 | /elpa/ 168 | 169 | # reftex files 170 | *.rel 171 | 172 | # AUCTeX auto folder 173 | /auto/ 174 | 175 | # cask packages 176 | .cask/ 177 | ### Vim template 178 | [._]*.s[a-w][a-z] 179 | [._]s[a-w][a-z] 180 | *.un~ 181 | Session.vim 182 | .netrwhist 183 | *~ 184 | ### JetBrains template 185 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 186 | 187 | *.iml 188 | 189 | ## Directory-based project format: 190 | .idea/ 191 | # if you remove the above rule, at least ignore the following: 192 | 193 | # User-specific stuff: 194 | # .idea/workspace.xml 195 | # .idea/tasks.xml 196 | # .idea/dictionaries 197 | 198 | # Sensitive or high-churn files: 199 | # .idea/dataSources.ids 200 | # .idea/dataSources.xml 201 | # .idea/sqlDataSources.xml 202 | # .idea/dynamic.xml 203 | # .idea/uiDesigner.xml 204 | 205 | # Gradle: 206 | # .idea/gradle.xml 207 | # .idea/libraries 208 | 209 | # Mongo Explorer plugin: 210 | # .idea/mongoSettings.xml 211 | 212 | ## File-based project format: 213 | *.ipr 214 | *.iws 215 | 216 | ## Plugin-specific files: 217 | 218 | # IntelliJ 219 | /out/ 220 | 221 | # mpeltonen/sbt-idea plugin 222 | .idea_modules/ 223 | 224 | # JIRA plugin 225 | atlassian-ide-plugin.xml 226 | 227 | # Crashlytics plugin (for Android Studio and IntelliJ) 228 | com_crashlytics_export_strings.xml 229 | crashlytics.properties 230 | crashlytics-build.properties 231 | ### C++ template 232 | # Compiled Object files 233 | *.slo 234 | *.lo 235 | *.o 236 | *.obj 237 | 238 | # Precompiled Headers 239 | *.gch 240 | *.pch 241 | 242 | # Compiled Dynamic libraries 243 | *.so 244 | *.dylib 245 | *.dll 246 | 247 | # Fortran module files 248 | *.mod 249 | 250 | # Compiled Static libraries 251 | *.lai 252 | *.la 253 | *.a 254 | *.lib 255 | 256 | # Executables 257 | *.exe 258 | *.out 259 | *.app 260 | ### OSX template 261 | .DS_Store 262 | .AppleDouble 263 | .LSOverride 264 | 265 | # Icon must end with two \r 266 | Icon 267 | 268 | # Thumbnails 269 | ._* 270 | 271 | # Files that might appear in the root of a volume 272 | .DocumentRevisions-V100 273 | .fseventsd 274 | .Spotlight-V100 275 | .TemporaryItems 276 | .Trashes 277 | .VolumeIcon.icns 278 | 279 | # Directories potentially created on remote AFP share 280 | .AppleDB 281 | .AppleDesktop 282 | Network Trash Folder 283 | Temporary Items 284 | .apdisk 285 | ### Xcode template 286 | # Xcode 287 | # 288 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 289 | 290 | ## Build generated 291 | build/ 292 | DerivedData 293 | 294 | ## Various settings 295 | *.pbxuser 296 | !default.pbxuser 297 | *.mode1v3 298 | !default.mode1v3 299 | *.mode2v3 300 | !default.mode2v3 301 | *.perspectivev3 302 | !default.perspectivev3 303 | xcuserdata 304 | 305 | ## Other 306 | *.xccheckout 307 | *.moved-aside 308 | *.xcuserstate 309 | ### Scala template 310 | *.class 311 | *.log 312 | /.bsp 313 | 314 | # sbt specific 315 | .cache 316 | .history 317 | .lib/ 318 | dist/* 319 | target/ 320 | lib_managed/ 321 | src_managed/ 322 | project/boot/ 323 | project/plugins/project/ 324 | 325 | # Scala-IDE specific 326 | .scala_dependencies 327 | .worksheet 328 | ### Java template 329 | *.class 330 | 331 | # Mobile Tools for Java (J2ME) 332 | .mtj.tmp/ 333 | 334 | # Package Files # 335 | *.jar 336 | *.war 337 | *.ear 338 | 339 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 340 | hs_err_pid* 341 | 342 | -------------------------------------------------------------------------------- /mill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a wrapper script, that automatically download mill from GitHub release pages 4 | # You can give the required mill version with --mill-version parameter 5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION 6 | # 7 | # Original Project page: https://github.com/lefou/millw 8 | # Script Version: 0.4.12 9 | # 10 | # If you want to improve this script, please also contribute your changes back! 11 | # 12 | # Licensed under the Apache License, Version 2.0 13 | 14 | set -e 15 | 16 | if [ -z "${DEFAULT_MILL_VERSION}" ] ; then 17 | DEFAULT_MILL_VERSION=0.12.5 18 | fi 19 | 20 | 21 | if [ -z "${GITHUB_RELEASE_CDN}" ] ; then 22 | GITHUB_RELEASE_CDN="" 23 | fi 24 | 25 | 26 | MILL_REPO_URL="https://github.com/com-lihaoyi/mill" 27 | 28 | if [ -z "${CURL_CMD}" ] ; then 29 | CURL_CMD=curl 30 | fi 31 | 32 | # Explicit commandline argument takes precedence over all other methods 33 | if [ "$1" = "--mill-version" ] ; then 34 | shift 35 | if [ "x$1" != "x" ] ; then 36 | MILL_VERSION="$1" 37 | shift 38 | else 39 | echo "You specified --mill-version without a version." 1>&2 40 | echo "Please provide a version that matches one provided on" 1>&2 41 | echo "${MILL_REPO_URL}/releases" 1>&2 42 | false 43 | fi 44 | fi 45 | 46 | # Please note, that if a MILL_VERSION is already set in the environment, 47 | # We reuse it's value and skip searching for a value. 48 | 49 | # If not already set, read .mill-version file 50 | if [ -z "${MILL_VERSION}" ] ; then 51 | if [ -f ".mill-version" ] ; then 52 | MILL_VERSION="$(tr '\r' '\n' < .mill-version | head -n 1 2> /dev/null)" 53 | elif [ -f ".config/mill-version" ] ; then 54 | MILL_VERSION="$(tr '\r' '\n' < .config/mill-version | head -n 1 2> /dev/null)" 55 | fi 56 | fi 57 | 58 | MILL_USER_CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/mill" 59 | 60 | if [ -z "${MILL_DOWNLOAD_PATH}" ] ; then 61 | MILL_DOWNLOAD_PATH="${MILL_USER_CACHE_DIR}/download" 62 | fi 63 | 64 | # If not already set, try to fetch newest from Github 65 | if [ -z "${MILL_VERSION}" ] ; then 66 | # TODO: try to load latest version from release page 67 | echo "No mill version specified." 1>&2 68 | echo "You should provide a version via '.mill-version' file or --mill-version option." 1>&2 69 | 70 | mkdir -p "${MILL_DOWNLOAD_PATH}" 71 | LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 2>/dev/null || ( 72 | # we might be on OSX or BSD which don't have -d option for touch 73 | # but probably a -A [-][[hh]mm]SS 74 | touch "${MILL_DOWNLOAD_PATH}/.expire_latest"; touch -A -010000 "${MILL_DOWNLOAD_PATH}/.expire_latest" 75 | ) || ( 76 | # in case we still failed, we retry the first touch command with the intention 77 | # to show the (previously suppressed) error message 78 | LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 79 | ) 80 | 81 | # POSIX shell variant of bash's -nt operator, see https://unix.stackexchange.com/a/449744/6993 82 | # if [ "${MILL_DOWNLOAD_PATH}/.latest" -nt "${MILL_DOWNLOAD_PATH}/.expire_latest" ] ; then 83 | if [ -n "$(find -L "${MILL_DOWNLOAD_PATH}/.latest" -prune -newer "${MILL_DOWNLOAD_PATH}/.expire_latest")" ]; then 84 | # we know a current latest version 85 | MILL_VERSION=$(head -n 1 "${MILL_DOWNLOAD_PATH}"/.latest 2> /dev/null) 86 | fi 87 | 88 | if [ -z "${MILL_VERSION}" ] ; then 89 | # we don't know a current latest version 90 | echo "Retrieving latest mill version ..." 1>&2 91 | LANG=C ${CURL_CMD} -s -i -f -I ${MILL_REPO_URL}/releases/latest 2> /dev/null | grep --ignore-case Location: | sed s'/^.*tag\///' | tr -d '\r\n' > "${MILL_DOWNLOAD_PATH}/.latest" 92 | MILL_VERSION=$(head -n 1 "${MILL_DOWNLOAD_PATH}"/.latest 2> /dev/null) 93 | fi 94 | 95 | if [ -z "${MILL_VERSION}" ] ; then 96 | # Last resort 97 | MILL_VERSION="${DEFAULT_MILL_VERSION}" 98 | echo "Falling back to hardcoded mill version ${MILL_VERSION}" 1>&2 99 | else 100 | echo "Using mill version ${MILL_VERSION}" 1>&2 101 | fi 102 | fi 103 | 104 | MILL="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" 105 | 106 | try_to_use_system_mill() { 107 | if [ "$(uname)" != "Linux" ]; then 108 | return 0 109 | fi 110 | 111 | MILL_IN_PATH="$(command -v mill || true)" 112 | 113 | if [ -z "${MILL_IN_PATH}" ]; then 114 | return 0 115 | fi 116 | 117 | SYSTEM_MILL_FIRST_TWO_BYTES=$(head --bytes=2 "${MILL_IN_PATH}") 118 | if [ "${SYSTEM_MILL_FIRST_TWO_BYTES}" = "#!" ]; then 119 | # MILL_IN_PATH is (very likely) a shell script and not the mill 120 | # executable, ignore it. 121 | return 0 122 | fi 123 | 124 | SYSTEM_MILL_PATH=$(readlink -e "${MILL_IN_PATH}") 125 | SYSTEM_MILL_SIZE=$(stat --format=%s "${SYSTEM_MILL_PATH}") 126 | SYSTEM_MILL_MTIME=$(stat --format=%y "${SYSTEM_MILL_PATH}") 127 | 128 | if [ ! -d "${MILL_USER_CACHE_DIR}" ]; then 129 | mkdir -p "${MILL_USER_CACHE_DIR}" 130 | fi 131 | 132 | SYSTEM_MILL_INFO_FILE="${MILL_USER_CACHE_DIR}/system-mill-info" 133 | if [ -f "${SYSTEM_MILL_INFO_FILE}" ]; then 134 | parseSystemMillInfo() { 135 | LINE_NUMBER="${1}" 136 | # Select the line number of the SYSTEM_MILL_INFO_FILE, cut the 137 | # variable definition in that line in two halves and return 138 | # the value, and finally remove the quotes. 139 | sed -n "${LINE_NUMBER}p" "${SYSTEM_MILL_INFO_FILE}" |\ 140 | cut -d= -f2 |\ 141 | sed 's/"\(.*\)"/\1/' 142 | } 143 | 144 | CACHED_SYSTEM_MILL_PATH=$(parseSystemMillInfo 1) 145 | CACHED_SYSTEM_MILL_VERSION=$(parseSystemMillInfo 2) 146 | CACHED_SYSTEM_MILL_SIZE=$(parseSystemMillInfo 3) 147 | CACHED_SYSTEM_MILL_MTIME=$(parseSystemMillInfo 4) 148 | 149 | if [ "${SYSTEM_MILL_PATH}" = "${CACHED_SYSTEM_MILL_PATH}" ] \ 150 | && [ "${SYSTEM_MILL_SIZE}" = "${CACHED_SYSTEM_MILL_SIZE}" ] \ 151 | && [ "${SYSTEM_MILL_MTIME}" = "${CACHED_SYSTEM_MILL_MTIME}" ]; then 152 | if [ "${CACHED_SYSTEM_MILL_VERSION}" = "${MILL_VERSION}" ]; then 153 | MILL="${SYSTEM_MILL_PATH}" 154 | return 0 155 | else 156 | return 0 157 | fi 158 | fi 159 | fi 160 | 161 | SYSTEM_MILL_VERSION=$(${SYSTEM_MILL_PATH} --version | head -n1 | sed -n 's/^Mill.*version \(.*\)/\1/p') 162 | 163 | cat < "${SYSTEM_MILL_INFO_FILE}" 164 | CACHED_SYSTEM_MILL_PATH="${SYSTEM_MILL_PATH}" 165 | CACHED_SYSTEM_MILL_VERSION="${SYSTEM_MILL_VERSION}" 166 | CACHED_SYSTEM_MILL_SIZE="${SYSTEM_MILL_SIZE}" 167 | CACHED_SYSTEM_MILL_MTIME="${SYSTEM_MILL_MTIME}" 168 | EOF 169 | 170 | if [ "${SYSTEM_MILL_VERSION}" = "${MILL_VERSION}" ]; then 171 | MILL="${SYSTEM_MILL_PATH}" 172 | fi 173 | } 174 | try_to_use_system_mill 175 | 176 | # If not already downloaded, download it 177 | if [ ! -s "${MILL}" ] ; then 178 | 179 | # support old non-XDG download dir 180 | MILL_OLD_DOWNLOAD_PATH="${HOME}/.mill/download" 181 | OLD_MILL="${MILL_OLD_DOWNLOAD_PATH}/${MILL_VERSION}" 182 | if [ -x "${OLD_MILL}" ] ; then 183 | MILL="${OLD_MILL}" 184 | else 185 | case $MILL_VERSION in 186 | 0.0.* | 0.1.* | 0.2.* | 0.3.* | 0.4.* ) 187 | DOWNLOAD_SUFFIX="" 188 | DOWNLOAD_FROM_MAVEN=0 189 | ;; 190 | 0.5.* | 0.6.* | 0.7.* | 0.8.* | 0.9.* | 0.10.* | 0.11.0-M* ) 191 | DOWNLOAD_SUFFIX="-assembly" 192 | DOWNLOAD_FROM_MAVEN=0 193 | ;; 194 | *) 195 | DOWNLOAD_SUFFIX="-assembly" 196 | DOWNLOAD_FROM_MAVEN=1 197 | ;; 198 | esac 199 | 200 | DOWNLOAD_FILE=$(mktemp mill.XXXXXX) 201 | 202 | if [ "$DOWNLOAD_FROM_MAVEN" = "1" ] ; then 203 | DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/${MILL_VERSION}/mill-dist-${MILL_VERSION}.jar" 204 | else 205 | MILL_VERSION_TAG=$(echo "$MILL_VERSION" | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') 206 | DOWNLOAD_URL="${GITHUB_RELEASE_CDN}${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" 207 | unset MILL_VERSION_TAG 208 | fi 209 | 210 | # TODO: handle command not found 211 | echo "Downloading mill ${MILL_VERSION} from ${DOWNLOAD_URL} ..." 1>&2 212 | ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" "${DOWNLOAD_URL}" 213 | chmod +x "${DOWNLOAD_FILE}" 214 | mkdir -p "${MILL_DOWNLOAD_PATH}" 215 | mv "${DOWNLOAD_FILE}" "${MILL}" 216 | 217 | unset DOWNLOAD_FILE 218 | unset DOWNLOAD_SUFFIX 219 | fi 220 | fi 221 | 222 | if [ -z "$MILL_MAIN_CLI" ] ; then 223 | MILL_MAIN_CLI="${0}" 224 | fi 225 | 226 | MILL_FIRST_ARG="" 227 | if [ "$1" = "--bsp" ] || [ "$1" = "-i" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then 228 | # Need to preserve the first position of those listed options 229 | MILL_FIRST_ARG=$1 230 | shift 231 | fi 232 | 233 | unset MILL_DOWNLOAD_PATH 234 | unset MILL_OLD_DOWNLOAD_PATH 235 | unset OLD_MILL 236 | unset MILL_VERSION 237 | unset MILL_REPO_URL 238 | 239 | # We don't quote MILL_FIRST_ARG on purpose, so we can expand the empty value without quotes 240 | # shellcheck disable=SC2086 241 | exec "${MILL}" $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" --------------------------------------------------------------------------------