diff --git a/.gitignore b/.gitignore index 9291deb..e2d164b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ verilog_RTL # files generated for FPGA ULX3s implementation ulx3s_fpga/mkTop.d ulx3s_fpga/mkTop.json +ulx3s_fpga/mkTop.bit +ulx3s_fpga/mkTop.config # generated experiment outputs experiments/bram/*.cxx diff --git a/Makefile b/Makefile index 28921c9..1a42d46 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,7 @@ b_all: b_compile b_link b_sim b_compile: mkdir -p build_b_sim @echo Compiling for Bluesim ... - bsc -u -sim $(B_SIM_DIRS) $(BSC_COMP_FLAGS) $(BSC_PATHS) -g $(TOPMODULE) $(TOPFILE) + bsc -u -sim $(B_SIM_DIRS) $(BSC_COMP_FLAGS) $(BSC_PATHS) -g $(TOPMODULE) $(TOPFILE) @echo Compiling for Bluesim finished .PHONY: b_link @@ -141,7 +141,7 @@ v_compile: .PHONY: v_link v_link: $(BDPI_OBJ) @echo Linking for Verilog sim ... - bsc -e $(TOPMODULE) -verilog -o ./$(V_SIM_EXE) $(V_DIRS) -vsim $(V_SIM) verilog_RTL/$(TOPMODULE).v + bsc -e $(TOPMODULE) -verilog -o ./$(V_SIM_EXE) $(V_DIRS) -vsim $(V_SIM) verilog_RTL/$(TOPMODULE).v @echo Linking for Verilog sim finished .PHONY: v_sim @@ -159,7 +159,7 @@ v_sim_vcd: # ---------------------------------------------------------------- fpga: - make -C ulx3s_fpga + make -C ulx3s_fpga mkTop.bit .PHONY: clean clean: diff --git a/bs/Bus/Bus.bs b/bs/Bus/Bus.bs index 2386995..67e96dc 100644 --- a/bs/Bus/Bus.bs +++ b/bs/Bus/Bus.bs @@ -30,8 +30,8 @@ mkBus serverMap = do tagEngineByClientVec :: Vector numClients (TagEngine inFlightTransactions) tagEngineByClientVec <- replicateM mkTagEngine - -- There are `numClients` clients, each of which needs its own client - -- response arbiter as there are `numServer` servers that may wish to + -- There are `numClients` clients, each of which needs its own client + -- response arbiter as there are `numServer` servers that may wish to -- submit a response to a given client. Furthermore the rule that routes -- client requests to servers makes for another potential submitter to -- the client response arbiter as it may determine that a request is @@ -56,7 +56,7 @@ mkBus serverMap = do clientResponseQueues :: Vector numClients (FIFOF (TaggedBusResponse inFlightTransactions)) clientResponseQueues <- replicateM (mkSizedBypassFIFOF (valueOf inFlightTransactions)) - -- The following two vectors of single depth FIFOs make it easier to push/pull data + -- The following two vectors of single depth FIFOs make it easier to push/pull data -- to/from internal server methods as they provide back-pressure in both directions, -- and behave as a wire when queue is empty. -- If looking at the example bus.drawio diagram, the following two vectors effectively @@ -89,7 +89,7 @@ mkBus serverMap = do selectedClientRespArbiter = select responseArbiterByClient clientIdx clientRouterRule :: Rules - clientRouterRule = clientRouteRequest + clientRouterRule = clientRouteRequest clientIdx selectedClientReqQueue requestArbiterByServer diff --git a/bs/ClkDivider.bs b/bs/ClkDivider.bs index cd94bc9..ab39cab 100644 --- a/bs/ClkDivider.bs +++ b/bs/ClkDivider.bs @@ -34,7 +34,7 @@ mkClkDivider fileHandle = do counter := if (counter == hi_value) then 0 else counter + 1 - + return $ interface ClkDivider reset :: Action diff --git a/bs/Deserializer.bs b/bs/Deserializer.bs index 51c98ed..cebc355 100644 --- a/bs/Deserializer.bs +++ b/bs/Deserializer.bs @@ -1,15 +1,15 @@ package Deserializer( mkDeserialize, IDeserializer(..), - State(..)) + State(..)) where import ClkDivider import State -interface (IDeserializer :: # -> # -> *) clkFreq baudRate = - get :: Bit 8 +interface (IDeserializer :: # -> # -> *) clkFreq baudRate = + get :: Bit 8 putBitIn :: (Bit 1) -> Action {-# always_enabled, always_ready #-} mkDeserialize :: Handle -> Module (IDeserializer clkFreq baudRate) @@ -35,10 +35,10 @@ mkDeserialize fileHandle = do ftdiState := ftdiState' ftdiState {-# ASSERT fire when enabled #-} - "SAMPLING" : when + "SAMPLING" : when DATA(n) <- ftdiState, n >= 0, - n <= 7, + n <= 7, let sampleTrigger = clkDivider.isHalfCycle in sampleTrigger ==> @@ -48,6 +48,6 @@ mkDeserialize fileHandle = do return $ interface IDeserializer {get = shiftReg when (ftdiState == STOP), (clkDivider.isAdvancing) - ;putBitIn bit = + ;putBitIn bit = ftdiRxIn := bit } \ No newline at end of file diff --git a/bs/Serializer.bs b/bs/Serializer.bs index acfb196..ff445fa 100644 --- a/bs/Serializer.bs +++ b/bs/Serializer.bs @@ -1,7 +1,7 @@ package Serializer( mkSerialize, ISerializer(..), - State(..)) + State(..)) where import ClkDivider @@ -14,7 +14,7 @@ serialize ftdiState dataReg = (DATA n) -> dataReg[n:n] _ -> 1'b1 -interface (ISerializer :: # -> # -> *) clkFreq baudRate = +interface (ISerializer :: # -> # -> *) clkFreq baudRate = putBit8 :: (Bit 8) -> Action {-# always_enabled, always_ready #-} bitLineOut :: Bit 1 {-# always_ready #-} @@ -29,8 +29,8 @@ mkSerialize fileHandle = do addRules $ rules {-# ASSERT fire when enabled #-} - "ADVANCE UART STATE WHEN NOT IDLE" : when - (ftdiState /= IDLE), + "ADVANCE UART STATE WHEN NOT IDLE" : when + (ftdiState /= IDLE), (clkDivider.isAdvancing) ==> do ftdiState := ftdiState' ftdiState @@ -42,11 +42,10 @@ mkSerialize fileHandle = do return $ interface ISerializer - putBit8 bit8Val = + putBit8 bit8Val = do clkDivider.reset - dataReg := bit8Val + dataReg := bit8Val ftdiState := ftdiState' ftdiState when (ftdiState == IDLE) bitLineOut = ftdiTxOut - \ No newline at end of file diff --git a/bs/State.bs b/bs/State.bs index e68a482..0186f2a 100644 --- a/bs/State.bs +++ b/bs/State.bs @@ -2,15 +2,15 @@ package State( State(..), ftdiState') where -data State = IDLE - | START - | DATA (UInt (TLog 8)) - | PARITY +data State = IDLE + | START + | DATA (UInt (TLog 8)) + | PARITY | STOP deriving (Bits, Eq, FShow) ftdiState' :: State -> State -ftdiState' state = +ftdiState' state = case state of IDLE -> START START -> DATA(0) diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..2ba2a3e --- /dev/null +++ b/default.nix @@ -0,0 +1,25 @@ +{ + system ? builtins.currentSystem, +}: +let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + + root = lock.nodes.${lock.root}; + inherit (lock.nodes.${root.inputs.flake-compat}.locked) + owner + repo + rev + narHash + ; + + flake-compat = fetchTarball { + url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; + sha256 = narHash; + }; + + flake = import flake-compat { + inherit system; + src = ./.; + }; +in +flake.defaultNix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d3a02b0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..6f8f727 --- /dev/null +++ b/flake.nix @@ -0,0 +1,78 @@ +{ + inputs = { + nixpkgs = { + url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + }; + utils.url = "github:numtide/flake-utils"; + }; + + outputs = + inputs: + inputs.utils.lib.eachDefaultSystem ( + system: + let + pkgs = import inputs.nixpkgs { + localSystem = system; + overlays = [ + (final: prev: { + + riscv-bluespec-classic = pkgs.callPackage ( + { + stdenv, + bluespec, + nextpnr, + openfpgaloader, + trellis, + which, + yosys, + }: + stdenv.mkDerivation { + pname = "riscv-bluespec-classic"; + version = "0.1.0"; + src = ./.; + + # Versions can be checked with + # `nix eval --json ".#riscv-bluespec-classic.nativeBuildInputs" | nix-shell -p jq --run jq` + nativeBuildInputs = [ + bluespec + nextpnr + openfpgaloader + trellis + which + yosys + ]; + + makeFlags = [ + "fpga" + ]; + + installPhase = '' + runHook preInstall + + mkdir -p "$out" + cp "./ulx3s_fpga/mkTop.bit" "$out/" + + runHook postInstall + ''; + + } + ) { }; + + }) + ]; + }; + in + { + packages = { + default = inputs.self.packages."${system}".riscv-bluespec-classic; + riscv-bluespec-classic = pkgs.riscv-bluespec-classic; + }; + + devShells.default = + with pkgs; + mkShell { + inputsFrom = [ riscv-bluespec-classic ]; + }; + } + ); +} diff --git a/shell.nix b/shell.nix index 328453b..9332b75 100644 --- a/shell.nix +++ b/shell.nix @@ -1,14 +1,25 @@ -{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/d34a98666913267786d9ab4aa803a1fc75f81f4d.tar.gz") {} }: +{ + system ? builtins.currentSystem, +}: +let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); -pkgs.mkShell { - buildInputs = [ - pkgs.yosys - pkgs.nextpnr - pkgs.bluespec - pkgs.yosys-bluespec - ]; + root = lock.nodes.${lock.root}; + inherit (lock.nodes.${root.inputs.flake-compat}.locked) + owner + repo + rev + narHash + ; - shellHook = '' - echo "Dev environment for Manna Chip." - ''; -} \ No newline at end of file + flake-compat = fetchTarball { + url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; + sha256 = narHash; + }; + + flake = import flake-compat { + inherit system; + src = ./.; + }; +in +flake.shellNix diff --git a/ulx3s_fpga/makefile b/ulx3s_fpga/makefile index 681fade..ea44793 100644 --- a/ulx3s_fpga/makefile +++ b/ulx3s_fpga/makefile @@ -5,7 +5,7 @@ IDCODE ?= 0x41113043 # 85f all: prog -../verilog_RTL/$(TOPMODULE).v: ../src/Top.bsv +../verilog_RTL/$(TOPMODULE).v: ../bs/Top.bs V_SIM=verilator TOPMODULE=$(TOPMODULE) make -C ../ v_compile $(TOPMODULE).json: ../verilog_RTL/$(TOPMODULE).v @@ -21,6 +21,7 @@ $(TOPMODULE).config: $(TOPMODULE).json --textcfg $@ \ --lpf ulx3s_v20.lpf \ --85k \ + --lpf-allow-unconstrained \ --package CABGA381 $(TOPMODULE).bit: $(TOPMODULE).config