* build.sh: compile as `quartus_sh --flow compile <project> -c <revision>`
(the .qpf is the project, each .qsf a revision) - matching the Jenkins CI.
coreMZ has revisions coreMZ_E115/E75[_emuMZ|_SoftCPU]; CPLDs have one
revision == project. Validated: CPLD builds 0 errors.
* docker/QuartusPrime/Dockerfile.{13.0.1,13.1} - self-contained Web-Edition
images (from the MZ80A ones) for the MAX7000 CPLDs and the SW-700 v1.2
Cyclone III FPGA. Dockerfile.17.1 - Quartus 17.1 **Lite** (free, no licence
- the Jenkins CI uses the licensed Standard edition) for the SW-700 v1.3 /
Fusion Cyclone IV EP4CE115/EP4CE75, installed under xvfb with libglib2.0-0.
* setup_tranZPUter.sh + Windows .ps1/.cmd - install Docker + Java, clone
--recurse-submodules (pulls TZFS/zSoft/ZPU transparently), build the three
Quartus images, then build.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
120 lines
7.6 KiB
PowerShell
120 lines
7.6 KiB
PowerShell
#########################################################################################################
|
|
## tranZPUter 80-Column Colour - Build Environment Setup for Windows 10/11 (Docker Desktop)
|
|
## Copyright (c) 2019-2026 Philip Smart <philip.smart@net2net.org>. GPL v3. See license.txt.
|
|
##
|
|
## The two Quartus versions (13.0.1 for the CPLD, 13.1 for the FPGA) run inside self-contained Linux
|
|
## Docker images - the free Web Edition, no licence file. On Windows they run under Docker Desktop.
|
|
## NOTE: each image is large (Quartus adds several GB); allow plenty of disk for Docker Desktop.
|
|
##
|
|
## Usage - EASIEST (window stays open, logged): double-click setup_tranZPUter_windows.cmd
|
|
## Usage - from PowerShell: powershell -NoProfile -ExecutionPolicy Bypass -File .\setup_tranZPUter_windows_native.ps1
|
|
## Private repo: $env:tranZPUter_REPO_URL = "https://git.eaw.app/pdsmart/tranZPUter-private.git"
|
|
#########################################################################################################
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$LogFile = Join-Path $env:TEMP ("setup_tranZPUter_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".log")
|
|
try { Start-Transcript -Path $LogFile -Force | Out-Null } catch {}
|
|
function Pause-Exit ($code) {
|
|
try { Stop-Transcript | Out-Null } catch {}
|
|
Write-Host ""; Write-Host "Full log saved to: $LogFile" -ForegroundColor DarkGray
|
|
if ($env:tranZPUter_ASSUME_YES -ne '1') { Read-Host "Press Enter to close this window" }
|
|
exit $code
|
|
}
|
|
trap { Write-Host ""; Write-Host "[ERROR] $($_ | Out-String)" -ForegroundColor Red; Pause-Exit 1 }
|
|
|
|
function Write-Info ($m) { Write-Host "[INFO] $m" -ForegroundColor Cyan }
|
|
function Write-Ok ($m) { Write-Host "[OK] $m" -ForegroundColor Green }
|
|
function Write-Warn ($m) { Write-Host "[WARN] $m" -ForegroundColor Yellow }
|
|
function Write-Fail ($m) { Write-Host "[FAIL] $m" -ForegroundColor Red; Pause-Exit 1 }
|
|
function Confirm-Yes ($p) { if ($env:tranZPUter_ASSUME_YES -eq '1') { return $true }; $a = Read-Host $p; return ($a -notmatch '^[Nn]') }
|
|
function Test-Cmd ($n) { return [bool](Get-Command $n -ErrorAction SilentlyContinue) }
|
|
function Refresh-Path { $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") }
|
|
function Find-Winget {
|
|
$w = Get-Command winget -ErrorAction SilentlyContinue; if ($w) { return $w.Source }
|
|
$c = Get-ChildItem 'C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*\winget.exe' -ErrorAction SilentlyContinue
|
|
if ($c) { return ($c | Sort-Object FullName)[-1].FullName }; return $null
|
|
}
|
|
|
|
$RepoUrl = if ($env:tranZPUter_REPO_URL) { $env:tranZPUter_REPO_URL } else { "https://git.eaw.app/eaw/tranZPUter.git" }
|
|
$CpldImage = if ($env:tranZPUter_CPLD_IMAGE) { $env:tranZPUter_CPLD_IMAGE } else { "tzpu-quartus:13.0.1" }
|
|
$FpgaImage = if ($env:tranZPUter_FPGA_IMAGE) { $env:tranZPUter_FPGA_IMAGE } else { "tzpu-quartus:13.1" }
|
|
|
|
Write-Host ""
|
|
Write-Host "===========================================================================" -ForegroundColor White
|
|
Write-Host " tranZPUter 80-Column Colour - Windows setup (Docker Desktop)" -ForegroundColor White
|
|
Write-Host "===========================================================================" -ForegroundColor White
|
|
|
|
# --- winget + Git ---
|
|
$WinGet = Find-Winget
|
|
if (-not $WinGet) { Write-Warn "winget not found - install Git + Docker Desktop manually if missing." }
|
|
if (-not (Test-Cmd git)) {
|
|
if (-not $WinGet) { Write-Fail "Git not found and winget unavailable. Install Git for Windows, then re-run." }
|
|
Write-Info "Installing Git for Windows..."
|
|
& $WinGet install --id Git.Git -e --source winget --accept-package-agreements --accept-source-agreements
|
|
Refresh-Path
|
|
if (-not (Test-Cmd git)) { Write-Fail "Git install did not complete. Open a new PowerShell and re-run." }
|
|
}
|
|
Write-Ok "Git: $((git --version))"
|
|
|
|
# --- Docker Desktop ---
|
|
if (-not (Test-Cmd docker)) {
|
|
if (-not $WinGet) { Write-Fail "Docker not found and winget unavailable. Install Docker Desktop, then re-run." }
|
|
Write-Info "Installing Docker Desktop..."
|
|
& $WinGet install --id Docker.DockerDesktop -e --source winget --accept-package-agreements --accept-source-agreements
|
|
Refresh-Path
|
|
Write-Warn "Docker Desktop installed - START IT (system tray), wait until it reports Running, then re-run this script."
|
|
Pause-Exit 0
|
|
}
|
|
try { & docker info *> $null; if ($LASTEXITCODE -ne 0) { throw } } catch { Write-Fail "Docker is installed but not running - start Docker Desktop (wait for 'Running'), then re-run." }
|
|
Write-Ok "Docker is available and running."
|
|
|
|
# --- Repository ---
|
|
$DefaultProj = if ($env:tranZPUter_DIR) { $env:tranZPUter_DIR.TrimEnd('\') } else { Join-Path $HOME "tranZPUter" }
|
|
if ($env:tranZPUter_DIR) { $ProjDir = $DefaultProj }
|
|
else { $inp = Read-Host " Checkout directory [$DefaultProj]"; $ProjDir = if ([string]::IsNullOrWhiteSpace($inp)) { $DefaultProj } else { $inp.Trim() } }
|
|
function Is-Checkout ($d) { return ((Test-Path (Join-Path $d "build.sh")) -and (Test-Path (Join-Path $d "docker\QuartusPrime"))) }
|
|
if (Is-Checkout $ProjDir) {
|
|
Write-Ok "Existing checkout at $ProjDir - updating."
|
|
Push-Location $ProjDir; try { & git pull --ff-only 2>&1 | Out-Null } finally { Pop-Location }
|
|
} else {
|
|
if ((Test-Path $ProjDir) -and (Get-ChildItem $ProjDir -Force -ErrorAction SilentlyContinue)) { Write-Fail "$ProjDir exists and is not an tranZPUter checkout." }
|
|
$cloned = $false
|
|
for ($i=1; $i -le 5; $i++) {
|
|
Write-Info "Cloning $RepoUrl into $ProjDir (attempt $i of 5)..."
|
|
& git clone --recurse-submodules $RepoUrl $ProjDir; if (($LASTEXITCODE -eq 0) -and (Is-Checkout $ProjDir)) { $cloned=$true; break }
|
|
if (Test-Path $ProjDir) { Remove-Item -Recurse -Force $ProjDir -ErrorAction SilentlyContinue }; Start-Sleep 3
|
|
}
|
|
if (-not $cloned) { Write-Fail "git clone failed after 5 attempts." }
|
|
Write-Ok "Cloned into $ProjDir."
|
|
}
|
|
|
|
# --- Build the two Quartus Docker images ---
|
|
function Build-Image ($dockerfile, $tag, $name) {
|
|
& docker image inspect $tag *> $null
|
|
if ($LASTEXITCODE -eq 0) { Write-Ok "$name image ($tag) already built."; return }
|
|
Write-Info "Building the $name Quartus image ($tag) - downloads ~1.5 GB + installs Quartus (~20-40 min)..."
|
|
& docker build -f (Join-Path $ProjDir "docker\QuartusPrime\$dockerfile") -t $tag (Join-Path $ProjDir "docker\QuartusPrime")
|
|
if ($LASTEXITCODE -ne 0) { Write-Fail "Failed to build the $name image." }
|
|
Write-Ok "$name image built ($tag)."
|
|
}
|
|
Build-Image "Dockerfile.13.0.1" $CpldImage "CPLD (Quartus 13.0.1)"
|
|
Build-Image "Dockerfile.13.1" "tzpu-quartus:13.1" "FPGA SW-700 v1.2 (Quartus 13.1)"
|
|
Build-Image "Dockerfile.17.1" "tzpu-quartus:17.1" "FPGA SW-700 v1.3 (Quartus 17.1)"
|
|
|
|
$bashProj = ($ProjDir -replace '\\','/')
|
|
Write-Host ""
|
|
if (Confirm-Yes "Build everything now (ROMs + CPLD + FPGA)? [Y/n]") {
|
|
$Bash = "C:\Program Files\Git\bin\bash.exe"
|
|
if (Test-Path $Bash) {
|
|
& $Bash -lc "cd '$bashProj' && tranZPUter_CPLD_IMAGE='$CpldImage' tranZPUter_FPGA_IMAGE='$FpgaImage' ./build.sh -t all"
|
|
} else { Write-Warn "Git Bash not found; run './build.sh -t all' from Git Bash manually." }
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "===========================================================================" -ForegroundColor White
|
|
Write-Host " Ready. In Git Bash: cd $bashProj && ./build.sh -t all" -ForegroundColor White
|
|
Write-Host " Outputs: CPLD/build/output_files/VideoInterface.pof," -ForegroundColor White
|
|
Write-Host " FPGA/build/output_files/VideoController.sof (+ .jic EPCS16 boot flash)." -ForegroundColor White
|
|
Write-Host "===========================================================================" -ForegroundColor White
|
|
Pause-Exit 0
|