{"id":13786979,"url":"https://github.com/MatthewLoveQUB/SKILL_Tools","last_synced_at":"2025-05-12T00:30:36.392Z","repository":{"id":216015489,"uuid":"97092632","full_name":"MatthewLoveQUB/SKILL_Tools","owner":"MatthewLoveQUB","description":"Utilities for working with Cadence's SKILL/SKILL++ including a unit testing framework.","archived":false,"fork":false,"pushed_at":"2020-11-06T12:21:20.000Z","size":408,"stargazers_count":36,"open_issues_count":2,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-18T00:37:16.630Z","etag":null,"topics":["cadence","lisp","skill","unittest","unittesting","virtuoso"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MatthewLoveQUB.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-13T07:21:40.000Z","updated_at":"2024-07-22T12:41:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"e0146301-3386-4b37-a1f2-4e5636b0ab22","html_url":"https://github.com/MatthewLoveQUB/SKILL_Tools","commit_stats":null,"previous_names":["matthewlovequb/skill_tools"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatthewLoveQUB%2FSKILL_Tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatthewLoveQUB%2FSKILL_Tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatthewLoveQUB%2FSKILL_Tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatthewLoveQUB%2FSKILL_Tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MatthewLoveQUB","download_url":"https://codeload.github.com/MatthewLoveQUB/SKILL_Tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253655755,"owners_count":21943068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cadence","lisp","skill","unittest","unittesting","virtuoso"],"created_at":"2024-08-03T20:00:23.878Z","updated_at":"2025-05-12T00:30:35.745Z","avatar_url":"https://github.com/MatthewLoveQUB.png","language":"Common Lisp","funding_links":[],"categories":["Full Custom Design"],"sub_categories":["Verification"],"readme":"# SKILL Tools\n\nTools to ease working with SKILL and SKILL++ in Cadence Virtuoso. The main feature of interest is the unit testing framework in the folder `qtest`.\nThis repo contains the code that I use regularly in my PhD so it's also available in case anyone finds any use for it.\nThere's not a lot of SKILL code in the wild beyond the Cadence forums.\n\n## Project Structure\n\n| Folder | Namespace | Purpose\n|---|---|---|\n| `circuits` | `qub` | Circuit analysis\n| `design_environment` | `qub` | Manipulating the Cadence Virtuoso design environment\n| `geometry` | `qub` | Geometry calculations\n| `ocean` | `qub` | Processing simulation results\n| `pcell` | `qub` | Generating custom PCells\n| `qtest` | `qtest` | Unit testing.\n| `std` | `qub` | A \"standard library\" of useful functions.\n| `inductor_generator` | `qub` | Inductor PCell generation.\n\n## Importing the project\n\nCreate the environment variable `QUB_CODE_REPO_DIR` and point it at the repo root directory.\nAdd the `src` folder to the SKILL path and run `(load (strcat (getShellEnvVar \"QUB_CODE_REPO_DIR\") \"/src/init.ils\"))` and all other modules will be imported.\nThe `src` folder can be added to the SKILL path like so: `(setSkillPath (append (getSkillPath) (list (strcat (getShellEnvVar \"QUB_CODE_REPO_DIR\") \"/src/\"))))`.\nIf the inductor PCell code is to be used, this code library needs to be re-added using libInit.il for the Virtuoso library that the PCell resides in or else stream-out will fail.\n\n## Unit Testing\n\nThe unit testing framework is modelled after [Python's `unittest` module](https://docs.python.org/3/library/unittest.html) and provides a basic set of assertions for testing your code.\n\n### Example Test\n\nThe test is run by calling `load` on the file containing the test.\n\n```lisp\n(qtest::runSuites\n  (qtest::TestSuite ((f qub:::join_lists))\n    (qtest::TestCase join_three_lists\n      (qtest::assertEqual (list \"X\" 2 3 4 5 6)\n                           (f (list (list 1 2) (list 3 4) (list 5 6))))))\n  (qtest::TestSuite ((f qub::flatten_list))\n    (qtest::TestCase normal_use\n      (qtest::assertEqual (list 1 2 3 4 5 6 7)\n                           (f (list 1 2 (list 3 (list 4 (list 5 6) 7))))))))\n```\n\n```lisp\n(load \"./code/src/std/test_lists.ils\")\n1 of 2 tests passed (1 failures) (0 skipped) (0 expected failures)\nTest: join_three_lists\nResult: Fail\n Message: No msg.\n Inputs: (list(\"X\" 2 3 4 5 6) (f list(list(1 2) list(3 4) list(5 6))))\n Evaluated Inputs: ((\"X\" 2 3 4 5 6) (1 2 3 4 5 6))\n``` \n\n## Main Functions and Macros\n\n### `qtest::runAllTests`\n\n| Parameter(s)  |  Side Effect(s) |\n|-----------------|----------------|\n| Directory (`string`)|Calls `load` on all files prefixed with `test_` in the directory |\n\nTakes a folder path and loads all modules prefixed with test_.\n\n### `qtest::TestCase`\n\n| Parameters(s)| Keyword Parameters  | Output(s)\n|---|---|---|\n| Test Name (unquoted symbol) |`skip` (bool)| List of the test name symbol and the function object\n|body|  `expect_fail` (bool)\n\nRepresents a single test. Can contain any code but must return the result of an assertion function. The test name is contained in a list with the function object so tests don't pollute the top level namespace.\n\n#### Skipping a test\n\nTo mark a test to be skipped, set the `skip` keyword argument to true.\n\n#### Marking a test that you expect to fail\n\nSet the `expect_fail` keyword argument to true. If the test passes it will count as a pass but if it fail it will not be recorded as a fail.\n\n### `qtest::TestSuite`\n\n| Parameter(s)  | Output(s) |\n|---|---|\n| Test Cases | List containing lists returned by `qtest::TestCase` |\n\nA collection of test cases. A suite should be used to test a single function or method.\n\n### `qtest::runSuites`\n\n| Parameter(s)  | Side Effect(s) |\n|-----------------|----------------|\n| Any number of Test Suites | Prints the results of the tests |\n\nTest suites should be written in the body of this macro. When the module file is loaded in Virtuoso, the tests are initialised and the results are printed in the CIW.\n\n## Assertions\n\nEach assertion takes a keyword argument `msg` which is printed if the test fails.\n\n### `qtest::assertEqual`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\n\n\nChecks if two objects are equal. Uses the `qub::equal` method to allow you to implement equality for your own objects as well as numbers, strings etc.\n\n### `qtest::assertNotEqual`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\n\nChecks if two objects are not equal. Uses the `qub::notEqual` method to allow you to implement equality for your own objects as well as numbers, strings etc.\n\n### `qtest::assertTrue`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n\nChecks that the argument is true.\n\n### `qtest::assertNil`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n\nChecks that the argument is `nil`.\n\n### `qtest::assertEq`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\n\nBoth arguments are the same object.\n\n### `qtest::assertNotEq`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\nThe arguments are different objects.\n\n### `qtest::assertMember`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| value | msg (`string`) | `qtest::Result` |\n| list \n\nThe object is a member of the list.\n\n### `qtest::assertNotMember`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| value | msg (`string`) | `qtest::Result` |\n| list\n\n\n\nThe object is not a member of the list.\n\n### `qtest::assertIsInstance`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| Object | msg (`string`) | `qtest::Result` |\n| Quoted Class\n\n\nThe object is an instance of the class.\n\n### `qtest::assertNotIsInstance`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| Object | msg (`string`) | `qtest::Result` |\n| Quoted Class\n\n\nThe object is not an instance of the class.\n\n### `qtest::assertRaises`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| Function Call | msg (`string`) | `qtest::Result` |\n\nChecks that the expression raises an error using `error`. \nIt may not catch other errors within the expression.\n\n### `qtest::assertAlmostEqual`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\n\nChecks that two floats are almost equal. Uses `qub::almostEqual` which is a port of Python's [`math.isclose`](https://docs.python.org/3/library/math.html#math.isclose) and uses the same optional arguments.\n\n### `qtest::assertNotAlmostEqual`\n\n| Parameter(s)  | Keyword Parameters | Output(s) |\n|-----------------|-----------|---|\n| a | msg (`string`) | `qtest::Result` |\n| b \n\nChecks that two floats are not almost equal.\n\n## Standard Library Functions and Macros\n\n### `qub::checkType`\n\n| Parameters | Side Effects |\n| --- | --- |\n| Object | Throws an error if the object is of the expected type.\n| Quoted Class Name\n\nFor implementing run-time type checking in functions.\n\n### `qub::equal`\n\n| Parameters | Result |\n| --- | --- |\n| a | Bool\n| b\n\nA generic function for implementing equality for your own types.\n\n### `qub::nequal`\n\n| Parameters | Result |\n| --- | --- |\n| a | Bool\n| b\n\nA generic function for implementing inequality for your own types.\n\n### `qub::allEqual`\n\n| Parameters | Result |\n| --- | --- |\n| `@rest values` | bool\n\nChecks if all values are equal. It uses `qub::equal` for checking equality.\n\n### `qub::listFileRec`\n\n| Parameter | Result |\n|---|---|\n| Path (string) | List of files in the directory |\n\nRecursively searches the path for all files. It ignores all dotted directories.\n\n### `qub::foldl`\n\n| Paramater | Result |\n|---|---|\n| fn(accumulator value) | The \"folded\" value\n| Initial Value\n| List of Values\n\nThe [HaskellWiki](https://wiki.haskell.org/Fold) can probably explain this better than I could.\n\n### `qub::foldr`\n\nThe same as `qub::foldl` but it calls `reverse` on the list before it processes it.\n\n### `qub::sum`\n\nSums a list of numbers\n\n### `qub:::lcmp`\n\nAn implementation of python's list comprehensions.\nThe predicate is optional.\n\n```lisp\n\u003e\u003e\u003e(qub:::lcmp (times x 2) for x in (list 1 2 3 4) if (evenp x))\n(4 8)\n```\n\n### `qub::joinLists`\n\n| Paramater | Result |\n| --- | --- |\n| List of lists | A single list of the values within the input lists |\n\n### `qub::range`\n\n| Keyword parameters | Result |\n| --- | --- |\n| start | List of integers \n| stop\n| step\n\nA port of python's `range` function.\n\n```lisp\n\u003e\u003e\u003e(qub::range ?start 0 ?stop 20 ?step 3)\n(0 3 6 9 12\n    15 18\n)\n```\n\n### `qub::almostEqual`\n\n| Parameters | Keyword Parameters | Result |\n|---|---|---|\n| a |`rel_tol`| Bool\n| b | `abs_tol`\n\nChecks that two values are almost equal. This is a generic function and can be applied to your own types. The method specialised on numbers is a port of Python's [`math.isclose`](https://docs.python.org/3/library/math.html#math.isclose) and uses the same optional arguments.\n\n`rel_tol` is the relative tolerance. 0.05 would be a 5% relative tolerance.\n`abs_tol` is the absolute tolerance. \n\n\n\n### `qub::startsWith`\n\n| Parameters | Result |\n| ---|---|\n| string | Bool\n| prefix (string)\n\nChecks if a string begins with a particular prefix\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMatthewLoveQUB%2FSKILL_Tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMatthewLoveQUB%2FSKILL_Tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMatthewLoveQUB%2FSKILL_Tools/lists"}