Merge pull request 'Add flake' (#7) from Artturin/riscv-bluespec-classic:addflake into main

Reviewed-on: #7
This commit is contained in:
Yehowshua 2025-04-18 19:35:18 +00:00
commit d03cceb283
12 changed files with 216 additions and 39 deletions

2
.gitignore vendored
View file

@ -16,6 +16,8 @@ verilog_RTL
# files generated for FPGA ULX3s implementation # files generated for FPGA ULX3s implementation
ulx3s_fpga/mkTop.d ulx3s_fpga/mkTop.d
ulx3s_fpga/mkTop.json ulx3s_fpga/mkTop.json
ulx3s_fpga/mkTop.bit
ulx3s_fpga/mkTop.config
# generated experiment outputs # generated experiment outputs
experiments/bram/*.cxx experiments/bram/*.cxx

View file

@ -99,7 +99,7 @@ b_all: b_compile b_link b_sim
b_compile: b_compile:
mkdir -p build_b_sim mkdir -p build_b_sim
@echo Compiling for Bluesim ... @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 @echo Compiling for Bluesim finished
.PHONY: b_link .PHONY: b_link
@ -141,7 +141,7 @@ v_compile:
.PHONY: v_link .PHONY: v_link
v_link: $(BDPI_OBJ) v_link: $(BDPI_OBJ)
@echo Linking for Verilog sim ... @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 @echo Linking for Verilog sim finished
.PHONY: v_sim .PHONY: v_sim
@ -159,7 +159,7 @@ v_sim_vcd:
# ---------------------------------------------------------------- # ----------------------------------------------------------------
fpga: fpga:
make -C ulx3s_fpga make -C ulx3s_fpga mkTop.bit
.PHONY: clean .PHONY: clean
clean: clean:

View file

@ -30,8 +30,8 @@ mkBus serverMap = do
tagEngineByClientVec :: Vector numClients (TagEngine inFlightTransactions) tagEngineByClientVec :: Vector numClients (TagEngine inFlightTransactions)
tagEngineByClientVec <- replicateM mkTagEngine tagEngineByClientVec <- replicateM mkTagEngine
-- There are `numClients` clients, each of which needs its own client -- There are `numClients` clients, each of which needs its own client
-- response arbiter as there are `numServer` servers that may wish to -- response arbiter as there are `numServer` servers that may wish to
-- submit a response to a given client. Furthermore the rule that routes -- submit a response to a given client. Furthermore the rule that routes
-- client requests to servers makes for another potential submitter to -- client requests to servers makes for another potential submitter to
-- the client response arbiter as it may determine that a request is -- 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 :: Vector numClients (FIFOF (TaggedBusResponse inFlightTransactions))
clientResponseQueues <- replicateM (mkSizedBypassFIFOF (valueOf 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, -- to/from internal server methods as they provide back-pressure in both directions,
-- and behave as a wire when queue is empty. -- and behave as a wire when queue is empty.
-- If looking at the example bus.drawio diagram, the following two vectors effectively -- If looking at the example bus.drawio diagram, the following two vectors effectively
@ -89,7 +89,7 @@ mkBus serverMap = do
selectedClientRespArbiter = select responseArbiterByClient clientIdx selectedClientRespArbiter = select responseArbiterByClient clientIdx
clientRouterRule :: Rules clientRouterRule :: Rules
clientRouterRule = clientRouteRequest clientRouterRule = clientRouteRequest
clientIdx clientIdx
selectedClientReqQueue selectedClientReqQueue
requestArbiterByServer requestArbiterByServer

View file

@ -34,7 +34,7 @@ mkClkDivider fileHandle = do
counter := if (counter == hi_value) counter := if (counter == hi_value)
then 0 then 0
else counter + 1 else counter + 1
return $ return $
interface ClkDivider interface ClkDivider
reset :: Action reset :: Action

View file

@ -1,15 +1,15 @@
package Deserializer( package Deserializer(
mkDeserialize, mkDeserialize,
IDeserializer(..), IDeserializer(..),
State(..)) State(..))
where where
import ClkDivider import ClkDivider
import State import State
interface (IDeserializer :: # -> # -> *) clkFreq baudRate = interface (IDeserializer :: # -> # -> *) clkFreq baudRate =
get :: Bit 8 get :: Bit 8
putBitIn :: (Bit 1) -> Action {-# always_enabled, always_ready #-} putBitIn :: (Bit 1) -> Action {-# always_enabled, always_ready #-}
mkDeserialize :: Handle -> Module (IDeserializer clkFreq baudRate) mkDeserialize :: Handle -> Module (IDeserializer clkFreq baudRate)
@ -35,10 +35,10 @@ mkDeserialize fileHandle = do
ftdiState := ftdiState' ftdiState ftdiState := ftdiState' ftdiState
{-# ASSERT fire when enabled #-} {-# ASSERT fire when enabled #-}
"SAMPLING" : when "SAMPLING" : when
DATA(n) <- ftdiState, DATA(n) <- ftdiState,
n >= 0, n >= 0,
n <= 7, n <= 7,
let sampleTrigger = clkDivider.isHalfCycle let sampleTrigger = clkDivider.isHalfCycle
in sampleTrigger in sampleTrigger
==> ==>
@ -48,6 +48,6 @@ mkDeserialize fileHandle = do
return $ return $
interface IDeserializer interface IDeserializer
{get = shiftReg when (ftdiState == STOP), (clkDivider.isAdvancing) {get = shiftReg when (ftdiState == STOP), (clkDivider.isAdvancing)
;putBitIn bit = ;putBitIn bit =
ftdiRxIn := bit ftdiRxIn := bit
} }

View file

@ -1,7 +1,7 @@
package Serializer( package Serializer(
mkSerialize, mkSerialize,
ISerializer(..), ISerializer(..),
State(..)) State(..))
where where
import ClkDivider import ClkDivider
@ -14,7 +14,7 @@ serialize ftdiState dataReg =
(DATA n) -> dataReg[n:n] (DATA n) -> dataReg[n:n]
_ -> 1'b1 _ -> 1'b1
interface (ISerializer :: # -> # -> *) clkFreq baudRate = interface (ISerializer :: # -> # -> *) clkFreq baudRate =
putBit8 :: (Bit 8) -> Action {-# always_enabled, always_ready #-} putBit8 :: (Bit 8) -> Action {-# always_enabled, always_ready #-}
bitLineOut :: Bit 1 {-# always_ready #-} bitLineOut :: Bit 1 {-# always_ready #-}
@ -29,8 +29,8 @@ mkSerialize fileHandle = do
addRules $ addRules $
rules rules
{-# ASSERT fire when enabled #-} {-# ASSERT fire when enabled #-}
"ADVANCE UART STATE WHEN NOT IDLE" : when "ADVANCE UART STATE WHEN NOT IDLE" : when
(ftdiState /= IDLE), (ftdiState /= IDLE),
(clkDivider.isAdvancing) ==> (clkDivider.isAdvancing) ==>
do do
ftdiState := ftdiState' ftdiState ftdiState := ftdiState' ftdiState
@ -42,11 +42,10 @@ mkSerialize fileHandle = do
return $ return $
interface ISerializer interface ISerializer
putBit8 bit8Val = putBit8 bit8Val =
do do
clkDivider.reset clkDivider.reset
dataReg := bit8Val dataReg := bit8Val
ftdiState := ftdiState' ftdiState ftdiState := ftdiState' ftdiState
when (ftdiState == IDLE) when (ftdiState == IDLE)
bitLineOut = ftdiTxOut bitLineOut = ftdiTxOut

View file

@ -2,15 +2,15 @@ package State(
State(..), State(..),
ftdiState') where ftdiState') where
data State = IDLE data State = IDLE
| START | START
| DATA (UInt (TLog 8)) | DATA (UInt (TLog 8))
| PARITY | PARITY
| STOP | STOP
deriving (Bits, Eq, FShow) deriving (Bits, Eq, FShow)
ftdiState' :: State -> State ftdiState' :: State -> State
ftdiState' state = ftdiState' state =
case state of case state of
IDLE -> START IDLE -> START
START -> DATA(0) START -> DATA(0)

25
default.nix Normal file
View file

@ -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

61
flake.lock Normal file
View file

@ -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
}

78
flake.nix Normal file
View file

@ -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 ];
};
}
);
}

View file

@ -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 { root = lock.nodes.${lock.root};
buildInputs = [ inherit (lock.nodes.${root.inputs.flake-compat}.locked)
pkgs.yosys owner
pkgs.nextpnr repo
pkgs.bluespec rev
pkgs.yosys-bluespec narHash
]; ;
shellHook = '' flake-compat = fetchTarball {
echo "Dev environment for Manna Chip." url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz";
''; sha256 = narHash;
} };
flake = import flake-compat {
inherit system;
src = ./.;
};
in
flake.shellNix

View file

@ -5,7 +5,7 @@ IDCODE ?= 0x41113043 # 85f
all: prog 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 V_SIM=verilator TOPMODULE=$(TOPMODULE) make -C ../ v_compile
$(TOPMODULE).json: ../verilog_RTL/$(TOPMODULE).v $(TOPMODULE).json: ../verilog_RTL/$(TOPMODULE).v
@ -21,6 +21,7 @@ $(TOPMODULE).config: $(TOPMODULE).json
--textcfg $@ \ --textcfg $@ \
--lpf ulx3s_v20.lpf \ --lpf ulx3s_v20.lpf \
--85k \ --85k \
--lpf-allow-unconstrained \
--package CABGA381 --package CABGA381
$(TOPMODULE).bit: $(TOPMODULE).config $(TOPMODULE).bit: $(TOPMODULE).config