Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
25fd8bb
Upgraded version of package dependencies.
Morgan2010 Apr 9, 2024
83cca8c
Changed init to reflect new model format for Arrangement.
Morgan2010 Apr 9, 2024
38c2dd1
Commit old test that is printing arrangement.
Morgan2010 Apr 9, 2024
79be24a
Separated init into inits on 3 separate types.
Morgan2010 Apr 9, 2024
ea4d257
Created machines folder.
Morgan2010 Apr 10, 2024
c6e9894
Created structure for Arrangement testing.
Morgan2010 Apr 10, 2024
a452f4d
Moved FileTester into separate TestHelpers target.
Morgan2010 Apr 10, 2024
b2af31f
Added some common test constants.
Morgan2010 Apr 10, 2024
4bde43a
Moved target-specific properties into target.
Morgan2010 Apr 10, 2024
6b68d47
Moved property into global FileTester.
Morgan2010 Apr 10, 2024
a11e9d2
Inherit from Transformations File Tester.
Morgan2010 Apr 10, 2024
e7667f7
Added ping machine model.
Morgan2010 Apr 10, 2024
204590c
Added encoder and decoder.
Morgan2010 Apr 10, 2024
a8f3e30
Removed folder correctly.
Morgan2010 Apr 10, 2024
e129cd3
Now depend on VHDLMachines version 3.1.0.
Morgan2010 Apr 10, 2024
f2f6c1b
Added global mappings into javascript model.
Morgan2010 Apr 10, 2024
b7d74e9
Added math_real includes.
Morgan2010 Apr 10, 2024
6898d71
Trying to test arrangement creation.
Morgan2010 Apr 10, 2024
441e8cc
Converting global mappings.
Morgan2010 Apr 10, 2024
1ad0ad4
Made MAchineMapping init shorter by using new VariableMapping init.
Morgan2010 Apr 10, 2024
090fee3
Fixed error where transitions were pointing to the wrong states.
Morgan2010 Apr 10, 2024
def43a5
Tested arrangement initialisation from model.
Morgan2010 Apr 10, 2024
8813279
Finished testing conversion init for Arrangement.
Morgan2010 Apr 10, 2024
2039b10
Moved ping arrangement creation into TestHelpers.
Morgan2010 Apr 10, 2024
a7c9d7f
Created relative path test that fails.
Morgan2010 Apr 10, 2024
27220d4
Added basePath to initialiser to allow relative paths in Arrangement …
Morgan2010 Apr 10, 2024
980c3a7
Removed print and merged guards.
Morgan2010 Apr 10, 2024
4f8c2a8
Made basePath nil by default.
Morgan2010 Apr 10, 2024
738ed65
Removed print test.
Morgan2010 Apr 11, 2024
c78652e
Added FileHelper for the MachineGeneratorTests target.
Morgan2010 Apr 11, 2024
47bb3fd
Created test for arrangement creation.
Morgan2010 Apr 11, 2024
0cf1325
Finished testing arrangement generation.
Morgan2010 Apr 11, 2024
141a41b
Created test for arrangement creation.
Morgan2010 Apr 11, 2024
0b6d078
Create name before generation.
Morgan2010 Apr 11, 2024
958643a
Added more tests for arrangement creation.
Morgan2010 Apr 11, 2024
390af88
Linted file.
Morgan2010 Apr 11, 2024
25632fd
Tested cleaning arrangements.
Morgan2010 Apr 11, 2024
c9276b5
Move away from setup-swift action.
Morgan2010 Apr 11, 2024
2c72d17
Add TestHelpers dependency to MachineGeneratorTests.
Morgan2010 Apr 11, 2024
63e0567
Changed dependency to TestHelpers.
Morgan2010 Apr 11, 2024
e28d5d4
Deleted FileTester.
Morgan2010 Apr 11, 2024
1f173e2
Upgrade macos workflows to use macos14.
Morgan2010 Apr 16, 2024
906b2e0
Updated version to 1.4.0.
Morgan2010 Apr 16, 2024
2ab12c0
Changed test to use strings instead of URL causing crash on macOS.
Morgan2010 Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: swift-actions/setup-swift@v1
- uses: slashmo/install-swift@v0.4.0
with:
swift-version: ${{ matrix.swift }}
version: ${{ matrix.swift }}

- name: Setup SSH Key
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-macOS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
build_macos:
strategy:
matrix:
os: [macos-13]
os: [macos-14]
build_mode: ["debug", "release"]
name: Swift ${{ matrix.build_mode }} CI for ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
runs-on: ubuntu-20.04

steps:
- uses: swift-actions/setup-swift@v1
- uses: slashmo/install-swift@v0.4.0
with:
swift-version: "5.9"
version: "5.9"

- name: Setup SSH Key
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-20.04

steps:
- uses: swift-actions/setup-swift@v1
- uses: slashmo/install-swift@v0.4.0
with:
swift-version: "5.9"
version: "5.9"

- name: Setup SSH Key
run: |
Expand Down
15 changes: 11 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
.package(url: "https://github.com/mipalgu/VHDLMachines", from: "2.1.0"),
.package(url: "https://github.com/mipalgu/VHDLMachines", from: "3.1.0"),
.package(url: "https://github.com/mipalgu/VHDLParsing", from: "2.4.0"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"),
.package(url: "https://github.com/mipalgu/VHDLKripkeStructureGenerator.git", from: "0.2.0"),
.package(url: "https://github.com/mipalgu/VHDLKripkeStructureGenerator.git", from: "0.2.1"),
.package(url: "https://github.com/CPSLabGU/SwiftUtils.git", from: "0.1.0")
],
targets: [
Expand Down Expand Up @@ -63,12 +63,19 @@ let package = Package(
.product(name: "VHDLParsing", package: "VHDLParsing"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "VHDLKripkeStructureGenerator", package: "VHDLKripkeStructureGenerator"),
.product(name: "SwiftUtils", package: "SwiftUtils")
.product(name: "SwiftUtils", package: "SwiftUtils"),
"TestHelpers"
]
),
.testTarget(
name: "VHDLMachineTransformationsTests",
name: "TestHelpers",
dependencies: ["VHDLMachineTransformations", "VHDLParsing", "VHDLMachines", "JavascriptModel"]
),
.testTarget(
name: "VHDLMachineTransformationsTests",
dependencies: [
"VHDLMachineTransformations", "VHDLParsing", "VHDLMachines", "JavascriptModel", "TestHelpers"
]
)
]
)
7 changes: 6 additions & 1 deletion Sources/JavascriptModel/ArrangementModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public struct ArrangementModel: Equatable, Hashable, Codable, Sendable {
/// but cannot affect the outside world.
public var globalVariables: String

/// The mappings between external and global variables.
public var globalMappings: [VariableMapping]

/// Initialise the arrangement from it's stored properties.
/// - Parameters:
/// - clocks: The clocks used in this arrangement.
Expand All @@ -86,12 +89,14 @@ public struct ArrangementModel: Equatable, Hashable, Codable, Sendable {
clocks: [ClockModel],
externalVariables: String,
machines: [MachineReference],
globalVariables: String
globalVariables: String,
globalMappings: [VariableMapping] = []
) {
self.clocks = clocks
self.externalVariables = externalVariables
self.machines = machines
self.globalVariables = globalVariables
self.globalMappings = globalMappings
}

}
5 changes: 4 additions & 1 deletion Sources/MachineGenerator/Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,12 @@ struct Generate: ParsableCommand {
try createModel()
}

/// Create an `Arrangement` from the model.
func createArrangement() throws {
let model = try decoder.decode(ArrangementModel.self, from: model)
guard let arrangement = Arrangement(model: model) else {
guard let arrangement = Arrangement(
model: model, basePath: self.pathURL.deletingLastPathComponent()
) else {
throw GenerationError.invalidGeneration(message: "Cannot create valid arrangement from model.")
}
let data = try encoder.encode(arrangement)
Expand Down
2 changes: 1 addition & 1 deletion Sources/MachineGenerator/LLFSMGenerate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct LLFSMGenerate: ParsableCommand {
static var configuration = CommandConfiguration(
commandName: "llfsmgenerate",
abstract: "A utility for performing operations on LLFSM formats.",
version: "1.3.1",
version: "1.4.0",
subcommands: [Generate.self, VHDLGenerator.self, CleanCommand.self, InstallCommand.self]
)

Expand Down
21 changes: 16 additions & 5 deletions Sources/MachineGenerator/VHDLGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,21 @@ struct VHDLGenerator: ParsableCommand {
try self.createMachine(sourcePath: options.pathURL, destinationPath: buildFolder)
}

// swiftlint:disable function_body_length

/// Create an arrangement.
@inlinable
func createArrangement() throws {
let decoder = JSONDecoder()
let modelData = try Data(
contentsOf: options.pathURL.appendingPathComponent("model.json", isDirectory: false)
)
let model = try decoder.decode(ArrangementModel.self, from: modelData)
let nameRaw = options.pathURL.lastPathComponent.dropLast(".arrangement".count)
.trimmingCharacters(in: .whitespacesAndNewlines)
guard !nameRaw.isEmpty, let name = VariableName(rawValue: nameRaw) else {
throw GenerationError.invalidFormat(message: "The arrangement is not named correctly!")
}
let decoder = JSONDecoder()
let modelData = try Data(
contentsOf: options.pathURL.appendingPathComponent("model.json", isDirectory: false)
)
let model = try decoder.decode(ArrangementModel.self, from: modelData)
let arrangementFile = options.pathURL.appendingPathComponent("arrangement.json", isDirectory: false)
let data = try Data(contentsOf: arrangementFile)
let arrangement = try decoder.decode(Arrangement.self, from: data)
Expand Down Expand Up @@ -155,6 +159,13 @@ struct VHDLGenerator: ParsableCommand {
try vhdlFile.write(to: destination, options: .atomic)
}

// swiftlint:enable function_body_length

/// Create the VHDL for a machine.
/// - Parameters:
/// - sourcePath: The path to the machine to generate.
/// - destinationPath: The folder to store the VHDL generated files.
@inlinable
func createMachine(sourcePath: URL, destinationPath: URL) throws {
let path = sourcePath.appendingPathComponent("machine.json", isDirectory: false)
let data = try Data(contentsOf: path)
Expand Down
135 changes: 94 additions & 41 deletions Sources/VHDLMachineTransformations/Arrangement+modelInit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,39 +58,27 @@ import JavascriptModel
import VHDLMachines
import VHDLParsing

/// Add conversion initialiser between ``ArrangementModel`` and `Arrangement`.
extension Arrangement {

public init?(model: ArrangementModel) {
let decoder = JSONDecoder()
let machineTuples: [(VariableName, MachineMapping)] = model.machines
.compactMap { (reference: MachineReference) -> (VariableName, MachineMapping)? in
let url = URL(fileURLWithPath: reference.path, isDirectory: true)
guard
let name = VariableName(rawValue: reference.name),
let data = try? Data(
contentsOf: url.appendingPathComponent("model.json", isDirectory: false)
),
let machineModel = try? decoder.decode(MachineModel.self, from: data),
let machine = Machine(model: machineModel)
else {
return nil
}
let mappings: [VHDLMachines.VariableMapping] = reference.mappings.compactMap {
guard
let source = VariableName(rawValue: $0.source),
let destination = VariableName(rawValue: $0.destination)
else {
return nil
}
return VHDLMachines.VariableMapping(source: source, destination: destination)
}
/// Create an `Arrangement` from its javascript representation.
/// - Parameter model: The javascript model to convert.
/// - Parameter basePath: The path of the directory containing the arrangement folder.
@inlinable
public init?(model: ArrangementModel, basePath: URL? = nil) {
let keyNames = model.machines.map(\.name)
guard keyNames.count == Set(keyNames).count else {
return nil
}
let machineTuples: [(MachineInstance, MachineMapping)] = model.machines
.compactMap { (reference: MachineReference) -> (MachineInstance, MachineMapping)? in
guard
mappings.count == reference.mappings.count,
let mapping = MachineMapping(machine: machine, with: mappings)
let instance = MachineInstance(reference: reference),
let mapping = MachineMapping(reference: reference, basePath: basePath)
else {
return nil
}
return (name, mapping)
return (instance, mapping)
}
guard
machineTuples.count == model.machines.count,
Expand All @@ -102,32 +90,97 @@ extension Arrangement {
let externalsRaw = model.externalVariables.components(separatedBy: ";")
.filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
let externalSignals = externalsRaw.compactMap { PortSignal(rawValue: $0 + ";") }
guard externalSignals.count == externalsRaw.count else {
return nil
}
let signalsRaw = model.globalVariables.components(separatedBy: ";")
.filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
let localSignals = signalsRaw.compactMap { LocalSignal(rawValue: $0 + ";") }
guard localSignals.count == signalsRaw.count else {
return nil
}
let clocks = model.clocks.compactMap { Clock(model: $0) }
guard clocks.count == model.clocks.count else {
return nil
}
let clockNames = clocks.map(\.name)
let signalNames = localSignals.map(\.name) + externalSignals.map(\.name)
let machineNames: [VariableName] = Array(machines.keys)
let allNames = clockNames + signalNames + machineNames
guard Set(allNames).count == allNames.count else {
let allNames = clockNames + signalNames
let globalMappings = model.globalMappings.compactMap {
VHDLMachines.VariableMapping(mapping: $0)
}
guard
externalSignals.count == externalsRaw.count,
localSignals.count == signalsRaw.count,
clocks.count == model.clocks.count,
globalMappings.count == model.globalMappings.count,
Set(allNames).count == allNames.count
else {
return nil
}
self.init(
machines: machines,
mappings: machines,
externalSignals: externalSignals,
signals: localSignals,
clocks: clocks
clocks: clocks,
globalMappings: globalMappings
)
}

}

/// Add init from javascript model.
extension MachineInstance {

/// Create a `MachineInstace` from its javascript model.
/// - Parameter reference: The ``MachineReferece`` js model to convert.
@inlinable
init?(reference: MachineReference) {
let url = URL(fileURLWithPath: reference.path, isDirectory: true)
let nameRaw = url.lastPathComponent
guard
nameRaw.hasSuffix(".machine"),
let name = VariableName(rawValue: reference.name),
let type = VariableName(rawValue: String(nameRaw.dropLast(8)))
else {
return nil
}
self.init(name: name, type: type)
}

}

/// Add init from js model.
extension MachineMapping {

/// Create a `MachineMapping` from its javascript model.
/// - Parameter reference: The ``MachineReferece`` js model to convert.
/// - Parameter basePath: The path of the directory containing the arrangement folder.
@inlinable
init?(reference: MachineReference, basePath: URL? = nil) {
let url = URL(fileURLWithPath: reference.path, isDirectory: true, relativeTo: basePath)
.appendingPathComponent("model.json", isDirectory: false)
let mappings: [VHDLMachines.VariableMapping] = reference.mappings.compactMap {
VHDLMachines.VariableMapping(mapping: $0)
}
guard
mappings.count == reference.mappings.count,
let data = try? Data(contentsOf: url),
let machineModel = try? JSONDecoder().decode(MachineModel.self, from: data),
let machine = Machine(model: machineModel)
else {
return nil
}
self.init(machine: machine, with: mappings)
}

}

/// Add init from js model.
extension VHDLMachines.VariableMapping {

/// Create a `VariableMapping` from its javascript model.
/// - Parameter mapping: The ``VariableMapping`` js model to convert.
@inlinable
init?(mapping: JavascriptModel.VariableMapping) {
guard
let source = VariableName(rawValue: mapping.source),
let destination = VariableName(rawValue: mapping.destination)
else {
return nil
}
self.init(source: source, destination: destination)
}

}
Loading