leonardt / fault

A Python package for testing hardware (part of the magma ecosystem)
BSD 3-Clause "New" or "Revised" License
40 stars 13 forks source link

Where should we type check? #40

Open rsetaluri opened 5 years ago

rsetaluri commented 5 years ago

Imagine a circuit with input I of type Bits(4). If we have a fault.Tester for this circuit, and we issue for example a poke(circuit.I, 100), what should happen? I see 3 options:

The issue is more complex for expect() than poke() because if a bit-vector gets truncated it may return a false-positive equality. For example

BitVector(3, 4) == BitVector(BitVector(35, 8), 4)

though

BitVector(3, 4) != BitVector(35, 8)

My hunch is that we should issue a warning in the top-level poke and expect functions and try to enforce that the targets maintain as much structure as possible (i.e. do not truncate/zext).

leonardt commented 5 years ago

One way to approach this would be consider that the interface to the fault Tester object is a magma circuit, so perhaps poke, expect should match the magma type system. How this is enforced (fault frontend versus target) would be an implementation detail, but I would vote that poke and expect exhibit the same semantics as wiring constant values in magma. So, we do promotion when possible, but truncation is an error (the user needs to do this themselves).

One question is whether we can factor the code in a way such that we can use the exact same rules as magma (perhaps this requires magma to abstract it's type checking code for integers into routines which we can call in fault).

I think this might be better to do at the frontend, because the targets may have different semantics/ For example, verilator and ncsim might follow different type checking/promotion/conversion rules for integers than magma. I think our goal was to have a test bench work on all targets, so it should be specified in one frontend, and mapped to the semantics of the target. So my vote is to use magma's typing rules for the frontend.

rsetaluri commented 5 years ago

Good idea, I'm on board for that. So just to be clear, the most-user facing functions (e.g. Tester.poke/expect) should have promotion logic (e.g. python int to magma.uint), and the interface to the targets will be such that they all receive magma values (via the action objects).