Author Topic: HardwareScript - Just another description language.  (Read 1222 times)

0 Members and 1 Guest are viewing this topic.

Offline CaneTopic starter

  • Newbie
  • Posts: 5
  • Country: ng
    • Cane the dev
HardwareScript - Just another description language.
« on: August 14, 2026, 10:36:22 pm »
Hardware Script (.hw) is a text-based hardware design language that compiles to industry-standard formats. The goal is to design PCBs, silicon chips, and electronic systems from human-readable, Git-friendly text. Source code and info available here github.com/HardwareScript/hwc
« Last Edit: August 14, 2026, 10:44:07 pm by Cane »
 

Offline Renate

  • Super Contributor
  • ***
  • Posts: 1817
  • Country: de
    • Renate's Android Page
Re: HardwareScript - Just another description language.
« Reply #1 on: August 15, 2026, 04:36:53 am »
Not a lot of "meat" here.

If it's text-based, why not give us an example instead of just posting a link?
 

Offline CaneTopic starter

  • Newbie
  • Posts: 5
  • Country: ng
    • Cane the dev
Re: HardwareScript - Just another description language.
« Reply #2 on: August 15, 2026, 06:42:36 am »
"For example, whether you are laying out an SMT board or a 130nm polysilicon resistor targeting the SkyWater PDK, you write the physical and electrical constraints once in .hw text.
The compiler (hwc) validates the 3D material stackup and via depths, performs DRC/LVS and EM/thermal checks, and compiles out everything required downstream:
Manufacturing: Gerber X3 / Excellon (PCBs) or GDSII (Silicon)
Simulation: SPICE netlists with extracted parasitic R/C(dc.sp, ac.sp, tran.sp)
Visualization & Mechanical: 2D DXF and 3D GLB/OBJ models
Procurement: Full BOM accounting (bom.csv)
"
Code: [Select]
# simple_resistor_test.hw - SKY130 P+ Poly Resistor Test (100% Relational Layout)
# Device: sky130_fd_pr__res_high_po (350 Ω/□)
# Geometry: 4μm × 1.41μm = ~1.0kΩ expected (using PDK-compliant quantized width)
#
import * from @std/primitives/units
import * from "./resistor_pdk"

module SimpleResistor:
    pins: [input In, output Out]
    route In to Out

space Simple_Resistor_Space implements SimpleResistor:
    dimensions: 20.0um by 10.0um
    profile: Resistor_3D

    nets:
        In:  { classification: signal, potential: 1.8V, current: 1.0uA }
        Out: { classification: signal, potential: 0.0V, current: 1.0uA }
        GND: { classification: ground, potential: 0.0V, current: 0.0uA }

    device_nets R1:
        BULK: GND

    # ========================================================================
    # PARAMETRIC DIMENSIONS (Self-Healing Layout)
    # ========================================================================
    let res_length = 4.0um
    let res_width = 1.41um          # SKY130 quantized width (W ∈ {0.35, 0.69, 1.41, 2.85, 5.73}μm)
    let contact_length = 400nm      # Contact head length along current flow direction
    let pad_size = 1.0um
    let pad_spacing = 3.0um
    let tap_size = 400nm
    let tap_offset_y = 2.5um
    let via_pitch = 400nm           # Via pitch: diameter (170nm) + min_spacing (230nm clearance)


    add pour(Polysilicon) named Resistor_Body on layer: polyres:
        device: R1.A, R1.B
        dimensions: res_length by res_width
        at: [x: 10.0um, y: 5.0um]   


    add pour(Resistor_Poly_Mask) named RPM_Block on layer: rpm:
        dimensions: res_length + 360nm by res_width + 360nm
        align: center_x with Resistor_Body
        align: center_y with Resistor_Body

    add pour(Titanium_Silicide) named Contact_A_LI on layer: li1:
        device: R1.A
        net: In
        dimensions: contact_length by res_width
        align: center_x with Resistor_Body.left + contact_length / 2
        align: center_y with Resistor_Body
   
    # Right Contact B: Centered on Resistor_Body.right - half contact length
    add pour(Titanium_Silicide) named Contact_B_LI on layer: li1:
        device: R1.B
        net: Out
        dimensions: contact_length by res_width
        align: center_x with Resistor_Body.right - contact_length / 2
        align: center_y with Resistor_Body

    for i in 0..3:
        add contact(Tungsten) named Via_A_Poly_{i} spanning layer: polyres to li1:
            diameter: 170nm
            align: center_x with Contact_A_LI
            align: center_y with Contact_A_LI.center_y + (i - 1) * via_pitch
            net: In
   
    # Terminal B via array (3 vias symmetrically centered)
    for i in 0..3:
        add contact(Tungsten) named Via_B_Poly_{i} spanning layer: polyres to li1:
            diameter: 170nm
            align: center_x with Contact_B_LI
            align: center_y with Contact_B_LI.center_y + (i - 1) * via_pitch
            net: Out

    add pour(Aluminum) named Contact_A_Metal on layer: metal1:
        dimensions: contact_length by res_width
        align: center_x with Contact_A_LI
        align: center_y with Contact_A_LI
        net: In

    add pour(Aluminum) named Contact_B_Metal on layer: metal1:
        dimensions: contact_length by res_width
        align: center_x with Contact_B_LI
        align: center_y with Contact_B_LI
        net: Out

    for i in 0..3:
        add contact(Tungsten) named Via_A_Metal_{i} spanning layer: li1 to metal1:
            diameter: 170nm
            align: center_x with Contact_A_LI
            align: center_y with Contact_A_LI.center_y + (i - 1) * via_pitch
            net: In
   
    # Terminal B via array (3 vias symmetrically centered)
    for i in 0..3:
        add contact(Tungsten) named Via_B_Metal_{i} spanning layer: li1 to metal1:
            diameter: 170nm
            align: center_x with Contact_B_LI
            align: center_y with Contact_B_LI.center_y + (i - 1) * via_pitch
            net: Out


    add pour(Aluminum) named In_Pad on layer: metal1:
        dimensions: pad_size by pad_size
        align: center_x with Contact_A_Metal.left - pad_spacing
        align: center_y with Contact_A_Metal
        net: In

    add pour(Aluminum) named Out_Pad on layer: metal1:
        dimensions: pad_size by pad_size
        align: center_x with Contact_B_Metal.right + pad_spacing
        align: center_y with Contact_B_Metal
        net: Out

    route In_Pad to Contact_A_Metal:
        net: In
        width: 300nm
        layer: metal1
        intent: Signal

    route Contact_B_Metal to Out_Pad:
        net: Out
        width: 300nm
        layer: metal1
        intent: Signal


    add pour(P_Plus_Diffusion) named Bulk_Tap_Diff on layer: pdiff:
        dimensions: tap_size by tap_size
        align: center_x with Resistor_Body
        align: center_y with Resistor_Body.center_y + tap_offset_y
        net: GND
        device: R1.BULK
   
    # 8b. LOCAL INTERCONNECT CONTACT (licon - connects pdiff to li1)
    add contact(Tungsten) named Bulk_Tap_Contact spanning layer: pdiff to li1:
        diameter: 170nm
        align: center_x with Bulk_Tap_Diff
        align: center_y with Bulk_Tap_Diff
        net: GND
   
    # 8c. LOCAL INTERCONNECT METAL (li1 layer)
    add pour(Titanium_Silicide) named Bulk_Tap_LI on layer: li1:
        dimensions: tap_size by tap_size
        align: center_x with Bulk_Tap_Diff
        align: center_y with Bulk_Tap_Diff
        net: GND


test Simple_Resistor_AC_Test for Simple_Resistor_Space:
    ac: { sweep: dec, points: 20, freq: 100Hz..100MHz }
    tran: { step: 10ps, stop: 200ns }
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 6140
  • Country: nl
Re: HardwareScript - Just another description language.
« Reply #3 on: August 15, 2026, 09:59:42 am »
Not sure if this is very useful. A lot of text to describe something that is far easier done, and better to understand with the use of a schematic.

In this case I think it is true that a picture says more than a thousand words.

But who knows were it aids in making designs.

Offline CaneTopic starter

  • Newbie
  • Posts: 5
  • Country: ng
    • Cane the dev
Re: HardwareScript - Just another description language.
« Reply #4 on: August 15, 2026, 10:10:39 am »
You made an excellent point. Too much text just for describing a resistor but the point is when you move higher on the ladder to something more complex, like CMOS, logic gates and more complex socketry, it makes it easier for the inbuilt system to work. This is because it ships with
DRC
LVS   
PIVB   
EM   
Thermal   
Crosstalk
RF Parasitics in the box. All this descriptive information is necessary as the base level if someone else imports it, all the information transfers so these are like the building blocks, not necessarily the build itself.
It also helps when .hw transpiling to other languages like SPICE.
And it won't build if everything doesn't add up. I added example log output.
Code: [Select]
[NETLIST PARASITIC DEBUG]     Γ£ô MATCH! Adding device_nodes[("R1", "A")] = 'In'
[NETLIST PARASITIC DEBUG]     Checking terminal 'BULK' -> 'GND' (looking for net 'In')
[NETLIST PARASITIC DEBUG] Processing net 'Out' with 1 segments
[NETLIST PARASITIC DEBUG] Net 'Out' seg 0: Found material properties
[NETLIST PARASITIC DEBUG] Net 'Out' seg 0: resistivity = 0.0000000282
[NETLIST PARASITIC DEBUG] Net 'Out' seg 0: R = 0.6527777777777776Ω (length=0.0000025m,
area=0.00000000000010800000000000003m┬▓)
[NETLIST PARASITIC DEBUG] Net 'Out' seg 0: Adding trace resistor
[NETLIST PARASITIC DEBUG] Net 'Out': Mapping device terminals to logical net
[NETLIST PARASITIC DEBUG]   Device 'R1': terminals = {"B": "Out", "A": "In", "BULK": "GND"}
[NETLIST PARASITIC DEBUG]     Checking terminal 'B' -> 'Out' (looking for net 'Out')
[NETLIST PARASITIC DEBUG]     Γ£ô MATCH! Adding device_nodes[("R1", "B")] = 'Out'
[NETLIST PARASITIC DEBUG]     Checking terminal 'A' -> 'In' (looking for net 'Out')
[NETLIST PARASITIC DEBUG]     Checking terminal 'BULK' -> 'GND' (looking for net 'Out')
[NETLIST DEBUG] physical_netlist is_some: true
[NETLIST DEBUG] physical_netlist.devices.len(): 1
[NETLIST PARASITIC DEBUG] About to check if parasitics should be written: 4 parasitics
[NETLIST PARASITIC DEBUG] Writing 4 parasitics to SPICE netlist
[  695.64ms] PIVB connectivity check completed in 2.74ms
[  699.60ms] About to create exporter...
   Γ£à GLB: tests\Resistor-Basics\build\Simple_Resistor_Space\board.glb
[  853.42ms] Format Glb exported in 153.7923ms
   Γ£à DXF: tests\Resistor-Basics\build\Simple_Resistor_Space\board.dxf
[  942.53ms] Format Dxf exported in 89.0924ms
✅ SPICE Suite: tests\Resistor-Basics\build\Simple_Resistor_Space/spice/ (21 components, 11 nets)
   Γö£ΓöÇ circuit.sp (raw DUT)
   Γö£ΓöÇ dc.sp (DC operating point)
   Γö£ΓöÇ ac.sp (AC frequency response)
   ΓööΓöÇ tran.sp (transient waveform)
[  949.60ms] Format Netlist exported in 7.0458ms
[  949.62ms] All requested formats exported
   Γ£à BOM: tests\Resistor-Basics\build\Simple_Resistor_Space\bom.csv (0 discrete items, 24 material items: 9 pours, 2 routes, 13 contacts)
    Finished build in 0.95s
 
« Last Edit: August 15, 2026, 10:12:52 am by Cane »
 

Offline fredswed

  • Contributor
  • Posts: 12
  • Country: se
Re: HardwareScript - Just another description language.
« Reply #5 on: September 02, 2026, 02:51:14 pm »
I ran into this post with no previous knowledge and while it seems like an interesting idea, I don't understand what problem it solves.
Could you give one or two concrete real-world examples where it would be a preferred tool?

To me (as an outsider) it seems the examples you give (e.g. IC design) are already using tools that generate geometries and 3D files needed for fabrication. And that capturing the same information in a text file would be extremly tedious.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->