{"id":13647295,"url":"https://github.com/sifive/duh-scala","last_synced_at":"2025-08-10T04:17:31.698Z","repository":{"id":34835512,"uuid":"174436464","full_name":"sifive/duh-scala","owner":"sifive","description":"⛏️ DUH component export to Scala","archived":false,"fork":false,"pushed_at":"2022-05-28T19:01:20.000Z","size":274,"stargazers_count":7,"open_issues_count":11,"forks_count":3,"subscribers_count":56,"default_branch":"master","last_synced_at":"2025-08-09T05:02:14.836Z","etag":null,"topics":["duh","hacktoberfest"],"latest_commit_sha":null,"homepage":"https://github.com/sifive/duh","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sifive.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}},"created_at":"2019-03-07T23:32:07.000Z","updated_at":"2023-09-23T19:08:43.000Z","dependencies_parsed_at":"2022-09-20T07:40:31.139Z","dependency_job_id":null,"html_url":"https://github.com/sifive/duh-scala","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/sifive/duh-scala","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sifive%2Fduh-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sifive%2Fduh-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sifive%2Fduh-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sifive%2Fduh-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sifive","download_url":"https://codeload.github.com/sifive/duh-scala/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sifive%2Fduh-scala/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269674904,"owners_count":24457457,"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","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["duh","hacktoberfest"],"created_at":"2024-08-02T01:03:28.329Z","updated_at":"2025-08-10T04:17:31.641Z","avatar_url":"https://github.com/sifive.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"[![NPM version](https://img.shields.io/npm/v/duh-scala.svg)](https://www.npmjs.org/package/duh-scala)\n[![Actions Status](https://github.com/sifive/duh-scala/workflows/Tests/badge.svg)](https://github.com/sifive/duh-scala/actions)\n\nDUH component export to Scala\n\n## Installation\n```\nnpm i duh-scala\n```\n\n### Exporting a blackbox wrapper and `attach` method\nThis is a scala `LazyModule` that has diplomatic nodes corresponding to the bus\ninterfaces of the duh component.\n```bash\nduh-export-scala \u003cmycomp\u003e.json5 -o \u003coutput-dir\u003e\n```\n\n### Exporting a `RegisterRouter`\n`duh-export-regmap` will export a `RegisterRouter` corresponding the the\n`memoryMap`s in a duh component. A `RegisterRouter` is an abstract Scala\ndescription of memory-mapped registers that is generic to any bus interface.\nConcrete implementations for TileLink and AXI4 are included in the generated\nScala.\n```bash\nduh-export-regmap \u003cmycomp\u003e.json5 -o \u003coutput-dir\u003e\n```\n\n### Exporting a monitor wrapper and `attach` method\nThis is a special kind of chisel `Module` that can be attached to diplomatic\nedges corresponding to the monitor's bus interface type.\n```bash\nduh-export-monitor \u003cmycomp\u003e.json5 -o \u003coutput-dir\u003e\n```\n\n## Blackbox wrapper API\nThis section describes the API of the blackbox wrapper generated by\n`duh-export-scala`. The hierarchy of the output modules is looks like\n```\ntop: N${name}Top\n└── imp: L${name}\n    └── blackbox: ${name}\n```\nThe reason for having two layers of wrapping is to separate the purely\ncombinational wrapper logic from the sequential logic. The inner `L${name}`\nmodule only contains combinational wrapper logic while the outer `N${name}Top`\nmodule contains sequential logic\n\n\nThe `L${name}` module contains the node declarations, blackbox instantiation,\nand connections between node bundles and blackbox ports. There is also an\n`extraResources` method that is called when the DTS data structure is\nconstructed. The fields returned by this method are included in the entry\ncorresponding the component in the DTS.\n```scala\nclass L${name}Base(c: ${name}Params)(implicit p: Parameters) extends LazyModule {\n\n  // device declaration\n  val device = new SimpleDevice(\"${name}\", Seq(\"sifive,${name}-${version}\")) {\n    ...\n  }\n\n  // extra fields to include in the entry of this device in the DTS\n  def extraResources(resources: ResourceBindings) = Map[String, Seq[ResourceValue]]()\n\n  // node declarations\n  val axiNode = ...\n  val apbNode = ...\n  ...\n\n  // blackbox instantiation and wiring\n  lazy val module = new L${name}BaseImp\n}\n```\n\nThe corresponding user class that extends `L${name}Base` looks like\n```scala\nclass L${name}(c: ${name}Params)(implicit p: Parameters) extends L${name}Base(c)(p)\n{\n\n// User code here\n\n}\n```\n\nTo add another integer field called `data-width` and string field called `name`\nyou would add the following code into the user `L${name}` class.\n```scala\n  override def extraResources(resources: ResourceBindings) =\n      Map(\"data-width\" -\u003e Seq(ResourceInt(dataWidth)),\n        \"name\" -\u003e Seq(ResourceString(name)))\n```\n\nThe result should look like\n```scala\nclass L${name}(c: ${name}Params)(implicit p: Parameters) extends L${name}Base(c)(p)\n{\n  override def extraResources(resources: ResourceBindings) =\n      Map(\"data-width\" -\u003e Seq(ResourceInt(dataWidth)),\n        \"name\" -\u003e Seq(ResourceString(name)))\n}\n```\n\n\n\nThe `N${name}` module contains methods to instantate TileLink adapters for the\nnodes. It also contains a method called `userOM` that is called when the object\nmodel of the component is constructed. The object returned by `userOM` is\nincluded with the base object model. This can be overrided to include arbitrary\ninformation in the object model and defaults to empty. The value returned by\nthis method should be an instance of a `case class` which is why it returns\n`Product with Serializable`.\n```scala\nclass N${name}TopBase(val c: N${name}TopParams)(implicit p: Parameters) extends SimpleLazyModule\n  with BindingScope {\n\n  // userOM method\n  def userOM: Product with Serializable = Nil\n\n  // adapter methods\n  def getaxilNodeTLAdapter(): TLInwardNode = ...\n  def getahblNodeTLAdapter(): TLInwardNode = ...\n  ...\n}\n```\n\n\nThe corresponding user class that extends `N${name}Base` looks like\n```scala\nclass N${name}Top(c: N${name}TopParams)(implicit p: Parameters) extends N${name}TopBase(c)(p)\n{\n\n// User code here\n\n}\n```\n\nTo add the following fields to the `OMDevice` of the component\n```javascript\nfoo: \"foo\",\nfoobar: {\n  foo: \"foo\",\n  bar: \"bar\"\n}\n```\n\nadd the following code to the user `N${name}` by defining the following case class\n```\ncase class MyOM(foo: String, foobar: Map[String, String])\n```\n\nand add the following code to `N${name}`\n```scala\n  override def userOM = new MyOM(\"foo\", Map(\"foo\" -\u003e \"foo\", \"bar\" -\u003e \"bar\"))\n```\n\nThe result should look like\n```scala\nclass N${name}Top(c: N${name}TopParams)(implicit p: Parameters) extends N${name}TopBase(c)(p)\n{\n  override def userOM = new MyOM(\"foo\", Map(\"foo\" -\u003e \"foo\", \"bar\" -\u003e \"bar\"))\n}\n```\n\nAnd the output object model should look like\n```javascript\n{\n  \"foo\" : {\n    \"foo\" : \"foo\",\n    \"bar\" : \"bar\"\n  },\n  \"memoryRegions\" : [ ... ],\n  \"interrupts\" : [ ... ],\n  \"_types\" : [ \"OM${name}\", \"OMDevice\", \"OMComponent\", \"OMCompoundType\" ]\n}\n```\n\n\n## Testing\n```\nnpm test\n```\n\n## License\nApache 2.0 [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsifive%2Fduh-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsifive%2Fduh-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsifive%2Fduh-scala/lists"}