From 6a45e7c2ecb1e8e2558199e472f6216c23684274 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Thu, 4 Jan 2024 17:49:22 +0200 Subject: [PATCH] Fix Tests (#42) * Changed SPM to an active-low reset design and updated tests accordingly * Fixed bug where newer versions of IcarusVerilog decided to add fluff to the output, breaking it * Switched from https://github.com/lukaskubanek/OrderedDictionary to [Swift Collections](https://github.com/apple/swift-collections) --- Package.resolved | 18 ++--- Package.swift | 4 +- Sources/Fault/Entries/main.swift | 4 +- Sources/Fault/Port.swift | 8 ++- Sources/Fault/Simulation.swift | 5 +- Sources/Fault/Synthesis.swift | 2 +- Tests/FaultTests/FaultTests.swift | 28 +++++--- Tests/RTL/spm.v | 113 ++++++++++++++---------------- shell.nix | 1 + 9 files changed, 91 insertions(+), 92 deletions(-) diff --git a/Package.resolved b/Package.resolved index d507c3f..d7d85a9 100644 --- a/Package.resolved +++ b/Package.resolved @@ -28,15 +28,6 @@ "version": "5.2.1" } }, - { - "package": "OrderedDictionary", - "repositoryURL": "https://github.com/lukaskubanek/OrderedDictionary.git", - "state": { - "branch": null, - "revision": "9adcc6f84c470bd80a29e16887c0f94fea2a783d", - "version": "3.0.1" - } - }, { "package": "PythonKit", "repositoryURL": "https://github.com/pvieito/PythonKit", @@ -46,6 +37,15 @@ "version": null } }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections.git", + "state": { + "branch": null, + "revision": "d029d9d39c87bed85b1c50adee7c41795261a192", + "version": "1.0.6" + } + }, { "package": "Yams", "repositoryURL": "https://github.com/jpsim/Yams.git", diff --git a/Package.swift b/Package.swift index a82b775..7ded9d2 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), - .package(url: "https://github.com/lukaskubanek/OrderedDictionary.git", from: "3.0.1"), + .package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.0")), .package(url: "https://github.com/pvieito/PythonKit", .branch("master")), .package(url: "https://github.com/pvieito/CommandLineKit", .branch("master")), .package(url: "https://github.com/donn/Defile.git", from: "5.2.1"), @@ -23,7 +23,7 @@ let package = Package( // Targets can depend on other targets in this package, and on products in packages which this package depends on. .executableTarget( name: "Fault", - dependencies: ["PythonKit", "CommandLineKit", "Defile", "OrderedDictionary", "BigInt", "Yams"], + dependencies: ["PythonKit", "CommandLineKit", "Defile", .product(name: "Collections", package: "swift-collections"), "BigInt", "Yams"], path: "Sources" ), .testTarget( diff --git a/Sources/Fault/Entries/main.swift b/Sources/Fault/Entries/main.swift index 6f34f89..4a85914 100644 --- a/Sources/Fault/Entries/main.swift +++ b/Sources/Fault/Entries/main.swift @@ -17,10 +17,10 @@ import CommandLineKit import CoreFoundation // Not automatically imported on Linux import Defile import Foundation -import OrderedDictionary +import Collections import PythonKit -let VERSION = "0.6.0" +let VERSION = "0.6.1" var env = ProcessInfo.processInfo.environment let iverilogBase = env["FAULT_IVL_BASE"] ?? "/usr/local/lib/ivl" diff --git a/Sources/Fault/Port.swift b/Sources/Fault/Port.swift index 3ded858..7d03444 100644 --- a/Sources/Fault/Port.swift +++ b/Sources/Fault/Port.swift @@ -11,11 +11,12 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - +import Defile import Foundation import PythonKit +import Collections -class Port: Codable { +struct Port: Codable { enum Polarity: String, Codable { case input case output @@ -59,7 +60,7 @@ class Port: Codable { paramaters["\(declaration.name)"] = Port.evaluate(expr: declaration.value.var, params: paramaters) } else if declType == "Input" || declType == "Output" { - guard let port = ports["\(declaration.name)"] else { + guard var port = ports["\(declaration.name)"] else { throw "Unknown port \(declaration.name)" } if declaration.width != Python.None { @@ -75,6 +76,7 @@ class Port: Codable { port.polarity = .output outputs.append(port) } + ports["\(declaration.name)"] = port } } } diff --git a/Sources/Fault/Simulation.swift b/Sources/Fault/Simulation.swift index e644821..04ddeef 100644 --- a/Sources/Fault/Simulation.swift +++ b/Sources/Fault/Simulation.swift @@ -184,9 +184,8 @@ enum Simulator { _ = "rm -rf \(folderName)".sh() } } - var faults = output.components(separatedBy: "\n").filter { - !$0.trimmingCharacters(in: .whitespaces).isEmpty + !$0.trimmingCharacters(in: .whitespaces).isEmpty && !$0.contains("$finish") } var gmOutput = "" if goldenOutput { @@ -194,7 +193,7 @@ enum Simulator { if let bin = BigUInt(last, radix: 2) { gmOutput = String(bin, radix: 16) } else { - print("[Warning]: golden output contains x or z.") + print("[Warning]: Golden output was invalid: '\(last)'.") } } diff --git a/Sources/Fault/Synthesis.swift b/Sources/Fault/Synthesis.swift index 77f814b..0d4a87d 100644 --- a/Sources/Fault/Synthesis.swift +++ b/Sources/Fault/Synthesis.swift @@ -39,7 +39,7 @@ enum Synthesis { ) -> String { let opt = optimize ? "opt" : "" return """ - read_verilog \(files.map { file in "'\(file)'" }.joined(separator: " ")) + read_verilog -sv \(files.map { file in "'\(file)'" }.joined(separator: " ")) # check design hierarchy hierarchy \(checkHierarchy ? "-check" : "") -top \(module) diff --git a/Tests/FaultTests/FaultTests.swift b/Tests/FaultTests/FaultTests.swift index 0ba3d2b..456bdd1 100644 --- a/Tests/FaultTests/FaultTests.swift +++ b/Tests/FaultTests/FaultTests.swift @@ -5,8 +5,10 @@ var env = ProcessInfo.processInfo.environment extension Process { func startAndBlock() throws { - try launch() + log("$ \(self.executableURL!.path()) \((self.arguments ?? []).joined(separator: " "))") + launch() waitUntilExit() + print("Exited with: \(self.terminationStatus)") } } @@ -35,6 +37,11 @@ extension String { } } +func log(_ string: String) { + print(string) + fflush(stdout) +} + final class FaultTests: XCTestCase { func testFull() throws { guard #available(macOS 10.13, *) else { @@ -70,7 +77,7 @@ final class FaultTests: XCTestCase { let models = "Tech/osu035/osu035_stdcells.v" let fileName = "Tests/RTL/spm.v" - let topModule = "SPM" + let topModule = "spm" let clock = "clk" let reset = "rst" let ignoredInputs = "\(reset)" @@ -88,7 +95,7 @@ final class FaultTests: XCTestCase { try process.startAndBlock() XCTAssertEqual(process.terminationStatus, 0) - print("1/6") + log("1/6") // 1. Cut process = newProcess() process.arguments = ["cut", "-o", fileCut, fileSynth] @@ -100,16 +107,15 @@ final class FaultTests: XCTestCase { process = newProcess() process.arguments = ["-c", models, "-i", ignoredInputs, "--clock", clock, "-o", fileJson, fileCut] try process.startAndBlock() - print("2/6") + log("2/6") XCTAssertEqual(process.terminationStatus, 0) // 3. Chain process = newProcess() - process.arguments = ["chain", "-c", models, "-l", liberty, "-o", fileChained, "--clock", clock, "--reset", reset, "-i", ignoredInputs, fileSynth] - print(process.arguments!.joined(separator: " ")) + process.arguments = ["chain", "-c", models, "-l", liberty, "-o", fileChained, "--clock", clock, "--reset", reset, "--activeLow", "-i", ignoredInputs, fileSynth] try process.startAndBlock() - print("3/6") + log("3/6") XCTAssertEqual(process.terminationStatus, 0) @@ -117,7 +123,7 @@ final class FaultTests: XCTestCase { process = newProcess() process.arguments = ["asm", fileJson, fileChained] try process.startAndBlock() - print("4/6") + log("4/6") XCTAssertEqual(process.terminationStatus, 0) @@ -125,13 +131,13 @@ final class FaultTests: XCTestCase { process = newProcess() process.arguments = ["compact", "-o", "/dev/null", fileJson] try process.startAndBlock() - print("5/6") + log("5/6") // 6. Tap process = newProcess() - process.arguments = ["tap", fileChained, "-c", models, "--clock", clock, "--reset", reset, "-l", liberty, "-t", fileAsmVec, "-g", fileAsmOut, "-i", ignoredInputs] + process.arguments = ["tap", fileChained, "-c", models, "--clock", clock, "--reset", reset, "--activeLow", "-l", liberty, "-t", fileAsmVec, "-g", fileAsmOut, "-i", ignoredInputs,] try process.startAndBlock() - print("6/6") + log("6/6") XCTAssertEqual(process.terminationStatus, 0) } diff --git a/Tests/RTL/spm.v b/Tests/RTL/spm.v index 0439846..be02ce3 100644 --- a/Tests/RTL/spm.v +++ b/Tests/RTL/spm.v @@ -1,4 +1,4 @@ -// Copyright 2020 Efabless Corporation +// Copyright 2023 Efabless Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,73 +12,64 @@ // See the License for the specific language governing permissions and // limitations under the License. -module spm(clk, rst, x, y, p); - parameter size = 32; - input clk, rst; - input y; - input[size-1:0] x; - output p; +// (Parameterized) Unsigned Serial/Parallel Multiplier: +// - Multiplicand x (Input bit-serially) +// - Multiplier a (All bits at the same time/Parallel) +// - Product y (Output bit-serial) +module spm #(parameter bits=32) ( + input clk, + input rst, + input x, + input[bits-1: 0] a, + output y, + output always_high, +); + wire[bits: 0] y_chain; + assign y_chain[0] = 0; + assign y = y_chain[bits]; - wire[size-1:1] pp; - wire[size-1:0] xy; + wire[bits-1:0] a_flip; + generate + for (genvar i = 0; i < bits; i = i + 1) begin : flip_block + assign a_flip[i] = a[bits - i - 1]; + end + endgenerate - genvar i; - - CSADD csa0 (.clk(clk), .rst(rst), .x(x[0]&y), .y(pp[1]), .sum(p)); - generate for(i=1; i