├── .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}" "$@"
--------------------------------------------------------------------------------